reth_trie/hashed_cursor/
mod.rs1use alloy_primitives::{keccak256, Address, B256, U256};
2use reth_primitives_traits::Account;
3use reth_storage_errors::db::DatabaseError;
4use reth_trie_common::HashedPostState;
5use revm::database::BundleAccount;
6
7mod post_state;
9pub use post_state::*;
10
11pub mod noop;
13
14#[cfg(any(test, feature = "test-utils"))]
16pub mod mock;
17
18pub mod metrics;
20#[cfg(feature = "metrics")]
21pub use metrics::HashedCursorMetrics;
22pub use metrics::{HashedCursorMetricsCache, InstrumentedHashedCursor};
23
24#[auto_impl::auto_impl(&)]
26pub trait HashedCursorFactory {
27 type AccountCursor<'a>: HashedCursor<Value = Account>
29 where
30 Self: 'a;
31 type StorageCursor<'a>: HashedStorageCursor<Value = U256>
33 where
34 Self: 'a;
35
36 fn hashed_account_cursor(&self) -> Result<Self::AccountCursor<'_>, DatabaseError>;
38
39 fn hashed_storage_cursor(
41 &self,
42 hashed_address: B256,
43 ) -> Result<Self::StorageCursor<'_>, DatabaseError>;
44}
45
46#[auto_impl::auto_impl(&mut)]
48pub trait HashedCursor {
49 type Value: std::fmt::Debug;
51
52 fn seek(&mut self, key: B256) -> Result<Option<(B256, Self::Value)>, DatabaseError>;
55
56 fn next(&mut self) -> Result<Option<(B256, Self::Value)>, DatabaseError>;
58
59 fn reset(&mut self);
65}
66
67#[auto_impl::auto_impl(&mut)]
69pub trait HashedStorageCursor: HashedCursor {
70 fn is_storage_empty(&mut self) -> Result<bool, DatabaseError>;
72
73 fn set_hashed_address(&mut self, hashed_address: B256);
79}
80
81pub fn zero_destroyed_account_storage<'a>(
86 cursor_factory: &impl HashedCursorFactory,
87 accounts: impl IntoIterator<Item = (&'a Address, &'a BundleAccount)>,
88 hashed_state: &mut HashedPostState,
89) -> Result<(), DatabaseError> {
90 let mut destroyed_accounts = accounts
91 .into_iter()
92 .filter(|(_, account)| account.was_destroyed())
93 .map(|(address, _)| keccak256(address));
94 let Some(mut hashed_address) = destroyed_accounts.next() else { return Ok(()) };
95 let mut cursor = cursor_factory.hashed_storage_cursor(hashed_address)?;
96
97 loop {
98 if let Some((hashed_slot, _)) = cursor.seek(B256::ZERO)? {
99 let storage = &mut hashed_state.storages.entry(hashed_address).or_default().storage;
100 storage.entry(hashed_slot).or_insert(U256::ZERO);
101 while let Some((hashed_slot, _)) = cursor.next()? {
102 storage.entry(hashed_slot).or_insert(U256::ZERO);
103 }
104 }
105
106 let Some(next_hashed_address) = destroyed_accounts.next() else { break };
107 hashed_address = next_hashed_address;
108 cursor.set_hashed_address(hashed_address);
109 }
110
111 Ok(())
112}