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(
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) {
145 self.cache.insert_not_existing(address)
146 }
147
148 pub fn insert_account(&mut self, address: Address, info: AccountInfo) {
149 self.cache.insert_account(address, info)
150 }
151
152 pub fn insert_account_with_storage(
153 &mut self,
154 address: Address,
155 info: AccountInfo,
156 storage: PlainStorage,
157 ) {
158 self.cache
159 .insert_account_with_storage(address, info, storage)
160 }
161
162 pub fn apply_transition(&mut self, transitions: Vec<(Address, TransitionAccount)>) {
164 if let Some(s) = self.transition_state.as_mut() {
166 s.add_transitions(transitions)
167 }
168 }
169
170 pub fn merge_transitions(&mut self, retention: BundleRetention) {
176 if let Some(transition_state) = self.transition_state.as_mut().map(TransitionState::take) {
177 self.bundle_state
178 .apply_transitions_and_create_reverts(transition_state, retention);
179 }
180 }
181
182 pub fn load_cache_account(&mut self, address: Address) -> Result<&mut CacheAccount, DB::Error> {
187 match self.cache.accounts.entry(address) {
188 hash_map::Entry::Vacant(entry) => {
189 if self.use_preloaded_bundle {
190 if let Some(account) =
192 self.bundle_state.account(&address).cloned().map(Into::into)
193 {
194 return Ok(entry.insert(account));
195 }
196 }
197 let info = self.database.basic(address)?;
199 let account = match info {
200 None => CacheAccount::new_loaded_not_existing(),
201 Some(acc) if acc.is_empty() => {
202 CacheAccount::new_loaded_empty_eip161(HashMap::default())
203 }
204 Some(acc) => CacheAccount::new_loaded(acc, HashMap::default()),
205 };
206 Ok(entry.insert(account))
207 }
208 hash_map::Entry::Occupied(entry) => Ok(entry.into_mut()),
209 }
210 }
211
212 pub fn take_bundle(&mut self) -> BundleState {
224 core::mem::take(&mut self.bundle_state)
225 }
226}
227
228impl<DB: Database> Database for State<DB> {
229 type Error = DB::Error;
230
231 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
232 self.load_cache_account(address).map(|a| a.account_info())
233 }
234
235 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
236 let res = match self.cache.contracts.entry(code_hash) {
237 hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()),
238 hash_map::Entry::Vacant(entry) => {
239 if self.use_preloaded_bundle {
240 if let Some(code) = self.bundle_state.contracts.get(&code_hash) {
241 entry.insert(code.clone());
242 return Ok(code.clone());
243 }
244 }
245 let code = self.database.code_by_hash(code_hash)?;
247 entry.insert(code.clone());
248 Ok(code)
249 }
250 };
251 res
252 }
253
254 fn storage(&mut self, address: Address, index: U256) -> Result<U256, Self::Error> {
255 if let Some(account) = self.cache.accounts.get_mut(&address) {
258 let is_storage_known = account.status.is_storage_known();
260 Ok(account
261 .account
262 .as_mut()
263 .map(|account| match account.storage.entry(index) {
264 hash_map::Entry::Occupied(entry) => Ok(*entry.get()),
265 hash_map::Entry::Vacant(entry) => {
266 let value = if is_storage_known {
269 U256::ZERO
270 } else {
271 self.database.storage(address, index)?
272 };
273 entry.insert(value);
274 Ok(value)
275 }
276 })
277 .transpose()?
278 .unwrap_or_default())
279 } else {
280 unreachable!("For accessing any storage account is guaranteed to be loaded beforehand")
281 }
282 }
283
284 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
285 match self.block_hashes.entry(number) {
286 btree_map::Entry::Occupied(entry) => Ok(*entry.get()),
287 btree_map::Entry::Vacant(entry) => {
288 let ret = *entry.insert(self.database.block_hash(number)?);
289
290 let last_block = number.saturating_sub(BLOCK_HASH_HISTORY);
292 while let Some(entry) = self.block_hashes.first_entry() {
293 if *entry.key() < last_block {
294 entry.remove();
295 } else {
296 break;
297 }
298 }
299
300 Ok(ret)
301 }
302 }
303 }
304}
305
306impl<DB: Database> DatabaseCommit for State<DB> {
307 fn commit(&mut self, evm_state: HashMap<Address, Account>) {
308 let transitions = self.cache.apply_evm_state(evm_state);
309 self.apply_transition(transitions);
310 }
311}
312
313#[cfg(test)]
314mod tests {
315 use super::*;
316 use crate::{
317 states::{reverts::AccountInfoRevert, StorageSlot},
318 AccountRevert, AccountStatus, BundleAccount, RevertToSlot,
319 };
320 use primitives::keccak256;
321
322 #[test]
323 fn block_hash_cache() {
324 let mut state = State::builder().build();
325 state.block_hash(1u64).unwrap();
326 state.block_hash(2u64).unwrap();
327
328 let test_number = BLOCK_HASH_HISTORY + 2;
329
330 let block1_hash = keccak256(U256::from(1).to_string().as_bytes());
331 let block2_hash = keccak256(U256::from(2).to_string().as_bytes());
332 let block_test_hash = keccak256(U256::from(test_number).to_string().as_bytes());
333
334 assert_eq!(
335 state.block_hashes,
336 BTreeMap::from([(1, block1_hash), (2, block2_hash)])
337 );
338
339 state.block_hash(test_number).unwrap();
340 assert_eq!(
341 state.block_hashes,
342 BTreeMap::from([(test_number, block_test_hash), (2, block2_hash)])
343 );
344 }
345
346 #[test]
353 fn reverts_preserve_old_values() {
354 let mut state = State::builder().with_bundle_update().build();
355
356 let (slot1, slot2, slot3) = (U256::from(1), U256::from(2), U256::from(3));
357
358 let new_account_address = Address::from_slice(&[0x1; 20]);
361 let new_account_created_info = AccountInfo {
362 nonce: 1,
363 balance: U256::from(1),
364 ..Default::default()
365 };
366 let new_account_changed_info = AccountInfo {
367 nonce: 2,
368 ..new_account_created_info.clone()
369 };
370 let new_account_changed_info2 = AccountInfo {
371 nonce: 3,
372 ..new_account_changed_info.clone()
373 };
374
375 let existing_account_address = Address::from_slice(&[0x2; 20]);
377 let existing_account_initial_info = AccountInfo {
378 nonce: 1,
379 ..Default::default()
380 };
381 let existing_account_initial_storage = HashMap::<U256, U256>::from_iter([
382 (slot1, U256::from(100)), (slot2, U256::from(200)), ]);
385 let existing_account_changed_info = AccountInfo {
386 nonce: 2,
387 ..existing_account_initial_info.clone()
388 };
389
390 state.apply_transition(Vec::from([
392 (
393 new_account_address,
394 TransitionAccount {
395 status: AccountStatus::InMemoryChange,
396 info: Some(new_account_created_info.clone()),
397 previous_status: AccountStatus::LoadedNotExisting,
398 previous_info: None,
399 ..Default::default()
400 },
401 ),
402 (
403 existing_account_address,
404 TransitionAccount {
405 status: AccountStatus::InMemoryChange,
406 info: Some(existing_account_changed_info.clone()),
407 previous_status: AccountStatus::Loaded,
408 previous_info: Some(existing_account_initial_info.clone()),
409 storage: HashMap::from_iter([(
410 slot1,
411 StorageSlot::new_changed(
412 *existing_account_initial_storage.get(&slot1).unwrap(),
413 U256::from(1000),
414 ),
415 )]),
416 storage_was_destroyed: false,
417 },
418 ),
419 ]));
420
421 state.apply_transition(Vec::from([(
423 new_account_address,
424 TransitionAccount {
425 status: AccountStatus::InMemoryChange,
426 info: Some(new_account_changed_info.clone()),
427 previous_status: AccountStatus::InMemoryChange,
428 previous_info: Some(new_account_created_info.clone()),
429 ..Default::default()
430 },
431 )]));
432
433 state.apply_transition(Vec::from([
435 (
436 new_account_address,
437 TransitionAccount {
438 status: AccountStatus::InMemoryChange,
439 info: Some(new_account_changed_info2.clone()),
440 previous_status: AccountStatus::InMemoryChange,
441 previous_info: Some(new_account_changed_info),
442 storage: HashMap::from_iter([(
443 slot1,
444 StorageSlot::new_changed(U256::ZERO, U256::from(1)),
445 )]),
446 storage_was_destroyed: false,
447 },
448 ),
449 (
450 existing_account_address,
451 TransitionAccount {
452 status: AccountStatus::InMemoryChange,
453 info: Some(existing_account_changed_info.clone()),
454 previous_status: AccountStatus::InMemoryChange,
455 previous_info: Some(existing_account_changed_info.clone()),
456 storage: HashMap::from_iter([
457 (
458 slot1,
459 StorageSlot::new_changed(U256::from(100), U256::from(1_000)),
460 ),
461 (
462 slot2,
463 StorageSlot::new_changed(
464 *existing_account_initial_storage.get(&slot2).unwrap(),
465 U256::from(2_000),
466 ),
467 ),
468 (
470 slot3,
471 StorageSlot::new_changed(U256::ZERO, U256::from(3_000)),
472 ),
473 ]),
474 storage_was_destroyed: false,
475 },
476 ),
477 ]));
478
479 state.merge_transitions(BundleRetention::Reverts);
480 let mut bundle_state = state.take_bundle();
481
482 bundle_state.reverts.sort();
485 assert_eq!(
486 bundle_state.reverts.as_ref(),
487 Vec::from([Vec::from([
488 (
489 new_account_address,
490 AccountRevert {
491 account: AccountInfoRevert::DeleteIt,
492 previous_status: AccountStatus::LoadedNotExisting,
493 storage: HashMap::from_iter([(slot1, RevertToSlot::Some(U256::ZERO))]),
494 wipe_storage: false,
495 }
496 ),
497 (
498 existing_account_address,
499 AccountRevert {
500 account: AccountInfoRevert::RevertTo(existing_account_initial_info.clone()),
501 previous_status: AccountStatus::Loaded,
502 storage: HashMap::from_iter([
503 (
504 slot1,
505 RevertToSlot::Some(
506 *existing_account_initial_storage.get(&slot1).unwrap()
507 )
508 ),
509 (
510 slot2,
511 RevertToSlot::Some(
512 *existing_account_initial_storage.get(&slot2).unwrap()
513 )
514 ),
515 (slot3, RevertToSlot::Some(U256::ZERO))
516 ]),
517 wipe_storage: false,
518 }
519 ),
520 ])]),
521 "The account or storage reverts are incorrect"
522 );
523
524 assert_eq!(
527 bundle_state.account(&new_account_address),
528 Some(&BundleAccount {
529 info: Some(new_account_changed_info2),
530 original_info: None,
531 status: AccountStatus::InMemoryChange,
532 storage: HashMap::from_iter([(
533 slot1,
534 StorageSlot::new_changed(U256::ZERO, U256::from(1))
535 )]),
536 }),
537 "The latest state of the new account is incorrect"
538 );
539
540 assert_eq!(
543 bundle_state.account(&existing_account_address),
544 Some(&BundleAccount {
545 info: Some(existing_account_changed_info),
546 original_info: Some(existing_account_initial_info),
547 status: AccountStatus::InMemoryChange,
548 storage: HashMap::from_iter([
549 (
550 slot1,
551 StorageSlot::new_changed(
552 *existing_account_initial_storage.get(&slot1).unwrap(),
553 U256::from(1_000)
554 )
555 ),
556 (
557 slot2,
558 StorageSlot::new_changed(
559 *existing_account_initial_storage.get(&slot2).unwrap(),
560 U256::from(2_000)
561 )
562 ),
563 (
565 slot3,
566 StorageSlot::new_changed(U256::ZERO, U256::from(3_000))
567 ),
568 ]),
569 }),
570 "The latest state of the existing account is incorrect"
571 );
572 }
573
574 #[test]
577 fn bundle_scoped_reverts_collapse() {
578 let mut state = State::builder().with_bundle_update().build();
579
580 let new_account_address = Address::from_slice(&[0x1; 20]);
582 let new_account_created_info = AccountInfo {
583 nonce: 1,
584 balance: U256::from(1),
585 ..Default::default()
586 };
587
588 let existing_account_address = Address::from_slice(&[0x2; 20]);
590 let existing_account_initial_info = AccountInfo {
591 nonce: 1,
592 ..Default::default()
593 };
594 let existing_account_updated_info = AccountInfo {
595 nonce: 1,
596 balance: U256::from(1),
597 ..Default::default()
598 };
599
600 let (slot1, slot2) = (U256::from(1), U256::from(2));
602 let existing_account_with_storage_address = Address::from_slice(&[0x3; 20]);
603 let existing_account_with_storage_info = AccountInfo {
604 nonce: 1,
605 ..Default::default()
606 };
607 state.apply_transition(Vec::from([
609 (
610 new_account_address,
611 TransitionAccount {
612 status: AccountStatus::InMemoryChange,
613 info: Some(new_account_created_info.clone()),
614 previous_status: AccountStatus::LoadedNotExisting,
615 previous_info: None,
616 ..Default::default()
617 },
618 ),
619 (
620 existing_account_address,
621 TransitionAccount {
622 status: AccountStatus::Changed,
623 info: Some(existing_account_updated_info.clone()),
624 previous_status: AccountStatus::Loaded,
625 previous_info: Some(existing_account_initial_info.clone()),
626 ..Default::default()
627 },
628 ),
629 (
630 existing_account_with_storage_address,
631 TransitionAccount {
632 status: AccountStatus::Changed,
633 info: Some(existing_account_with_storage_info.clone()),
634 previous_status: AccountStatus::Loaded,
635 previous_info: Some(existing_account_with_storage_info.clone()),
636 storage: HashMap::from_iter([
637 (
638 slot1,
639 StorageSlot::new_changed(U256::from(1), U256::from(10)),
640 ),
641 (slot2, StorageSlot::new_changed(U256::ZERO, U256::from(20))),
642 ]),
643 storage_was_destroyed: false,
644 },
645 ),
646 ]));
647
648 state.apply_transition(Vec::from([
650 (
651 new_account_address,
652 TransitionAccount {
653 status: AccountStatus::Destroyed,
654 info: None,
655 previous_status: AccountStatus::InMemoryChange,
656 previous_info: Some(new_account_created_info),
657 ..Default::default()
658 },
659 ),
660 (
661 existing_account_address,
662 TransitionAccount {
663 status: AccountStatus::Changed,
664 info: Some(existing_account_initial_info),
665 previous_status: AccountStatus::Changed,
666 previous_info: Some(existing_account_updated_info),
667 ..Default::default()
668 },
669 ),
670 (
671 existing_account_with_storage_address,
672 TransitionAccount {
673 status: AccountStatus::Changed,
674 info: Some(existing_account_with_storage_info.clone()),
675 previous_status: AccountStatus::Changed,
676 previous_info: Some(existing_account_with_storage_info.clone()),
677 storage: HashMap::from_iter([
678 (
679 slot1,
680 StorageSlot::new_changed(U256::from(10), U256::from(1)),
681 ),
682 (slot2, StorageSlot::new_changed(U256::from(20), U256::ZERO)),
683 ]),
684 storage_was_destroyed: false,
685 },
686 ),
687 ]));
688
689 state.merge_transitions(BundleRetention::Reverts);
690
691 let mut bundle_state = state.take_bundle();
692 bundle_state.reverts.sort();
693
694 assert_eq!(bundle_state.reverts.as_ref(), Vec::from([Vec::from([])]));
697 }
698
699 #[test]
701 fn selfdestruct_state_and_reverts() {
702 let mut state = State::builder().with_bundle_update().build();
703
704 let existing_account_address = Address::from_slice(&[0x1; 20]);
706 let existing_account_info = AccountInfo {
707 nonce: 1,
708 ..Default::default()
709 };
710
711 let (slot1, slot2) = (U256::from(1), U256::from(2));
712
713 state.apply_transition(Vec::from([(
715 existing_account_address,
716 TransitionAccount {
717 status: AccountStatus::Destroyed,
718 info: None,
719 previous_status: AccountStatus::Loaded,
720 previous_info: Some(existing_account_info.clone()),
721 storage: HashMap::default(),
722 storage_was_destroyed: true,
723 },
724 )]));
725
726 state.apply_transition(Vec::from([(
728 existing_account_address,
729 TransitionAccount {
730 status: AccountStatus::DestroyedChanged,
731 info: Some(existing_account_info.clone()),
732 previous_status: AccountStatus::Destroyed,
733 previous_info: None,
734 storage: HashMap::from_iter([(
735 slot1,
736 StorageSlot::new_changed(U256::ZERO, U256::from(1)),
737 )]),
738 storage_was_destroyed: false,
739 },
740 )]));
741
742 state.apply_transition(Vec::from([(
744 existing_account_address,
745 TransitionAccount {
746 status: AccountStatus::DestroyedAgain,
747 info: None,
748 previous_status: AccountStatus::DestroyedChanged,
749 previous_info: Some(existing_account_info.clone()),
750 storage: HashMap::default(),
752 storage_was_destroyed: true,
753 },
754 )]));
755
756 state.apply_transition(Vec::from([(
758 existing_account_address,
759 TransitionAccount {
760 status: AccountStatus::DestroyedChanged,
761 info: Some(existing_account_info.clone()),
762 previous_status: AccountStatus::DestroyedAgain,
763 previous_info: None,
764 storage: HashMap::from_iter([(
765 slot2,
766 StorageSlot::new_changed(U256::ZERO, U256::from(2)),
767 )]),
768 storage_was_destroyed: false,
769 },
770 )]));
771
772 state.merge_transitions(BundleRetention::Reverts);
773
774 let bundle_state = state.take_bundle();
775
776 assert_eq!(
777 bundle_state.state,
778 HashMap::from_iter([(
779 existing_account_address,
780 BundleAccount {
781 info: Some(existing_account_info.clone()),
782 original_info: Some(existing_account_info.clone()),
783 storage: HashMap::from_iter([(
784 slot2,
785 StorageSlot::new_changed(U256::ZERO, U256::from(2))
786 )]),
787 status: AccountStatus::DestroyedChanged,
788 }
789 )])
790 );
791
792 assert_eq!(
793 bundle_state.reverts.as_ref(),
794 Vec::from([Vec::from([(
795 existing_account_address,
796 AccountRevert {
797 account: AccountInfoRevert::DoNothing,
798 previous_status: AccountStatus::Loaded,
799 storage: HashMap::from_iter([(slot2, RevertToSlot::Destroyed)]),
800 wipe_storage: true,
801 }
802 )])])
803 )
804 }
805}