1use super::{
2 bundle_state::BundleRetention, cache::CacheState, plain_account::PlainStorage, BundleState,
3 CacheAccount, StateBuilder, TransitionAccount, TransitionState,
4};
5use crate::db::EmptyDB;
6use revm_interpreter::primitives::{
7 db::{Database, DatabaseCommit},
8 hash_map, Account, AccountInfo, Address, Bytecode, HashMap, B256, BLOCK_HASH_HISTORY, U256,
9};
10use std::{
11 boxed::Box,
12 collections::{btree_map, BTreeMap},
13 vec::Vec,
14};
15
16pub type DBBox<'a, E> = Box<dyn Database<Error = E> + Send + 'a>;
18
19pub type StateDBBox<'a, E> = State<DBBox<'a, E>>;
23
24#[derive(Debug)]
29pub struct State<DB> {
30 pub cache: CacheState,
34 pub database: DB,
39 pub transition_state: Option<TransitionState>,
43 pub bundle_state: BundleState,
47 pub use_preloaded_bundle: bool,
53 pub block_hashes: BTreeMap<u64, B256>,
59}
60
61impl State<EmptyDB> {
63 pub fn builder() -> StateBuilder<EmptyDB> {
65 StateBuilder::default()
66 }
67}
68
69impl<DB: Database> State<DB> {
70 pub fn bundle_size_hint(&self) -> usize {
73 self.bundle_state.size_hint()
74 }
75
76 pub fn increment_balances(
85 &mut self,
86 balances: impl IntoIterator<Item = (Address, u128)>,
87 ) -> Result<(), DB::Error> {
88 let mut transitions = Vec::new();
90 for (address, balance) in balances {
91 if balance == 0 {
92 continue;
93 }
94 let original_account = self.load_cache_account(address)?;
95 transitions.push((
96 address,
97 original_account
98 .increment_balance(balance)
99 .expect("Balance is not zero"),
100 ))
101 }
102 if let Some(s) = self.transition_state.as_mut() {
104 s.add_transitions(transitions)
105 }
106 Ok(())
107 }
108
109 pub fn drain_balances(
113 &mut self,
114 addresses: impl IntoIterator<Item = Address>,
115 ) -> Result<Vec<u128>, DB::Error> {
116 let mut transitions = Vec::new();
118 let mut balances = Vec::new();
119 for address in addresses {
120 let original_account = self.load_cache_account(address)?;
121 let (balance, transition) = original_account.drain_balance();
122 balances.push(balance);
123 transitions.push((address, transition))
124 }
125 if let Some(s) = self.transition_state.as_mut() {
127 s.add_transitions(transitions)
128 }
129 Ok(balances)
130 }
131
132 pub fn set_state_clear_flag(&mut self, has_state_clear: bool) {
134 self.cache.set_state_clear_flag(has_state_clear);
135 }
136
137 pub fn insert_not_existing(&mut self, address: Address) {
138 self.cache.insert_not_existing(address)
139 }
140
141 pub fn insert_account(&mut self, address: Address, info: AccountInfo) {
142 self.cache.insert_account(address, info)
143 }
144
145 pub fn insert_account_with_storage(
146 &mut self,
147 address: Address,
148 info: AccountInfo,
149 storage: PlainStorage,
150 ) {
151 self.cache
152 .insert_account_with_storage(address, info, storage)
153 }
154
155 pub fn apply_transition(&mut self, transitions: Vec<(Address, TransitionAccount)>) {
157 if let Some(s) = self.transition_state.as_mut() {
159 s.add_transitions(transitions)
160 }
161 }
162
163 pub fn merge_transitions(&mut self, retention: BundleRetention) {
168 if let Some(transition_state) = self.transition_state.as_mut().map(TransitionState::take) {
169 self.bundle_state
170 .apply_transitions_and_create_reverts(transition_state, retention);
171 }
172 }
173
174 pub fn load_cache_account(&mut self, address: Address) -> Result<&mut CacheAccount, DB::Error> {
178 match self.cache.accounts.entry(address) {
179 hash_map::Entry::Vacant(entry) => {
180 if self.use_preloaded_bundle {
181 if let Some(account) =
183 self.bundle_state.account(&address).cloned().map(Into::into)
184 {
185 return Ok(entry.insert(account));
186 }
187 }
188 let info = self.database.basic(address)?;
190 let account = match info {
191 None => CacheAccount::new_loaded_not_existing(),
192 Some(acc) if acc.is_empty() => {
193 CacheAccount::new_loaded_empty_eip161(HashMap::default())
194 }
195 Some(acc) => CacheAccount::new_loaded(acc, HashMap::default()),
196 };
197 Ok(entry.insert(account))
198 }
199 hash_map::Entry::Occupied(entry) => Ok(entry.into_mut()),
200 }
201 }
202
203 pub fn take_bundle(&mut self) -> BundleState {
214 core::mem::take(&mut self.bundle_state)
215 }
216}
217
218impl<DB: Database> Database for State<DB> {
219 type Error = DB::Error;
220
221 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
222 self.load_cache_account(address).map(|a| a.account_info())
223 }
224
225 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
226 let res = match self.cache.contracts.entry(code_hash) {
227 hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()),
228 hash_map::Entry::Vacant(entry) => {
229 if self.use_preloaded_bundle {
230 if let Some(code) = self.bundle_state.contracts.get(&code_hash) {
231 entry.insert(code.clone());
232 return Ok(code.clone());
233 }
234 }
235 let code = self.database.code_by_hash(code_hash)?;
237 entry.insert(code.clone());
238 Ok(code)
239 }
240 };
241 res
242 }
243
244 fn storage(&mut self, address: Address, index: U256) -> Result<U256, Self::Error> {
245 if let Some(account) = self.cache.accounts.get_mut(&address) {
248 let is_storage_known = account.status.is_storage_known();
250 Ok(account
251 .account
252 .as_mut()
253 .map(|account| match account.storage.entry(index) {
254 hash_map::Entry::Occupied(entry) => Ok(*entry.get()),
255 hash_map::Entry::Vacant(entry) => {
256 let value = if is_storage_known {
259 U256::ZERO
260 } else {
261 self.database.storage(address, index)?
262 };
263 entry.insert(value);
264 Ok(value)
265 }
266 })
267 .transpose()?
268 .unwrap_or_default())
269 } else {
270 unreachable!("For accessing any storage account is guaranteed to be loaded beforehand")
271 }
272 }
273
274 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
275 match self.block_hashes.entry(number) {
276 btree_map::Entry::Occupied(entry) => Ok(*entry.get()),
277 btree_map::Entry::Vacant(entry) => {
278 let ret = *entry.insert(self.database.block_hash(number)?);
279
280 let last_block = number.saturating_sub(BLOCK_HASH_HISTORY);
282 while let Some(entry) = self.block_hashes.first_entry() {
283 if *entry.key() < last_block {
284 entry.remove();
285 } else {
286 break;
287 }
288 }
289
290 Ok(ret)
291 }
292 }
293 }
294}
295
296impl<DB: Database> DatabaseCommit for State<DB> {
297 fn commit(&mut self, evm_state: HashMap<Address, Account>) {
298 let transitions = self.cache.apply_evm_state(evm_state);
299 self.apply_transition(transitions);
300 }
301}
302
303#[cfg(test)]
304mod tests {
305 use super::*;
306 use crate::db::{
307 states::{reverts::AccountInfoRevert, StorageSlot},
308 AccountRevert, AccountStatus, BundleAccount, RevertToSlot,
309 };
310 use revm_interpreter::primitives::keccak256;
311
312 #[test]
313 fn block_hash_cache() {
314 let mut state = State::builder().build();
315 state.block_hash(1u64).unwrap();
316 state.block_hash(2u64).unwrap();
317
318 let test_number = BLOCK_HASH_HISTORY + 2;
319
320 let block1_hash = keccak256(U256::from(1).to_string().as_bytes());
321 let block2_hash = keccak256(U256::from(2).to_string().as_bytes());
322 let block_test_hash = keccak256(U256::from(test_number).to_string().as_bytes());
323
324 assert_eq!(
325 state.block_hashes,
326 BTreeMap::from([(1, block1_hash), (2, block2_hash)])
327 );
328
329 state.block_hash(test_number).unwrap();
330 assert_eq!(
331 state.block_hashes,
332 BTreeMap::from([(test_number, block_test_hash), (2, block2_hash)])
333 );
334 }
335
336 #[test]
343 fn reverts_preserve_old_values() {
344 let mut state = State::builder().with_bundle_update().build();
345
346 let (slot1, slot2, slot3) = (U256::from(1), U256::from(2), U256::from(3));
347
348 let new_account_address = Address::from_slice(&[0x1; 20]);
351 let new_account_created_info = AccountInfo {
352 nonce: 1,
353 balance: U256::from(1),
354 ..Default::default()
355 };
356 let new_account_changed_info = AccountInfo {
357 nonce: 2,
358 ..new_account_created_info.clone()
359 };
360 let new_account_changed_info2 = AccountInfo {
361 nonce: 3,
362 ..new_account_changed_info.clone()
363 };
364
365 let existing_account_address = Address::from_slice(&[0x2; 20]);
367 let existing_account_initial_info = AccountInfo {
368 nonce: 1,
369 ..Default::default()
370 };
371 let existing_account_initial_storage = HashMap::<U256, U256>::from_iter([
372 (slot1, U256::from(100)), (slot2, U256::from(200)), ]);
375 let existing_account_changed_info = AccountInfo {
376 nonce: 2,
377 ..existing_account_initial_info.clone()
378 };
379
380 state.apply_transition(Vec::from([
382 (
383 new_account_address,
384 TransitionAccount {
385 status: AccountStatus::InMemoryChange,
386 info: Some(new_account_created_info.clone()),
387 previous_status: AccountStatus::LoadedNotExisting,
388 previous_info: None,
389 ..Default::default()
390 },
391 ),
392 (
393 existing_account_address,
394 TransitionAccount {
395 status: AccountStatus::InMemoryChange,
396 info: Some(existing_account_changed_info.clone()),
397 previous_status: AccountStatus::Loaded,
398 previous_info: Some(existing_account_initial_info.clone()),
399 storage: HashMap::from_iter([(
400 slot1,
401 StorageSlot::new_changed(
402 *existing_account_initial_storage.get(&slot1).unwrap(),
403 U256::from(1000),
404 ),
405 )]),
406 storage_was_destroyed: false,
407 },
408 ),
409 ]));
410
411 state.apply_transition(Vec::from([(
413 new_account_address,
414 TransitionAccount {
415 status: AccountStatus::InMemoryChange,
416 info: Some(new_account_changed_info.clone()),
417 previous_status: AccountStatus::InMemoryChange,
418 previous_info: Some(new_account_created_info.clone()),
419 ..Default::default()
420 },
421 )]));
422
423 state.apply_transition(Vec::from([
425 (
426 new_account_address,
427 TransitionAccount {
428 status: AccountStatus::InMemoryChange,
429 info: Some(new_account_changed_info2.clone()),
430 previous_status: AccountStatus::InMemoryChange,
431 previous_info: Some(new_account_changed_info),
432 storage: HashMap::from_iter([(
433 slot1,
434 StorageSlot::new_changed(U256::ZERO, U256::from(1)),
435 )]),
436 storage_was_destroyed: false,
437 },
438 ),
439 (
440 existing_account_address,
441 TransitionAccount {
442 status: AccountStatus::InMemoryChange,
443 info: Some(existing_account_changed_info.clone()),
444 previous_status: AccountStatus::InMemoryChange,
445 previous_info: Some(existing_account_changed_info.clone()),
446 storage: HashMap::from_iter([
447 (
448 slot1,
449 StorageSlot::new_changed(U256::from(100), U256::from(1_000)),
450 ),
451 (
452 slot2,
453 StorageSlot::new_changed(
454 *existing_account_initial_storage.get(&slot2).unwrap(),
455 U256::from(2_000),
456 ),
457 ),
458 (
460 slot3,
461 StorageSlot::new_changed(U256::ZERO, U256::from(3_000)),
462 ),
463 ]),
464 storage_was_destroyed: false,
465 },
466 ),
467 ]));
468
469 state.merge_transitions(BundleRetention::Reverts);
470 let mut bundle_state = state.take_bundle();
471
472 bundle_state.reverts.sort();
475 assert_eq!(
476 bundle_state.reverts.as_ref(),
477 Vec::from([Vec::from([
478 (
479 new_account_address,
480 AccountRevert {
481 account: AccountInfoRevert::DeleteIt,
482 previous_status: AccountStatus::LoadedNotExisting,
483 storage: HashMap::from_iter([(slot1, RevertToSlot::Some(U256::ZERO))]),
484 wipe_storage: false,
485 }
486 ),
487 (
488 existing_account_address,
489 AccountRevert {
490 account: AccountInfoRevert::RevertTo(existing_account_initial_info.clone()),
491 previous_status: AccountStatus::Loaded,
492 storage: HashMap::from_iter([
493 (
494 slot1,
495 RevertToSlot::Some(
496 *existing_account_initial_storage.get(&slot1).unwrap()
497 )
498 ),
499 (
500 slot2,
501 RevertToSlot::Some(
502 *existing_account_initial_storage.get(&slot2).unwrap()
503 )
504 ),
505 (slot3, RevertToSlot::Some(U256::ZERO))
506 ]),
507 wipe_storage: false,
508 }
509 ),
510 ])]),
511 "The account or storage reverts are incorrect"
512 );
513
514 assert_eq!(
517 bundle_state.account(&new_account_address),
518 Some(&BundleAccount {
519 info: Some(new_account_changed_info2),
520 original_info: None,
521 status: AccountStatus::InMemoryChange,
522 storage: HashMap::from_iter([(
523 slot1,
524 StorageSlot::new_changed(U256::ZERO, U256::from(1))
525 )]),
526 }),
527 "The latest state of the new account is incorrect"
528 );
529
530 assert_eq!(
533 bundle_state.account(&existing_account_address),
534 Some(&BundleAccount {
535 info: Some(existing_account_changed_info),
536 original_info: Some(existing_account_initial_info),
537 status: AccountStatus::InMemoryChange,
538 storage: HashMap::from_iter([
539 (
540 slot1,
541 StorageSlot::new_changed(
542 *existing_account_initial_storage.get(&slot1).unwrap(),
543 U256::from(1_000)
544 )
545 ),
546 (
547 slot2,
548 StorageSlot::new_changed(
549 *existing_account_initial_storage.get(&slot2).unwrap(),
550 U256::from(2_000)
551 )
552 ),
553 (
555 slot3,
556 StorageSlot::new_changed(U256::ZERO, U256::from(3_000))
557 ),
558 ]),
559 }),
560 "The latest state of the existing account is incorrect"
561 );
562 }
563
564 #[test]
567 fn bundle_scoped_reverts_collapse() {
568 let mut state = State::builder().with_bundle_update().build();
569
570 let new_account_address = Address::from_slice(&[0x1; 20]);
572 let new_account_created_info = AccountInfo {
573 nonce: 1,
574 balance: U256::from(1),
575 ..Default::default()
576 };
577
578 let existing_account_address = Address::from_slice(&[0x2; 20]);
580 let existing_account_initial_info = AccountInfo {
581 nonce: 1,
582 ..Default::default()
583 };
584 let existing_account_updated_info = AccountInfo {
585 nonce: 1,
586 balance: U256::from(1),
587 ..Default::default()
588 };
589
590 let (slot1, slot2) = (U256::from(1), U256::from(2));
592 let existing_account_with_storage_address = Address::from_slice(&[0x3; 20]);
593 let existing_account_with_storage_info = AccountInfo {
594 nonce: 1,
595 ..Default::default()
596 };
597 state.apply_transition(Vec::from([
599 (
600 new_account_address,
601 TransitionAccount {
602 status: AccountStatus::InMemoryChange,
603 info: Some(new_account_created_info.clone()),
604 previous_status: AccountStatus::LoadedNotExisting,
605 previous_info: None,
606 ..Default::default()
607 },
608 ),
609 (
610 existing_account_address,
611 TransitionAccount {
612 status: AccountStatus::Changed,
613 info: Some(existing_account_updated_info.clone()),
614 previous_status: AccountStatus::Loaded,
615 previous_info: Some(existing_account_initial_info.clone()),
616 ..Default::default()
617 },
618 ),
619 (
620 existing_account_with_storage_address,
621 TransitionAccount {
622 status: AccountStatus::Changed,
623 info: Some(existing_account_with_storage_info.clone()),
624 previous_status: AccountStatus::Loaded,
625 previous_info: Some(existing_account_with_storage_info.clone()),
626 storage: HashMap::from_iter([
627 (
628 slot1,
629 StorageSlot::new_changed(U256::from(1), U256::from(10)),
630 ),
631 (slot2, StorageSlot::new_changed(U256::ZERO, U256::from(20))),
632 ]),
633 storage_was_destroyed: false,
634 },
635 ),
636 ]));
637
638 state.apply_transition(Vec::from([
640 (
641 new_account_address,
642 TransitionAccount {
643 status: AccountStatus::Destroyed,
644 info: None,
645 previous_status: AccountStatus::InMemoryChange,
646 previous_info: Some(new_account_created_info),
647 ..Default::default()
648 },
649 ),
650 (
651 existing_account_address,
652 TransitionAccount {
653 status: AccountStatus::Changed,
654 info: Some(existing_account_initial_info),
655 previous_status: AccountStatus::Changed,
656 previous_info: Some(existing_account_updated_info),
657 ..Default::default()
658 },
659 ),
660 (
661 existing_account_with_storage_address,
662 TransitionAccount {
663 status: AccountStatus::Changed,
664 info: Some(existing_account_with_storage_info.clone()),
665 previous_status: AccountStatus::Changed,
666 previous_info: Some(existing_account_with_storage_info.clone()),
667 storage: HashMap::from_iter([
668 (
669 slot1,
670 StorageSlot::new_changed(U256::from(10), U256::from(1)),
671 ),
672 (slot2, StorageSlot::new_changed(U256::from(20), U256::ZERO)),
673 ]),
674 storage_was_destroyed: false,
675 },
676 ),
677 ]));
678
679 state.merge_transitions(BundleRetention::Reverts);
680
681 let mut bundle_state = state.take_bundle();
682 bundle_state.reverts.sort();
683
684 assert_eq!(bundle_state.reverts.as_ref(), Vec::from([Vec::from([])]));
687 }
688
689 #[test]
691 fn selfdestruct_state_and_reverts() {
692 let mut state = State::builder().with_bundle_update().build();
693
694 let existing_account_address = Address::from_slice(&[0x1; 20]);
696 let existing_account_info = AccountInfo {
697 nonce: 1,
698 ..Default::default()
699 };
700
701 let (slot1, slot2) = (U256::from(1), U256::from(2));
702
703 state.apply_transition(Vec::from([(
705 existing_account_address,
706 TransitionAccount {
707 status: AccountStatus::Destroyed,
708 info: None,
709 previous_status: AccountStatus::Loaded,
710 previous_info: Some(existing_account_info.clone()),
711 storage: HashMap::default(),
712 storage_was_destroyed: true,
713 },
714 )]));
715
716 state.apply_transition(Vec::from([(
718 existing_account_address,
719 TransitionAccount {
720 status: AccountStatus::DestroyedChanged,
721 info: Some(existing_account_info.clone()),
722 previous_status: AccountStatus::Destroyed,
723 previous_info: None,
724 storage: HashMap::from_iter([(
725 slot1,
726 StorageSlot::new_changed(U256::ZERO, U256::from(1)),
727 )]),
728 storage_was_destroyed: false,
729 },
730 )]));
731
732 state.apply_transition(Vec::from([(
734 existing_account_address,
735 TransitionAccount {
736 status: AccountStatus::DestroyedAgain,
737 info: None,
738 previous_status: AccountStatus::DestroyedChanged,
739 previous_info: Some(existing_account_info.clone()),
740 storage: HashMap::default(),
742 storage_was_destroyed: true,
743 },
744 )]));
745
746 state.apply_transition(Vec::from([(
748 existing_account_address,
749 TransitionAccount {
750 status: AccountStatus::DestroyedChanged,
751 info: Some(existing_account_info.clone()),
752 previous_status: AccountStatus::DestroyedAgain,
753 previous_info: None,
754 storage: HashMap::from_iter([(
755 slot2,
756 StorageSlot::new_changed(U256::ZERO, U256::from(2)),
757 )]),
758 storage_was_destroyed: false,
759 },
760 )]));
761
762 state.merge_transitions(BundleRetention::Reverts);
763
764 let bundle_state = state.take_bundle();
765
766 assert_eq!(
767 bundle_state.state,
768 HashMap::from_iter([(
769 existing_account_address,
770 BundleAccount {
771 info: Some(existing_account_info.clone()),
772 original_info: Some(existing_account_info.clone()),
773 storage: HashMap::from_iter([(
774 slot2,
775 StorageSlot::new_changed(U256::ZERO, U256::from(2))
776 )]),
777 status: AccountStatus::DestroyedChanged,
778 }
779 )])
780 );
781
782 assert_eq!(
783 bundle_state.reverts.as_ref(),
784 Vec::from([Vec::from([(
785 existing_account_address,
786 AccountRevert {
787 account: AccountInfoRevert::DoNothing,
788 previous_status: AccountStatus::Loaded,
789 storage: HashMap::from_iter([(slot2, RevertToSlot::Destroyed)]),
790 wipe_storage: true,
791 }
792 )])])
793 )
794 }
795}