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, EmptyDB};
7use primitives::{hash_map, Address, HashMap, B256, BLOCK_HASH_HISTORY, U256};
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(
95 &mut self,
96 balances: impl IntoIterator<Item = (Address, u128)>,
97 ) -> Result<(), DB::Error> {
98 let mut transitions = Vec::new();
100 for (address, balance) in balances {
101 if balance == 0 {
102 continue;
103 }
104 let original_account = self.load_cache_account(address)?;
105 transitions.push((
106 address,
107 original_account
108 .increment_balance(balance)
109 .expect("Balance is not zero"),
110 ))
111 }
112 if let Some(s) = self.transition_state.as_mut() {
114 s.add_transitions(transitions)
115 }
116 Ok(())
117 }
118
119 pub fn drain_balances(
123 &mut self,
124 addresses: impl IntoIterator<Item = Address>,
125 ) -> Result<Vec<u128>, DB::Error> {
126 let mut transitions = Vec::new();
128 let mut balances = Vec::new();
129 for address in addresses {
130 let original_account = self.load_cache_account(address)?;
131 let (balance, transition) = original_account.drain_balance();
132 balances.push(balance);
133 transitions.push((address, transition))
134 }
135 if let Some(s) = self.transition_state.as_mut() {
137 s.add_transitions(transitions)
138 }
139 Ok(balances)
140 }
141
142 pub fn set_state_clear_flag(&mut self, has_state_clear: bool) {
144 self.cache.set_state_clear_flag(has_state_clear);
145 }
146
147 pub fn insert_not_existing(&mut self, address: Address) {
148 self.cache.insert_not_existing(address)
149 }
150
151 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(
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) =
195 self.bundle_state.account(&address).cloned().map(Into::into)
196 {
197 return Ok(entry.insert(account));
198 }
199 }
200 let info = self.database.basic(address)?;
202 let account = match info {
203 None => CacheAccount::new_loaded_not_existing(),
204 Some(acc) if acc.is_empty() => {
205 CacheAccount::new_loaded_empty_eip161(HashMap::default())
206 }
207 Some(acc) => CacheAccount::new_loaded(acc, HashMap::default()),
208 };
209 Ok(entry.insert(account))
210 }
211 hash_map::Entry::Occupied(entry) => Ok(entry.into_mut()),
212 }
213 }
214
215 pub fn take_bundle(&mut self) -> BundleState {
227 core::mem::take(&mut self.bundle_state)
228 }
229}
230
231impl<DB: Database> Database for State<DB> {
232 type Error = DB::Error;
233
234 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
235 self.load_cache_account(address).map(|a| a.account_info())
236 }
237
238 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
239 let res = match self.cache.contracts.entry(code_hash) {
240 hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()),
241 hash_map::Entry::Vacant(entry) => {
242 if self.use_preloaded_bundle {
243 if let Some(code) = self.bundle_state.contracts.get(&code_hash) {
244 entry.insert(code.clone());
245 return Ok(code.clone());
246 }
247 }
248 let code = self.database.code_by_hash(code_hash)?;
250 entry.insert(code.clone());
251 Ok(code)
252 }
253 };
254 res
255 }
256
257 fn storage(&mut self, address: Address, index: U256) -> Result<U256, Self::Error> {
258 if let Some(account) = self.cache.accounts.get_mut(&address) {
261 let is_storage_known = account.status.is_storage_known();
263 Ok(account
264 .account
265 .as_mut()
266 .map(|account| match account.storage.entry(index) {
267 hash_map::Entry::Occupied(entry) => Ok(*entry.get()),
268 hash_map::Entry::Vacant(entry) => {
269 let value = if is_storage_known {
272 U256::ZERO
273 } else {
274 self.database.storage(address, index)?
275 };
276 entry.insert(value);
277 Ok(value)
278 }
279 })
280 .transpose()?
281 .unwrap_or_default())
282 } else {
283 unreachable!("For accessing any storage account is guaranteed to be loaded beforehand")
284 }
285 }
286
287 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
288 match self.block_hashes.entry(number) {
289 btree_map::Entry::Occupied(entry) => Ok(*entry.get()),
290 btree_map::Entry::Vacant(entry) => {
291 let ret = *entry.insert(self.database.block_hash(number)?);
292
293 let last_block = number.saturating_sub(BLOCK_HASH_HISTORY);
295 while let Some(entry) = self.block_hashes.first_entry() {
296 if *entry.key() < last_block {
297 entry.remove();
298 } else {
299 break;
300 }
301 }
302
303 Ok(ret)
304 }
305 }
306 }
307}
308
309impl<DB: Database> DatabaseCommit for State<DB> {
310 fn commit(&mut self, evm_state: HashMap<Address, Account>) {
311 let transitions = self.cache.apply_evm_state(evm_state);
312 self.apply_transition(transitions);
313 }
314}
315
316#[cfg(test)]
317mod tests {
318 use super::*;
319 use crate::{
320 states::{reverts::AccountInfoRevert, StorageSlot},
321 AccountRevert, AccountStatus, BundleAccount, RevertToSlot,
322 };
323 use primitives::keccak256;
324
325 #[test]
326 fn block_hash_cache() {
327 let mut state = State::builder().build();
328 state.block_hash(1u64).unwrap();
329 state.block_hash(2u64).unwrap();
330
331 let test_number = BLOCK_HASH_HISTORY + 2;
332
333 let block1_hash = keccak256(U256::from(1).to_string().as_bytes());
334 let block2_hash = keccak256(U256::from(2).to_string().as_bytes());
335 let block_test_hash = keccak256(U256::from(test_number).to_string().as_bytes());
336
337 assert_eq!(
338 state.block_hashes,
339 BTreeMap::from([(1, block1_hash), (2, block2_hash)])
340 );
341
342 state.block_hash(test_number).unwrap();
343 assert_eq!(
344 state.block_hashes,
345 BTreeMap::from([(test_number, block_test_hash), (2, block2_hash)])
346 );
347 }
348
349 #[test]
356 fn reverts_preserve_old_values() {
357 let mut state = State::builder().with_bundle_update().build();
358
359 let (slot1, slot2, slot3) = (U256::from(1), U256::from(2), U256::from(3));
360
361 let new_account_address = Address::from_slice(&[0x1; 20]);
364 let new_account_created_info = AccountInfo {
365 nonce: 1,
366 balance: U256::from(1),
367 ..Default::default()
368 };
369 let new_account_changed_info = AccountInfo {
370 nonce: 2,
371 ..new_account_created_info.clone()
372 };
373 let new_account_changed_info2 = AccountInfo {
374 nonce: 3,
375 ..new_account_changed_info.clone()
376 };
377
378 let existing_account_address = Address::from_slice(&[0x2; 20]);
380 let existing_account_initial_info = AccountInfo {
381 nonce: 1,
382 ..Default::default()
383 };
384 let existing_account_initial_storage = HashMap::<U256, U256>::from_iter([
385 (slot1, U256::from(100)), (slot2, U256::from(200)), ]);
388 let existing_account_changed_info = AccountInfo {
389 nonce: 2,
390 ..existing_account_initial_info.clone()
391 };
392
393 state.apply_transition(Vec::from([
395 (
396 new_account_address,
397 TransitionAccount {
398 status: AccountStatus::InMemoryChange,
399 info: Some(new_account_created_info.clone()),
400 previous_status: AccountStatus::LoadedNotExisting,
401 previous_info: None,
402 ..Default::default()
403 },
404 ),
405 (
406 existing_account_address,
407 TransitionAccount {
408 status: AccountStatus::InMemoryChange,
409 info: Some(existing_account_changed_info.clone()),
410 previous_status: AccountStatus::Loaded,
411 previous_info: Some(existing_account_initial_info.clone()),
412 storage: HashMap::from_iter([(
413 slot1,
414 StorageSlot::new_changed(
415 *existing_account_initial_storage.get(&slot1).unwrap(),
416 U256::from(1000),
417 ),
418 )]),
419 storage_was_destroyed: false,
420 },
421 ),
422 ]));
423
424 state.apply_transition(Vec::from([(
426 new_account_address,
427 TransitionAccount {
428 status: AccountStatus::InMemoryChange,
429 info: Some(new_account_changed_info.clone()),
430 previous_status: AccountStatus::InMemoryChange,
431 previous_info: Some(new_account_created_info.clone()),
432 ..Default::default()
433 },
434 )]));
435
436 state.apply_transition(Vec::from([
438 (
439 new_account_address,
440 TransitionAccount {
441 status: AccountStatus::InMemoryChange,
442 info: Some(new_account_changed_info2.clone()),
443 previous_status: AccountStatus::InMemoryChange,
444 previous_info: Some(new_account_changed_info),
445 storage: HashMap::from_iter([(
446 slot1,
447 StorageSlot::new_changed(U256::ZERO, U256::from(1)),
448 )]),
449 storage_was_destroyed: false,
450 },
451 ),
452 (
453 existing_account_address,
454 TransitionAccount {
455 status: AccountStatus::InMemoryChange,
456 info: Some(existing_account_changed_info.clone()),
457 previous_status: AccountStatus::InMemoryChange,
458 previous_info: Some(existing_account_changed_info.clone()),
459 storage: HashMap::from_iter([
460 (
461 slot1,
462 StorageSlot::new_changed(U256::from(100), U256::from(1_000)),
463 ),
464 (
465 slot2,
466 StorageSlot::new_changed(
467 *existing_account_initial_storage.get(&slot2).unwrap(),
468 U256::from(2_000),
469 ),
470 ),
471 (
473 slot3,
474 StorageSlot::new_changed(U256::ZERO, U256::from(3_000)),
475 ),
476 ]),
477 storage_was_destroyed: false,
478 },
479 ),
480 ]));
481
482 state.merge_transitions(BundleRetention::Reverts);
483 let mut bundle_state = state.take_bundle();
484
485 bundle_state.reverts.sort();
488 assert_eq!(
489 bundle_state.reverts.as_ref(),
490 Vec::from([Vec::from([
491 (
492 new_account_address,
493 AccountRevert {
494 account: AccountInfoRevert::DeleteIt,
495 previous_status: AccountStatus::LoadedNotExisting,
496 storage: HashMap::from_iter([(slot1, RevertToSlot::Some(U256::ZERO))]),
497 wipe_storage: false,
498 }
499 ),
500 (
501 existing_account_address,
502 AccountRevert {
503 account: AccountInfoRevert::RevertTo(existing_account_initial_info.clone()),
504 previous_status: AccountStatus::Loaded,
505 storage: HashMap::from_iter([
506 (
507 slot1,
508 RevertToSlot::Some(
509 *existing_account_initial_storage.get(&slot1).unwrap()
510 )
511 ),
512 (
513 slot2,
514 RevertToSlot::Some(
515 *existing_account_initial_storage.get(&slot2).unwrap()
516 )
517 ),
518 (slot3, RevertToSlot::Some(U256::ZERO))
519 ]),
520 wipe_storage: false,
521 }
522 ),
523 ])]),
524 "The account or storage reverts are incorrect"
525 );
526
527 assert_eq!(
530 bundle_state.account(&new_account_address),
531 Some(&BundleAccount {
532 info: Some(new_account_changed_info2),
533 original_info: None,
534 status: AccountStatus::InMemoryChange,
535 storage: HashMap::from_iter([(
536 slot1,
537 StorageSlot::new_changed(U256::ZERO, U256::from(1))
538 )]),
539 }),
540 "The latest state of the new account is incorrect"
541 );
542
543 assert_eq!(
546 bundle_state.account(&existing_account_address),
547 Some(&BundleAccount {
548 info: Some(existing_account_changed_info),
549 original_info: Some(existing_account_initial_info),
550 status: AccountStatus::InMemoryChange,
551 storage: HashMap::from_iter([
552 (
553 slot1,
554 StorageSlot::new_changed(
555 *existing_account_initial_storage.get(&slot1).unwrap(),
556 U256::from(1_000)
557 )
558 ),
559 (
560 slot2,
561 StorageSlot::new_changed(
562 *existing_account_initial_storage.get(&slot2).unwrap(),
563 U256::from(2_000)
564 )
565 ),
566 (
568 slot3,
569 StorageSlot::new_changed(U256::ZERO, U256::from(3_000))
570 ),
571 ]),
572 }),
573 "The latest state of the existing account is incorrect"
574 );
575 }
576
577 #[test]
580 fn bundle_scoped_reverts_collapse() {
581 let mut state = State::builder().with_bundle_update().build();
582
583 let new_account_address = Address::from_slice(&[0x1; 20]);
585 let new_account_created_info = AccountInfo {
586 nonce: 1,
587 balance: U256::from(1),
588 ..Default::default()
589 };
590
591 let existing_account_address = Address::from_slice(&[0x2; 20]);
593 let existing_account_initial_info = AccountInfo {
594 nonce: 1,
595 ..Default::default()
596 };
597 let existing_account_updated_info = AccountInfo {
598 nonce: 1,
599 balance: U256::from(1),
600 ..Default::default()
601 };
602
603 let (slot1, slot2) = (U256::from(1), U256::from(2));
605 let existing_account_with_storage_address = Address::from_slice(&[0x3; 20]);
606 let existing_account_with_storage_info = AccountInfo {
607 nonce: 1,
608 ..Default::default()
609 };
610 state.apply_transition(Vec::from([
612 (
613 new_account_address,
614 TransitionAccount {
615 status: AccountStatus::InMemoryChange,
616 info: Some(new_account_created_info.clone()),
617 previous_status: AccountStatus::LoadedNotExisting,
618 previous_info: None,
619 ..Default::default()
620 },
621 ),
622 (
623 existing_account_address,
624 TransitionAccount {
625 status: AccountStatus::Changed,
626 info: Some(existing_account_updated_info.clone()),
627 previous_status: AccountStatus::Loaded,
628 previous_info: Some(existing_account_initial_info.clone()),
629 ..Default::default()
630 },
631 ),
632 (
633 existing_account_with_storage_address,
634 TransitionAccount {
635 status: AccountStatus::Changed,
636 info: Some(existing_account_with_storage_info.clone()),
637 previous_status: AccountStatus::Loaded,
638 previous_info: Some(existing_account_with_storage_info.clone()),
639 storage: HashMap::from_iter([
640 (
641 slot1,
642 StorageSlot::new_changed(U256::from(1), U256::from(10)),
643 ),
644 (slot2, StorageSlot::new_changed(U256::ZERO, U256::from(20))),
645 ]),
646 storage_was_destroyed: false,
647 },
648 ),
649 ]));
650
651 state.apply_transition(Vec::from([
653 (
654 new_account_address,
655 TransitionAccount {
656 status: AccountStatus::Destroyed,
657 info: None,
658 previous_status: AccountStatus::InMemoryChange,
659 previous_info: Some(new_account_created_info),
660 ..Default::default()
661 },
662 ),
663 (
664 existing_account_address,
665 TransitionAccount {
666 status: AccountStatus::Changed,
667 info: Some(existing_account_initial_info),
668 previous_status: AccountStatus::Changed,
669 previous_info: Some(existing_account_updated_info),
670 ..Default::default()
671 },
672 ),
673 (
674 existing_account_with_storage_address,
675 TransitionAccount {
676 status: AccountStatus::Changed,
677 info: Some(existing_account_with_storage_info.clone()),
678 previous_status: AccountStatus::Changed,
679 previous_info: Some(existing_account_with_storage_info.clone()),
680 storage: HashMap::from_iter([
681 (
682 slot1,
683 StorageSlot::new_changed(U256::from(10), U256::from(1)),
684 ),
685 (slot2, StorageSlot::new_changed(U256::from(20), U256::ZERO)),
686 ]),
687 storage_was_destroyed: false,
688 },
689 ),
690 ]));
691
692 state.merge_transitions(BundleRetention::Reverts);
693
694 let mut bundle_state = state.take_bundle();
695 bundle_state.reverts.sort();
696
697 assert_eq!(bundle_state.reverts.as_ref(), Vec::from([Vec::from([])]));
700 }
701
702 #[test]
704 fn selfdestruct_state_and_reverts() {
705 let mut state = State::builder().with_bundle_update().build();
706
707 let existing_account_address = Address::from_slice(&[0x1; 20]);
709 let existing_account_info = AccountInfo {
710 nonce: 1,
711 ..Default::default()
712 };
713
714 let (slot1, slot2) = (U256::from(1), U256::from(2));
715
716 state.apply_transition(Vec::from([(
718 existing_account_address,
719 TransitionAccount {
720 status: AccountStatus::Destroyed,
721 info: None,
722 previous_status: AccountStatus::Loaded,
723 previous_info: Some(existing_account_info.clone()),
724 storage: HashMap::default(),
725 storage_was_destroyed: true,
726 },
727 )]));
728
729 state.apply_transition(Vec::from([(
731 existing_account_address,
732 TransitionAccount {
733 status: AccountStatus::DestroyedChanged,
734 info: Some(existing_account_info.clone()),
735 previous_status: AccountStatus::Destroyed,
736 previous_info: None,
737 storage: HashMap::from_iter([(
738 slot1,
739 StorageSlot::new_changed(U256::ZERO, U256::from(1)),
740 )]),
741 storage_was_destroyed: false,
742 },
743 )]));
744
745 state.apply_transition(Vec::from([(
747 existing_account_address,
748 TransitionAccount {
749 status: AccountStatus::DestroyedAgain,
750 info: None,
751 previous_status: AccountStatus::DestroyedChanged,
752 previous_info: Some(existing_account_info.clone()),
753 storage: HashMap::default(),
755 storage_was_destroyed: true,
756 },
757 )]));
758
759 state.apply_transition(Vec::from([(
761 existing_account_address,
762 TransitionAccount {
763 status: AccountStatus::DestroyedChanged,
764 info: Some(existing_account_info.clone()),
765 previous_status: AccountStatus::DestroyedAgain,
766 previous_info: None,
767 storage: HashMap::from_iter([(
768 slot2,
769 StorageSlot::new_changed(U256::ZERO, U256::from(2)),
770 )]),
771 storage_was_destroyed: false,
772 },
773 )]));
774
775 state.merge_transitions(BundleRetention::Reverts);
776
777 let bundle_state = state.take_bundle();
778
779 assert_eq!(
780 bundle_state.state,
781 HashMap::from_iter([(
782 existing_account_address,
783 BundleAccount {
784 info: Some(existing_account_info.clone()),
785 original_info: Some(existing_account_info.clone()),
786 storage: HashMap::from_iter([(
787 slot2,
788 StorageSlot::new_changed(U256::ZERO, U256::from(2))
789 )]),
790 status: AccountStatus::DestroyedChanged,
791 }
792 )])
793 );
794
795 assert_eq!(
796 bundle_state.reverts.as_ref(),
797 Vec::from([Vec::from([(
798 existing_account_address,
799 AccountRevert {
800 account: AccountInfoRevert::DoNothing,
801 previous_status: AccountStatus::Loaded,
802 storage: HashMap::from_iter([(slot2, RevertToSlot::Destroyed)]),
803 wipe_storage: true,
804 }
805 )])])
806 )
807 }
808}