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