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