revm_database/states/
cache.rs1use super::{
2 plain_account::PlainStorage, transition_account::TransitionAccount, CacheAccount, PlainAccount,
3};
4use bytecode::Bytecode;
5use primitives::{Address, HashMap, B256};
6use state::{Account, AccountInfo, EvmState};
7use std::vec::Vec;
8
9#[derive(Clone, Debug, PartialEq, Eq)]
18pub struct CacheState {
19 pub accounts: HashMap<Address, CacheAccount>,
21 pub contracts: HashMap<B256, Bytecode>,
23 pub has_state_clear: bool,
25}
26
27impl Default for CacheState {
28 fn default() -> Self {
29 Self::new(true)
30 }
31}
32
33impl CacheState {
34 pub fn new(has_state_clear: bool) -> Self {
36 Self {
37 accounts: HashMap::default(),
38 contracts: HashMap::default(),
39 has_state_clear,
40 }
41 }
42
43 pub fn set_state_clear_flag(&mut self, has_state_clear: bool) {
45 self.has_state_clear = has_state_clear;
46 }
47
48 pub fn trie_account(&self) -> impl IntoIterator<Item = (Address, &PlainAccount)> {
52 self.accounts.iter().filter_map(|(address, account)| {
53 account
54 .account
55 .as_ref()
56 .map(|plain_acc| (*address, plain_acc))
57 })
58 }
59
60 pub fn insert_not_existing(&mut self, address: Address) {
62 self.accounts
63 .insert(address, CacheAccount::new_loaded_not_existing());
64 }
65
66 pub fn insert_account(&mut self, address: Address, info: AccountInfo) {
68 let account = if !info.is_empty() {
69 CacheAccount::new_loaded(info, HashMap::default())
70 } else {
71 CacheAccount::new_loaded_empty_eip161(HashMap::default())
72 };
73 self.accounts.insert(address, account);
74 }
75
76 pub fn insert_account_with_storage(
78 &mut self,
79 address: Address,
80 info: AccountInfo,
81 storage: PlainStorage,
82 ) {
83 let account = if !info.is_empty() {
84 CacheAccount::new_loaded(info, storage)
85 } else {
86 CacheAccount::new_loaded_empty_eip161(storage)
87 };
88 self.accounts.insert(address, account);
89 }
90
91 pub fn apply_evm_state(&mut self, evm_state: EvmState) -> Vec<(Address, TransitionAccount)> {
93 let mut transitions = Vec::with_capacity(evm_state.len());
94 for (address, account) in evm_state {
95 if let Some(transition) = self.apply_account_state(address, account) {
96 transitions.push((address, transition));
97 }
98 }
99 transitions
100 }
101
102 fn apply_account_state(
106 &mut self,
107 address: Address,
108 account: Account,
109 ) -> Option<TransitionAccount> {
110 if !account.is_touched() {
112 return None;
113 }
114
115 let this_account = self
116 .accounts
117 .get_mut(&address)
118 .expect("All accounts should be present inside cache");
119
120 if account.is_selfdestructed() {
123 return this_account.selfdestruct();
124 }
125
126 let is_created = account.is_created();
127 let is_empty = account.is_empty();
128
129 let changed_storage = account
131 .storage
132 .into_iter()
133 .filter(|(_, slot)| slot.is_changed())
134 .map(|(key, slot)| (key, slot.into()))
135 .collect();
136
137 if is_created {
146 return Some(this_account.newly_created(account.info, changed_storage));
147 }
148
149 if is_empty {
154 if self.has_state_clear {
155 this_account.touch_empty_eip161()
157 } else {
158 this_account.touch_create_pre_eip161(changed_storage)
161 }
162 } else {
163 Some(this_account.change(account.info, changed_storage))
164 }
165 }
166}