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, DecodedMultiProofV2, HashedPostStateSorted, HashedStorage, MultiProof,
10 MultiProofTargets, MultiProofTargetsV2, StorageMultiProof, TrieInput,
11};
12
13pub trait DatabaseProof<'a> {
15 type Tx;
17
18 fn from_tx(tx: &'a Self::Tx) -> Self;
20
21 fn overlay_account_proof(
23 &self,
24 input: TrieInput,
25 address: Address,
26 slots: &[B256],
27 ) -> Result<AccountProof, StateProofError>;
28
29 fn overlay_multiproof(
31 &self,
32 input: TrieInput,
33 targets: MultiProofTargets,
34 ) -> Result<MultiProof, StateProofError>;
35
36 fn overlay_multiproof_v2(
38 &self,
39 input: TrieInput,
40 targets: MultiProofTargetsV2,
41 ) -> Result<DecodedMultiProofV2, StateProofError>;
42}
43
44impl<'a, TX: DbTx, A: TrieTableAdapter> DatabaseProof<'a>
45 for Proof<DatabaseTrieCursorFactory<&'a TX, A>, DatabaseHashedCursorFactory<&'a TX>>
46{
47 type Tx = TX;
48
49 fn from_tx(tx: &'a Self::Tx) -> Self {
50 Self::new(DatabaseTrieCursorFactory::new(tx), DatabaseHashedCursorFactory::new(tx))
51 }
52 fn overlay_account_proof(
53 &self,
54 input: TrieInput,
55 address: Address,
56 slots: &[B256],
57 ) -> Result<AccountProof, StateProofError> {
58 let nodes_sorted = input.nodes.into_sorted();
59 let state_sorted = input.state.into_sorted();
60 Proof::new(
61 InMemoryTrieCursorFactory::new(self.trie_cursor_factory().clone(), &nodes_sorted),
62 HashedPostStateCursorFactory::new(self.hashed_cursor_factory().clone(), &state_sorted),
63 )
64 .with_prefix_sets_mut(input.prefix_sets)
65 .account_proof(address, slots)
66 }
67
68 fn overlay_multiproof(
69 &self,
70 input: TrieInput,
71 targets: MultiProofTargets,
72 ) -> Result<MultiProof, StateProofError> {
73 let nodes_sorted = input.nodes.into_sorted();
74 let state_sorted = input.state.into_sorted();
75 Proof::new(
76 InMemoryTrieCursorFactory::new(self.trie_cursor_factory().clone(), &nodes_sorted),
77 HashedPostStateCursorFactory::new(self.hashed_cursor_factory().clone(), &state_sorted),
78 )
79 .with_prefix_sets_mut(input.prefix_sets)
80 .multiproof(targets)
81 }
82
83 fn overlay_multiproof_v2(
84 &self,
85 input: TrieInput,
86 targets: MultiProofTargetsV2,
87 ) -> Result<DecodedMultiProofV2, StateProofError> {
88 let nodes_sorted = input.nodes.into_sorted();
89 let state_sorted = input.state.into_sorted();
90 Proof::new(
91 InMemoryTrieCursorFactory::new(self.trie_cursor_factory().clone(), &nodes_sorted),
92 HashedPostStateCursorFactory::new(self.hashed_cursor_factory().clone(), &state_sorted),
93 )
94 .with_prefix_sets_mut(input.prefix_sets)
95 .multiproof_v2(targets)
96 }
97}
98
99pub trait DatabaseStorageProof<'a, TX> {
101 fn from_tx(tx: &'a TX, address: Address) -> Self;
103
104 fn overlay_storage_proof(
106 tx: &'a TX,
107 address: Address,
108 slot: B256,
109 storage: HashedStorage,
110 ) -> Result<reth_trie::StorageProof, StateProofError>;
111
112 fn overlay_storage_multiproof(
114 tx: &'a TX,
115 address: Address,
116 slots: &[B256],
117 storage: HashedStorage,
118 ) -> Result<StorageMultiProof, StateProofError>;
119}
120
121impl<'a, TX: DbTx, A: TrieTableAdapter> DatabaseStorageProof<'a, TX>
122 for StorageProof<
123 'static,
124 DatabaseTrieCursorFactory<&'a TX, A>,
125 DatabaseHashedCursorFactory<&'a TX>,
126 >
127{
128 fn from_tx(tx: &'a TX, address: Address) -> Self {
129 Self::new(
130 DatabaseTrieCursorFactory::<_, A>::new(tx),
131 DatabaseHashedCursorFactory::new(tx),
132 address,
133 )
134 }
135
136 fn overlay_storage_proof(
137 tx: &'a TX,
138 address: Address,
139 slot: B256,
140 storage: HashedStorage,
141 ) -> Result<reth_trie::StorageProof, StateProofError> {
142 let hashed_address = keccak256(address);
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_proof(slot)
155 }
156
157 fn overlay_storage_multiproof(
158 tx: &'a TX,
159 address: Address,
160 slots: &[B256],
161 storage: HashedStorage,
162 ) -> Result<StorageMultiProof, StateProofError> {
163 let hashed_address = keccak256(address);
164 let targets = slots.iter().map(keccak256).collect();
165 let prefix_set = storage.construct_prefix_set();
166 let state_sorted = HashedPostStateSorted::new(
167 Default::default(),
168 HashMap::from_iter([(hashed_address, storage.into_sorted())]),
169 );
170 StorageProof::new(
171 DatabaseTrieCursorFactory::<_, A>::new(tx),
172 HashedPostStateCursorFactory::new(DatabaseHashedCursorFactory::new(tx), &state_sorted),
173 address,
174 )
175 .with_prefix_set_mut(prefix_set)
176 .storage_multiproof(targets)
177 }
178}