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.
11#[derive(Debug)]
12pub(crate) struct StateWitnessRecorderDatabase<D> {
13    database: D,
14    state: HashedPostState,
15}
16
17impl<D> StateWitnessRecorderDatabase<D> {
18    pub(crate) fn new(database: D) -> Self {
19        Self { database, state: Default::default() }
20    }
21
22    pub(crate) fn into_state(self) -> HashedPostState {
23        self.state
24    }
25}
26
27impl<D: Database> Database for StateWitnessRecorderDatabase<D> {
28    type Error = D::Error;
29
30    fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
31        let maybe_account = self.database.basic(address)?;
32        let hashed_address = keccak256(address);
33        self.state.accounts.insert(hashed_address, maybe_account.as_ref().map(|acc| acc.into()));
34        Ok(maybe_account)
35    }
36
37    fn storage(&mut self, address: Address, index: U256) -> Result<U256, Self::Error> {
38        let value = self.database.storage(address, index)?;
39        let hashed_address = keccak256(address);
40        let hashed_slot = keccak256(B256::from(index));
41        self.state
42            .storages
43            .entry(hashed_address)
44            .or_insert_with(|| HashedStorage::new(false))
45            .storage
46            .insert(hashed_slot, value);
47        Ok(value)
48    }
49
50    fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
51        self.database.block_hash(number)
52    }
53
54    fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
55        self.database.code_by_hash(code_hash)
56    }
57}