reth_trie_db/
hashed_cursor.rs

1use alloy_primitives::B256;
2use reth_db::tables;
3use reth_db_api::{
4    cursor::{DbCursorRO, DbDupCursorRO},
5    transaction::DbTx,
6};
7use reth_primitives::Account;
8use reth_trie::hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor};
9use revm::primitives::FlaggedStorage;
10
11/// A struct wrapping database transaction that implements [`HashedCursorFactory`].
12#[derive(Debug)]
13pub struct DatabaseHashedCursorFactory<'a, TX>(&'a TX);
14
15impl<TX> Clone for DatabaseHashedCursorFactory<'_, TX> {
16    fn clone(&self) -> Self {
17        Self(self.0)
18    }
19}
20
21impl<'a, TX> DatabaseHashedCursorFactory<'a, TX> {
22    /// Create new database hashed cursor factory.
23    pub const fn new(tx: &'a TX) -> Self {
24        Self(tx)
25    }
26}
27
28impl<TX: DbTx> HashedCursorFactory for DatabaseHashedCursorFactory<'_, TX> {
29    type AccountCursor = DatabaseHashedAccountCursor<<TX as DbTx>::Cursor<tables::HashedAccounts>>;
30    type StorageCursor =
31        DatabaseHashedStorageCursor<<TX as DbTx>::DupCursor<tables::HashedStorages>>;
32
33    fn hashed_account_cursor(&self) -> Result<Self::AccountCursor, reth_db::DatabaseError> {
34        Ok(DatabaseHashedAccountCursor(self.0.cursor_read::<tables::HashedAccounts>()?))
35    }
36
37    fn hashed_storage_cursor(
38        &self,
39        hashed_address: B256,
40    ) -> Result<Self::StorageCursor, reth_db::DatabaseError> {
41        Ok(DatabaseHashedStorageCursor::new(
42            self.0.cursor_dup_read::<tables::HashedStorages>()?,
43            hashed_address,
44        ))
45    }
46}
47
48/// A struct wrapping database cursor over hashed accounts implementing [`HashedCursor`] for
49/// iterating over accounts.
50#[derive(Debug)]
51pub struct DatabaseHashedAccountCursor<C>(C);
52
53impl<C> DatabaseHashedAccountCursor<C> {
54    /// Create new database hashed account cursor.
55    pub const fn new(cursor: C) -> Self {
56        Self(cursor)
57    }
58}
59
60impl<C> HashedCursor for DatabaseHashedAccountCursor<C>
61where
62    C: DbCursorRO<tables::HashedAccounts>,
63{
64    type Value = Account;
65
66    fn seek(&mut self, key: B256) -> Result<Option<(B256, Self::Value)>, reth_db::DatabaseError> {
67        self.0.seek(key)
68    }
69
70    fn next(&mut self) -> Result<Option<(B256, Self::Value)>, reth_db::DatabaseError> {
71        self.0.next()
72    }
73}
74
75/// The structure wrapping a database cursor for hashed storage and
76/// a target hashed address. Implements [`HashedCursor`] and [`HashedStorageCursor`]
77/// for iterating over hashed storage.
78#[derive(Debug)]
79pub struct DatabaseHashedStorageCursor<C> {
80    /// Database hashed storage cursor.
81    cursor: C,
82    /// Target hashed address of the account that the storage belongs to.
83    hashed_address: B256,
84}
85
86impl<C> DatabaseHashedStorageCursor<C> {
87    /// Create new [`DatabaseHashedStorageCursor`].
88    pub const fn new(cursor: C, hashed_address: B256) -> Self {
89        Self { cursor, hashed_address }
90    }
91}
92
93impl<C> HashedCursor for DatabaseHashedStorageCursor<C>
94where
95    C: DbCursorRO<tables::HashedStorages> + DbDupCursorRO<tables::HashedStorages>,
96{
97    type Value = FlaggedStorage;
98
99    fn seek(
100        &mut self,
101        subkey: B256,
102    ) -> Result<Option<(B256, Self::Value)>, reth_db::DatabaseError> {
103        Ok(self.cursor.seek_by_key_subkey(self.hashed_address, subkey)?.map(|e| (e.key, e.into())))
104    }
105
106    fn next(&mut self) -> Result<Option<(B256, Self::Value)>, reth_db::DatabaseError> {
107        Ok(self.cursor.next_dup_val()?.map(|e| (e.key, e.into())))
108    }
109}
110
111impl<C> HashedStorageCursor for DatabaseHashedStorageCursor<C>
112where
113    C: DbCursorRO<tables::HashedStorages> + DbDupCursorRO<tables::HashedStorages>,
114{
115    fn is_storage_empty(&mut self) -> Result<bool, reth_db::DatabaseError> {
116        Ok(self.cursor.seek_exact(self.hashed_address)?.is_none())
117    }
118}