reth_ress_provider/
recorder.rs

1use alloy_primitives::{keccak256, Address, B256, U256};
2use reth_revm::{
3    state::{AccountInfo, Bytecode},
4    Database,
5};
6use reth_trie::{HashedPostState, HashedStorage};
7
8/// The state witness recorder that records all state accesses during execution.
9/// It does so by implementing the [`reth_revm::Database`] and recording accesses of accounts and
10/// slots.
11pub(crate) struct StateWitnessRecorderDatabase<D> {
12    database: D,
13    state: HashedPostState,
14}
15
16impl<D> StateWitnessRecorderDatabase<D> {
17    pub(crate) fn new(database: D) -> Self {
18        Self { database, state: Default::default() }
19    }
20
21    pub(crate) fn into_state(self) -> HashedPostState {
22        self.state
23    }
24}
25
26impl<D: Database> Database for StateWitnessRecorderDatabase<D> {
27    type Error = D::Error;
28
29    fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
30        let maybe_account = self.database.basic(address)?;
31        let hashed_address = keccak256(address);
32        self.state.accounts.insert(hashed_address, maybe_account.as_ref().map(|acc| acc.into()));
33        Ok(maybe_account)
34    }
35
36    fn storage(&mut self, address: Address, index: U256) -> Result<U256, Self::Error> {
37        let value = self.database.storage(address, index)?;
38        let hashed_address = keccak256(address);
39        let hashed_slot = keccak256(B256::from(index));
40        self.state
41            .storages
42            .entry(hashed_address)
43            .or_insert_with(|| HashedStorage::new(false))
44            .storage
45            .insert(hashed_slot, value);
46        Ok(value)
47    }
48
49    fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
50        self.database.block_hash(number)
51    }
52
53    fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
54        self.database.code_by_hash(code_hash)
55    }
56}