reth_trie_db/
proof.rs

1use crate::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory};
2use alloy_primitives::{keccak256, map::HashMap, Address, B256};
3use reth_db_api::transaction::DbTx;
4use reth_execution_errors::StateProofError;
5use reth_trie::{
6    hashed_cursor::HashedPostStateCursorFactory,
7    proof::{Proof, StorageProof},
8    trie_cursor::InMemoryTrieCursorFactory,
9    AccountProof, HashedPostStateSorted, HashedStorage, MultiProof, MultiProofTargets,
10    StorageMultiProof, TrieInput,
11};
12
13/// Extends [`Proof`] with operations specific for working with a database transaction.
14pub trait DatabaseProof<'a, TX> {
15    /// Create a new [Proof] from database transaction.
16    fn from_tx(tx: &'a TX) -> Self;
17
18    /// Generates the state proof for target account based on [`TrieInput`].
19    fn overlay_account_proof(
20        tx: &'a TX,
21        input: TrieInput,
22        address: Address,
23        slots: &[B256],
24    ) -> Result<AccountProof, StateProofError>;
25
26    /// Generates the state [`MultiProof`] for target hashed account and storage keys.
27    fn overlay_multiproof(
28        tx: &'a TX,
29        input: TrieInput,
30        targets: MultiProofTargets,
31    ) -> Result<MultiProof, StateProofError>;
32}
33
34impl<'a, TX: DbTx> DatabaseProof<'a, TX>
35    for Proof<DatabaseTrieCursorFactory<'a, TX>, DatabaseHashedCursorFactory<'a, TX>>
36{
37    /// Create a new [Proof] instance from database transaction.
38    fn from_tx(tx: &'a TX) -> Self {
39        Self::new(DatabaseTrieCursorFactory::new(tx), DatabaseHashedCursorFactory::new(tx))
40    }
41
42    fn overlay_account_proof(
43        tx: &'a TX,
44        input: TrieInput,
45        address: Address,
46        slots: &[B256],
47    ) -> Result<AccountProof, StateProofError> {
48        let nodes_sorted = input.nodes.into_sorted();
49        let state_sorted = input.state.into_sorted();
50        Self::from_tx(tx)
51            .with_trie_cursor_factory(InMemoryTrieCursorFactory::new(
52                DatabaseTrieCursorFactory::new(tx),
53                &nodes_sorted,
54            ))
55            .with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
56                DatabaseHashedCursorFactory::new(tx),
57                &state_sorted,
58            ))
59            .with_prefix_sets_mut(input.prefix_sets)
60            .account_proof(address, slots)
61    }
62
63    fn overlay_multiproof(
64        tx: &'a TX,
65        input: TrieInput,
66        targets: MultiProofTargets,
67    ) -> Result<MultiProof, StateProofError> {
68        let nodes_sorted = input.nodes.into_sorted();
69        let state_sorted = input.state.into_sorted();
70        Self::from_tx(tx)
71            .with_trie_cursor_factory(InMemoryTrieCursorFactory::new(
72                DatabaseTrieCursorFactory::new(tx),
73                &nodes_sorted,
74            ))
75            .with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
76                DatabaseHashedCursorFactory::new(tx),
77                &state_sorted,
78            ))
79            .with_prefix_sets_mut(input.prefix_sets)
80            .multiproof(targets)
81    }
82}
83
84/// Extends [`StorageProof`] with operations specific for working with a database transaction.
85pub trait DatabaseStorageProof<'a, TX> {
86    /// Create a new [`StorageProof`] from database transaction and account address.
87    fn from_tx(tx: &'a TX, address: Address) -> Self;
88
89    /// Generates the storage proof for target slot based on [`TrieInput`].
90    fn overlay_storage_proof(
91        tx: &'a TX,
92        address: Address,
93        slot: B256,
94        storage: HashedStorage,
95    ) -> Result<reth_trie::StorageProof, StateProofError>;
96
97    /// Generates the storage multiproof for target slots based on [`TrieInput`].
98    fn overlay_storage_multiproof(
99        tx: &'a TX,
100        address: Address,
101        slots: &[B256],
102        storage: HashedStorage,
103    ) -> Result<StorageMultiProof, StateProofError>;
104}
105
106impl<'a, TX: DbTx> DatabaseStorageProof<'a, TX>
107    for StorageProof<DatabaseTrieCursorFactory<'a, TX>, DatabaseHashedCursorFactory<'a, TX>>
108{
109    fn from_tx(tx: &'a TX, address: Address) -> Self {
110        Self::new(DatabaseTrieCursorFactory::new(tx), DatabaseHashedCursorFactory::new(tx), address)
111    }
112
113    fn overlay_storage_proof(
114        tx: &'a TX,
115        address: Address,
116        slot: B256,
117        storage: HashedStorage,
118    ) -> Result<reth_trie::StorageProof, StateProofError> {
119        let hashed_address = keccak256(address);
120        let prefix_set = storage.construct_prefix_set();
121        let state_sorted = HashedPostStateSorted::new(
122            Default::default(),
123            HashMap::from_iter([(hashed_address, storage.into_sorted())]),
124        );
125        Self::from_tx(tx, address)
126            .with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
127                DatabaseHashedCursorFactory::new(tx),
128                &state_sorted,
129            ))
130            .with_prefix_set_mut(prefix_set)
131            .storage_proof(slot)
132    }
133
134    fn overlay_storage_multiproof(
135        tx: &'a TX,
136        address: Address,
137        slots: &[B256],
138        storage: HashedStorage,
139    ) -> Result<StorageMultiProof, StateProofError> {
140        let hashed_address = keccak256(address);
141        let targets = slots.iter().map(keccak256).collect();
142        let prefix_set = storage.construct_prefix_set();
143        let state_sorted = HashedPostStateSorted::new(
144            Default::default(),
145            HashMap::from_iter([(hashed_address, storage.into_sorted())]),
146        );
147        Self::from_tx(tx, address)
148            .with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
149                DatabaseHashedCursorFactory::new(tx),
150                &state_sorted,
151            ))
152            .with_prefix_set_mut(prefix_set)
153            .storage_multiproof(targets)
154    }
155}