1use crate::{
2 provider::{TrieNodeProvider, TrieNodeProviderFactory},
3 traits::SparseTrieInterface,
4 SerialSparseTrie, SparseTrie,
5};
6use alloc::{collections::VecDeque, vec::Vec};
7use alloy_primitives::{
8 map::{B256Map, HashSet},
9 Bytes, B256,
10};
11use alloy_rlp::{Decodable, Encodable};
12use alloy_trie::proof::DecodedProofNodes;
13use reth_execution_errors::{SparseStateTrieErrorKind, SparseStateTrieResult, SparseTrieErrorKind};
14use reth_primitives_traits::Account;
15use reth_trie_common::{
16 proof::ProofNodes,
17 updates::{StorageTrieUpdates, TrieUpdates},
18 BranchNodeMasksMap, DecodedMultiProof, DecodedStorageMultiProof, MultiProof, Nibbles,
19 ProofTrieNode, RlpNode, StorageMultiProof, TrieAccount, TrieMasks, TrieNode, EMPTY_ROOT_HASH,
20 TRIE_ACCOUNT_RLP_MAX_SIZE,
21};
22use tracing::{instrument, trace};
23
24#[derive(Debug)]
27pub struct ClearedSparseStateTrie<
28 A = SerialSparseTrie, S = SerialSparseTrie, >(SparseStateTrie<A, S>);
31
32impl<A, S> ClearedSparseStateTrie<A, S>
33where
34 A: SparseTrieInterface,
35 S: SparseTrieInterface,
36{
37 pub fn from_state_trie(mut trie: SparseStateTrie<A, S>) -> Self {
40 trie.state = trie.state.clear();
41 trie.revealed_account_paths.clear();
42 trie.storage.clear();
43 trie.account_rlp_buf.clear();
44 Self(trie)
45 }
46
47 pub fn shrink_to(&mut self, node_size: usize, value_size: usize) {
51 let storage_tries_count = self.0.storage.tries.len() + self.0.storage.cleared_tries.len();
53
54 let total_tries = 1 + storage_tries_count;
56
57 let node_size_per_trie = node_size / total_tries;
59 let value_size_per_trie = value_size / total_tries;
60
61 self.0.state.shrink_nodes_to(node_size_per_trie);
63 self.0.state.shrink_values_to(value_size_per_trie);
64
65 let storage_node_size = node_size.saturating_sub(node_size_per_trie);
67 let storage_value_size = value_size.saturating_sub(value_size_per_trie);
68
69 self.0.storage.shrink_to(storage_node_size, storage_value_size);
71 }
72
73 pub fn into_inner(self) -> SparseStateTrie<A, S> {
75 self.0
76 }
77}
78
79#[derive(Debug)]
80pub struct SparseStateTrie<
82 A = SerialSparseTrie, S = SerialSparseTrie, > {
85 state: SparseTrie<A>,
87 revealed_account_paths: HashSet<Nibbles>,
89 storage: StorageTries<S>,
91 retain_updates: bool,
93 account_rlp_buf: Vec<u8>,
95 #[cfg(feature = "metrics")]
97 metrics: crate::metrics::SparseStateTrieMetrics,
98}
99
100impl<A, S> Default for SparseStateTrie<A, S>
101where
102 A: Default,
103 S: Default,
104{
105 fn default() -> Self {
106 Self {
107 state: Default::default(),
108 revealed_account_paths: Default::default(),
109 storage: Default::default(),
110 retain_updates: false,
111 account_rlp_buf: Vec::with_capacity(TRIE_ACCOUNT_RLP_MAX_SIZE),
112 #[cfg(feature = "metrics")]
113 metrics: Default::default(),
114 }
115 }
116}
117
118#[cfg(test)]
119impl SparseStateTrie {
120 pub fn from_state(state: SparseTrie) -> Self {
122 Self { state, ..Default::default() }
123 }
124}
125
126impl<A, S> SparseStateTrie<A, S> {
127 pub const fn with_updates(mut self, retain_updates: bool) -> Self {
129 self.retain_updates = retain_updates;
130 self
131 }
132
133 pub fn with_accounts_trie(mut self, trie: SparseTrie<A>) -> Self {
135 self.state = trie;
136 self
137 }
138
139 pub fn with_default_storage_trie(mut self, trie: SparseTrie<S>) -> Self {
141 self.storage.default_trie = trie;
142 self
143 }
144}
145
146impl<A, S> SparseStateTrie<A, S>
147where
148 A: SparseTrieInterface + Default,
149 S: SparseTrieInterface + Default + Clone,
150{
151 pub fn new() -> Self {
153 Self::default()
154 }
155
156 pub fn is_account_revealed(&self, account: B256) -> bool {
158 self.revealed_account_paths.contains(&Nibbles::unpack(account))
159 }
160
161 pub fn check_valid_account_witness(&self, address: B256) -> bool {
163 let path = Nibbles::unpack(address);
164 let trie = match self.state_trie_ref() {
165 Some(t) => t,
166 None => return false,
167 };
168
169 trie.find_leaf(&path, None).is_ok()
170 }
171
172 pub fn check_valid_storage_witness(&self, address: B256, slot: B256) -> bool {
174 let path = Nibbles::unpack(slot);
175 let trie = match self.storage_trie_ref(&address) {
176 Some(t) => t,
177 None => return false,
178 };
179
180 trie.find_leaf(&path, None).is_ok()
181 }
182
183 pub fn is_storage_slot_revealed(&self, account: B256, slot: B256) -> bool {
185 self.storage
186 .revealed_paths
187 .get(&account)
188 .is_some_and(|slots| slots.contains(&Nibbles::unpack(slot)))
189 }
190
191 pub fn get_account_value(&self, account: &B256) -> Option<&Vec<u8>> {
193 self.state.as_revealed_ref()?.get_leaf_value(&Nibbles::unpack(account))
194 }
195
196 pub fn get_storage_slot_value(&self, account: &B256, slot: &B256) -> Option<&Vec<u8>> {
198 self.storage.tries.get(account)?.as_revealed_ref()?.get_leaf_value(&Nibbles::unpack(slot))
199 }
200
201 pub const fn state_trie_ref(&self) -> Option<&A> {
203 self.state.as_revealed_ref()
204 }
205
206 pub fn storage_trie_ref(&self, address: &B256) -> Option<&S> {
208 self.storage.tries.get(address).and_then(|e| e.as_revealed_ref())
209 }
210
211 pub fn storage_trie_mut(&mut self, address: &B256) -> Option<&mut S> {
213 self.storage.tries.get_mut(address).and_then(|e| e.as_revealed_mut())
214 }
215
216 pub fn take_storage_trie(&mut self, address: &B256) -> Option<SparseTrie<S>> {
218 self.storage.tries.remove(address)
219 }
220
221 pub fn insert_storage_trie(&mut self, address: B256, storage_trie: SparseTrie<S>) {
223 self.storage.tries.insert(address, storage_trie);
224 }
225
226 pub fn reveal_multiproof(&mut self, multiproof: MultiProof) -> SparseStateTrieResult<()> {
229 let decoded_multiproof = multiproof.try_into()?;
231
232 self.reveal_decoded_multiproof(decoded_multiproof)
234 }
235
236 #[instrument(
239 target = "trie::sparse",
240 skip_all,
241 fields(
242 account_nodes = multiproof.account_subtree.len(),
243 storages = multiproof.storages.len()
244 )
245 )]
246 pub fn reveal_decoded_multiproof(
247 &mut self,
248 multiproof: DecodedMultiProof,
249 ) -> SparseStateTrieResult<()> {
250 let DecodedMultiProof { account_subtree, storages, branch_node_masks } = multiproof;
251
252 self.reveal_decoded_account_multiproof(account_subtree, branch_node_masks)?;
254
255 #[cfg(not(feature = "std"))]
256 {
258 for (account, storage_subtree) in storages {
259 self.reveal_decoded_storage_multiproof(account, storage_subtree)?;
260 }
261
262 Ok(())
263 }
264
265 #[cfg(feature = "std")]
266 {
268 use rayon::iter::{ParallelBridge, ParallelIterator};
269
270 let retain_updates = self.retain_updates;
271
272 let results: Vec<_> = storages
276 .into_iter()
277 .map(|(account, storage_subtree)| {
278 let revealed_nodes = self.storage.take_or_create_revealed_paths(&account);
279 let trie = self.storage.take_or_create_trie(&account);
280 (account, storage_subtree, revealed_nodes, trie)
281 })
282 .par_bridge()
283 .map(|(account, storage_subtree, mut revealed_nodes, mut trie)| {
284 let result = Self::reveal_decoded_storage_multiproof_inner(
285 account,
286 storage_subtree,
287 &mut revealed_nodes,
288 &mut trie,
289 retain_updates,
290 );
291
292 (account, revealed_nodes, trie, result)
293 })
294 .collect();
295
296 let mut any_err = Ok(());
299 for (account, revealed_nodes, trie, result) in results {
300 self.storage.revealed_paths.insert(account, revealed_nodes);
301 self.storage.tries.insert(account, trie);
302 if let Ok(_metric_values) = result {
303 #[cfg(feature = "metrics")]
304 {
305 self.metrics
306 .increment_total_storage_nodes(_metric_values.total_nodes as u64);
307 self.metrics
308 .increment_skipped_storage_nodes(_metric_values.skipped_nodes as u64);
309 }
310 } else {
311 any_err = result.map(|_| ());
312 }
313 }
314
315 any_err
316 }
317 }
318
319 pub fn reveal_account_multiproof(
321 &mut self,
322 account_subtree: ProofNodes,
323 branch_node_masks: BranchNodeMasksMap,
324 ) -> SparseStateTrieResult<()> {
325 let decoded_multiproof = account_subtree.try_into()?;
327 self.reveal_decoded_account_multiproof(decoded_multiproof, branch_node_masks)
328 }
329
330 pub fn reveal_decoded_account_multiproof(
332 &mut self,
333 account_subtree: DecodedProofNodes,
334 branch_node_masks: BranchNodeMasksMap,
335 ) -> SparseStateTrieResult<()> {
336 let FilterMappedProofNodes { root_node, nodes, new_nodes, metric_values: _metric_values } =
337 filter_map_revealed_nodes(
338 account_subtree,
339 &mut self.revealed_account_paths,
340 &branch_node_masks,
341 )?;
342 #[cfg(feature = "metrics")]
343 {
344 self.metrics.increment_total_account_nodes(_metric_values.total_nodes as u64);
345 self.metrics.increment_skipped_account_nodes(_metric_values.skipped_nodes as u64);
346 }
347
348 if let Some(root_node) = root_node {
349 trace!(target: "trie::sparse", ?root_node, "Revealing root account node");
351 let trie =
352 self.state.reveal_root(root_node.node, root_node.masks, self.retain_updates)?;
353
354 trie.reserve_nodes(new_nodes);
357
358 trace!(target: "trie::sparse", total_nodes = ?nodes.len(), "Revealing account nodes");
359 trie.reveal_nodes(nodes)?;
360 }
361
362 Ok(())
363 }
364
365 pub fn reveal_storage_multiproof(
367 &mut self,
368 account: B256,
369 storage_subtree: StorageMultiProof,
370 ) -> SparseStateTrieResult<()> {
371 let decoded_multiproof = storage_subtree.try_into()?;
373 self.reveal_decoded_storage_multiproof(account, decoded_multiproof)
374 }
375
376 pub fn reveal_decoded_storage_multiproof(
378 &mut self,
379 account: B256,
380 storage_subtree: DecodedStorageMultiProof,
381 ) -> SparseStateTrieResult<()> {
382 let (trie, revealed_paths) = self.storage.get_trie_and_revealed_paths_mut(account);
383 let _metric_values = Self::reveal_decoded_storage_multiproof_inner(
384 account,
385 storage_subtree,
386 revealed_paths,
387 trie,
388 self.retain_updates,
389 )?;
390
391 #[cfg(feature = "metrics")]
392 {
393 self.metrics.increment_total_storage_nodes(_metric_values.total_nodes as u64);
394 self.metrics.increment_skipped_storage_nodes(_metric_values.skipped_nodes as u64);
395 }
396
397 Ok(())
398 }
399
400 fn reveal_decoded_storage_multiproof_inner(
403 account: B256,
404 storage_subtree: DecodedStorageMultiProof,
405 revealed_nodes: &mut HashSet<Nibbles>,
406 trie: &mut SparseTrie<S>,
407 retain_updates: bool,
408 ) -> SparseStateTrieResult<ProofNodesMetricValues> {
409 let FilterMappedProofNodes { root_node, nodes, new_nodes, metric_values } =
410 filter_map_revealed_nodes(
411 storage_subtree.subtree,
412 revealed_nodes,
413 &storage_subtree.branch_node_masks,
414 )?;
415
416 if let Some(root_node) = root_node {
417 trace!(target: "trie::sparse", ?account, ?root_node, "Revealing root storage node");
419 let trie = trie.reveal_root(root_node.node, root_node.masks, retain_updates)?;
420
421 trie.reserve_nodes(new_nodes);
424
425 trace!(target: "trie::sparse", ?account, total_nodes = ?nodes.len(), "Revealing storage nodes");
426 trie.reveal_nodes(nodes)?;
427 }
428
429 Ok(metric_values)
430 }
431
432 pub fn reveal_witness(
436 &mut self,
437 state_root: B256,
438 witness: &B256Map<Bytes>,
439 ) -> SparseStateTrieResult<()> {
440 let mut queue = VecDeque::from([(state_root, Nibbles::default(), None)]);
443
444 while let Some((hash, path, maybe_account)) = queue.pop_front() {
445 let Some(trie_node_bytes) = witness.get(&hash) else { continue };
447 let trie_node = TrieNode::decode(&mut &trie_node_bytes[..])?;
448
449 match &trie_node {
451 TrieNode::Branch(branch) => {
452 for (idx, maybe_child) in branch.as_ref().children() {
453 if let Some(child_hash) = maybe_child.and_then(RlpNode::as_hash) {
454 let mut child_path = path;
455 child_path.push_unchecked(idx);
456 queue.push_back((child_hash, child_path, maybe_account));
457 }
458 }
459 }
460 TrieNode::Extension(ext) => {
461 if let Some(child_hash) = ext.child.as_hash() {
462 let mut child_path = path;
463 child_path.extend(&ext.key);
464 queue.push_back((child_hash, child_path, maybe_account));
465 }
466 }
467 TrieNode::Leaf(leaf) => {
468 let mut full_path = path;
469 full_path.extend(&leaf.key);
470 if maybe_account.is_none() {
471 let hashed_address = B256::from_slice(&full_path.pack());
472 let account = TrieAccount::decode(&mut &leaf.value[..])?;
473 if account.storage_root != EMPTY_ROOT_HASH {
474 queue.push_back((
475 account.storage_root,
476 Nibbles::default(),
477 Some(hashed_address),
478 ));
479 }
480 }
481 }
482 TrieNode::EmptyRoot => {} };
484
485 if let Some(account) = maybe_account {
487 if self
489 .storage
490 .revealed_paths
491 .get(&account)
492 .is_none_or(|paths| !paths.contains(&path))
493 {
494 let retain_updates = self.retain_updates;
495 let (storage_trie_entry, revealed_storage_paths) =
496 self.storage.get_trie_and_revealed_paths_mut(account);
497
498 if path.is_empty() {
499 storage_trie_entry.reveal_root(
501 trie_node,
502 TrieMasks::none(),
503 retain_updates,
504 )?;
505 } else {
506 storage_trie_entry
508 .as_revealed_mut()
509 .ok_or(SparseTrieErrorKind::Blind)?
510 .reveal_node(path, trie_node, TrieMasks::none())?;
511 }
512
513 revealed_storage_paths.insert(path);
515 }
516 }
517 else if !self.revealed_account_paths.contains(&path) {
519 if path.is_empty() {
520 self.state.reveal_root(trie_node, TrieMasks::none(), self.retain_updates)?;
522 } else {
523 self.state.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?.reveal_node(
525 path,
526 trie_node,
527 TrieMasks::none(),
528 )?;
529 }
530
531 self.revealed_account_paths.insert(path);
533 }
534 }
535
536 Ok(())
537 }
538
539 pub fn wipe_storage(&mut self, address: B256) -> SparseStateTrieResult<()> {
541 if let Some(trie) = self.storage.tries.get_mut(&address) {
542 trie.wipe()?;
543 }
544 Ok(())
545 }
546
547 #[instrument(target = "trie::sparse", skip_all)]
551 pub fn calculate_subtries(&mut self) {
552 if let SparseTrie::Revealed(trie) = &mut self.state {
553 trie.update_subtrie_hashes();
554 }
555 }
556
557 pub fn storage_root(&mut self, account: B256) -> Option<B256> {
559 self.storage.tries.get_mut(&account).and_then(|trie| trie.root())
560 }
561
562 fn revealed_trie_mut(
566 &mut self,
567 provider_factory: impl TrieNodeProviderFactory,
568 ) -> SparseStateTrieResult<&mut A> {
569 match self.state {
570 SparseTrie::Blind(_) => {
571 let (root_node, hash_mask, tree_mask) = provider_factory
572 .account_node_provider()
573 .trie_node(&Nibbles::default())?
574 .map(|node| {
575 TrieNode::decode(&mut &node.node[..])
576 .map(|decoded| (decoded, node.hash_mask, node.tree_mask))
577 })
578 .transpose()?
579 .unwrap_or((TrieNode::EmptyRoot, None, None));
580 self.state
581 .reveal_root(root_node, TrieMasks { hash_mask, tree_mask }, self.retain_updates)
582 .map_err(Into::into)
583 }
584 SparseTrie::Revealed(ref mut trie) => Ok(trie),
585 }
586 }
587
588 pub fn root(
592 &mut self,
593 provider_factory: impl TrieNodeProviderFactory,
594 ) -> SparseStateTrieResult<B256> {
595 #[cfg(feature = "metrics")]
597 self.metrics.record();
598
599 Ok(self.revealed_trie_mut(provider_factory)?.root())
600 }
601
602 #[instrument(target = "trie::sparse", skip_all)]
604 pub fn root_with_updates(
605 &mut self,
606 provider_factory: impl TrieNodeProviderFactory,
607 ) -> SparseStateTrieResult<(B256, TrieUpdates)> {
608 #[cfg(feature = "metrics")]
610 self.metrics.record();
611
612 let storage_tries = self.storage_trie_updates();
613 let revealed = self.revealed_trie_mut(provider_factory)?;
614
615 let (root, updates) = (revealed.root(), revealed.take_updates());
616 let updates = TrieUpdates {
617 account_nodes: updates.updated_nodes,
618 removed_nodes: updates.removed_nodes,
619 storage_tries,
620 };
621 Ok((root, updates))
622 }
623
624 pub fn storage_trie_updates(&mut self) -> B256Map<StorageTrieUpdates> {
628 self.storage
629 .tries
630 .iter_mut()
631 .map(|(address, trie)| {
632 let trie = trie.as_revealed_mut().unwrap();
633 let updates = trie.take_updates();
634 let updates = StorageTrieUpdates {
635 is_deleted: updates.wiped,
636 storage_nodes: updates.updated_nodes,
637 removed_nodes: updates.removed_nodes,
638 };
639 (*address, updates)
640 })
641 .filter(|(_, updates)| !updates.is_empty())
642 .collect()
643 }
644
645 pub fn take_trie_updates(&mut self) -> Option<TrieUpdates> {
649 let storage_tries = self.storage_trie_updates();
650 self.state.as_revealed_mut().map(|state| {
651 let updates = state.take_updates();
652 TrieUpdates {
653 account_nodes: updates.updated_nodes,
654 removed_nodes: updates.removed_nodes,
655 storage_tries,
656 }
657 })
658 }
659
660 pub fn update_account_leaf(
662 &mut self,
663 path: Nibbles,
664 value: Vec<u8>,
665 provider_factory: impl TrieNodeProviderFactory,
666 ) -> SparseStateTrieResult<()> {
667 if !self.revealed_account_paths.contains(&path) {
668 self.revealed_account_paths.insert(path);
669 }
670
671 let provider = provider_factory.account_node_provider();
672 self.state.update_leaf(path, value, provider)?;
673 Ok(())
674 }
675
676 pub fn update_storage_leaf(
678 &mut self,
679 address: B256,
680 slot: Nibbles,
681 value: Vec<u8>,
682 provider_factory: impl TrieNodeProviderFactory,
683 ) -> SparseStateTrieResult<()> {
684 let provider = provider_factory.storage_node_provider(address);
685 self.storage
686 .tries
687 .get_mut(&address)
688 .ok_or(SparseTrieErrorKind::Blind)?
689 .update_leaf(slot, value, provider)?;
690 self.storage.get_revealed_paths_mut(address).insert(slot);
691 Ok(())
692 }
693
694 #[instrument(level = "trace", target = "trie::sparse", skip_all)]
700 pub fn update_account(
701 &mut self,
702 address: B256,
703 account: Account,
704 provider_factory: impl TrieNodeProviderFactory,
705 ) -> SparseStateTrieResult<bool> {
706 let storage_root = if let Some(storage_trie) = self.storage.tries.get_mut(&address) {
707 trace!(target: "trie::sparse", ?address, "Calculating storage root to update account");
708 storage_trie.root().ok_or(SparseTrieErrorKind::Blind)?
709 } else if self.is_account_revealed(address) {
710 trace!(target: "trie::sparse", ?address, "Retrieving storage root from account leaf to update account");
711 if let Some(value) = self.get_account_value(&address) {
713 TrieAccount::decode(&mut &value[..])?.storage_root
715 } else {
716 EMPTY_ROOT_HASH
718 }
719 } else {
720 return Err(SparseTrieErrorKind::Blind.into())
721 };
722
723 if account.is_empty() && storage_root == EMPTY_ROOT_HASH {
724 return Ok(false);
725 }
726
727 trace!(target: "trie::sparse", ?address, "Updating account");
728 let nibbles = Nibbles::unpack(address);
729 self.account_rlp_buf.clear();
730 account.into_trie_account(storage_root).encode(&mut self.account_rlp_buf);
731 self.update_account_leaf(nibbles, self.account_rlp_buf.clone(), provider_factory)?;
732
733 Ok(true)
734 }
735
736 #[instrument(target = "trie::sparse", skip_all)]
743 pub fn update_account_storage_root(
744 &mut self,
745 address: B256,
746 provider_factory: impl TrieNodeProviderFactory,
747 ) -> SparseStateTrieResult<bool> {
748 if !self.is_account_revealed(address) {
749 return Err(SparseTrieErrorKind::Blind.into())
750 }
751
752 let Some(mut trie_account) = self
754 .get_account_value(&address)
755 .map(|v| TrieAccount::decode(&mut &v[..]))
756 .transpose()?
757 else {
758 trace!(target: "trie::sparse", ?address, "Account not found in trie, skipping storage root update");
759 return Ok(true)
760 };
761
762 let storage_root = if let Some(storage_trie) = self.storage.tries.get_mut(&address) {
765 trace!(target: "trie::sparse", ?address, "Calculating storage root to update account");
766 storage_trie.root().ok_or(SparseTrieErrorKind::Blind)?
767 } else {
768 EMPTY_ROOT_HASH
769 };
770
771 trie_account.storage_root = storage_root;
773
774 if trie_account == TrieAccount::default() {
776 return Ok(false)
777 }
778
779 trace!(target: "trie::sparse", ?address, "Updating account with the new storage root");
781 let nibbles = Nibbles::unpack(address);
782 self.account_rlp_buf.clear();
783 trie_account.encode(&mut self.account_rlp_buf);
784 self.update_account_leaf(nibbles, self.account_rlp_buf.clone(), provider_factory)?;
785
786 Ok(true)
787 }
788
789 #[instrument(target = "trie::sparse", skip_all)]
791 pub fn remove_account_leaf(
792 &mut self,
793 path: &Nibbles,
794 provider_factory: impl TrieNodeProviderFactory,
795 ) -> SparseStateTrieResult<()> {
796 let provider = provider_factory.account_node_provider();
797 self.state.remove_leaf(path, provider)?;
798 Ok(())
799 }
800
801 pub fn remove_storage_leaf(
803 &mut self,
804 address: B256,
805 slot: &Nibbles,
806 provider_factory: impl TrieNodeProviderFactory,
807 ) -> SparseStateTrieResult<()> {
808 let storage_trie =
809 self.storage.tries.get_mut(&address).ok_or(SparseTrieErrorKind::Blind)?;
810
811 let provider = provider_factory.storage_node_provider(address);
812 storage_trie.remove_leaf(slot, provider)?;
813 Ok(())
814 }
815}
816
817#[derive(Debug, Default)]
821struct StorageTries<S = SerialSparseTrie> {
822 tries: B256Map<SparseTrie<S>>,
824 cleared_tries: Vec<SparseTrie<S>>,
826 revealed_paths: B256Map<HashSet<Nibbles>>,
828 cleared_revealed_paths: Vec<HashSet<Nibbles>>,
830 default_trie: SparseTrie<S>,
832}
833
834impl<S: SparseTrieInterface> StorageTries<S> {
835 fn clear(&mut self) {
838 self.cleared_tries.extend(self.tries.drain().map(|(_, trie)| trie.clear()));
839 self.cleared_revealed_paths.extend(self.revealed_paths.drain().map(|(_, mut set)| {
840 set.clear();
841 set
842 }));
843 }
844
845 fn shrink_to(&mut self, node_size: usize, value_size: usize) {
848 let active_count = self.tries.len();
850 let cleared_count = self.cleared_tries.len();
851 let total_tries = 1 + active_count + cleared_count;
852
853 let node_size_per_trie = node_size / total_tries;
855 let value_size_per_trie = value_size / total_tries;
856
857 for trie in self.tries.values_mut() {
859 trie.shrink_nodes_to(node_size_per_trie);
860 trie.shrink_values_to(value_size_per_trie);
861 }
862
863 for trie in &mut self.cleared_tries {
865 trie.shrink_nodes_to(node_size_per_trie);
866 trie.shrink_values_to(value_size_per_trie);
867 }
868 }
869}
870
871impl<S: SparseTrieInterface + Clone> StorageTries<S> {
872 fn get_revealed_paths_mut(&mut self, account: B256) -> &mut HashSet<Nibbles> {
875 self.revealed_paths
876 .entry(account)
877 .or_insert_with(|| self.cleared_revealed_paths.pop().unwrap_or_default())
878 }
879
880 fn get_trie_and_revealed_paths_mut(
883 &mut self,
884 account: B256,
885 ) -> (&mut SparseTrie<S>, &mut HashSet<Nibbles>) {
886 let trie = self.tries.entry(account).or_insert_with(|| {
887 self.cleared_tries.pop().unwrap_or_else(|| self.default_trie.clone())
888 });
889
890 let revealed_paths = self
891 .revealed_paths
892 .entry(account)
893 .or_insert_with(|| self.cleared_revealed_paths.pop().unwrap_or_default());
894
895 (trie, revealed_paths)
896 }
897
898 #[cfg(feature = "std")]
901 fn take_or_create_trie(&mut self, account: &B256) -> SparseTrie<S> {
902 self.tries.remove(account).unwrap_or_else(|| {
903 self.cleared_tries.pop().unwrap_or_else(|| self.default_trie.clone())
904 })
905 }
906
907 #[cfg(feature = "std")]
910 fn take_or_create_revealed_paths(&mut self, account: &B256) -> HashSet<Nibbles> {
911 self.revealed_paths
912 .remove(account)
913 .unwrap_or_else(|| self.cleared_revealed_paths.pop().unwrap_or_default())
914 }
915}
916
917#[derive(Debug, PartialEq, Eq, Default)]
918struct ProofNodesMetricValues {
919 total_nodes: usize,
921 skipped_nodes: usize,
923}
924
925#[derive(Debug, PartialEq, Eq)]
927struct FilterMappedProofNodes {
928 root_node: Option<ProofTrieNode>,
930 nodes: Vec<ProofTrieNode>,
932 new_nodes: usize,
935 metric_values: ProofNodesMetricValues,
937}
938
939fn filter_map_revealed_nodes(
943 proof_nodes: DecodedProofNodes,
944 revealed_nodes: &mut HashSet<Nibbles>,
945 branch_node_masks: &BranchNodeMasksMap,
946) -> SparseStateTrieResult<FilterMappedProofNodes> {
947 let mut result = FilterMappedProofNodes {
948 root_node: None,
949 nodes: Vec::with_capacity(proof_nodes.len()),
950 new_nodes: 0,
951 metric_values: Default::default(),
952 };
953
954 let proof_nodes_len = proof_nodes.len();
955 for (path, proof_node) in proof_nodes.into_inner() {
956 result.metric_values.total_nodes += 1;
957
958 let is_root = path.is_empty();
959
960 if !is_root && !revealed_nodes.insert(path) {
963 result.metric_values.skipped_nodes += 1;
964 continue
965 }
966
967 result.new_nodes += 1;
968
969 let masks = match &proof_node {
972 TrieNode::Branch(branch) => {
973 result.new_nodes += branch.state_mask.count_ones() as usize;
976 if let Some(branch_masks) = branch_node_masks.get(&path) {
977 TrieMasks {
978 hash_mask: Some(branch_masks.hash_mask),
979 tree_mask: Some(branch_masks.tree_mask),
980 }
981 } else {
982 TrieMasks::none()
983 }
984 }
985 TrieNode::Extension(_) => {
986 result.new_nodes += 1;
988 TrieMasks::none()
989 }
990 _ => TrieMasks::none(),
991 };
992
993 let node = ProofTrieNode { path, node: proof_node, masks };
994
995 if is_root {
996 if matches!(node.node, TrieNode::EmptyRoot) && proof_nodes_len > 1 {
998 return Err(SparseStateTrieErrorKind::InvalidRootNode {
999 path,
1000 node: alloy_rlp::encode(&node.node).into(),
1001 }
1002 .into())
1003 }
1004
1005 result.root_node = Some(node);
1006
1007 continue
1008 }
1009
1010 result.nodes.push(node);
1011 }
1012
1013 Ok(result)
1014}
1015
1016#[cfg(test)]
1017mod tests {
1018 use super::*;
1019 use crate::provider::DefaultTrieNodeProviderFactory;
1020 use alloy_primitives::{
1021 b256,
1022 map::{HashMap, HashSet},
1023 U256,
1024 };
1025 use arbitrary::Arbitrary;
1026 use rand::{rngs::StdRng, Rng, SeedableRng};
1027 use reth_primitives_traits::Account;
1028 use reth_trie::{updates::StorageTrieUpdates, HashBuilder, MultiProof, EMPTY_ROOT_HASH};
1029 use reth_trie_common::{
1030 proof::{ProofNodes, ProofRetainer},
1031 BranchNode, BranchNodeMasks, LeafNode, StorageMultiProof, TrieMask,
1032 };
1033
1034 #[test]
1035 fn reveal_account_path_twice() {
1036 let provider_factory = DefaultTrieNodeProviderFactory;
1037 let mut sparse = SparseStateTrie::<SerialSparseTrie>::default();
1038
1039 let leaf_value = alloy_rlp::encode(TrieAccount::default());
1040 let leaf_1 = alloy_rlp::encode(TrieNode::Leaf(LeafNode::new(
1041 Nibbles::default(),
1042 leaf_value.clone(),
1043 )));
1044 let leaf_2 = alloy_rlp::encode(TrieNode::Leaf(LeafNode::new(
1045 Nibbles::default(),
1046 leaf_value.clone(),
1047 )));
1048
1049 let multiproof = MultiProof {
1050 account_subtree: ProofNodes::from_iter([
1051 (
1052 Nibbles::default(),
1053 alloy_rlp::encode(TrieNode::Branch(BranchNode {
1054 stack: vec![RlpNode::from_rlp(&leaf_1), RlpNode::from_rlp(&leaf_2)],
1055 state_mask: TrieMask::new(0b11),
1056 }))
1057 .into(),
1058 ),
1059 (Nibbles::from_nibbles([0x0]), leaf_1.clone().into()),
1060 (Nibbles::from_nibbles([0x1]), leaf_1.clone().into()),
1061 ]),
1062 ..Default::default()
1063 };
1064
1065 sparse.reveal_decoded_multiproof(multiproof.clone().try_into().unwrap()).unwrap();
1067 assert!(sparse
1068 .state_trie_ref()
1069 .unwrap()
1070 .nodes_ref()
1071 .contains_key(&Nibbles::from_nibbles([0x0])),);
1072 assert_eq!(
1073 sparse.state_trie_ref().unwrap().get_leaf_value(&Nibbles::from_nibbles([0x0])),
1074 Some(&leaf_value)
1075 );
1076
1077 sparse.remove_account_leaf(&Nibbles::from_nibbles([0x0]), &provider_factory).unwrap();
1080 assert!(!sparse
1081 .state_trie_ref()
1082 .unwrap()
1083 .nodes_ref()
1084 .contains_key(&Nibbles::from_nibbles([0x0])),);
1085 assert!(sparse
1086 .state_trie_ref()
1087 .unwrap()
1088 .get_leaf_value(&Nibbles::from_nibbles([0x0]))
1089 .is_none());
1090
1091 sparse.reveal_decoded_multiproof(multiproof.try_into().unwrap()).unwrap();
1094 assert!(!sparse
1095 .state_trie_ref()
1096 .unwrap()
1097 .nodes_ref()
1098 .contains_key(&Nibbles::from_nibbles([0x0])));
1099 assert!(sparse
1100 .state_trie_ref()
1101 .unwrap()
1102 .get_leaf_value(&Nibbles::from_nibbles([0x0]))
1103 .is_none());
1104 }
1105
1106 #[test]
1107 fn reveal_storage_path_twice() {
1108 let provider_factory = DefaultTrieNodeProviderFactory;
1109 let mut sparse = SparseStateTrie::<SerialSparseTrie>::default();
1110
1111 let leaf_value = alloy_rlp::encode(TrieAccount::default());
1112 let leaf_1 = alloy_rlp::encode(TrieNode::Leaf(LeafNode::new(
1113 Nibbles::default(),
1114 leaf_value.clone(),
1115 )));
1116 let leaf_2 = alloy_rlp::encode(TrieNode::Leaf(LeafNode::new(
1117 Nibbles::default(),
1118 leaf_value.clone(),
1119 )));
1120
1121 let multiproof = MultiProof {
1122 storages: HashMap::from_iter([(
1123 B256::ZERO,
1124 StorageMultiProof {
1125 root: B256::ZERO,
1126 subtree: ProofNodes::from_iter([
1127 (
1128 Nibbles::default(),
1129 alloy_rlp::encode(TrieNode::Branch(BranchNode {
1130 stack: vec![RlpNode::from_rlp(&leaf_1), RlpNode::from_rlp(&leaf_2)],
1131 state_mask: TrieMask::new(0b11),
1132 }))
1133 .into(),
1134 ),
1135 (Nibbles::from_nibbles([0x0]), leaf_1.clone().into()),
1136 (Nibbles::from_nibbles([0x1]), leaf_1.clone().into()),
1137 ]),
1138 branch_node_masks: Default::default(),
1139 },
1140 )]),
1141 ..Default::default()
1142 };
1143
1144 sparse.reveal_decoded_multiproof(multiproof.clone().try_into().unwrap()).unwrap();
1146 assert!(sparse
1147 .storage_trie_ref(&B256::ZERO)
1148 .unwrap()
1149 .nodes_ref()
1150 .contains_key(&Nibbles::from_nibbles([0x0])),);
1151 assert_eq!(
1152 sparse
1153 .storage_trie_ref(&B256::ZERO)
1154 .unwrap()
1155 .get_leaf_value(&Nibbles::from_nibbles([0x0])),
1156 Some(&leaf_value)
1157 );
1158
1159 sparse
1162 .remove_storage_leaf(B256::ZERO, &Nibbles::from_nibbles([0x0]), &provider_factory)
1163 .unwrap();
1164 assert!(!sparse
1165 .storage_trie_ref(&B256::ZERO)
1166 .unwrap()
1167 .nodes_ref()
1168 .contains_key(&Nibbles::from_nibbles([0x0])),);
1169 assert!(sparse
1170 .storage_trie_ref(&B256::ZERO)
1171 .unwrap()
1172 .get_leaf_value(&Nibbles::from_nibbles([0x0]))
1173 .is_none());
1174
1175 sparse.reveal_decoded_multiproof(multiproof.try_into().unwrap()).unwrap();
1178 assert!(!sparse
1179 .storage_trie_ref(&B256::ZERO)
1180 .unwrap()
1181 .nodes_ref()
1182 .contains_key(&Nibbles::from_nibbles([0x0])));
1183 assert!(sparse
1184 .storage_trie_ref(&B256::ZERO)
1185 .unwrap()
1186 .get_leaf_value(&Nibbles::from_nibbles([0x0]))
1187 .is_none());
1188 }
1189
1190 #[test]
1191 fn take_trie_updates() {
1192 reth_tracing::init_test_tracing();
1193
1194 let mut rng = StdRng::seed_from_u64(1);
1196
1197 let mut bytes = [0u8; 1024];
1198 rng.fill(bytes.as_mut_slice());
1199
1200 let slot_1 = b256!("0x1000000000000000000000000000000000000000000000000000000000000000");
1201 let slot_path_1 = Nibbles::unpack(slot_1);
1202 let value_1 = U256::from(rng.random::<u64>());
1203 let slot_2 = b256!("0x1100000000000000000000000000000000000000000000000000000000000000");
1204 let slot_path_2 = Nibbles::unpack(slot_2);
1205 let value_2 = U256::from(rng.random::<u64>());
1206 let slot_3 = b256!("0x2000000000000000000000000000000000000000000000000000000000000000");
1207 let slot_path_3 = Nibbles::unpack(slot_3);
1208 let value_3 = U256::from(rng.random::<u64>());
1209
1210 let mut storage_hash_builder = HashBuilder::default()
1211 .with_proof_retainer(ProofRetainer::from_iter([slot_path_1, slot_path_2]));
1212 storage_hash_builder.add_leaf(slot_path_1, &alloy_rlp::encode_fixed_size(&value_1));
1213 storage_hash_builder.add_leaf(slot_path_2, &alloy_rlp::encode_fixed_size(&value_2));
1214
1215 let storage_root = storage_hash_builder.root();
1216 let storage_proof_nodes = storage_hash_builder.take_proof_nodes();
1217 let storage_branch_node_masks = BranchNodeMasksMap::from_iter([
1218 (
1219 Nibbles::default(),
1220 BranchNodeMasks { hash_mask: TrieMask::new(0b010), tree_mask: TrieMask::default() },
1221 ),
1222 (
1223 Nibbles::from_nibbles([0x1]),
1224 BranchNodeMasks { hash_mask: TrieMask::new(0b11), tree_mask: TrieMask::default() },
1225 ),
1226 ]);
1227
1228 let address_1 = b256!("0x1000000000000000000000000000000000000000000000000000000000000000");
1229 let address_path_1 = Nibbles::unpack(address_1);
1230 let account_1 = Account::arbitrary(&mut arbitrary::Unstructured::new(&bytes)).unwrap();
1231 let mut trie_account_1 = account_1.into_trie_account(storage_root);
1232 let address_2 = b256!("0x1100000000000000000000000000000000000000000000000000000000000000");
1233 let address_path_2 = Nibbles::unpack(address_2);
1234 let account_2 = Account::arbitrary(&mut arbitrary::Unstructured::new(&bytes)).unwrap();
1235 let mut trie_account_2 = account_2.into_trie_account(EMPTY_ROOT_HASH);
1236
1237 let mut hash_builder = HashBuilder::default()
1238 .with_proof_retainer(ProofRetainer::from_iter([address_path_1, address_path_2]));
1239 hash_builder.add_leaf(address_path_1, &alloy_rlp::encode(trie_account_1));
1240 hash_builder.add_leaf(address_path_2, &alloy_rlp::encode(trie_account_2));
1241
1242 let root = hash_builder.root();
1243 let proof_nodes = hash_builder.take_proof_nodes();
1244
1245 let provider_factory = DefaultTrieNodeProviderFactory;
1246 let mut sparse = SparseStateTrie::<SerialSparseTrie>::default().with_updates(true);
1247 sparse
1248 .reveal_decoded_multiproof(
1249 MultiProof {
1250 account_subtree: proof_nodes,
1251 branch_node_masks: BranchNodeMasksMap::from_iter([(
1252 Nibbles::from_nibbles([0x1]),
1253 BranchNodeMasks {
1254 hash_mask: TrieMask::new(0b00),
1255 tree_mask: TrieMask::default(),
1256 },
1257 )]),
1258 storages: HashMap::from_iter([
1259 (
1260 address_1,
1261 StorageMultiProof {
1262 root,
1263 subtree: storage_proof_nodes.clone(),
1264 branch_node_masks: storage_branch_node_masks.clone(),
1265 },
1266 ),
1267 (
1268 address_2,
1269 StorageMultiProof {
1270 root,
1271 subtree: storage_proof_nodes,
1272 branch_node_masks: storage_branch_node_masks,
1273 },
1274 ),
1275 ]),
1276 }
1277 .try_into()
1278 .unwrap(),
1279 )
1280 .unwrap();
1281
1282 assert_eq!(sparse.root(&provider_factory).unwrap(), root);
1283
1284 let address_3 = b256!("0x2000000000000000000000000000000000000000000000000000000000000000");
1285 let address_path_3 = Nibbles::unpack(address_3);
1286 let account_3 = Account { nonce: account_1.nonce + 1, ..account_1 };
1287 let trie_account_3 = account_3.into_trie_account(EMPTY_ROOT_HASH);
1288
1289 sparse
1290 .update_account_leaf(
1291 address_path_3,
1292 alloy_rlp::encode(trie_account_3),
1293 &provider_factory,
1294 )
1295 .unwrap();
1296
1297 sparse
1298 .update_storage_leaf(
1299 address_1,
1300 slot_path_3,
1301 alloy_rlp::encode(value_3),
1302 &provider_factory,
1303 )
1304 .unwrap();
1305 trie_account_1.storage_root = sparse.storage_root(address_1).unwrap();
1306 sparse
1307 .update_account_leaf(
1308 address_path_1,
1309 alloy_rlp::encode(trie_account_1),
1310 &provider_factory,
1311 )
1312 .unwrap();
1313
1314 sparse.wipe_storage(address_2).unwrap();
1315 trie_account_2.storage_root = sparse.storage_root(address_2).unwrap();
1316 sparse
1317 .update_account_leaf(
1318 address_path_2,
1319 alloy_rlp::encode(trie_account_2),
1320 &provider_factory,
1321 )
1322 .unwrap();
1323
1324 sparse.root(&provider_factory).unwrap();
1325
1326 let sparse_updates = sparse.take_trie_updates().unwrap();
1327 pretty_assertions::assert_eq!(
1329 sparse_updates,
1330 TrieUpdates {
1331 account_nodes: HashMap::default(),
1332 storage_tries: HashMap::from_iter([(
1333 b256!("0x1100000000000000000000000000000000000000000000000000000000000000"),
1334 StorageTrieUpdates {
1335 is_deleted: true,
1336 storage_nodes: HashMap::default(),
1337 removed_nodes: HashSet::default()
1338 }
1339 )]),
1340 removed_nodes: HashSet::default()
1341 }
1342 );
1343 }
1344
1345 #[test]
1346 fn test_filter_map_revealed_nodes() {
1347 let mut revealed_nodes = HashSet::from_iter([Nibbles::from_nibbles([0x0])]);
1348 let leaf = TrieNode::Leaf(LeafNode::new(Nibbles::default(), alloy_rlp::encode([])));
1349 let leaf_encoded = alloy_rlp::encode(&leaf);
1350 let branch = TrieNode::Branch(BranchNode::new(
1351 vec![RlpNode::from_rlp(&leaf_encoded), RlpNode::from_rlp(&leaf_encoded)],
1352 TrieMask::new(0b11),
1353 ));
1354 let proof_nodes = alloy_trie::proof::DecodedProofNodes::from_iter([
1355 (Nibbles::default(), branch.clone()),
1356 (Nibbles::from_nibbles([0x0]), leaf.clone()),
1357 (Nibbles::from_nibbles([0x1]), leaf.clone()),
1358 ]);
1359
1360 let branch_node_masks = BranchNodeMasksMap::default();
1361
1362 let decoded =
1363 filter_map_revealed_nodes(proof_nodes, &mut revealed_nodes, &branch_node_masks)
1364 .unwrap();
1365
1366 assert_eq!(
1367 decoded,
1368 FilterMappedProofNodes {
1369 root_node: Some(ProofTrieNode {
1370 path: Nibbles::default(),
1371 node: branch,
1372 masks: TrieMasks::none(),
1373 }),
1374 nodes: vec![ProofTrieNode {
1375 path: Nibbles::from_nibbles([0x1]),
1376 node: leaf,
1377 masks: TrieMasks::none(),
1378 }],
1379 new_nodes: 4,
1381 metric_values: ProofNodesMetricValues {
1383 total_nodes: 3,
1385 skipped_nodes: 1,
1387 },
1388 }
1389 );
1390 }
1391}