1use alloy_primitives::{keccak256, map::B256HashMap, Bytes, B256};
2use reth_trie::{HashedPostState, HashedStorage};
3use revm::State;
4
5#[derive(Debug, Clone, Default)]
7pub struct ExecutionWitnessRecord {
8 pub hashed_state: HashedPostState,
10 pub codes: B256HashMap<Bytes>,
15 pub keys: B256HashMap<Bytes>,
21}
22
23impl ExecutionWitnessRecord {
24 pub fn record_executed_state<DB>(&mut self, statedb: &State<DB>) {
26 self.codes = statedb
27 .cache
28 .contracts
29 .iter()
30 .map(|(hash, code)| (*hash, code.original_bytes()))
31 .chain(
32 statedb
37 .bundle_state
38 .contracts
39 .iter()
40 .map(|(hash, code)| (*hash, code.original_bytes())),
41 )
42 .collect();
43
44 for (address, account) in &statedb.cache.accounts {
45 let hashed_address = keccak256(address);
46 self.hashed_state
47 .accounts
48 .insert(hashed_address, account.account.as_ref().map(|a| (&a.info).into()));
49
50 let storage = self
51 .hashed_state
52 .storages
53 .entry(hashed_address)
54 .or_insert_with(|| HashedStorage::new(account.status.was_destroyed()));
55
56 if let Some(account) = &account.account {
57 self.keys.insert(hashed_address, address.to_vec().into());
58
59 for (slot, value) in &account.storage {
60 let slot = B256::from(*slot);
61 let hashed_slot = keccak256(slot);
62 storage.storage.insert(hashed_slot, *value);
63
64 self.keys.insert(hashed_slot, slot.into());
65 }
66 }
67 }
68 }
69
70 pub fn from_executed_state<DB>(state: &State<DB>) -> Self {
72 let mut record = Self::default();
73 record.record_executed_state(state);
74 record
75 }
76}