Skip to main content

reth_trie_db/
proof.rs

1use crate::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory, TrieTableAdapter};
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, A: TrieTableAdapter> DatabaseProof<'a>
38    for Proof<DatabaseTrieCursorFactory<&'a TX, A>, 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, A: TrieTableAdapter> DatabaseStorageProof<'a, TX>
100    for StorageProof<
101        'static,
102        DatabaseTrieCursorFactory<&'a TX, A>,
103        DatabaseHashedCursorFactory<&'a TX>,
104    >
105{
106    fn from_tx(tx: &'a TX, address: Address) -> Self {
107        Self::new(
108            DatabaseTrieCursorFactory::<_, A>::new(tx),
109            DatabaseHashedCursorFactory::new(tx),
110            address,
111        )
112    }
113
114    fn overlay_storage_proof(
115        tx: &'a TX,
116        address: Address,
117        slot: B256,
118        storage: HashedStorage,
119    ) -> Result<reth_trie::StorageProof, StateProofError> {
120        let hashed_address = keccak256(address);
121        let prefix_set = storage.construct_prefix_set();
122        let state_sorted = HashedPostStateSorted::new(
123            Default::default(),
124            HashMap::from_iter([(hashed_address, storage.into_sorted())]),
125        );
126        StorageProof::new(
127            DatabaseTrieCursorFactory::<_, A>::new(tx),
128            HashedPostStateCursorFactory::new(DatabaseHashedCursorFactory::new(tx), &state_sorted),
129            address,
130        )
131        .with_prefix_set_mut(prefix_set)
132        .storage_proof(slot)
133    }
134
135    fn overlay_storage_multiproof(
136        tx: &'a TX,
137        address: Address,
138        slots: &[B256],
139        storage: HashedStorage,
140    ) -> Result<StorageMultiProof, StateProofError> {
141        let hashed_address = keccak256(address);
142        let targets = slots.iter().map(keccak256).collect();
143        let prefix_set = storage.construct_prefix_set();
144        let state_sorted = HashedPostStateSorted::new(
145            Default::default(),
146            HashMap::from_iter([(hashed_address, storage.into_sorted())]),
147        );
148        StorageProof::new(
149            DatabaseTrieCursorFactory::<_, A>::new(tx),
150            HashedPostStateCursorFactory::new(DatabaseHashedCursorFactory::new(tx), &state_sorted),
151            address,
152        )
153        .with_prefix_set_mut(prefix_set)
154        .storage_multiproof(targets)
155    }
156}