revm/db/states/
cache.rs
1use super::{
2 plain_account::PlainStorage, transition_account::TransitionAccount, CacheAccount, PlainAccount,
3};
4use revm_interpreter::primitives::{
5 Account, AccountInfo, Address, Bytecode, EvmState, HashMap, B256,
6};
7use std::vec::Vec;
8
9#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct CacheState {
17 pub accounts: HashMap<Address, CacheAccount>,
19 pub contracts: HashMap<B256, Bytecode>,
22 pub has_state_clear: bool,
24}
25
26impl Default for CacheState {
27 fn default() -> Self {
28 Self::new(true)
29 }
30}
31
32impl CacheState {
33 pub fn new(has_state_clear: bool) -> Self {
35 Self {
36 accounts: HashMap::default(),
37 contracts: HashMap::default(),
38 has_state_clear,
39 }
40 }
41
42 pub fn set_state_clear_flag(&mut self, has_state_clear: bool) {
44 self.has_state_clear = has_state_clear;
45 }
46
47 pub fn trie_account(&self) -> impl IntoIterator<Item = (Address, &PlainAccount)> {
51 self.accounts.iter().filter_map(|(address, account)| {
52 account
53 .account
54 .as_ref()
55 .map(|plain_acc| (*address, plain_acc))
56 })
57 }
58
59 pub fn insert_not_existing(&mut self, address: Address) {
61 self.accounts
62 .insert(address, CacheAccount::new_loaded_not_existing());
63 }
64
65 pub fn insert_account(&mut self, address: Address, info: AccountInfo) {
67 let account = if !info.is_empty() {
68 CacheAccount::new_loaded(info, HashMap::default())
69 } else {
70 CacheAccount::new_loaded_empty_eip161(HashMap::default())
71 };
72 self.accounts.insert(address, account);
73 }
74
75 pub fn insert_account_with_storage(
77 &mut self,
78 address: Address,
79 info: AccountInfo,
80 storage: PlainStorage,
81 ) {
82 let account = if !info.is_empty() {
83 CacheAccount::new_loaded(info, storage)
84 } else {
85 CacheAccount::new_loaded_empty_eip161(storage)
86 };
87 self.accounts.insert(address, account);
88 }
89
90 pub fn apply_evm_state(&mut self, evm_state: EvmState) -> Vec<(Address, TransitionAccount)> {
92 let mut transitions = Vec::with_capacity(evm_state.len());
93 for (address, account) in evm_state {
94 if let Some(transition) = self.apply_account_state(address, account) {
95 transitions.push((address, transition));
96 }
97 }
98 transitions
99 }
100
101 fn apply_account_state(
104 &mut self,
105 address: Address,
106 account: Account,
107 ) -> Option<TransitionAccount> {
108 if !account.is_touched() {
110 return None;
111 }
112
113 let this_account = self
114 .accounts
115 .get_mut(&address)
116 .expect("All accounts should be present inside cache");
117
118 if account.is_selfdestructed() {
121 return this_account.selfdestruct();
122 }
123
124 let is_created = account.is_created();
125 let is_empty = account.is_empty();
126
127 let changed_storage = account
129 .storage
130 .into_iter()
131 .filter(|(_, slot)| slot.is_changed())
132 .map(|(key, slot)| (key, slot.into()))
133 .collect();
134
135 if is_created {
144 return Some(this_account.newly_created(account.info, changed_storage));
145 }
146
147 if is_empty {
152 if self.has_state_clear {
153 this_account.touch_empty_eip161()
155 } else {
156 this_account.touch_create_pre_eip161(changed_storage)
159 }
160 } else {
161 Some(this_account.change(account.info, changed_storage))
162 }
163 }
164}