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