1use super::{
2 bundle_state::BundleRetention, cache::CacheState, plain_account::PlainStorage, BundleState,
3 CacheAccount, StateBuilder, TransitionAccount, TransitionState,
4};
5use bytecode::Bytecode;
6use database_interface::{Database, DatabaseCommit, DatabaseRef, EmptyDB};
7use primitives::{hash_map, Address, HashMap, StorageKey, StorageValue, B256, BLOCK_HASH_HISTORY};
8use state::{Account, AccountInfo};
9use std::{
10 boxed::Box,
11 collections::{btree_map, BTreeMap},
12};
13
14pub type DBBox<'a, E> = Box<dyn Database<Error = E> + Send + 'a>;
16
17pub type StateDBBox<'a, E> = State<DBBox<'a, E>>;
21
22#[derive(Debug)]
28pub struct State<DB> {
29 pub cache: CacheState,
36 pub database: DB,
42 pub transition_state: Option<TransitionState>,
46 pub bundle_state: BundleState,
52 pub use_preloaded_bundle: bool,
58 pub block_hashes: BTreeMap<u64, B256>,
65}
66
67impl State<EmptyDB> {
69 pub fn builder() -> StateBuilder<EmptyDB> {
71 StateBuilder::default()
72 }
73}
74
75impl<DB: Database> State<DB> {
76 pub fn bundle_size_hint(&self) -> usize {
80 self.bundle_state.size_hint()
81 }
82
83 pub fn set_state_clear_flag(&mut self, has_state_clear: bool) {
85 self.cache.set_state_clear_flag(has_state_clear);
86 }
87
88 pub fn insert_not_existing(&mut self, address: Address) {
90 self.cache.insert_not_existing(address)
91 }
92
93 pub fn insert_account(&mut self, address: Address, info: AccountInfo) {
95 self.cache.insert_account(address, info)
96 }
97
98 pub fn insert_account_with_storage(
100 &mut self,
101 address: Address,
102 info: AccountInfo,
103 storage: PlainStorage,
104 ) {
105 self.cache
106 .insert_account_with_storage(address, info, storage)
107 }
108
109 pub fn apply_transition(
111 &mut self,
112 transitions: impl IntoIterator<Item = (Address, TransitionAccount)>,
113 ) {
114 if let Some(s) = self.transition_state.as_mut() {
116 s.add_transitions(transitions)
117 }
118 }
119
120 pub fn merge_transitions(&mut self, retention: BundleRetention) {
126 if let Some(transition_state) = self.transition_state.as_mut().map(TransitionState::take) {
127 self.bundle_state
128 .apply_transitions_and_create_reverts(transition_state, retention);
129 }
130 }
131
132 pub fn load_cache_account(&mut self, address: Address) -> Result<&mut CacheAccount, DB::Error> {
137 match self.cache.accounts.entry(address) {
138 hash_map::Entry::Vacant(entry) => {
139 if self.use_preloaded_bundle {
140 if let Some(account) = self.bundle_state.account(&address).map(Into::into) {
142 return Ok(entry.insert(account));
143 }
144 }
145 let info = self.database.basic(address)?;
147 let account = match info {
148 None => CacheAccount::new_loaded_not_existing(),
149 Some(acc) if acc.is_empty() => {
150 CacheAccount::new_loaded_empty_eip161(HashMap::default())
151 }
152 Some(acc) => CacheAccount::new_loaded(acc, HashMap::default()),
153 };
154 Ok(entry.insert(account))
155 }
156 hash_map::Entry::Occupied(entry) => Ok(entry.into_mut()),
157 }
158 }
159
160 pub fn take_bundle(&mut self) -> BundleState {
172 core::mem::take(&mut self.bundle_state)
173 }
174}
175
176impl<DB: Database> Database for State<DB> {
177 type Error = DB::Error;
178
179 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
180 self.load_cache_account(address).map(|a| a.account_info())
181 }
182
183 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
184 let res = match self.cache.contracts.entry(code_hash) {
185 hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()),
186 hash_map::Entry::Vacant(entry) => {
187 if self.use_preloaded_bundle {
188 if let Some(code) = self.bundle_state.contracts.get(&code_hash) {
189 entry.insert(code.clone());
190 return Ok(code.clone());
191 }
192 }
193 let code = self.database.code_by_hash(code_hash)?;
195 entry.insert(code.clone());
196 Ok(code)
197 }
198 };
199 res
200 }
201
202 fn storage(
203 &mut self,
204 address: Address,
205 index: StorageKey,
206 ) -> Result<StorageValue, Self::Error> {
207 let account = if let Some(account) = self.cache.accounts.get_mut(&address) {
209 account
210 } else {
211 self.load_cache_account(address)?;
212 self.cache.accounts.get_mut(&address).unwrap()
214 };
215
216 let is_storage_known = account.status.is_storage_known();
218 Ok(account
219 .account
220 .as_mut()
221 .map(|account| match account.storage.entry(index) {
222 hash_map::Entry::Occupied(entry) => Ok(*entry.get()),
223 hash_map::Entry::Vacant(entry) => {
224 let value = if is_storage_known {
227 StorageValue::ZERO
228 } else {
229 self.database.storage(address, index)?
230 };
231 entry.insert(value);
232 Ok(value)
233 }
234 })
235 .transpose()?
236 .unwrap_or_default())
237 }
238
239 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
240 match self.block_hashes.entry(number) {
241 btree_map::Entry::Occupied(entry) => Ok(*entry.get()),
242 btree_map::Entry::Vacant(entry) => {
243 let ret = *entry.insert(self.database.block_hash(number)?);
244
245 let last_block = number.saturating_sub(BLOCK_HASH_HISTORY);
247 while let Some(entry) = self.block_hashes.first_entry() {
248 if *entry.key() < last_block {
249 entry.remove();
250 } else {
251 break;
252 }
253 }
254
255 Ok(ret)
256 }
257 }
258 }
259}
260
261impl<DB: Database> DatabaseCommit for State<DB> {
262 fn commit(&mut self, changes: HashMap<Address, Account>) {
263 let transitions = self.cache.apply_evm_state(changes);
264 if let Some(s) = self.transition_state.as_mut() {
265 s.add_transitions(transitions)
266 }
267 }
268
269 fn commit_iter(&mut self, changes: impl IntoIterator<Item = (Address, Account)>) {
270 let transitions = self.cache.apply_evm_state(changes);
271 if let Some(s) = self.transition_state.as_mut() {
272 s.add_transitions(transitions)
273 }
274 }
275}
276
277impl<DB: DatabaseRef> DatabaseRef for State<DB> {
278 type Error = DB::Error;
279
280 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
281 if let Some(account) = self.cache.accounts.get(&address) {
283 return Ok(account.account_info());
284 }
285 if self.use_preloaded_bundle {
287 if let Some(account) = self.bundle_state.account(&address) {
288 return Ok(account.account_info());
289 }
290 }
291 self.database.basic_ref(address)
293 }
294
295 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
296 if let Some(code) = self.cache.contracts.get(&code_hash) {
298 return Ok(code.clone());
299 }
300 if self.use_preloaded_bundle {
302 if let Some(code) = self.bundle_state.contracts.get(&code_hash) {
303 return Ok(code.clone());
304 }
305 }
306 self.database.code_by_hash_ref(code_hash)
308 }
309
310 fn storage_ref(
311 &self,
312 address: Address,
313 index: StorageKey,
314 ) -> Result<StorageValue, Self::Error> {
315 if let Some(account) = self.cache.accounts.get(&address) {
317 if let Some(plain_account) = &account.account {
318 if let Some(storage_value) = plain_account.storage.get(&index) {
320 return Ok(*storage_value);
321 }
322 if account.status.is_storage_known() {
325 return Ok(StorageValue::ZERO);
326 }
327 }
328 }
329 self.database.storage_ref(address, index)
331 }
332
333 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
334 if let Some(entry) = self.block_hashes.get(&number) {
335 return Ok(*entry);
336 }
337 self.database.block_hash_ref(number)
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use super::*;
345 use crate::{
346 states::{reverts::AccountInfoRevert, StorageSlot},
347 AccountRevert, AccountStatus, BundleAccount, RevertToSlot,
348 };
349 use primitives::{keccak256, U256};
350
351 #[test]
352 fn block_hash_cache() {
353 let mut state = State::builder().build();
354 state.block_hash(1u64).unwrap();
355 state.block_hash(2u64).unwrap();
356
357 let test_number = BLOCK_HASH_HISTORY + 2;
358
359 let block1_hash = keccak256(U256::from(1).to_string().as_bytes());
360 let block2_hash = keccak256(U256::from(2).to_string().as_bytes());
361 let block_test_hash = keccak256(U256::from(test_number).to_string().as_bytes());
362
363 assert_eq!(
364 state.block_hashes,
365 BTreeMap::from([(1, block1_hash), (2, block2_hash)])
366 );
367
368 state.block_hash(test_number).unwrap();
369 assert_eq!(
370 state.block_hashes,
371 BTreeMap::from([(test_number, block_test_hash), (2, block2_hash)])
372 );
373 }
374
375 #[test]
382 fn reverts_preserve_old_values() {
383 let mut state = State::builder().with_bundle_update().build();
384
385 let (slot1, slot2, slot3) = (
386 StorageKey::from(1),
387 StorageKey::from(2),
388 StorageKey::from(3),
389 );
390
391 let new_account_address = Address::from_slice(&[0x1; 20]);
394 let new_account_created_info = AccountInfo {
395 nonce: 1,
396 balance: U256::from(1),
397 ..Default::default()
398 };
399 let new_account_changed_info = AccountInfo {
400 nonce: 2,
401 ..new_account_created_info.clone()
402 };
403 let new_account_changed_info2 = AccountInfo {
404 nonce: 3,
405 ..new_account_changed_info.clone()
406 };
407
408 let existing_account_address = Address::from_slice(&[0x2; 20]);
410 let existing_account_initial_info = AccountInfo {
411 nonce: 1,
412 ..Default::default()
413 };
414 let existing_account_initial_storage = HashMap::<StorageKey, StorageValue>::from_iter([
415 (slot1, StorageValue::from(100)), (slot2, StorageValue::from(200)), ]);
418 let existing_account_changed_info = AccountInfo {
419 nonce: 2,
420 ..existing_account_initial_info.clone()
421 };
422
423 state.apply_transition(Vec::from([
425 (
426 new_account_address,
427 TransitionAccount {
428 status: AccountStatus::InMemoryChange,
429 info: Some(new_account_created_info.clone()),
430 previous_status: AccountStatus::LoadedNotExisting,
431 previous_info: None,
432 ..Default::default()
433 },
434 ),
435 (
436 existing_account_address,
437 TransitionAccount {
438 status: AccountStatus::InMemoryChange,
439 info: Some(existing_account_changed_info.clone()),
440 previous_status: AccountStatus::Loaded,
441 previous_info: Some(existing_account_initial_info.clone()),
442 storage: HashMap::from_iter([(
443 slot1,
444 StorageSlot::new_changed(
445 *existing_account_initial_storage.get(&slot1).unwrap(),
446 StorageValue::from(1000),
447 ),
448 )]),
449 storage_was_destroyed: false,
450 },
451 ),
452 ]));
453
454 state.apply_transition(Vec::from([(
456 new_account_address,
457 TransitionAccount {
458 status: AccountStatus::InMemoryChange,
459 info: Some(new_account_changed_info.clone()),
460 previous_status: AccountStatus::InMemoryChange,
461 previous_info: Some(new_account_created_info.clone()),
462 ..Default::default()
463 },
464 )]));
465
466 state.apply_transition(Vec::from([
468 (
469 new_account_address,
470 TransitionAccount {
471 status: AccountStatus::InMemoryChange,
472 info: Some(new_account_changed_info2.clone()),
473 previous_status: AccountStatus::InMemoryChange,
474 previous_info: Some(new_account_changed_info),
475 storage: HashMap::from_iter([(
476 slot1,
477 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(1)),
478 )]),
479 storage_was_destroyed: false,
480 },
481 ),
482 (
483 existing_account_address,
484 TransitionAccount {
485 status: AccountStatus::InMemoryChange,
486 info: Some(existing_account_changed_info.clone()),
487 previous_status: AccountStatus::InMemoryChange,
488 previous_info: Some(existing_account_changed_info.clone()),
489 storage: HashMap::from_iter([
490 (
491 slot1,
492 StorageSlot::new_changed(
493 StorageValue::from(100),
494 StorageValue::from(1_000),
495 ),
496 ),
497 (
498 slot2,
499 StorageSlot::new_changed(
500 *existing_account_initial_storage.get(&slot2).unwrap(),
501 StorageValue::from(2_000),
502 ),
503 ),
504 (
506 slot3,
507 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(3_000)),
508 ),
509 ]),
510 storage_was_destroyed: false,
511 },
512 ),
513 ]));
514
515 state.merge_transitions(BundleRetention::Reverts);
516 let mut bundle_state = state.take_bundle();
517
518 bundle_state.reverts.sort();
521 assert_eq!(
522 bundle_state.reverts.as_ref(),
523 Vec::from([Vec::from([
524 (
525 new_account_address,
526 AccountRevert {
527 account: AccountInfoRevert::DeleteIt,
528 previous_status: AccountStatus::LoadedNotExisting,
529 storage: HashMap::from_iter([(
530 slot1,
531 RevertToSlot::Some(StorageValue::ZERO)
532 )]),
533 wipe_storage: false,
534 }
535 ),
536 (
537 existing_account_address,
538 AccountRevert {
539 account: AccountInfoRevert::RevertTo(existing_account_initial_info.clone()),
540 previous_status: AccountStatus::Loaded,
541 storage: HashMap::from_iter([
542 (
543 slot1,
544 RevertToSlot::Some(
545 *existing_account_initial_storage.get(&slot1).unwrap()
546 )
547 ),
548 (
549 slot2,
550 RevertToSlot::Some(
551 *existing_account_initial_storage.get(&slot2).unwrap()
552 )
553 ),
554 (slot3, RevertToSlot::Some(StorageValue::ZERO))
555 ]),
556 wipe_storage: false,
557 }
558 ),
559 ])]),
560 "The account or storage reverts are incorrect"
561 );
562
563 assert_eq!(
566 bundle_state.account(&new_account_address),
567 Some(&BundleAccount {
568 info: Some(new_account_changed_info2),
569 original_info: None,
570 status: AccountStatus::InMemoryChange,
571 storage: HashMap::from_iter([(
572 slot1,
573 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(1))
574 )]),
575 }),
576 "The latest state of the new account is incorrect"
577 );
578
579 assert_eq!(
582 bundle_state.account(&existing_account_address),
583 Some(&BundleAccount {
584 info: Some(existing_account_changed_info),
585 original_info: Some(existing_account_initial_info),
586 status: AccountStatus::InMemoryChange,
587 storage: HashMap::from_iter([
588 (
589 slot1,
590 StorageSlot::new_changed(
591 *existing_account_initial_storage.get(&slot1).unwrap(),
592 StorageValue::from(1_000)
593 )
594 ),
595 (
596 slot2,
597 StorageSlot::new_changed(
598 *existing_account_initial_storage.get(&slot2).unwrap(),
599 StorageValue::from(2_000)
600 )
601 ),
602 (
604 slot3,
605 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(3_000))
606 ),
607 ]),
608 }),
609 "The latest state of the existing account is incorrect"
610 );
611 }
612
613 #[test]
616 fn bundle_scoped_reverts_collapse() {
617 let mut state = State::builder().with_bundle_update().build();
618
619 let new_account_address = Address::from_slice(&[0x1; 20]);
621 let new_account_created_info = AccountInfo {
622 nonce: 1,
623 balance: U256::from(1),
624 ..Default::default()
625 };
626
627 let existing_account_address = Address::from_slice(&[0x2; 20]);
629 let existing_account_initial_info = AccountInfo {
630 nonce: 1,
631 ..Default::default()
632 };
633 let existing_account_updated_info = AccountInfo {
634 nonce: 1,
635 balance: U256::from(1),
636 ..Default::default()
637 };
638
639 let (slot1, slot2) = (StorageKey::from(1), StorageKey::from(2));
641 let existing_account_with_storage_address = Address::from_slice(&[0x3; 20]);
642 let existing_account_with_storage_info = AccountInfo {
643 nonce: 1,
644 ..Default::default()
645 };
646 state.apply_transition(Vec::from([
648 (
649 new_account_address,
650 TransitionAccount {
651 status: AccountStatus::InMemoryChange,
652 info: Some(new_account_created_info.clone()),
653 previous_status: AccountStatus::LoadedNotExisting,
654 previous_info: None,
655 ..Default::default()
656 },
657 ),
658 (
659 existing_account_address,
660 TransitionAccount {
661 status: AccountStatus::Changed,
662 info: Some(existing_account_updated_info.clone()),
663 previous_status: AccountStatus::Loaded,
664 previous_info: Some(existing_account_initial_info.clone()),
665 ..Default::default()
666 },
667 ),
668 (
669 existing_account_with_storage_address,
670 TransitionAccount {
671 status: AccountStatus::Changed,
672 info: Some(existing_account_with_storage_info.clone()),
673 previous_status: AccountStatus::Loaded,
674 previous_info: Some(existing_account_with_storage_info.clone()),
675 storage: HashMap::from_iter([
676 (
677 slot1,
678 StorageSlot::new_changed(StorageValue::from(1), StorageValue::from(10)),
679 ),
680 (
681 slot2,
682 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(20)),
683 ),
684 ]),
685 storage_was_destroyed: false,
686 },
687 ),
688 ]));
689
690 state.apply_transition(Vec::from([
692 (
693 new_account_address,
694 TransitionAccount {
695 status: AccountStatus::Destroyed,
696 info: None,
697 previous_status: AccountStatus::InMemoryChange,
698 previous_info: Some(new_account_created_info),
699 ..Default::default()
700 },
701 ),
702 (
703 existing_account_address,
704 TransitionAccount {
705 status: AccountStatus::Changed,
706 info: Some(existing_account_initial_info),
707 previous_status: AccountStatus::Changed,
708 previous_info: Some(existing_account_updated_info),
709 ..Default::default()
710 },
711 ),
712 (
713 existing_account_with_storage_address,
714 TransitionAccount {
715 status: AccountStatus::Changed,
716 info: Some(existing_account_with_storage_info.clone()),
717 previous_status: AccountStatus::Changed,
718 previous_info: Some(existing_account_with_storage_info.clone()),
719 storage: HashMap::from_iter([
720 (
721 slot1,
722 StorageSlot::new_changed(StorageValue::from(10), StorageValue::from(1)),
723 ),
724 (
725 slot2,
726 StorageSlot::new_changed(StorageValue::from(20), StorageValue::ZERO),
727 ),
728 ]),
729 storage_was_destroyed: false,
730 },
731 ),
732 ]));
733
734 state.merge_transitions(BundleRetention::Reverts);
735
736 let mut bundle_state = state.take_bundle();
737 bundle_state.reverts.sort();
738
739 assert_eq!(bundle_state.reverts.as_ref(), Vec::from([Vec::from([])]));
742 }
743
744 #[test]
746 fn selfdestruct_state_and_reverts() {
747 let mut state = State::builder().with_bundle_update().build();
748
749 let existing_account_address = Address::from_slice(&[0x1; 20]);
751 let existing_account_info = AccountInfo {
752 nonce: 1,
753 ..Default::default()
754 };
755
756 let (slot1, slot2) = (StorageKey::from(1), StorageKey::from(2));
757
758 state.apply_transition(Vec::from([(
760 existing_account_address,
761 TransitionAccount {
762 status: AccountStatus::Destroyed,
763 info: None,
764 previous_status: AccountStatus::Loaded,
765 previous_info: Some(existing_account_info.clone()),
766 storage: HashMap::default(),
767 storage_was_destroyed: true,
768 },
769 )]));
770
771 state.apply_transition(Vec::from([(
773 existing_account_address,
774 TransitionAccount {
775 status: AccountStatus::DestroyedChanged,
776 info: Some(existing_account_info.clone()),
777 previous_status: AccountStatus::Destroyed,
778 previous_info: None,
779 storage: HashMap::from_iter([(
780 slot1,
781 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(1)),
782 )]),
783 storage_was_destroyed: false,
784 },
785 )]));
786
787 state.apply_transition(Vec::from([(
789 existing_account_address,
790 TransitionAccount {
791 status: AccountStatus::DestroyedAgain,
792 info: None,
793 previous_status: AccountStatus::DestroyedChanged,
794 previous_info: Some(existing_account_info.clone()),
795 storage: HashMap::default(),
797 storage_was_destroyed: true,
798 },
799 )]));
800
801 state.apply_transition(Vec::from([(
803 existing_account_address,
804 TransitionAccount {
805 status: AccountStatus::DestroyedChanged,
806 info: Some(existing_account_info.clone()),
807 previous_status: AccountStatus::DestroyedAgain,
808 previous_info: None,
809 storage: HashMap::from_iter([(
810 slot2,
811 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(2)),
812 )]),
813 storage_was_destroyed: false,
814 },
815 )]));
816
817 state.merge_transitions(BundleRetention::Reverts);
818
819 let bundle_state = state.take_bundle();
820
821 assert_eq!(
822 bundle_state.state,
823 HashMap::from_iter([(
824 existing_account_address,
825 BundleAccount {
826 info: Some(existing_account_info.clone()),
827 original_info: Some(existing_account_info.clone()),
828 storage: HashMap::from_iter([(
829 slot2,
830 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(2))
831 )]),
832 status: AccountStatus::DestroyedChanged,
833 }
834 )])
835 );
836
837 assert_eq!(
838 bundle_state.reverts.as_ref(),
839 Vec::from([Vec::from([(
840 existing_account_address,
841 AccountRevert {
842 account: AccountInfoRevert::DoNothing,
843 previous_status: AccountStatus::Loaded,
844 storage: HashMap::from_iter([(slot2, RevertToSlot::Destroyed)]),
845 wipe_storage: true,
846 }
847 )])])
848 )
849 }
850}