reth_trie_db/
hashed_cursor.rs

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