reth_trie_db/
storage.rs
1use crate::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory};
2use alloy_primitives::{keccak256, map::hash_map, Address, BlockNumber, B256};
3use reth_db_api::{
4 cursor::DbCursorRO, models::BlockNumberAddress, tables, transaction::DbTx, DatabaseError,
5};
6use reth_execution_errors::StorageRootError;
7use reth_trie::{
8 hashed_cursor::HashedPostStateCursorFactory, HashedPostState, HashedStorage, StorageRoot,
9};
10
11#[cfg(feature = "metrics")]
12use reth_trie::metrics::TrieRootMetrics;
13
14pub trait DatabaseStorageRoot<'a, TX> {
16 fn from_tx(tx: &'a TX, address: Address) -> Self;
18
19 fn from_tx_hashed(tx: &'a TX, hashed_address: B256) -> Self;
21
22 fn overlay_root(
24 tx: &'a TX,
25 address: Address,
26 hashed_storage: HashedStorage,
27 ) -> Result<B256, StorageRootError>;
28}
29
30pub trait DatabaseHashedStorage<TX>: Sized {
32 fn from_reverts(tx: &TX, address: Address, from: BlockNumber) -> Result<Self, DatabaseError>;
35}
36
37impl<'a, TX: DbTx> DatabaseStorageRoot<'a, TX>
38 for StorageRoot<DatabaseTrieCursorFactory<'a, TX>, DatabaseHashedCursorFactory<'a, TX>>
39{
40 fn from_tx(tx: &'a TX, address: Address) -> Self {
41 Self::new(
42 DatabaseTrieCursorFactory::new(tx),
43 DatabaseHashedCursorFactory::new(tx),
44 address,
45 Default::default(),
46 #[cfg(feature = "metrics")]
47 TrieRootMetrics::new(reth_trie::TrieType::Storage),
48 )
49 }
50
51 fn from_tx_hashed(tx: &'a TX, hashed_address: B256) -> Self {
52 Self::new_hashed(
53 DatabaseTrieCursorFactory::new(tx),
54 DatabaseHashedCursorFactory::new(tx),
55 hashed_address,
56 Default::default(),
57 #[cfg(feature = "metrics")]
58 TrieRootMetrics::new(reth_trie::TrieType::Storage),
59 )
60 }
61
62 fn overlay_root(
63 tx: &'a TX,
64 address: Address,
65 hashed_storage: HashedStorage,
66 ) -> Result<B256, StorageRootError> {
67 let prefix_set = hashed_storage.construct_prefix_set().freeze();
68 let state_sorted =
69 HashedPostState::from_hashed_storage(keccak256(address), hashed_storage).into_sorted();
70 StorageRoot::new(
71 DatabaseTrieCursorFactory::new(tx),
72 HashedPostStateCursorFactory::new(DatabaseHashedCursorFactory::new(tx), &state_sorted),
73 address,
74 prefix_set,
75 #[cfg(feature = "metrics")]
76 TrieRootMetrics::new(reth_trie::TrieType::Storage),
77 )
78 .root()
79 }
80}
81
82impl<TX: DbTx> DatabaseHashedStorage<TX> for HashedStorage {
83 fn from_reverts(tx: &TX, address: Address, from: BlockNumber) -> Result<Self, DatabaseError> {
84 let mut storage = Self::new(false);
85 let mut storage_changesets_cursor = tx.cursor_read::<tables::StorageChangeSets>()?;
86 for entry in storage_changesets_cursor.walk_range(BlockNumberAddress((from, address))..)? {
87 let (BlockNumberAddress((_, storage_address)), storage_change) = entry?;
88 if storage_address == address {
89 let hashed_slot = keccak256(storage_change.key);
90 if let hash_map::Entry::Vacant(entry) = storage.storage.entry(hashed_slot) {
91 entry.insert(storage_change.value);
92 }
93 }
94 }
95 Ok(storage)
96 }
97}