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