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