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 vec::Vec,
13};
14
15pub type DBBox<'a, E> = Box<dyn Database<Error = E> + Send + 'a>;
17
18pub type StateDBBox<'a, E> = State<DBBox<'a, E>>;
22
23#[derive(Debug)]
29pub struct State<DB> {
30 pub cache: CacheState,
37 pub database: DB,
43 pub transition_state: Option<TransitionState>,
47 pub bundle_state: BundleState,
53 pub use_preloaded_bundle: bool,
59 pub block_hashes: BTreeMap<u64, B256>,
66}
67
68impl State<EmptyDB> {
70 pub fn builder() -> StateBuilder<EmptyDB> {
72 StateBuilder::default()
73 }
74}
75
76impl<DB: Database> State<DB> {
77 pub fn bundle_size_hint(&self) -> usize {
81 self.bundle_state.size_hint()
82 }
83
84 pub fn increment_balances(
92 &mut self,
93 balances: impl IntoIterator<Item = (Address, u128)>,
94 ) -> Result<(), DB::Error> {
95 let balances = balances.into_iter();
97 let mut transitions = Vec::with_capacity(balances.size_hint().0);
98 for (address, balance) in balances {
99 if balance == 0 {
100 continue;
101 }
102 let original_account = self.load_cache_account(address)?;
103 transitions.push((
104 address,
105 original_account
106 .increment_balance(balance)
107 .expect("Balance is not zero"),
108 ))
109 }
110 if let Some(s) = self.transition_state.as_mut() {
112 s.add_transitions(transitions)
113 }
114 Ok(())
115 }
116
117 pub fn drain_balances(
121 &mut self,
122 addresses: impl IntoIterator<Item = Address>,
123 ) -> Result<Vec<u128>, DB::Error> {
124 let mut transitions = Vec::new();
126 let mut balances = Vec::new();
127 for address in addresses {
128 let original_account = self.load_cache_account(address)?;
129 let (balance, transition) = original_account.drain_balance();
130 balances.push(balance);
131 transitions.push((address, transition))
132 }
133 if let Some(s) = self.transition_state.as_mut() {
135 s.add_transitions(transitions)
136 }
137 Ok(balances)
138 }
139
140 pub fn set_state_clear_flag(&mut self, has_state_clear: bool) {
142 self.cache.set_state_clear_flag(has_state_clear);
143 }
144
145 pub fn insert_not_existing(&mut self, address: Address) {
147 self.cache.insert_not_existing(address)
148 }
149
150 pub fn insert_account(&mut self, address: Address, info: AccountInfo) {
152 self.cache.insert_account(address, info)
153 }
154
155 pub fn insert_account_with_storage(
157 &mut self,
158 address: Address,
159 info: AccountInfo,
160 storage: PlainStorage,
161 ) {
162 self.cache
163 .insert_account_with_storage(address, info, storage)
164 }
165
166 pub fn apply_transition(&mut self, transitions: Vec<(Address, TransitionAccount)>) {
168 if let Some(s) = self.transition_state.as_mut() {
170 s.add_transitions(transitions)
171 }
172 }
173
174 pub fn merge_transitions(&mut self, retention: BundleRetention) {
180 if let Some(transition_state) = self.transition_state.as_mut().map(TransitionState::take) {
181 self.bundle_state
182 .apply_transitions_and_create_reverts(transition_state, retention);
183 }
184 }
185
186 pub fn load_cache_account(&mut self, address: Address) -> Result<&mut CacheAccount, DB::Error> {
191 match self.cache.accounts.entry(address) {
192 hash_map::Entry::Vacant(entry) => {
193 if self.use_preloaded_bundle {
194 if let Some(account) = self.bundle_state.account(&address).map(Into::into) {
196 return Ok(entry.insert(account));
197 }
198 }
199 let info = self.database.basic(address)?;
201 let account = match info {
202 None => CacheAccount::new_loaded_not_existing(),
203 Some(acc) if acc.is_empty() => {
204 CacheAccount::new_loaded_empty_eip161(HashMap::default())
205 }
206 Some(acc) => CacheAccount::new_loaded(acc, HashMap::default()),
207 };
208 Ok(entry.insert(account))
209 }
210 hash_map::Entry::Occupied(entry) => Ok(entry.into_mut()),
211 }
212 }
213
214 pub fn take_bundle(&mut self) -> BundleState {
226 core::mem::take(&mut self.bundle_state)
227 }
228}
229
230impl<DB: Database> Database for State<DB> {
231 type Error = DB::Error;
232
233 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
234 self.load_cache_account(address).map(|a| a.account_info())
235 }
236
237 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
238 let res = match self.cache.contracts.entry(code_hash) {
239 hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()),
240 hash_map::Entry::Vacant(entry) => {
241 if self.use_preloaded_bundle {
242 if let Some(code) = self.bundle_state.contracts.get(&code_hash) {
243 entry.insert(code.clone());
244 return Ok(code.clone());
245 }
246 }
247 let code = self.database.code_by_hash(code_hash)?;
249 entry.insert(code.clone());
250 Ok(code)
251 }
252 };
253 res
254 }
255
256 fn storage(
257 &mut self,
258 address: Address,
259 index: StorageKey,
260 ) -> Result<StorageValue, Self::Error> {
261 if let Some(account) = self.cache.accounts.get_mut(&address) {
264 let is_storage_known = account.status.is_storage_known();
266 Ok(account
267 .account
268 .as_mut()
269 .map(|account| match account.storage.entry(index) {
270 hash_map::Entry::Occupied(entry) => Ok(*entry.get()),
271 hash_map::Entry::Vacant(entry) => {
272 let value = if is_storage_known {
275 StorageValue::ZERO
276 } else {
277 self.database.storage(address, index)?
278 };
279 entry.insert(value);
280 Ok(value)
281 }
282 })
283 .transpose()?
284 .unwrap_or_default())
285 } else {
286 unreachable!("For accessing any storage account is guaranteed to be loaded beforehand")
287 }
288 }
289
290 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
291 match self.block_hashes.entry(number) {
292 btree_map::Entry::Occupied(entry) => Ok(*entry.get()),
293 btree_map::Entry::Vacant(entry) => {
294 let ret = *entry.insert(self.database.block_hash(number)?);
295
296 let last_block = number.saturating_sub(BLOCK_HASH_HISTORY);
298 while let Some(entry) = self.block_hashes.first_entry() {
299 if *entry.key() < last_block {
300 entry.remove();
301 } else {
302 break;
303 }
304 }
305
306 Ok(ret)
307 }
308 }
309 }
310}
311
312impl<DB: Database> DatabaseCommit for State<DB> {
313 fn commit(&mut self, evm_state: HashMap<Address, Account>) {
314 let transitions = self.cache.apply_evm_state(evm_state);
315 self.apply_transition(transitions);
316 }
317}
318
319impl<DB: DatabaseRef> DatabaseRef for State<DB> {
320 type Error = DB::Error;
321
322 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
323 if let Some(account) = self.cache.accounts.get(&address) {
325 return Ok(account.account_info());
326 }
327 if self.use_preloaded_bundle {
329 if let Some(account) = self.bundle_state.account(&address) {
330 return Ok(account.account_info());
331 }
332 }
333 self.database.basic_ref(address)
335 }
336
337 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
338 if let Some(code) = self.cache.contracts.get(&code_hash) {
340 return Ok(code.clone());
341 }
342 if self.use_preloaded_bundle {
344 if let Some(code) = self.bundle_state.contracts.get(&code_hash) {
345 return Ok(code.clone());
346 }
347 }
348 self.database.code_by_hash_ref(code_hash)
350 }
351
352 fn storage_ref(
353 &self,
354 address: Address,
355 index: StorageKey,
356 ) -> Result<StorageValue, Self::Error> {
357 if let Some(account) = self.cache.accounts.get(&address) {
359 if let Some(plain_account) = &account.account {
360 if let Some(storage_value) = plain_account.storage.get(&index) {
362 return Ok(*storage_value);
363 }
364 if account.status.is_storage_known() {
367 return Ok(StorageValue::ZERO);
368 }
369 }
370 }
371 self.database.storage_ref(address, index)
373 }
374
375 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
376 if let Some(entry) = self.block_hashes.get(&number) {
377 return Ok(*entry);
378 }
379 self.database.block_hash_ref(number)
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::*;
387 use crate::{
388 states::{reverts::AccountInfoRevert, StorageSlot},
389 AccountRevert, AccountStatus, BundleAccount, RevertToSlot,
390 };
391 use primitives::{keccak256, U256};
392
393 #[test]
394 fn block_hash_cache() {
395 let mut state = State::builder().build();
396 state.block_hash(1u64).unwrap();
397 state.block_hash(2u64).unwrap();
398
399 let test_number = BLOCK_HASH_HISTORY + 2;
400
401 let block1_hash = keccak256(U256::from(1).to_string().as_bytes());
402 let block2_hash = keccak256(U256::from(2).to_string().as_bytes());
403 let block_test_hash = keccak256(U256::from(test_number).to_string().as_bytes());
404
405 assert_eq!(
406 state.block_hashes,
407 BTreeMap::from([(1, block1_hash), (2, block2_hash)])
408 );
409
410 state.block_hash(test_number).unwrap();
411 assert_eq!(
412 state.block_hashes,
413 BTreeMap::from([(test_number, block_test_hash), (2, block2_hash)])
414 );
415 }
416
417 #[test]
424 fn reverts_preserve_old_values() {
425 let mut state = State::builder().with_bundle_update().build();
426
427 let (slot1, slot2, slot3) = (
428 StorageKey::from(1),
429 StorageKey::from(2),
430 StorageKey::from(3),
431 );
432
433 let new_account_address = Address::from_slice(&[0x1; 20]);
436 let new_account_created_info = AccountInfo {
437 nonce: 1,
438 balance: U256::from(1),
439 ..Default::default()
440 };
441 let new_account_changed_info = AccountInfo {
442 nonce: 2,
443 ..new_account_created_info.clone()
444 };
445 let new_account_changed_info2 = AccountInfo {
446 nonce: 3,
447 ..new_account_changed_info.clone()
448 };
449
450 let existing_account_address = Address::from_slice(&[0x2; 20]);
452 let existing_account_initial_info = AccountInfo {
453 nonce: 1,
454 ..Default::default()
455 };
456 let existing_account_initial_storage = HashMap::<StorageKey, StorageValue>::from_iter([
457 (slot1, StorageValue::from(100)), (slot2, StorageValue::from(200)), ]);
460 let existing_account_changed_info = AccountInfo {
461 nonce: 2,
462 ..existing_account_initial_info.clone()
463 };
464
465 state.apply_transition(Vec::from([
467 (
468 new_account_address,
469 TransitionAccount {
470 status: AccountStatus::InMemoryChange,
471 info: Some(new_account_created_info.clone()),
472 previous_status: AccountStatus::LoadedNotExisting,
473 previous_info: None,
474 ..Default::default()
475 },
476 ),
477 (
478 existing_account_address,
479 TransitionAccount {
480 status: AccountStatus::InMemoryChange,
481 info: Some(existing_account_changed_info.clone()),
482 previous_status: AccountStatus::Loaded,
483 previous_info: Some(existing_account_initial_info.clone()),
484 storage: HashMap::from_iter([(
485 slot1,
486 StorageSlot::new_changed(
487 *existing_account_initial_storage.get(&slot1).unwrap(),
488 StorageValue::from(1000),
489 ),
490 )]),
491 storage_was_destroyed: false,
492 },
493 ),
494 ]));
495
496 state.apply_transition(Vec::from([(
498 new_account_address,
499 TransitionAccount {
500 status: AccountStatus::InMemoryChange,
501 info: Some(new_account_changed_info.clone()),
502 previous_status: AccountStatus::InMemoryChange,
503 previous_info: Some(new_account_created_info.clone()),
504 ..Default::default()
505 },
506 )]));
507
508 state.apply_transition(Vec::from([
510 (
511 new_account_address,
512 TransitionAccount {
513 status: AccountStatus::InMemoryChange,
514 info: Some(new_account_changed_info2.clone()),
515 previous_status: AccountStatus::InMemoryChange,
516 previous_info: Some(new_account_changed_info),
517 storage: HashMap::from_iter([(
518 slot1,
519 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(1)),
520 )]),
521 storage_was_destroyed: false,
522 },
523 ),
524 (
525 existing_account_address,
526 TransitionAccount {
527 status: AccountStatus::InMemoryChange,
528 info: Some(existing_account_changed_info.clone()),
529 previous_status: AccountStatus::InMemoryChange,
530 previous_info: Some(existing_account_changed_info.clone()),
531 storage: HashMap::from_iter([
532 (
533 slot1,
534 StorageSlot::new_changed(
535 StorageValue::from(100),
536 StorageValue::from(1_000),
537 ),
538 ),
539 (
540 slot2,
541 StorageSlot::new_changed(
542 *existing_account_initial_storage.get(&slot2).unwrap(),
543 StorageValue::from(2_000),
544 ),
545 ),
546 (
548 slot3,
549 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(3_000)),
550 ),
551 ]),
552 storage_was_destroyed: false,
553 },
554 ),
555 ]));
556
557 state.merge_transitions(BundleRetention::Reverts);
558 let mut bundle_state = state.take_bundle();
559
560 bundle_state.reverts.sort();
563 assert_eq!(
564 bundle_state.reverts.as_ref(),
565 Vec::from([Vec::from([
566 (
567 new_account_address,
568 AccountRevert {
569 account: AccountInfoRevert::DeleteIt,
570 previous_status: AccountStatus::LoadedNotExisting,
571 storage: HashMap::from_iter([(
572 slot1,
573 RevertToSlot::Some(StorageValue::ZERO)
574 )]),
575 wipe_storage: false,
576 }
577 ),
578 (
579 existing_account_address,
580 AccountRevert {
581 account: AccountInfoRevert::RevertTo(existing_account_initial_info.clone()),
582 previous_status: AccountStatus::Loaded,
583 storage: HashMap::from_iter([
584 (
585 slot1,
586 RevertToSlot::Some(
587 *existing_account_initial_storage.get(&slot1).unwrap()
588 )
589 ),
590 (
591 slot2,
592 RevertToSlot::Some(
593 *existing_account_initial_storage.get(&slot2).unwrap()
594 )
595 ),
596 (slot3, RevertToSlot::Some(StorageValue::ZERO))
597 ]),
598 wipe_storage: false,
599 }
600 ),
601 ])]),
602 "The account or storage reverts are incorrect"
603 );
604
605 assert_eq!(
608 bundle_state.account(&new_account_address),
609 Some(&BundleAccount {
610 info: Some(new_account_changed_info2),
611 original_info: None,
612 status: AccountStatus::InMemoryChange,
613 storage: HashMap::from_iter([(
614 slot1,
615 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(1))
616 )]),
617 }),
618 "The latest state of the new account is incorrect"
619 );
620
621 assert_eq!(
624 bundle_state.account(&existing_account_address),
625 Some(&BundleAccount {
626 info: Some(existing_account_changed_info),
627 original_info: Some(existing_account_initial_info),
628 status: AccountStatus::InMemoryChange,
629 storage: HashMap::from_iter([
630 (
631 slot1,
632 StorageSlot::new_changed(
633 *existing_account_initial_storage.get(&slot1).unwrap(),
634 StorageValue::from(1_000)
635 )
636 ),
637 (
638 slot2,
639 StorageSlot::new_changed(
640 *existing_account_initial_storage.get(&slot2).unwrap(),
641 StorageValue::from(2_000)
642 )
643 ),
644 (
646 slot3,
647 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(3_000))
648 ),
649 ]),
650 }),
651 "The latest state of the existing account is incorrect"
652 );
653 }
654
655 #[test]
658 fn bundle_scoped_reverts_collapse() {
659 let mut state = State::builder().with_bundle_update().build();
660
661 let new_account_address = Address::from_slice(&[0x1; 20]);
663 let new_account_created_info = AccountInfo {
664 nonce: 1,
665 balance: U256::from(1),
666 ..Default::default()
667 };
668
669 let existing_account_address = Address::from_slice(&[0x2; 20]);
671 let existing_account_initial_info = AccountInfo {
672 nonce: 1,
673 ..Default::default()
674 };
675 let existing_account_updated_info = AccountInfo {
676 nonce: 1,
677 balance: U256::from(1),
678 ..Default::default()
679 };
680
681 let (slot1, slot2) = (StorageKey::from(1), StorageKey::from(2));
683 let existing_account_with_storage_address = Address::from_slice(&[0x3; 20]);
684 let existing_account_with_storage_info = AccountInfo {
685 nonce: 1,
686 ..Default::default()
687 };
688 state.apply_transition(Vec::from([
690 (
691 new_account_address,
692 TransitionAccount {
693 status: AccountStatus::InMemoryChange,
694 info: Some(new_account_created_info.clone()),
695 previous_status: AccountStatus::LoadedNotExisting,
696 previous_info: None,
697 ..Default::default()
698 },
699 ),
700 (
701 existing_account_address,
702 TransitionAccount {
703 status: AccountStatus::Changed,
704 info: Some(existing_account_updated_info.clone()),
705 previous_status: AccountStatus::Loaded,
706 previous_info: Some(existing_account_initial_info.clone()),
707 ..Default::default()
708 },
709 ),
710 (
711 existing_account_with_storage_address,
712 TransitionAccount {
713 status: AccountStatus::Changed,
714 info: Some(existing_account_with_storage_info.clone()),
715 previous_status: AccountStatus::Loaded,
716 previous_info: Some(existing_account_with_storage_info.clone()),
717 storage: HashMap::from_iter([
718 (
719 slot1,
720 StorageSlot::new_changed(StorageValue::from(1), StorageValue::from(10)),
721 ),
722 (
723 slot2,
724 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(20)),
725 ),
726 ]),
727 storage_was_destroyed: false,
728 },
729 ),
730 ]));
731
732 state.apply_transition(Vec::from([
734 (
735 new_account_address,
736 TransitionAccount {
737 status: AccountStatus::Destroyed,
738 info: None,
739 previous_status: AccountStatus::InMemoryChange,
740 previous_info: Some(new_account_created_info),
741 ..Default::default()
742 },
743 ),
744 (
745 existing_account_address,
746 TransitionAccount {
747 status: AccountStatus::Changed,
748 info: Some(existing_account_initial_info),
749 previous_status: AccountStatus::Changed,
750 previous_info: Some(existing_account_updated_info),
751 ..Default::default()
752 },
753 ),
754 (
755 existing_account_with_storage_address,
756 TransitionAccount {
757 status: AccountStatus::Changed,
758 info: Some(existing_account_with_storage_info.clone()),
759 previous_status: AccountStatus::Changed,
760 previous_info: Some(existing_account_with_storage_info.clone()),
761 storage: HashMap::from_iter([
762 (
763 slot1,
764 StorageSlot::new_changed(StorageValue::from(10), StorageValue::from(1)),
765 ),
766 (
767 slot2,
768 StorageSlot::new_changed(StorageValue::from(20), StorageValue::ZERO),
769 ),
770 ]),
771 storage_was_destroyed: false,
772 },
773 ),
774 ]));
775
776 state.merge_transitions(BundleRetention::Reverts);
777
778 let mut bundle_state = state.take_bundle();
779 bundle_state.reverts.sort();
780
781 assert_eq!(bundle_state.reverts.as_ref(), Vec::from([Vec::from([])]));
784 }
785
786 #[test]
788 fn selfdestruct_state_and_reverts() {
789 let mut state = State::builder().with_bundle_update().build();
790
791 let existing_account_address = Address::from_slice(&[0x1; 20]);
793 let existing_account_info = AccountInfo {
794 nonce: 1,
795 ..Default::default()
796 };
797
798 let (slot1, slot2) = (StorageKey::from(1), StorageKey::from(2));
799
800 state.apply_transition(Vec::from([(
802 existing_account_address,
803 TransitionAccount {
804 status: AccountStatus::Destroyed,
805 info: None,
806 previous_status: AccountStatus::Loaded,
807 previous_info: Some(existing_account_info.clone()),
808 storage: HashMap::default(),
809 storage_was_destroyed: true,
810 },
811 )]));
812
813 state.apply_transition(Vec::from([(
815 existing_account_address,
816 TransitionAccount {
817 status: AccountStatus::DestroyedChanged,
818 info: Some(existing_account_info.clone()),
819 previous_status: AccountStatus::Destroyed,
820 previous_info: None,
821 storage: HashMap::from_iter([(
822 slot1,
823 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(1)),
824 )]),
825 storage_was_destroyed: false,
826 },
827 )]));
828
829 state.apply_transition(Vec::from([(
831 existing_account_address,
832 TransitionAccount {
833 status: AccountStatus::DestroyedAgain,
834 info: None,
835 previous_status: AccountStatus::DestroyedChanged,
836 previous_info: Some(existing_account_info.clone()),
837 storage: HashMap::default(),
839 storage_was_destroyed: true,
840 },
841 )]));
842
843 state.apply_transition(Vec::from([(
845 existing_account_address,
846 TransitionAccount {
847 status: AccountStatus::DestroyedChanged,
848 info: Some(existing_account_info.clone()),
849 previous_status: AccountStatus::DestroyedAgain,
850 previous_info: None,
851 storage: HashMap::from_iter([(
852 slot2,
853 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(2)),
854 )]),
855 storage_was_destroyed: false,
856 },
857 )]));
858
859 state.merge_transitions(BundleRetention::Reverts);
860
861 let bundle_state = state.take_bundle();
862
863 assert_eq!(
864 bundle_state.state,
865 HashMap::from_iter([(
866 existing_account_address,
867 BundleAccount {
868 info: Some(existing_account_info.clone()),
869 original_info: Some(existing_account_info.clone()),
870 storage: HashMap::from_iter([(
871 slot2,
872 StorageSlot::new_changed(StorageValue::ZERO, StorageValue::from(2))
873 )]),
874 status: AccountStatus::DestroyedChanged,
875 }
876 )])
877 );
878
879 assert_eq!(
880 bundle_state.reverts.as_ref(),
881 Vec::from([Vec::from([(
882 existing_account_address,
883 AccountRevert {
884 account: AccountInfoRevert::DoNothing,
885 previous_status: AccountStatus::Loaded,
886 storage: HashMap::from_iter([(slot2, RevertToSlot::Destroyed)]),
887 wipe_storage: true,
888 }
889 )])])
890 )
891 }
892}