1use super::{DeferredValueEncoder, LeafValueEncoder, ProofCalculator, StorageProofCalculator};
4use crate::{
5 hashed_cursor::{HashedCursorFactory, HashedStorageCursor},
6 prefix_set::{PrefixSet, TriePrefixSets},
7 trie_cursor::{TrieCursorFactory, TrieStorageCursor},
8 DecodedMultiProofV2, MultiProofTargetsV2,
9};
10use alloy_primitives::{map::B256Map, B256, U256};
11use alloy_rlp::Encodable;
12use parking_lot::Mutex;
13use reth_execution_errors::StateProofError;
14use reth_primitives_traits::Account;
15use std::{fmt, marker::PhantomPinned, pin::Pin, sync::Arc};
16
17pub struct MultiProofCalculator<'a, T: TrieCursorFactory + 'a, H: HashedCursorFactory + 'a> {
27 account_calculator: Option<AccountCalculatorOf<'a, T, H>>,
28 storage_calculator: Option<Arc<Mutex<StorageCalculatorOf<'a, T, H>>>>,
29 prefix_sets: TriePrefixSets,
30 known_storage_roots: Arc<B256Map<B256>>,
31 factories: Pin<Box<MultiProofCalculatorFactories<T, H>>>,
33}
34
35impl<'a, T: TrieCursorFactory + 'a, H: HashedCursorFactory + 'a> MultiProofCalculator<'a, T, H> {
36 pub fn new(
45 trie_cursor_factory: T,
46 hashed_cursor_factory: H,
47 prefix_sets: TriePrefixSets,
48 known_storage_roots: Arc<B256Map<B256>>,
49 ) -> Self {
50 Self {
51 account_calculator: None,
52 storage_calculator: None,
53 prefix_sets,
54 known_storage_roots,
55 factories: Box::pin(MultiProofCalculatorFactories {
56 trie_cursor_factory,
57 hashed_cursor_factory,
58 _pin: PhantomPinned,
59 }),
60 }
61 }
62
63 pub fn multiproof(
68 &mut self,
69 targets: MultiProofTargetsV2,
70 ) -> Result<DecodedMultiProofV2, StateProofError> {
71 if targets.is_empty() {
72 return Ok(DecodedMultiProofV2::default())
73 }
74 let MultiProofTargetsV2 { mut account_targets, storage_targets } = targets;
75 let mut proof = DecodedMultiProofV2::default();
76
77 let storage_calculator = match &mut self.storage_calculator {
79 Some(storage_calculator) => storage_calculator,
80 slot @ None => {
81 let factories = unsafe { Self::borrow_factories(self.factories.as_ref()) };
83 let trie_cursor = factories.trie_cursor_factory.storage_trie_cursor(B256::ZERO)?;
85 let hashed_cursor =
86 factories.hashed_cursor_factory.hashed_storage_cursor(B256::ZERO)?;
87 let prefix_sets = std::mem::take(&mut self.prefix_sets.storage_prefix_sets);
90 slot.insert(Arc::new(Mutex::new(PrefixSetStorageCalculator {
91 calculator: StorageProofCalculator::new_storage(trie_cursor, hashed_cursor),
92 prefix_sets,
93 hashed_address: None,
94 })))
95 }
96 };
97
98 if !account_targets.is_empty() {
100 let account_calculator = match &mut self.account_calculator {
101 Some(account_calculator) => account_calculator,
102 slot @ None => {
103 let factories = unsafe { Self::borrow_factories(self.factories.as_ref()) };
105 let trie_cursor = factories.trie_cursor_factory.account_trie_cursor()?;
106 let hashed_cursor = factories.hashed_cursor_factory.hashed_account_cursor()?;
107 let prefix_set = std::mem::take(&mut self.prefix_sets.account_prefix_set);
108 slot.insert(
109 ProofCalculator::new(trie_cursor, hashed_cursor)
110 .with_prefix_set(prefix_set),
111 )
112 }
113 };
114 let mut encoder = AccountValueEncoder {
115 storage_calculator: storage_calculator.clone(),
116 known_storage_roots: self.known_storage_roots.clone(),
117 };
118 proof.account_proofs = account_calculator.proof(&mut encoder, &mut account_targets)?;
119 }
120
121 if !storage_targets.is_empty() {
123 let mut storage_calculator = storage_calculator.lock();
124 for (hashed_address, mut targets) in storage_targets {
125 let calculator = storage_calculator.calculator_for(hashed_address);
126 let nodes = if targets.is_empty() {
127 vec![calculator.storage_root_node(hashed_address)?]
128 } else {
129 calculator.storage_proof(hashed_address, &mut targets)?
130 };
131 proof.storage_proofs.insert(hashed_address, nodes);
132 }
133 }
134 Ok(proof)
135 }
136
137 const unsafe fn borrow_factories(
144 factories: Pin<&MultiProofCalculatorFactories<T, H>>,
145 ) -> &'a MultiProofCalculatorFactories<T, H> {
146 unsafe { &*(factories.get_ref() as *const MultiProofCalculatorFactories<T, H>) }
149 }
150}
151
152impl<'a, T: TrieCursorFactory + 'a, H: HashedCursorFactory + 'a> Drop
153 for MultiProofCalculator<'a, T, H>
154{
155 fn drop(&mut self) {
156 self.account_calculator = None;
158 self.storage_calculator = None;
159 }
160}
161
162impl<T: TrieCursorFactory, H: HashedCursorFactory> fmt::Debug for MultiProofCalculator<'_, T, H> {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 f.debug_struct("MultiProofCalculator")
165 .field("account_initialized", &self.account_calculator.is_some())
166 .field("storage_initialized", &self.storage_calculator.is_some())
167 .finish_non_exhaustive()
168 }
169}
170
171type AccountCalculatorOf<'a, T, H> = ProofCalculator<
173 <T as TrieCursorFactory>::AccountTrieCursor<'a>,
174 <H as HashedCursorFactory>::AccountCursor<'a>,
175 AccountValueEncoder<
176 <T as TrieCursorFactory>::StorageTrieCursor<'a>,
177 <H as HashedCursorFactory>::StorageCursor<'a>,
178 >,
179>;
180
181type StorageCalculatorOf<'a, T, H> = PrefixSetStorageCalculator<
183 <T as TrieCursorFactory>::StorageTrieCursor<'a>,
184 <H as HashedCursorFactory>::StorageCursor<'a>,
185>;
186
187struct MultiProofCalculatorFactories<T, H> {
189 trie_cursor_factory: T,
190 hashed_cursor_factory: H,
191 _pin: PhantomPinned,
192}
193
194struct PrefixSetStorageCalculator<TC, HC> {
199 calculator: StorageProofCalculator<TC, HC>,
200 prefix_sets: B256Map<PrefixSet>,
202 hashed_address: Option<B256>,
204}
205
206impl<TC: TrieStorageCursor, HC: HashedStorageCursor<Value = U256>>
207 PrefixSetStorageCalculator<TC, HC>
208{
209 fn calculator_for(&mut self, hashed_address: B256) -> &mut StorageProofCalculator<TC, HC> {
210 if self.hashed_address != Some(hashed_address) {
211 self.calculator
212 .set_prefix_set(self.prefix_sets.get(&hashed_address).cloned().unwrap_or_default());
213 self.hashed_address = Some(hashed_address);
214 }
215 &mut self.calculator
216 }
217}
218
219struct AccountValueEncoder<TC, HC> {
221 storage_calculator: Arc<Mutex<PrefixSetStorageCalculator<TC, HC>>>,
224 known_storage_roots: Arc<B256Map<B256>>,
225}
226
227impl<TC: TrieStorageCursor, HC: HashedStorageCursor<Value = U256>> LeafValueEncoder
228 for AccountValueEncoder<TC, HC>
229{
230 type Value = Account;
231 type DeferredEncoder = AccountDeferredValueEncoder<TC, HC>;
232
233 fn deferred_encoder(
234 &mut self,
235 hashed_address: B256,
236 account: Account,
237 ) -> Self::DeferredEncoder {
238 if let Some(root) = self.known_storage_roots.get(&hashed_address) {
239 AccountDeferredValueEncoder::Known { storage_root: *root, account }
240 } else {
241 AccountDeferredValueEncoder::Calculate {
242 storage_calculator: self.storage_calculator.clone(),
243 hashed_address,
244 account,
245 }
246 }
247 }
248}
249
250enum AccountDeferredValueEncoder<TC, HC> {
252 Known {
253 storage_root: B256,
254 account: Account,
255 },
256 Calculate {
257 storage_calculator: Arc<Mutex<PrefixSetStorageCalculator<TC, HC>>>,
258 hashed_address: B256,
259 account: Account,
260 },
261}
262
263impl<TC: TrieStorageCursor, HC: HashedStorageCursor<Value = U256>> DeferredValueEncoder
264 for AccountDeferredValueEncoder<TC, HC>
265{
266 fn encode(self, buf: &mut Vec<u8>) -> Result<(), StateProofError> {
267 let (account, root) = match self {
268 Self::Known { storage_root, account } => (account, storage_root),
269 Self::Calculate { storage_calculator, hashed_address, account } => {
270 let root = storage_calculator
271 .lock()
272 .calculator_for(hashed_address)
273 .storage_root(hashed_address)?;
274 (account, root)
275 }
276 };
277 account.into_trie_account(root).encode(buf);
278 Ok(())
279 }
280}