reth_trie_db/
hashed_cursor.rs

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