reth_rpc_eth_types/cache/
db.rs1use crate::error::StateOverrideError;
4use alloy_eip7928::{bal::DecodedBal, BlockAccessIndex};
5use alloy_primitives::{map::DefaultHashBuilder, Bytes, U256};
6use alloy_rpc_types_eth::{state::StateOverride, BlockOverrides};
7use evm2::{
8 bytecode::{Bytecode, BytecodeDecodeError},
9 constants::MAX_CODE_SIZE_AMSTERDAM,
10 evm::{
11 AccountChangeRef, Bal as EvmBal, CacheDB, Db, DynDatabase, StateChangeSink, StorageChange,
12 },
13};
14use fixed_cache::Cache;
15use reth_evm::{database::StateProviderDatabase, BundleState, EvmEnv};
16use reth_execution_types::{BlockState, TransactionChanges};
17use reth_storage_api::{EvmStateProviderAdapter, StateProviderBox};
18use std::sync::{Arc, LazyLock};
19
20pub type StateCacheDb =
22 CacheDB<Db<StateProviderDatabase<EvmStateProviderAdapter<StateProviderBox>>>>;
23
24const OVERRIDE_BYTECODES_CAPACITY: usize = 256;
26
27static OVERRIDE_BYTECODES: LazyLock<Cache<Bytes, Bytecode, DefaultHashBuilder>> =
35 LazyLock::new(|| Cache::new(OVERRIDE_BYTECODES_CAPACITY, DefaultHashBuilder::default()));
36
37pub fn apply_block_overrides<DB>(
39 overrides: BlockOverrides,
40 db: &mut CacheDB<DB>,
41 evm_env: &mut impl EvmEnv,
42) {
43 let BlockOverrides {
44 number,
45 difficulty,
46 time,
47 gas_limit,
48 coinbase,
49 random,
50 base_fee,
51 blob_base_fee,
52 block_hash,
53 ..
54 } = overrides;
55
56 if let Some(block_hashes) = block_hash {
57 for (number, hash) in block_hashes {
58 db.insert_block_hash(&U256::from(number), &hash);
59 }
60 }
61
62 let block = evm_env.block_env_mut();
63 if let Some(number) = number {
64 block.number = number;
65 }
66 if let Some(difficulty) = difficulty {
67 block.difficulty = difficulty;
68 }
69 if let Some(time) = time {
70 block.timestamp = U256::from(time);
71 }
72 if let Some(gas_limit) = gas_limit {
73 block.gas_limit = U256::from(gas_limit);
74 }
75 if let Some(coinbase) = coinbase {
76 block.beneficiary = coinbase;
77 }
78 if let Some(random) = random {
79 block.prevrandao = U256::from_be_slice(random.as_slice());
80 }
81 if let Some(base_fee) = base_fee {
82 block.basefee = U256::from(base_fee.saturating_to::<u64>());
83 }
84 if let Some(blob_base_fee) = blob_base_fee {
85 block.blob_basefee = U256::from(blob_base_fee.saturating_to::<u128>());
86 }
87}
88
89pub fn apply_state_overrides<DB: DynDatabase>(
91 overrides: StateOverride,
92 db: &mut CacheDB<DB>,
93) -> Result<(), StateOverrideError<evm2::DatabaseError>> {
94 apply_state_overrides_with_state(overrides, db, None)
95}
96
97pub fn apply_state_overrides_with_state<DB: DynDatabase>(
99 overrides: StateOverride,
100 db: &mut CacheDB<DB>,
101 state: Option<&mut BundleState>,
102) -> Result<(), StateOverrideError<evm2::DatabaseError>> {
103 let mut changes = state.is_some().then(TransactionChanges::default);
104 for (address, account_override) in overrides {
105 let original = db.get_account(&address).map_err(StateOverrideError::Database)?;
106 let mut account = original.clone().unwrap_or_default();
107
108 if let Some(nonce) = account_override.nonce {
109 account.nonce = nonce;
110 }
111 if let Some(code) = account_override.code {
112 account.set_code(override_bytecode(code)?);
113 }
114 if let Some(balance) = account_override.balance {
115 account.balance = balance;
116 }
117
118 let replaces_storage = account_override.state.is_some();
119 let storage = match (account_override.state, account_override.state_diff) {
120 (Some(_), Some(_)) => return Err(StateOverrideError::BothStateAndStateDiff(address)),
121 (Some(state), None) => {
122 db.cache.storage.entry(address).or_default().wipe();
123 if let Some(changes) = changes.as_mut() {
124 let Ok(()) = changes.storage_wipe(address);
125 }
126 Some(state)
127 }
128 (None, Some(state)) => Some(state),
129 (None, None) => None,
130 };
131
132 if !account.is_empty() ||
137 replaces_storage ||
138 storage.as_ref().is_some_and(|state| !state.is_empty())
139 {
140 if let Some(changes) = changes.as_mut() {
141 let Ok(()) = changes.account(AccountChangeRef {
142 address,
143 original: original.as_ref(),
144 current: Some(&account),
145 created: original.is_none(),
146 selfdestructed: false,
147 });
148 }
149 db.insert_account_info(&address, account);
150 } else if original.is_some() {
151 if let Some(changes) = changes.as_mut() {
152 let Ok(()) = changes.storage_wipe(address);
153 let Ok(()) = changes.account(AccountChangeRef {
154 address,
155 original: original.as_ref(),
156 current: None,
157 created: false,
158 selfdestructed: true,
159 });
160 }
161 db.cache.accounts.insert(address, None);
162 db.cache.storage.entry(address).or_default().wipe();
163 }
164 if let Some(storage) = storage {
165 for (key, value) in storage {
166 let key = U256::from_be_bytes(key.0);
167 let current = U256::from_be_bytes(value.0);
168 if let Some(changes) = changes.as_mut() {
169 let original =
170 db.get_storage(&address, &key).map_err(StateOverrideError::Database)?;
171 let Ok(()) = changes.storage(StorageChange { address, key, original, current });
172 }
173 db.insert_account_storage(&address, &key, ¤t);
174 }
175 }
176 }
177
178 if let Some(state) = state &&
179 let Some(changes) = changes
180 {
181 let mut block = BlockState::new();
182 block.commit(&changes);
183 state.extend(block.into_bundle());
184 }
185
186 Ok(())
187}
188
189fn override_bytecode(code: Bytes) -> Result<Bytecode, BytecodeDecodeError> {
192 if code.is_empty() || code.len() > MAX_CODE_SIZE_AMSTERDAM {
193 return Bytecode::new_raw_checked(code)
194 }
195 if let Some(bytecode) = OVERRIDE_BYTECODES.get(&code) {
196 return Ok(bytecode)
197 }
198
199 let bytecode = Bytecode::new_raw_checked(code)?;
200 bytecode.hash_slow();
201 OVERRIDE_BYTECODES.insert(bytecode.original_bytes(), bytecode.clone());
203 Ok(bytecode)
204}
205
206#[inline]
216pub fn attach_bal_before_tx<DB: DynDatabase>(
217 db: &mut CacheDB<DB>,
218 bal: &DecodedBal<Arc<EvmBal>>,
219 tx_index: usize,
220) {
221 db.bal_context.set_bal(bal.as_bal().clone());
222 db.bal_context.set_allow_db_fallback(true);
223 db.bal_context.set_bal_index(BlockAccessIndex::from_tx_index(tx_index as u64));
224}
225
226#[cfg(test)]
227mod tests {
228
229 use super::*;
230 use alloy_eip7928::{BalanceChange, StorageChange};
231 use alloy_primitives::{keccak256, Address, Bytes, B256, U256};
232 use alloy_rpc_types_eth::state::AccountOverride;
233 use evm2::evm::{AccountBal, AccountInfo, Bal, BalChanges, InMemoryDB};
234
235 #[test]
236 fn state_overrides_remove_accounts_left_empty() {
237 let emptied = Address::with_last_byte(1);
238 let absent = Address::with_last_byte(2);
239 let replaced = Address::with_last_byte(3);
240 let slot = U256::ONE;
241
242 let mut db = InMemoryDB::default();
243 for address in [emptied, replaced] {
244 db.insert_account_info(
245 &address,
246 AccountInfo { balance: U256::from(5), ..Default::default() },
247 );
248 db.insert_account_storage(&address, &slot, &U256::from(9));
249 }
250 let mut state = CacheDB::new(db);
251
252 let overrides = StateOverride::from_iter([
253 (emptied, AccountOverride::default().with_balance(U256::ZERO)),
254 (absent, AccountOverride::default()),
255 (
256 replaced,
257 AccountOverride::default()
258 .with_balance(U256::ZERO)
259 .with_state(std::iter::empty::<(B256, B256)>()),
260 ),
261 ]);
262 let mut bundle = BundleState::default();
263 apply_state_overrides_with_state(overrides, &mut state, Some(&mut bundle)).unwrap();
264
265 assert_eq!(state.get_account(&emptied).unwrap(), None);
267 assert_eq!(state.get_storage(&emptied, &slot).unwrap(), U256::ZERO);
268 let removed = bundle.account(&emptied).unwrap();
269 assert_eq!(removed.info, None);
270 assert!(removed.was_destroyed());
271 assert_eq!(state.get_account(&absent).unwrap(), None);
272 assert!(bundle.account(&absent).is_none());
273 assert_eq!(state.get_account(&replaced).unwrap(), Some(AccountInfo::default()));
275 assert_eq!(state.get_storage(&replaced, &slot).unwrap(), U256::ZERO);
276 assert!(bundle
277 .account(&replaced)
278 .unwrap()
279 .info
280 .as_ref()
281 .is_some_and(|info| info.is_empty()));
282 }
283
284 #[test]
285 fn code_overrides_reuse_bytecode() {
286 let code = Bytes::from_static(&[0x60, 0x01, 0x5b, 0x00]);
287 let first = override_bytecode(code.clone()).unwrap();
288 let second = override_bytecode(code.clone()).unwrap();
289
290 assert_eq!(first.original_byte_slice().as_ptr(), second.original_byte_slice().as_ptr());
292 assert_eq!(second.hash_slow(), keccak256(&code));
293 }
294
295 #[test]
296 fn attach_bal_before_tx_serves_positioned_reads() {
297 let covered = Address::with_last_byte(1);
298 let uncovered = Address::with_last_byte(2);
299 let written_slot = U256::ONE;
300 let read_slot = U256::from(2);
301
302 let mut db = InMemoryDB::default();
304 db.insert_account_info(
305 &covered,
306 AccountInfo { balance: U256::from(7), nonce: 5, ..Default::default() },
307 );
308 db.insert_account_storage(&covered, &written_slot, &U256::from(11));
309 db.insert_account_storage(&covered, &read_slot, &U256::from(99));
310 db.insert_account_info(
311 &uncovered,
312 AccountInfo { balance: U256::from(3), ..Default::default() },
313 );
314
315 let mut account = AccountBal::default();
317 account.storage.storage.insert(
318 written_slot,
319 BalChanges::new(vec![StorageChange::new(
320 BlockAccessIndex::from_tx_index(1),
321 U256::from(42),
322 )]),
323 );
324 account.account_info.balance = BalChanges::new(vec![BalanceChange::new(
325 BlockAccessIndex::from_tx_index(2),
326 U256::from(1000),
327 )]);
328 let mut bal = Bal::default();
329 bal.accounts.insert(covered, account);
330 let bal = DecodedBal::new(Arc::new(bal), Bytes::new());
331
332 let mut state = CacheDB::new(db);
333
334 attach_bal_before_tx(&mut state, &bal, 0);
336 assert_eq!(state.get_storage(&covered, &written_slot).unwrap(), U256::from(11));
337 assert_eq!(state.get_account(&covered).unwrap().unwrap().balance, U256::from(7));
338
339 attach_bal_before_tx(&mut state, &bal, 2);
341 assert_eq!(state.get_storage(&covered, &written_slot).unwrap(), U256::from(42));
342 assert_eq!(state.get_account(&covered).unwrap().unwrap().balance, U256::from(7));
343
344 attach_bal_before_tx(&mut state, &bal, 3);
346 assert_eq!(state.get_account(&covered).unwrap().unwrap().balance, U256::from(1000));
347
348 assert_eq!(state.get_storage(&covered, &read_slot).unwrap(), U256::from(99));
350 assert_eq!(state.get_account(&uncovered).unwrap().unwrap().balance, U256::from(3));
351 }
352}