1use crate::LowerSparseSubtrie;
2use alloc::borrow::Cow;
3use alloy_primitives::{
4 map::{Entry, HashMap},
5 B256,
6};
7use alloy_rlp::Decodable;
8use alloy_trie::{BranchNodeCompact, TrieMask, EMPTY_ROOT_HASH};
9use reth_execution_errors::{SparseTrieErrorKind, SparseTrieResult};
10use reth_trie_common::{
11 prefix_set::{PrefixSet, PrefixSetMut},
12 BranchNodeRef, ExtensionNodeRef, LeafNodeRef, Nibbles, ProofTrieNode, RlpNode, TrieMasks,
13 TrieNode, CHILD_INDEX_RANGE,
14};
15use reth_trie_sparse::{
16 provider::{RevealedNode, TrieNodeProvider},
17 LeafLookup, LeafLookupError, RlpNodeStackItem, SparseNode, SparseNodeType, SparseTrieInterface,
18 SparseTrieUpdates,
19};
20use smallvec::SmallVec;
21use std::{
22 cmp::{Ord, Ordering, PartialOrd},
23 sync::mpsc,
24};
25use tracing::{debug, instrument, trace};
26
27pub const UPPER_TRIE_MAX_DEPTH: usize = 2;
30
31pub const NUM_LOWER_SUBTRIES: usize = 16usize.pow(UPPER_TRIE_MAX_DEPTH as u32);
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
36pub struct ParallelismThresholds {
37 pub min_revealed_nodes: usize,
40 pub min_updated_nodes: usize,
44}
45
46#[derive(Clone, PartialEq, Eq, Debug)]
108pub struct ParallelSparseTrie {
109 upper_subtrie: Box<SparseSubtrie>,
111 lower_subtries: [LowerSparseSubtrie; NUM_LOWER_SUBTRIES],
113 prefix_set: PrefixSetMut,
116 updates: Option<SparseTrieUpdates>,
118 branch_node_tree_masks: HashMap<Nibbles, TrieMask>,
120 branch_node_hash_masks: HashMap<Nibbles, TrieMask>,
122 update_actions_buffers: Vec<Vec<SparseTrieUpdatesAction>>,
125 parallelism_thresholds: ParallelismThresholds,
127 #[cfg(feature = "metrics")]
129 metrics: crate::metrics::ParallelSparseTrieMetrics,
130}
131
132impl Default for ParallelSparseTrie {
133 fn default() -> Self {
134 Self {
135 upper_subtrie: Box::new(SparseSubtrie {
136 nodes: HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]),
137 ..Default::default()
138 }),
139 lower_subtries: [const { LowerSparseSubtrie::Blind(None) }; NUM_LOWER_SUBTRIES],
140 prefix_set: PrefixSetMut::default(),
141 updates: None,
142 branch_node_tree_masks: HashMap::default(),
143 branch_node_hash_masks: HashMap::default(),
144 update_actions_buffers: Vec::default(),
145 parallelism_thresholds: Default::default(),
146 #[cfg(feature = "metrics")]
147 metrics: Default::default(),
148 }
149 }
150}
151
152impl SparseTrieInterface for ParallelSparseTrie {
153 fn with_root(
154 mut self,
155 root: TrieNode,
156 masks: TrieMasks,
157 retain_updates: bool,
158 ) -> SparseTrieResult<Self> {
159 let path = Nibbles::default();
162 let _removed_root = self.upper_subtrie.nodes.remove(&path).expect("root node should exist");
163 debug_assert_eq!(_removed_root, SparseNode::Empty);
164
165 self = self.with_updates(retain_updates);
166
167 self.reveal_upper_node(Nibbles::default(), &root, masks)?;
168 Ok(self)
169 }
170
171 fn with_updates(mut self, retain_updates: bool) -> Self {
172 self.updates = retain_updates.then(Default::default);
173 self
174 }
175
176 fn reveal_nodes(&mut self, mut nodes: Vec<ProofTrieNode>) -> SparseTrieResult<()> {
177 if nodes.is_empty() {
178 return Ok(())
179 }
180
181 nodes.sort_unstable_by(
184 |ProofTrieNode { path: path_a, .. }, ProofTrieNode { path: path_b, .. }| {
185 let subtrie_type_a = SparseSubtrieType::from_path(path_a);
186 let subtrie_type_b = SparseSubtrieType::from_path(path_b);
187 subtrie_type_a.cmp(&subtrie_type_b).then(path_a.cmp(path_b))
188 },
189 );
190
191 for ProofTrieNode { path, masks, .. } in &nodes {
193 if let Some(tree_mask) = masks.tree_mask {
194 self.branch_node_tree_masks.insert(*path, tree_mask);
195 }
196 if let Some(hash_mask) = masks.hash_mask {
197 self.branch_node_hash_masks.insert(*path, hash_mask);
198 }
199 }
200
201 let num_upper_nodes = nodes
205 .iter()
206 .position(|n| !SparseSubtrieType::path_len_is_upper(n.path.len()))
207 .unwrap_or(nodes.len());
208
209 let upper_nodes = &nodes[..num_upper_nodes];
210 let lower_nodes = &nodes[num_upper_nodes..];
211
212 self.upper_subtrie.nodes.reserve(upper_nodes.len());
215 for node in upper_nodes {
216 self.reveal_upper_node(node.path, &node.node, node.masks)?;
217 }
218
219 if !self.is_reveal_parallelism_enabled(lower_nodes.len()) {
220 for node in lower_nodes {
221 if let Some(subtrie) = self.lower_subtrie_for_path_mut(&node.path) {
222 subtrie.reveal_node(node.path, &node.node, node.masks)?;
223 } else {
224 panic!("upper subtrie node {node:?} found amongst lower nodes");
225 }
226 }
227 return Ok(())
228 }
229
230 #[cfg(not(feature = "std"))]
231 unreachable!("nostd is checked by is_reveal_parallelism_enabled");
232
233 #[cfg(feature = "std")]
234 {
236 use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
237
238 let node_groups: Vec<_> = lower_nodes
241 .chunk_by(|node_a, node_b| {
242 SparseSubtrieType::from_path(&node_a.path) ==
243 SparseSubtrieType::from_path(&node_b.path)
244 })
245 .collect();
246
247 let lower_subtries: Vec<_> = node_groups
251 .iter()
252 .map(|nodes| {
253 let node = &nodes[0];
255 let idx =
256 SparseSubtrieType::from_path(&node.path).lower_index().unwrap_or_else(
257 || panic!("upper subtrie node {node:?} found amongst lower nodes"),
258 );
259 self.lower_subtries[idx].reveal(&node.path);
264 (idx, self.lower_subtries[idx].take_revealed().expect("just revealed"))
265 })
266 .collect();
267
268 let (tx, rx) = mpsc::channel();
269
270 lower_subtries
273 .into_par_iter()
274 .zip(node_groups.into_par_iter())
275 .map(|((subtrie_idx, mut subtrie), nodes)| {
276 subtrie.nodes.reserve(nodes.len());
279
280 for node in nodes {
281 let res = subtrie.reveal_node(node.path, &node.node, node.masks);
283 if res.is_err() {
284 return (subtrie_idx, subtrie, res)
285 }
286 }
287 (subtrie_idx, subtrie, Ok(()))
288 })
289 .for_each_init(|| tx.clone(), |tx, result| tx.send(result).unwrap());
290
291 drop(tx);
292
293 let mut any_err = Ok(());
298 for (subtrie_idx, subtrie, res) in rx {
299 self.lower_subtries[subtrie_idx] = LowerSparseSubtrie::Revealed(subtrie);
300 if res.is_err() {
301 any_err = res;
302 }
303 }
304
305 any_err
306 }
307 }
308
309 fn update_leaf<P: TrieNodeProvider>(
310 &mut self,
311 full_path: Nibbles,
312 value: Vec<u8>,
313 provider: P,
314 ) -> SparseTrieResult<()> {
315 self.prefix_set.insert(full_path);
316 let existing = self.upper_subtrie.inner.values.insert(full_path, value.clone());
317 if existing.is_some() {
318 return Ok(())
320 }
321
322 let retain_updates = self.updates_enabled();
323
324 let mut new_nodes = Vec::new();
333 let mut next = Some(Nibbles::default());
334
335 while let Some(current) =
340 next.filter(|next| SparseSubtrieType::path_len_is_upper(next.len()))
341 {
342 match self.upper_subtrie.update_next_node(current, &full_path, retain_updates)? {
345 LeafUpdateStep::Continue { next_node } => {
346 next = Some(next_node);
347 }
348 LeafUpdateStep::Complete { inserted_nodes, reveal_path } => {
349 new_nodes.extend(inserted_nodes);
350
351 if let Some(reveal_path) = reveal_path {
352 let subtrie = self.subtrie_for_path_mut(&reveal_path);
353 if subtrie.nodes.get(&reveal_path).expect("node must exist").is_hash() {
354 debug!(
355 target: "trie::parallel_sparse",
356 child_path = ?reveal_path,
357 leaf_full_path = ?full_path,
358 "Extension node child not revealed in update_leaf, falling back to db",
359 );
360 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
361 provider.trie_node(&reveal_path)?
362 {
363 let decoded = TrieNode::decode(&mut &node[..])?;
364 trace!(
365 target: "trie::parallel_sparse",
366 ?reveal_path,
367 ?decoded,
368 ?tree_mask,
369 ?hash_mask,
370 "Revealing child (from upper)",
371 );
372 subtrie.reveal_node(
373 reveal_path,
374 &decoded,
375 TrieMasks { hash_mask, tree_mask },
376 )?;
377 } else {
378 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
379 path: reveal_path,
380 }
381 .into())
382 }
383 }
384 }
385
386 next = None;
387 }
388 LeafUpdateStep::NodeNotFound => {
389 next = None;
390 }
391 }
392 }
393
394 for node_path in &new_nodes {
396 if SparseSubtrieType::path_len_is_upper(node_path.len()) {
398 continue
399 }
400
401 let node =
402 self.upper_subtrie.nodes.remove(node_path).expect("node belongs to upper subtrie");
403
404 let leaf_value = if let SparseNode::Leaf { key, .. } = &node {
406 let mut leaf_full_path = *node_path;
407 leaf_full_path.extend(key);
408 Some((
409 leaf_full_path,
410 self.upper_subtrie
411 .inner
412 .values
413 .remove(&leaf_full_path)
414 .expect("leaf nodes have associated values entries"),
415 ))
416 } else {
417 None
418 };
419
420 let subtrie = self.subtrie_for_path_mut(node_path);
422
423 if let Some((leaf_full_path, value)) = leaf_value {
425 subtrie.inner.values.insert(leaf_full_path, value);
426 }
427
428 subtrie.nodes.insert(*node_path, node);
430 }
431
432 if let Some(next_path) = next.filter(|n| !SparseSubtrieType::path_len_is_upper(n.len())) {
434 self.upper_subtrie.inner.values.remove(&full_path);
439
440 let subtrie = self.subtrie_for_path_mut(&next_path);
445
446 if subtrie.nodes.is_empty() {
448 subtrie.nodes.insert(subtrie.path, SparseNode::Empty);
449 }
450
451 subtrie.update_leaf(full_path, value, provider, retain_updates)?;
454 }
455
456 Ok(())
457 }
458
459 fn remove_leaf<P: TrieNodeProvider>(
460 &mut self,
461 full_path: &Nibbles,
462 provider: P,
463 ) -> SparseTrieResult<()> {
464 let leaf_path;
480 let leaf_subtrie;
481
482 let mut branch_parent_path: Option<Nibbles> = None;
483 let mut branch_parent_node: Option<SparseNode> = None;
484
485 let mut ext_grandparent_path: Option<Nibbles> = None;
486 let mut ext_grandparent_node: Option<SparseNode> = None;
487
488 let mut curr_path = Nibbles::new(); let mut curr_subtrie = self.upper_subtrie.as_mut();
490 let mut curr_subtrie_is_upper = true;
491
492 let mut paths_to_reset_hashes = Vec::new();
494
495 loop {
496 let curr_node = curr_subtrie.nodes.get_mut(&curr_path).unwrap();
497
498 match Self::find_next_to_leaf(&curr_path, curr_node, full_path) {
499 FindNextToLeafOutcome::NotFound => return Ok(()), FindNextToLeafOutcome::BlindedNode(hash) => {
501 return Err(SparseTrieErrorKind::BlindedNode { path: curr_path, hash }.into())
502 }
503 FindNextToLeafOutcome::Found => {
504 leaf_path = curr_path;
506 leaf_subtrie = curr_subtrie;
507 break;
508 }
509 FindNextToLeafOutcome::ContinueFrom(next_path) => {
510 match curr_node {
513 SparseNode::Branch { hash, .. } => {
514 if hash.is_some() {
515 paths_to_reset_hashes
516 .push((SparseSubtrieType::from_path(&curr_path), curr_path));
517 }
518
519 match (&branch_parent_path, &ext_grandparent_path) {
522 (Some(branch), Some(ext)) if branch.len() > ext.len() => {
523 ext_grandparent_path = None;
524 ext_grandparent_node = None;
525 }
526 _ => (),
527 };
528 branch_parent_path = Some(curr_path);
529 branch_parent_node = Some(curr_node.clone());
530 }
531 SparseNode::Extension { hash, .. } => {
532 if hash.is_some() {
533 paths_to_reset_hashes
534 .push((SparseSubtrieType::from_path(&curr_path), curr_path));
535 }
536
537 ext_grandparent_path = Some(curr_path);
541 ext_grandparent_node = Some(curr_node.clone());
542 }
543 SparseNode::Empty | SparseNode::Hash(_) | SparseNode::Leaf { .. } => {
544 unreachable!(
545 "find_next_to_leaf only continues to a branch or extension"
546 )
547 }
548 }
549
550 curr_path = next_path;
551
552 if curr_subtrie_is_upper &&
555 let SparseSubtrieType::Lower(idx) =
556 SparseSubtrieType::from_path(&curr_path)
557 {
558 curr_subtrie = self.lower_subtries[idx]
559 .as_revealed_mut()
560 .expect("lower subtrie is revealed");
561 curr_subtrie_is_upper = false;
562 }
563 }
564 };
565 }
566
567 self.prefix_set.insert(*full_path);
570 leaf_subtrie.inner.values.remove(full_path);
571 for (subtrie_type, path) in paths_to_reset_hashes {
572 let node = match subtrie_type {
573 SparseSubtrieType::Upper => self.upper_subtrie.nodes.get_mut(&path),
574 SparseSubtrieType::Lower(idx) => self.lower_subtries[idx]
575 .as_revealed_mut()
576 .expect("lower subtrie is revealed")
577 .nodes
578 .get_mut(&path),
579 }
580 .expect("node exists");
581
582 match node {
583 SparseNode::Extension { hash, .. } | SparseNode::Branch { hash, .. } => {
584 *hash = None
585 }
586 SparseNode::Empty | SparseNode::Hash(_) | SparseNode::Leaf { .. } => {
587 unreachable!("only branch and extension node hashes can be reset")
588 }
589 }
590 }
591 self.remove_node(&leaf_path);
592
593 if leaf_path.is_empty() {
596 self.upper_subtrie.nodes.insert(leaf_path, SparseNode::Empty);
597 return Ok(())
598 }
599
600 if let (Some(branch_path), &Some(SparseNode::Branch { mut state_mask, .. })) =
603 (&branch_parent_path, &branch_parent_node)
604 {
605 let child_nibble = leaf_path.get_unchecked(branch_path.len());
606 state_mask.unset_bit(child_nibble);
607
608 let new_branch_node = if state_mask.count_bits() == 1 {
609 let remaining_child_path = {
612 let mut p = *branch_path;
613 p.push_unchecked(
614 state_mask.first_set_bit_index().expect("state mask is not empty"),
615 );
616 p
617 };
618
619 trace!(
620 target: "trie::parallel_sparse",
621 ?leaf_path,
622 ?branch_path,
623 ?remaining_child_path,
624 "Branch node has only one child",
625 );
626
627 let remaining_child_node = self.reveal_remaining_child_on_leaf_removal(
630 provider,
631 full_path,
632 &remaining_child_path,
633 true, )?;
635
636 let (new_branch_node, remove_child) = Self::branch_changes_on_leaf_removal(
637 branch_path,
638 &remaining_child_path,
639 &remaining_child_node,
640 );
641
642 if remove_child {
643 self.move_value_on_leaf_removal(
644 branch_path,
645 &new_branch_node,
646 &remaining_child_path,
647 );
648 self.remove_node(&remaining_child_path);
649 }
650
651 if let Some(updates) = self.updates.as_mut() {
652 updates.updated_nodes.remove(branch_path);
653 updates.removed_nodes.insert(*branch_path);
654 }
655
656 new_branch_node
657 } else {
658 SparseNode::new_branch(state_mask)
661 };
662
663 let branch_subtrie = self.subtrie_for_path_mut(branch_path);
664 branch_subtrie.nodes.insert(*branch_path, new_branch_node.clone());
665 branch_parent_node = Some(new_branch_node);
666 };
667
668 if let (Some(ext_path), Some(SparseNode::Extension { key: shortkey, .. })) =
672 (ext_grandparent_path, &ext_grandparent_node)
673 {
674 let ext_subtrie = self.subtrie_for_path_mut(&ext_path);
675 let branch_path = branch_parent_path.as_ref().unwrap();
676
677 if let Some(new_ext_node) = Self::extension_changes_on_leaf_removal(
678 &ext_path,
679 shortkey,
680 branch_path,
681 branch_parent_node.as_ref().unwrap(),
682 ) {
683 ext_subtrie.nodes.insert(ext_path, new_ext_node.clone());
684 self.move_value_on_leaf_removal(&ext_path, &new_ext_node, branch_path);
685 self.remove_node(branch_path);
686 }
687 }
688
689 Ok(())
690 }
691
692 #[instrument(level = "trace", target = "trie::sparse::parallel", skip(self))]
693 fn root(&mut self) -> B256 {
694 trace!(target: "trie::parallel_sparse", "Calculating trie root hash");
695
696 self.update_subtrie_hashes();
698
699 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
702 let root_rlp = self.update_upper_subtrie_hashes(&mut prefix_set);
703
704 root_rlp.as_hash().unwrap_or(EMPTY_ROOT_HASH)
706 }
707
708 #[instrument(level = "trace", target = "trie::sparse::parallel", skip(self))]
709 fn update_subtrie_hashes(&mut self) {
710 trace!(target: "trie::parallel_sparse", "Updating subtrie hashes");
711
712 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
714 let num_changed_keys = prefix_set.len();
715 let (mut changed_subtries, unchanged_prefix_set) =
716 self.take_changed_lower_subtries(&mut prefix_set);
717
718 #[cfg(feature = "metrics")]
720 self.metrics.subtries_updated.record(changed_subtries.len() as f64);
721
722 self.prefix_set = unchanged_prefix_set;
724
725 if !self.is_update_parallelism_enabled(num_changed_keys) {
727 for changed_subtrie in &mut changed_subtries {
728 changed_subtrie.subtrie.update_hashes(
729 &mut changed_subtrie.prefix_set,
730 &mut changed_subtrie.update_actions_buf,
731 &self.branch_node_tree_masks,
732 &self.branch_node_hash_masks,
733 );
734 }
735
736 self.insert_changed_subtries(changed_subtries);
737 return
738 }
739
740 #[cfg(not(feature = "std"))]
741 unreachable!("nostd is checked by is_update_parallelism_enabled");
742
743 #[cfg(feature = "std")]
744 {
746 use rayon::iter::{IntoParallelIterator, ParallelIterator};
747
748 let (tx, rx) = mpsc::channel();
749
750 let branch_node_tree_masks = &self.branch_node_tree_masks;
751 let branch_node_hash_masks = &self.branch_node_hash_masks;
752 changed_subtries
753 .into_par_iter()
754 .map(|mut changed_subtrie| {
755 #[cfg(feature = "metrics")]
756 let start = std::time::Instant::now();
757 changed_subtrie.subtrie.update_hashes(
758 &mut changed_subtrie.prefix_set,
759 &mut changed_subtrie.update_actions_buf,
760 branch_node_tree_masks,
761 branch_node_hash_masks,
762 );
763 #[cfg(feature = "metrics")]
764 self.metrics.subtrie_hash_update_latency.record(start.elapsed());
765 changed_subtrie
766 })
767 .for_each_init(|| tx.clone(), |tx, result| tx.send(result).unwrap());
768
769 drop(tx);
770 self.insert_changed_subtries(rx);
771 }
772 }
773
774 fn get_leaf_value(&self, full_path: &Nibbles) -> Option<&Vec<u8>> {
775 self.subtrie_for_path(full_path).and_then(|subtrie| subtrie.inner.values.get(full_path))
776 }
777
778 fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
779 self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
780 }
781
782 fn take_updates(&mut self) -> SparseTrieUpdates {
783 self.updates.take().unwrap_or_default()
784 }
785
786 fn wipe(&mut self) {
787 self.upper_subtrie.wipe();
788 self.lower_subtries = [const { LowerSparseSubtrie::Blind(None) }; NUM_LOWER_SUBTRIES];
789 self.prefix_set = PrefixSetMut::all();
790 self.updates = self.updates.is_some().then(SparseTrieUpdates::wiped);
791 }
792
793 fn clear(&mut self) {
794 self.upper_subtrie.clear();
795 self.upper_subtrie.nodes.insert(Nibbles::default(), SparseNode::Empty);
796 for subtrie in &mut self.lower_subtries {
797 subtrie.clear();
798 }
799 self.prefix_set.clear();
800 self.updates = None;
801 self.branch_node_tree_masks.clear();
802 self.branch_node_hash_masks.clear();
803 }
806
807 fn find_leaf(
808 &self,
809 full_path: &Nibbles,
810 expected_value: Option<&Vec<u8>>,
811 ) -> Result<LeafLookup, LeafLookupError> {
812 if let Some(actual_value) = std::iter::once(self.upper_subtrie.as_ref())
818 .chain(self.lower_subtrie_for_path(full_path))
819 .filter_map(|subtrie| subtrie.inner.values.get(full_path))
820 .next()
821 {
822 return expected_value
824 .is_none_or(|v| v == actual_value)
825 .then_some(LeafLookup::Exists)
826 .ok_or_else(|| LeafLookupError::ValueMismatch {
827 path: *full_path,
828 expected: expected_value.cloned(),
829 actual: actual_value.clone(),
830 })
831 }
832
833 let mut curr_path = Nibbles::new(); let mut curr_subtrie = self.upper_subtrie.as_ref();
841 let mut curr_subtrie_is_upper = true;
842
843 loop {
844 let curr_node = curr_subtrie.nodes.get(&curr_path).unwrap();
845
846 match Self::find_next_to_leaf(&curr_path, curr_node, full_path) {
847 FindNextToLeafOutcome::NotFound => return Ok(LeafLookup::NonExistent),
848 FindNextToLeafOutcome::BlindedNode(hash) => {
849 return Err(LeafLookupError::BlindedNode { path: curr_path, hash });
851 }
852 FindNextToLeafOutcome::Found => {
853 panic!("target leaf {full_path:?} found at path {curr_path:?}, even though value wasn't in values hashmap");
854 }
855 FindNextToLeafOutcome::ContinueFrom(next_path) => {
856 curr_path = next_path;
857 if curr_subtrie_is_upper &&
860 let Some(lower_subtrie) = self.lower_subtrie_for_path(&curr_path)
861 {
862 curr_subtrie = lower_subtrie;
863 curr_subtrie_is_upper = false;
864 }
865 }
866 }
867 }
868 }
869
870 fn shrink_nodes_to(&mut self, size: usize) {
871 let total_subtries = 1 + NUM_LOWER_SUBTRIES;
875 let size_per_subtrie = size / total_subtries;
876
877 self.upper_subtrie.shrink_nodes_to(size_per_subtrie);
879
880 for subtrie in &mut self.lower_subtries {
882 subtrie.shrink_nodes_to(size_per_subtrie);
883 }
884
885 self.branch_node_hash_masks.shrink_to(size);
887 self.branch_node_tree_masks.shrink_to(size);
888 }
889
890 fn shrink_values_to(&mut self, size: usize) {
891 let total_subtries = 1 + NUM_LOWER_SUBTRIES;
895 let size_per_subtrie = size / total_subtries;
896
897 self.upper_subtrie.shrink_values_to(size_per_subtrie);
899
900 for subtrie in &mut self.lower_subtries {
902 subtrie.shrink_values_to(size_per_subtrie);
903 }
904 }
905}
906
907impl ParallelSparseTrie {
908 pub const fn with_parallelism_thresholds(mut self, thresholds: ParallelismThresholds) -> Self {
910 self.parallelism_thresholds = thresholds;
911 self
912 }
913
914 const fn updates_enabled(&self) -> bool {
916 self.updates.is_some()
917 }
918
919 const fn is_reveal_parallelism_enabled(&self, num_nodes: usize) -> bool {
922 #[cfg(not(feature = "std"))]
923 return false;
924
925 num_nodes >= self.parallelism_thresholds.min_revealed_nodes
926 }
927
928 const fn is_update_parallelism_enabled(&self, num_changed_keys: usize) -> bool {
931 #[cfg(not(feature = "std"))]
932 return false;
933
934 num_changed_keys >= self.parallelism_thresholds.min_updated_nodes
935 }
936
937 pub fn from_root(
952 root: TrieNode,
953 masks: TrieMasks,
954 retain_updates: bool,
955 ) -> SparseTrieResult<Self> {
956 Self::default().with_root(root, masks, retain_updates)
957 }
958
959 fn lower_subtrie_for_path(&self, path: &Nibbles) -> Option<&SparseSubtrie> {
963 match SparseSubtrieType::from_path(path) {
964 SparseSubtrieType::Upper => None,
965 SparseSubtrieType::Lower(idx) => self.lower_subtries[idx].as_revealed_ref(),
966 }
967 }
968
969 fn lower_subtrie_for_path_mut(&mut self, path: &Nibbles) -> Option<&mut SparseSubtrie> {
976 match SparseSubtrieType::from_path(path) {
977 SparseSubtrieType::Upper => None,
978 SparseSubtrieType::Lower(idx) => {
979 self.lower_subtries[idx].reveal(path);
980 Some(self.lower_subtries[idx].as_revealed_mut().expect("just revealed"))
981 }
982 }
983 }
984
985 fn subtrie_for_path(&self, path: &Nibbles) -> Option<&SparseSubtrie> {
990 if SparseSubtrieType::path_len_is_upper(path.len()) {
993 Some(&self.upper_subtrie)
994 } else {
995 self.lower_subtrie_for_path(path)
996 }
997 }
998
999 fn subtrie_for_path_mut(&mut self, path: &Nibbles) -> &mut SparseSubtrie {
1006 if SparseSubtrieType::path_len_is_upper(path.len()) {
1009 &mut self.upper_subtrie
1010 } else {
1011 self.lower_subtrie_for_path_mut(path).unwrap()
1012 }
1013 }
1014
1015 fn find_next_to_leaf(
1023 from_path: &Nibbles,
1024 from_node: &SparseNode,
1025 leaf_full_path: &Nibbles,
1026 ) -> FindNextToLeafOutcome {
1027 debug_assert!(leaf_full_path.len() >= from_path.len());
1028 debug_assert!(leaf_full_path.starts_with(from_path));
1029
1030 match from_node {
1031 SparseNode::Empty => FindNextToLeafOutcome::NotFound,
1034 SparseNode::Hash(hash) => FindNextToLeafOutcome::BlindedNode(*hash),
1035 SparseNode::Leaf { key, .. } => {
1036 let mut found_full_path = *from_path;
1037 found_full_path.extend(key);
1038
1039 if &found_full_path == leaf_full_path {
1040 return FindNextToLeafOutcome::Found
1041 }
1042 FindNextToLeafOutcome::NotFound
1043 }
1044 SparseNode::Extension { key, .. } => {
1045 if leaf_full_path.len() == from_path.len() {
1046 return FindNextToLeafOutcome::NotFound
1047 }
1048
1049 let mut child_path = *from_path;
1050 child_path.extend(key);
1051
1052 if !leaf_full_path.starts_with(&child_path) {
1053 return FindNextToLeafOutcome::NotFound
1054 }
1055 FindNextToLeafOutcome::ContinueFrom(child_path)
1056 }
1057 SparseNode::Branch { state_mask, .. } => {
1058 if leaf_full_path.len() == from_path.len() {
1059 return FindNextToLeafOutcome::NotFound
1060 }
1061
1062 let nibble = leaf_full_path.get_unchecked(from_path.len());
1063 if !state_mask.is_bit_set(nibble) {
1064 return FindNextToLeafOutcome::NotFound
1065 }
1066
1067 let mut child_path = *from_path;
1068 child_path.push_unchecked(nibble);
1069
1070 FindNextToLeafOutcome::ContinueFrom(child_path)
1071 }
1072 }
1073 }
1074
1075 fn move_value_on_leaf_removal(
1080 &mut self,
1081 parent_path: &Nibbles,
1082 new_parent_node: &SparseNode,
1083 prev_child_path: &Nibbles,
1084 ) {
1085 if SparseSubtrieType::from_path(parent_path).lower_index().is_some() {
1088 return;
1089 }
1090
1091 if let SparseNode::Leaf { key, .. } = new_parent_node {
1092 let Some(prev_child_subtrie) = self.lower_subtrie_for_path_mut(prev_child_path) else {
1093 return;
1094 };
1095
1096 let mut leaf_full_path = *parent_path;
1097 leaf_full_path.extend(key);
1098
1099 let val = prev_child_subtrie.inner.values.remove(&leaf_full_path).expect("ParallelSparseTrie is in an inconsistent state, expected value on subtrie which wasn't found");
1100 self.upper_subtrie.inner.values.insert(leaf_full_path, val);
1101 }
1102 }
1103
1104 fn remove_node(&mut self, path: &Nibbles) {
1116 let subtrie = self.subtrie_for_path_mut(path);
1117 let node = subtrie.nodes.remove(path);
1118
1119 let Some(idx) = SparseSubtrieType::from_path(path).lower_index() else {
1120 return;
1123 };
1124
1125 match node {
1126 Some(SparseNode::Leaf { .. }) => {
1127 if subtrie.nodes.is_empty() {
1130 self.lower_subtries[idx].clear();
1131 }
1132 }
1133 Some(SparseNode::Extension { key, .. }) => {
1134 if &subtrie.path == path {
1138 subtrie.path.extend(&key);
1139 }
1140 }
1141 _ => panic!("Expected to remove a leaf or extension, but removed {node:?}"),
1142 }
1143 }
1144
1145 fn branch_changes_on_leaf_removal(
1154 parent_path: &Nibbles,
1155 remaining_child_path: &Nibbles,
1156 remaining_child_node: &SparseNode,
1157 ) -> (SparseNode, bool) {
1158 debug_assert!(remaining_child_path.len() > parent_path.len());
1159 debug_assert!(remaining_child_path.starts_with(parent_path));
1160
1161 let remaining_child_nibble = remaining_child_path.get_unchecked(parent_path.len());
1162
1163 match remaining_child_node {
1166 SparseNode::Empty | SparseNode::Hash(_) => {
1167 panic!("remaining child must have been revealed already")
1168 }
1169 SparseNode::Leaf { key, .. } => {
1173 let mut new_key = Nibbles::from_nibbles_unchecked([remaining_child_nibble]);
1174 new_key.extend(key);
1175 (SparseNode::new_leaf(new_key), true)
1176 }
1177 SparseNode::Extension { key, .. } => {
1181 let mut new_key = Nibbles::from_nibbles_unchecked([remaining_child_nibble]);
1182 new_key.extend(key);
1183 (SparseNode::new_ext(new_key), true)
1184 }
1185 SparseNode::Branch { .. } => (
1188 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([remaining_child_nibble])),
1189 false,
1190 ),
1191 }
1192 }
1193
1194 fn extension_changes_on_leaf_removal(
1203 parent_path: &Nibbles,
1204 parent_key: &Nibbles,
1205 child_path: &Nibbles,
1206 child: &SparseNode,
1207 ) -> Option<SparseNode> {
1208 debug_assert!(child_path.len() > parent_path.len());
1209 debug_assert!(child_path.starts_with(parent_path));
1210
1211 match child {
1214 SparseNode::Empty | SparseNode::Hash(_) => {
1215 panic!("child must be revealed")
1216 }
1217 SparseNode::Leaf { key, .. } => {
1223 let mut new_key = *parent_key;
1224 new_key.extend(key);
1225 Some(SparseNode::new_leaf(new_key))
1226 }
1227 SparseNode::Extension { key, .. } => {
1230 let mut new_key = *parent_key;
1231 new_key.extend(key);
1232 Some(SparseNode::new_ext(new_key))
1233 }
1234 SparseNode::Branch { .. } => None,
1236 }
1237 }
1238
1239 fn reveal_remaining_child_on_leaf_removal<P: TrieNodeProvider>(
1249 &mut self,
1250 provider: P,
1251 full_path: &Nibbles, remaining_child_path: &Nibbles,
1253 recurse_into_extension: bool,
1254 ) -> SparseTrieResult<SparseNode> {
1255 let remaining_child_subtrie = self.subtrie_for_path_mut(remaining_child_path);
1256
1257 let remaining_child_node =
1258 match remaining_child_subtrie.nodes.get(remaining_child_path).unwrap() {
1259 SparseNode::Hash(_) => {
1260 debug!(
1261 target: "trie::parallel_sparse",
1262 child_path = ?remaining_child_path,
1263 leaf_full_path = ?full_path,
1264 "Node child not revealed in remove_leaf, falling back to db",
1265 );
1266 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1267 provider.trie_node(remaining_child_path)?
1268 {
1269 let decoded = TrieNode::decode(&mut &node[..])?;
1270 trace!(
1271 target: "trie::parallel_sparse",
1272 ?remaining_child_path,
1273 ?decoded,
1274 ?tree_mask,
1275 ?hash_mask,
1276 "Revealing remaining blinded branch child"
1277 );
1278 remaining_child_subtrie.reveal_node(
1279 *remaining_child_path,
1280 &decoded,
1281 TrieMasks { hash_mask, tree_mask },
1282 )?;
1283 remaining_child_subtrie.nodes.get(remaining_child_path).unwrap().clone()
1284 } else {
1285 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1286 path: *remaining_child_path,
1287 }
1288 .into())
1289 }
1290 }
1291 node => node.clone(),
1292 };
1293
1294 if let SparseNode::Extension { key, .. } = &remaining_child_node &&
1299 recurse_into_extension
1300 {
1301 let mut remaining_grandchild_path = *remaining_child_path;
1302 remaining_grandchild_path.extend(key);
1303
1304 trace!(
1305 target: "trie::parallel_sparse",
1306 remaining_grandchild_path = ?remaining_grandchild_path,
1307 child_path = ?remaining_child_path,
1308 leaf_full_path = ?full_path,
1309 "Revealing child of extension node, which is the last remaining child of the branch"
1310 );
1311
1312 self.reveal_remaining_child_on_leaf_removal(
1313 provider,
1314 full_path,
1315 &remaining_grandchild_path,
1316 false, )?;
1318 }
1319
1320 Ok(remaining_child_node)
1321 }
1322
1323 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all)]
1326 fn apply_subtrie_update_actions(
1327 &mut self,
1328 update_actions: impl Iterator<Item = SparseTrieUpdatesAction>,
1329 ) {
1330 if let Some(updates) = self.updates.as_mut() {
1331 for action in update_actions {
1332 match action {
1333 SparseTrieUpdatesAction::InsertRemoved(path) => {
1334 updates.updated_nodes.remove(&path);
1335 updates.removed_nodes.insert(path);
1336 }
1337 SparseTrieUpdatesAction::RemoveUpdated(path) => {
1338 updates.updated_nodes.remove(&path);
1339 }
1340 SparseTrieUpdatesAction::InsertUpdated(path, branch_node) => {
1341 updates.updated_nodes.insert(path, branch_node);
1342 }
1343 }
1344 }
1345 };
1346 }
1347
1348 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, ret)]
1350 fn update_upper_subtrie_hashes(&mut self, prefix_set: &mut PrefixSet) -> RlpNode {
1351 trace!(target: "trie::parallel_sparse", "Updating upper subtrie hashes");
1352
1353 debug_assert!(self.upper_subtrie.inner.buffers.path_stack.is_empty());
1354 self.upper_subtrie.inner.buffers.path_stack.push(RlpNodePathStackItem {
1355 path: Nibbles::default(), is_in_prefix_set: None,
1357 });
1358
1359 #[cfg(feature = "metrics")]
1360 let start = std::time::Instant::now();
1361
1362 let mut update_actions_buf =
1363 self.updates_enabled().then(|| self.update_actions_buffers.pop().unwrap_or_default());
1364
1365 while let Some(stack_item) = self.upper_subtrie.inner.buffers.path_stack.pop() {
1366 let path = stack_item.path;
1367 let node = if path.len() < UPPER_TRIE_MAX_DEPTH {
1368 self.upper_subtrie.nodes.get_mut(&path).expect("upper subtrie node must exist")
1369 } else {
1370 let index = path_subtrie_index_unchecked(&path);
1371 let node = self.lower_subtries[index]
1372 .as_revealed_mut()
1373 .expect("lower subtrie must exist")
1374 .nodes
1375 .get_mut(&path)
1376 .expect("lower subtrie node must exist");
1377 debug_assert!(
1380 node.hash().is_some(),
1381 "Lower subtrie root node at path {path:?} has no hash"
1382 );
1383 node
1384 };
1385
1386 self.upper_subtrie.inner.rlp_node(
1388 prefix_set,
1389 &mut update_actions_buf,
1390 stack_item,
1391 node,
1392 &self.branch_node_tree_masks,
1393 &self.branch_node_hash_masks,
1394 );
1395 }
1396
1397 if let Some(mut update_actions_buf) = update_actions_buf {
1400 self.apply_subtrie_update_actions(
1401 #[allow(clippy::iter_with_drain)]
1402 update_actions_buf.drain(..),
1403 );
1404 self.update_actions_buffers.push(update_actions_buf);
1405 }
1406
1407 #[cfg(feature = "metrics")]
1408 self.metrics.subtrie_upper_hash_latency.record(start.elapsed());
1409
1410 debug_assert_eq!(self.upper_subtrie.inner.buffers.rlp_node_stack.len(), 1);
1411 self.upper_subtrie.inner.buffers.rlp_node_stack.pop().unwrap().rlp_node
1412 }
1413
1414 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, fields(prefix_set_len = prefix_set.len()))]
1428 fn take_changed_lower_subtries(
1429 &mut self,
1430 prefix_set: &mut PrefixSet,
1431 ) -> (Vec<ChangedSubtrie>, PrefixSetMut) {
1432 if prefix_set.is_empty() && !prefix_set.all() {
1435 return Default::default();
1436 }
1437
1438 let prefix_set_clone = prefix_set.clone();
1440 let mut prefix_set_iter = prefix_set_clone.into_iter().copied().peekable();
1441 let mut changed_subtries = Vec::new();
1442 let mut unchanged_prefix_set = PrefixSetMut::default();
1443 let updates_enabled = self.updates_enabled();
1444
1445 for (index, subtrie) in self.lower_subtries.iter_mut().enumerate() {
1446 if let Some(subtrie) = subtrie.take_revealed_if(|subtrie| {
1447 prefix_set.contains(&subtrie.path) ||
1448 subtrie.nodes.get(&subtrie.path).is_some_and(|n| n.hash().is_none())
1449 }) {
1450 let prefix_set = if prefix_set.all() {
1451 unchanged_prefix_set = PrefixSetMut::all();
1452 PrefixSetMut::all()
1453 } else {
1454 let mut new_prefix_set = Vec::new();
1459 while let Some(key) = prefix_set_iter.peek() {
1460 if key.starts_with(&subtrie.path) {
1461 new_prefix_set.push(prefix_set_iter.next().unwrap());
1463 } else if new_prefix_set.is_empty() && key < &subtrie.path {
1464 unchanged_prefix_set.insert(prefix_set_iter.next().unwrap());
1468 } else {
1469 break
1473 }
1474 }
1475 PrefixSetMut::from(new_prefix_set)
1476 }
1477 .freeze();
1478
1479 match subtrie.nodes.get(&subtrie.path) {
1482 Some(SparseNode::Extension { key, .. } | SparseNode::Leaf { key, .. }) => {
1483 unchanged_prefix_set.insert(subtrie.path.join(key));
1484 }
1485 Some(SparseNode::Branch { .. }) => {
1486 unchanged_prefix_set.insert(subtrie.path);
1487 }
1488 _ => {}
1489 }
1490
1491 let update_actions_buf =
1492 updates_enabled.then(|| self.update_actions_buffers.pop().unwrap_or_default());
1493
1494 changed_subtries.push(ChangedSubtrie {
1495 index,
1496 subtrie,
1497 prefix_set,
1498 update_actions_buf,
1499 });
1500 }
1501 }
1502
1503 unchanged_prefix_set.extend_keys(prefix_set_iter);
1505
1506 (changed_subtries, unchanged_prefix_set)
1507 }
1508
1509 #[cfg(test)]
1511 fn all_nodes(&self) -> impl IntoIterator<Item = (&Nibbles, &SparseNode)> {
1512 let mut nodes = vec![];
1513 for subtrie in self.lower_subtries.iter().filter_map(LowerSparseSubtrie::as_revealed_ref) {
1514 nodes.extend(subtrie.nodes.iter())
1515 }
1516 nodes.extend(self.upper_subtrie.nodes.iter());
1517 nodes
1518 }
1519
1520 fn reveal_upper_node(
1537 &mut self,
1538 path: Nibbles,
1539 node: &TrieNode,
1540 masks: TrieMasks,
1541 ) -> SparseTrieResult<()> {
1542 self.upper_subtrie.reveal_node(path, node, masks)?;
1545
1546 match node {
1551 TrieNode::Branch(branch) => {
1552 if !SparseSubtrieType::path_len_is_upper(path.len() + 1) {
1556 let mut stack_ptr = branch.as_ref().first_child_index();
1557 for idx in CHILD_INDEX_RANGE {
1558 if branch.state_mask.is_bit_set(idx) {
1559 let mut child_path = path;
1560 child_path.push_unchecked(idx);
1561 self.lower_subtrie_for_path_mut(&child_path)
1562 .expect("child_path must have a lower subtrie")
1563 .reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
1564 stack_ptr += 1;
1565 }
1566 }
1567 }
1568 }
1569 TrieNode::Extension(ext) => {
1570 let mut child_path = path;
1571 child_path.extend(&ext.key);
1572 if let Some(subtrie) = self.lower_subtrie_for_path_mut(&child_path) {
1573 subtrie.reveal_node_or_hash(child_path, &ext.child)?;
1574 }
1575 }
1576 TrieNode::EmptyRoot | TrieNode::Leaf(_) => (),
1577 }
1578
1579 Ok(())
1580 }
1581
1582 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all)]
1585 fn insert_changed_subtries(
1586 &mut self,
1587 changed_subtries: impl IntoIterator<Item = ChangedSubtrie>,
1588 ) {
1589 for ChangedSubtrie { index, subtrie, update_actions_buf, .. } in changed_subtries {
1590 if let Some(mut update_actions_buf) = update_actions_buf {
1591 self.apply_subtrie_update_actions(
1592 #[allow(clippy::iter_with_drain)]
1593 update_actions_buf.drain(..),
1594 );
1595 self.update_actions_buffers.push(update_actions_buf);
1596 }
1597
1598 self.lower_subtries[index] = LowerSparseSubtrie::Revealed(subtrie);
1599 }
1600 }
1601}
1602
1603#[derive(Clone, PartialEq, Eq, Debug, Default)]
1606pub struct SparseSubtrie {
1607 pub(crate) path: Nibbles,
1615 nodes: HashMap<Nibbles, SparseNode>,
1617 inner: SparseSubtrieInner,
1619}
1620
1621enum FindNextToLeafOutcome {
1624 Found,
1626 ContinueFrom(Nibbles),
1628 NotFound,
1631 BlindedNode(B256),
1634}
1635
1636impl SparseSubtrie {
1637 pub(crate) fn new(path: Nibbles) -> Self {
1639 Self { path, ..Default::default() }
1640 }
1641
1642 pub(crate) fn is_empty(&self) -> bool {
1644 self.nodes.is_empty()
1645 }
1646
1647 fn is_child_same_level(current_path: &Nibbles, child_path: &Nibbles) -> bool {
1649 let current_level = core::mem::discriminant(&SparseSubtrieType::from_path(current_path));
1650 let child_level = core::mem::discriminant(&SparseSubtrieType::from_path(child_path));
1651 current_level == child_level
1652 }
1653
1654 pub fn update_leaf(
1667 &mut self,
1668 full_path: Nibbles,
1669 value: Vec<u8>,
1670 provider: impl TrieNodeProvider,
1671 retain_updates: bool,
1672 ) -> SparseTrieResult<()> {
1673 debug_assert!(full_path.starts_with(&self.path));
1674 let existing = self.inner.values.insert(full_path, value);
1675 if existing.is_some() {
1676 return Ok(())
1678 }
1679
1680 let mut current = Some(self.path);
1682 while let Some(current_path) = current {
1683 match self.update_next_node(current_path, &full_path, retain_updates)? {
1684 LeafUpdateStep::Continue { next_node } => {
1685 current = Some(next_node);
1686 }
1687 LeafUpdateStep::Complete { reveal_path, .. } => {
1688 if let Some(reveal_path) = reveal_path &&
1689 self.nodes.get(&reveal_path).expect("node must exist").is_hash()
1690 {
1691 debug!(
1692 target: "trie::parallel_sparse",
1693 child_path = ?reveal_path,
1694 leaf_full_path = ?full_path,
1695 "Extension node child not revealed in update_leaf, falling back to db",
1696 );
1697 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1698 provider.trie_node(&reveal_path)?
1699 {
1700 let decoded = TrieNode::decode(&mut &node[..])?;
1701 trace!(
1702 target: "trie::parallel_sparse",
1703 ?reveal_path,
1704 ?decoded,
1705 ?tree_mask,
1706 ?hash_mask,
1707 "Revealing child (from lower)",
1708 );
1709 self.reveal_node(
1710 reveal_path,
1711 &decoded,
1712 TrieMasks { hash_mask, tree_mask },
1713 )?;
1714 } else {
1715 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1716 path: reveal_path,
1717 }
1718 .into())
1719 }
1720 }
1721
1722 current = None;
1723 }
1724 LeafUpdateStep::NodeNotFound => {
1725 current = None;
1726 }
1727 }
1728 }
1729
1730 Ok(())
1731 }
1732
1733 fn update_next_node(
1740 &mut self,
1741 mut current: Nibbles,
1742 path: &Nibbles,
1743 retain_updates: bool,
1744 ) -> SparseTrieResult<LeafUpdateStep> {
1745 debug_assert!(path.starts_with(&self.path));
1746 debug_assert!(current.starts_with(&self.path));
1747 debug_assert!(path.starts_with(¤t));
1748 let Some(node) = self.nodes.get_mut(¤t) else {
1749 return Ok(LeafUpdateStep::NodeNotFound);
1750 };
1751 match node {
1752 SparseNode::Empty => {
1753 let path = path.slice(self.path.len()..);
1756 *node = SparseNode::new_leaf(path);
1757 Ok(LeafUpdateStep::complete_with_insertions(vec![current], None))
1758 }
1759 SparseNode::Hash(hash) => {
1760 Err(SparseTrieErrorKind::BlindedNode { path: current, hash: *hash }.into())
1761 }
1762 SparseNode::Leaf { key: current_key, .. } => {
1763 current.extend(current_key);
1764
1765 debug_assert!(
1767 ¤t != path,
1768 "we already checked leaf presence in the beginning"
1769 );
1770
1771 let common = current.common_prefix_length(path);
1773
1774 let new_ext_key = current.slice(current.len() - current_key.len()..common);
1776 *node = SparseNode::new_ext(new_ext_key);
1777
1778 self.nodes.reserve(3);
1780 let branch_path = current.slice(..common);
1781 let new_leaf_path = path.slice(..=common);
1782 let existing_leaf_path = current.slice(..=common);
1783
1784 self.nodes.insert(
1785 branch_path,
1786 SparseNode::new_split_branch(
1787 current.get_unchecked(common),
1788 path.get_unchecked(common),
1789 ),
1790 );
1791 self.nodes.insert(new_leaf_path, SparseNode::new_leaf(path.slice(common + 1..)));
1792 self.nodes
1793 .insert(existing_leaf_path, SparseNode::new_leaf(current.slice(common + 1..)));
1794
1795 Ok(LeafUpdateStep::complete_with_insertions(
1796 vec![branch_path, new_leaf_path, existing_leaf_path],
1797 None,
1798 ))
1799 }
1800 SparseNode::Extension { key, .. } => {
1801 current.extend(key);
1802
1803 if !path.starts_with(¤t) {
1804 let common = current.common_prefix_length(path);
1806 *key = current.slice(current.len() - key.len()..common);
1807
1808 let reveal_path = retain_updates.then_some(current);
1812
1813 self.nodes.reserve(3);
1816 let branch_path = current.slice(..common);
1817 let new_leaf_path = path.slice(..=common);
1818 let branch = SparseNode::new_split_branch(
1819 current.get_unchecked(common),
1820 path.get_unchecked(common),
1821 );
1822
1823 self.nodes.insert(branch_path, branch);
1824
1825 let new_leaf = SparseNode::new_leaf(path.slice(common + 1..));
1827 self.nodes.insert(new_leaf_path, new_leaf);
1828
1829 let mut inserted_nodes = vec![branch_path, new_leaf_path];
1830
1831 let key = current.slice(common + 1..);
1833 if !key.is_empty() {
1834 let ext_path = current.slice(..=common);
1835 self.nodes.insert(ext_path, SparseNode::new_ext(key));
1836 inserted_nodes.push(ext_path);
1837 }
1838
1839 return Ok(LeafUpdateStep::complete_with_insertions(inserted_nodes, reveal_path))
1840 }
1841
1842 Ok(LeafUpdateStep::continue_with(current))
1843 }
1844 SparseNode::Branch { state_mask, .. } => {
1845 let nibble = path.get_unchecked(current.len());
1846 current.push_unchecked(nibble);
1847 if !state_mask.is_bit_set(nibble) {
1848 state_mask.set_bit(nibble);
1849 let new_leaf = SparseNode::new_leaf(path.slice(current.len()..));
1850 self.nodes.insert(current, new_leaf);
1851 return Ok(LeafUpdateStep::complete_with_insertions(vec![current], None))
1852 }
1853
1854 Ok(LeafUpdateStep::continue_with(current))
1856 }
1857 }
1858 }
1859
1860 fn reveal_node(
1862 &mut self,
1863 path: Nibbles,
1864 node: &TrieNode,
1865 masks: TrieMasks,
1866 ) -> SparseTrieResult<()> {
1867 debug_assert!(path.starts_with(&self.path));
1868
1869 if self.nodes.get(&path).is_some_and(|node| !node.is_hash()) {
1871 return Ok(())
1872 }
1873
1874 match node {
1875 TrieNode::EmptyRoot => {
1876 debug_assert!(path.is_empty());
1878 debug_assert!(self.path.is_empty());
1879 self.nodes.insert(path, SparseNode::Empty);
1880 }
1881 TrieNode::Branch(branch) => {
1882 let mut stack_ptr = branch.as_ref().first_child_index();
1884 for idx in CHILD_INDEX_RANGE {
1885 if branch.state_mask.is_bit_set(idx) {
1886 let mut child_path = path;
1887 child_path.push_unchecked(idx);
1888 if Self::is_child_same_level(&path, &child_path) {
1889 self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
1892 }
1893 stack_ptr += 1;
1894 }
1895 }
1896 match self.nodes.entry(path) {
1899 Entry::Occupied(mut entry) => match entry.get() {
1900 SparseNode::Hash(hash) => {
1902 entry.insert(SparseNode::Branch {
1903 state_mask: branch.state_mask,
1904 hash: Some(*hash),
1907 store_in_db_trie: Some(
1908 masks.hash_mask.is_some_and(|mask| !mask.is_empty()) ||
1909 masks.tree_mask.is_some_and(|mask| !mask.is_empty()),
1910 ),
1911 });
1912 }
1913 SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
1916 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
1918 return Err(SparseTrieErrorKind::Reveal {
1919 path: *entry.key(),
1920 node: Box::new(node.clone()),
1921 }
1922 .into())
1923 }
1924 },
1925 Entry::Vacant(entry) => {
1926 entry.insert(SparseNode::new_branch(branch.state_mask));
1927 }
1928 }
1929 }
1930 TrieNode::Extension(ext) => match self.nodes.entry(path) {
1931 Entry::Occupied(mut entry) => match entry.get() {
1932 SparseNode::Hash(hash) => {
1934 let mut child_path = *entry.key();
1935 child_path.extend(&ext.key);
1936 entry.insert(SparseNode::Extension {
1937 key: ext.key,
1938 hash: Some(*hash),
1941 store_in_db_trie: None,
1942 });
1943 if Self::is_child_same_level(&path, &child_path) {
1944 self.reveal_node_or_hash(child_path, &ext.child)?;
1945 }
1946 }
1947 SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
1950 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
1952 return Err(SparseTrieErrorKind::Reveal {
1953 path: *entry.key(),
1954 node: Box::new(node.clone()),
1955 }
1956 .into())
1957 }
1958 },
1959 Entry::Vacant(entry) => {
1960 let mut child_path = *entry.key();
1961 child_path.extend(&ext.key);
1962 entry.insert(SparseNode::new_ext(ext.key));
1963 if Self::is_child_same_level(&path, &child_path) {
1964 self.reveal_node_or_hash(child_path, &ext.child)?;
1965 }
1966 }
1967 },
1968 TrieNode::Leaf(leaf) => match self.nodes.entry(path) {
1969 Entry::Occupied(mut entry) => match entry.get() {
1970 SparseNode::Hash(hash) => {
1972 let mut full = *entry.key();
1973 full.extend(&leaf.key);
1974 self.inner.values.insert(full, leaf.value.clone());
1975 entry.insert(SparseNode::Leaf {
1976 key: leaf.key,
1977 hash: Some(*hash),
1980 });
1981 }
1982 SparseNode::Leaf { .. } => {}
1984 node @ (SparseNode::Empty |
1986 SparseNode::Extension { .. } |
1987 SparseNode::Branch { .. }) => {
1988 return Err(SparseTrieErrorKind::Reveal {
1989 path: *entry.key(),
1990 node: Box::new(node.clone()),
1991 }
1992 .into())
1993 }
1994 },
1995 Entry::Vacant(entry) => {
1996 let mut full = *entry.key();
1997 full.extend(&leaf.key);
1998 entry.insert(SparseNode::new_leaf(leaf.key));
1999 self.inner.values.insert(full, leaf.value.clone());
2000 }
2001 },
2002 }
2003
2004 Ok(())
2005 }
2006
2007 fn reveal_node_or_hash(&mut self, path: Nibbles, child: &[u8]) -> SparseTrieResult<()> {
2026 if child.len() == B256::len_bytes() + 1 {
2027 let hash = B256::from_slice(&child[1..]);
2028 match self.nodes.entry(path) {
2029 Entry::Occupied(entry) => match entry.get() {
2030 SparseNode::Hash(previous_hash) if previous_hash != &hash => {
2032 return Err(SparseTrieErrorKind::Reveal {
2033 path: *entry.key(),
2034 node: Box::new(SparseNode::Hash(hash)),
2035 }
2036 .into())
2037 }
2038 _ => {}
2039 },
2040 Entry::Vacant(entry) => {
2041 entry.insert(SparseNode::Hash(hash));
2042 }
2043 }
2044 return Ok(())
2045 }
2046
2047 self.reveal_node(path, &TrieNode::decode(&mut &child[..])?, TrieMasks::none())
2048 }
2049
2050 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, fields(root = ?self.path), ret)]
2073 fn update_hashes(
2074 &mut self,
2075 prefix_set: &mut PrefixSet,
2076 update_actions: &mut Option<Vec<SparseTrieUpdatesAction>>,
2077 branch_node_tree_masks: &HashMap<Nibbles, TrieMask>,
2078 branch_node_hash_masks: &HashMap<Nibbles, TrieMask>,
2079 ) -> RlpNode {
2080 trace!(target: "trie::parallel_sparse", "Updating subtrie hashes");
2081
2082 debug_assert!(prefix_set.iter().all(|path| path.starts_with(&self.path)));
2083
2084 debug_assert!(self.inner.buffers.path_stack.is_empty());
2085 self.inner
2086 .buffers
2087 .path_stack
2088 .push(RlpNodePathStackItem { path: self.path, is_in_prefix_set: None });
2089
2090 while let Some(stack_item) = self.inner.buffers.path_stack.pop() {
2091 let path = stack_item.path;
2092 let node = self
2093 .nodes
2094 .get_mut(&path)
2095 .unwrap_or_else(|| panic!("node at path {path:?} does not exist"));
2096
2097 self.inner.rlp_node(
2098 prefix_set,
2099 update_actions,
2100 stack_item,
2101 node,
2102 branch_node_tree_masks,
2103 branch_node_hash_masks,
2104 );
2105 }
2106
2107 debug_assert_eq!(self.inner.buffers.rlp_node_stack.len(), 1);
2108 self.inner.buffers.rlp_node_stack.pop().unwrap().rlp_node
2109 }
2110
2111 fn wipe(&mut self) {
2114 self.nodes = HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]);
2115 self.inner.clear();
2116 }
2117
2118 pub(crate) fn clear(&mut self) {
2120 self.nodes.clear();
2121 self.inner.clear();
2122 }
2123
2124 pub(crate) fn shrink_nodes_to(&mut self, size: usize) {
2126 self.nodes.shrink_to(size);
2127 }
2128
2129 pub(crate) fn shrink_values_to(&mut self, size: usize) {
2131 self.inner.values.shrink_to(size);
2132 }
2133}
2134
2135#[derive(Clone, PartialEq, Eq, Debug, Default)]
2138struct SparseSubtrieInner {
2139 values: HashMap<Nibbles, Vec<u8>>,
2142 buffers: SparseSubtrieBuffers,
2144}
2145
2146impl SparseSubtrieInner {
2147 fn rlp_node(
2178 &mut self,
2179 prefix_set: &mut PrefixSet,
2180 update_actions: &mut Option<Vec<SparseTrieUpdatesAction>>,
2181 mut stack_item: RlpNodePathStackItem,
2182 node: &mut SparseNode,
2183 branch_node_tree_masks: &HashMap<Nibbles, TrieMask>,
2184 branch_node_hash_masks: &HashMap<Nibbles, TrieMask>,
2185 ) {
2186 let path = stack_item.path;
2187 trace!(
2188 target: "trie::parallel_sparse",
2189 ?path,
2190 ?node,
2191 "Calculating node RLP"
2192 );
2193
2194 let mut prefix_set_contains = |path: &Nibbles| {
2198 *stack_item.is_in_prefix_set.get_or_insert_with(|| prefix_set.contains(path))
2199 };
2200
2201 let (rlp_node, node_type) = match node {
2202 SparseNode::Empty => (RlpNode::word_rlp(&EMPTY_ROOT_HASH), SparseNodeType::Empty),
2203 SparseNode::Hash(hash) => {
2204 (RlpNode::word_rlp(hash), SparseNodeType::Hash)
2206 }
2207 SparseNode::Leaf { key, hash } => {
2208 let mut path = path;
2209 path.extend(key);
2210 let value = self.values.get(&path);
2211 if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path) || value.is_none())
2212 {
2213 (RlpNode::word_rlp(&hash), SparseNodeType::Leaf)
2217 } else {
2218 let value = self.values.get(&path).unwrap();
2220 self.buffers.rlp_buf.clear();
2221 let rlp_node = LeafNodeRef { key, value }.rlp(&mut self.buffers.rlp_buf);
2222 *hash = rlp_node.as_hash();
2223 (rlp_node, SparseNodeType::Leaf)
2224 }
2225 }
2226 SparseNode::Extension { key, hash, store_in_db_trie } => {
2227 let mut child_path = path;
2228 child_path.extend(key);
2229 if let Some((hash, store_in_db_trie)) =
2230 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
2231 {
2232 (
2235 RlpNode::word_rlp(&hash),
2236 SparseNodeType::Extension { store_in_db_trie: Some(store_in_db_trie) },
2237 )
2238 } else if self.buffers.rlp_node_stack.last().is_some_and(|e| e.path == child_path) {
2239 let RlpNodeStackItem { path: _, rlp_node: child, node_type: child_node_type } =
2242 self.buffers.rlp_node_stack.pop().unwrap();
2243 self.buffers.rlp_buf.clear();
2244 let rlp_node =
2245 ExtensionNodeRef::new(key, &child).rlp(&mut self.buffers.rlp_buf);
2246 *hash = rlp_node.as_hash();
2247
2248 let store_in_db_trie_value = child_node_type.store_in_db_trie();
2249
2250 trace!(
2251 target: "trie::parallel_sparse",
2252 ?path,
2253 ?child_path,
2254 ?child_node_type,
2255 "Extension node"
2256 );
2257
2258 *store_in_db_trie = store_in_db_trie_value;
2259
2260 (
2261 rlp_node,
2262 SparseNodeType::Extension {
2263 store_in_db_trie: store_in_db_trie_value,
2266 },
2267 )
2268 } else {
2269 self.buffers.path_stack.extend([
2272 RlpNodePathStackItem {
2273 path,
2274 is_in_prefix_set: Some(prefix_set_contains(&path)),
2275 },
2276 RlpNodePathStackItem { path: child_path, is_in_prefix_set: None },
2277 ]);
2278 return
2279 }
2280 }
2281 SparseNode::Branch { state_mask, hash, store_in_db_trie } => {
2282 if let Some((hash, store_in_db_trie)) =
2283 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
2284 {
2285 self.buffers.rlp_node_stack.push(RlpNodeStackItem {
2288 path,
2289 rlp_node: RlpNode::word_rlp(&hash),
2290 node_type: SparseNodeType::Branch {
2291 store_in_db_trie: Some(store_in_db_trie),
2292 },
2293 });
2294 return
2295 }
2296
2297 let retain_updates = update_actions.is_some() && prefix_set_contains(&path);
2298
2299 self.buffers.branch_child_buf.clear();
2300 for bit in CHILD_INDEX_RANGE.rev() {
2303 if state_mask.is_bit_set(bit) {
2304 let mut child = path;
2305 child.push_unchecked(bit);
2306 self.buffers.branch_child_buf.push(child);
2307 }
2308 }
2309
2310 self.buffers
2311 .branch_value_stack_buf
2312 .resize(self.buffers.branch_child_buf.len(), Default::default());
2313 let mut added_children = false;
2314
2315 let mut tree_mask = TrieMask::default();
2316 let mut hash_mask = TrieMask::default();
2317 let mut hashes = Vec::new();
2318 for (i, child_path) in self.buffers.branch_child_buf.iter().enumerate() {
2319 if self.buffers.rlp_node_stack.last().is_some_and(|e| &e.path == child_path) {
2320 let RlpNodeStackItem {
2321 path: _,
2322 rlp_node: child,
2323 node_type: child_node_type,
2324 } = self.buffers.rlp_node_stack.pop().unwrap();
2325
2326 if retain_updates {
2328 let last_child_nibble = child_path.last().unwrap();
2330
2331 let should_set_tree_mask_bit = if let Some(store_in_db_trie) =
2333 child_node_type.store_in_db_trie()
2334 {
2335 store_in_db_trie
2338 } else {
2339 child_node_type.is_hash() &&
2341 branch_node_tree_masks
2342 .get(&path)
2343 .is_some_and(|mask| mask.is_bit_set(last_child_nibble))
2344 };
2345 if should_set_tree_mask_bit {
2346 tree_mask.set_bit(last_child_nibble);
2347 }
2348
2349 let hash = child.as_hash().filter(|_| {
2353 child_node_type.is_branch() ||
2354 (child_node_type.is_hash() &&
2355 branch_node_hash_masks.get(&path).is_some_and(
2356 |mask| mask.is_bit_set(last_child_nibble),
2357 ))
2358 });
2359 if let Some(hash) = hash {
2360 hash_mask.set_bit(last_child_nibble);
2361 hashes.push(hash);
2362 }
2363 }
2364
2365 let original_idx = self.buffers.branch_child_buf.len() - i - 1;
2369 self.buffers.branch_value_stack_buf[original_idx] = child;
2370 added_children = true;
2371 } else {
2372 debug_assert!(!added_children);
2375 self.buffers.path_stack.push(RlpNodePathStackItem {
2376 path,
2377 is_in_prefix_set: Some(prefix_set_contains(&path)),
2378 });
2379 self.buffers.path_stack.extend(
2380 self.buffers
2381 .branch_child_buf
2382 .drain(..)
2383 .map(|path| RlpNodePathStackItem { path, is_in_prefix_set: None }),
2384 );
2385 return
2386 }
2387 }
2388
2389 trace!(
2390 target: "trie::parallel_sparse",
2391 ?path,
2392 ?tree_mask,
2393 ?hash_mask,
2394 "Branch node masks"
2395 );
2396
2397 self.buffers.rlp_buf.clear();
2400 let branch_node_ref =
2401 BranchNodeRef::new(&self.buffers.branch_value_stack_buf, *state_mask);
2402 let rlp_node = branch_node_ref.rlp(&mut self.buffers.rlp_buf);
2403 *hash = rlp_node.as_hash();
2404
2405 let store_in_db_trie_value = if let Some(update_actions) =
2408 update_actions.as_mut().filter(|_| retain_updates && !path.is_empty())
2409 {
2410 let store_in_db_trie = !tree_mask.is_empty() || !hash_mask.is_empty();
2411 if store_in_db_trie {
2412 hashes.reverse();
2415 let branch_node = BranchNodeCompact::new(
2416 *state_mask,
2417 tree_mask,
2418 hash_mask,
2419 hashes,
2420 hash.filter(|_| path.is_empty()),
2421 );
2422 update_actions
2423 .push(SparseTrieUpdatesAction::InsertUpdated(path, branch_node));
2424 } else if branch_node_tree_masks.get(&path).is_some_and(|mask| !mask.is_empty()) ||
2425 branch_node_hash_masks.get(&path).is_some_and(|mask| !mask.is_empty())
2426 {
2427 update_actions.push(SparseTrieUpdatesAction::InsertRemoved(path));
2431 } else if branch_node_tree_masks.get(&path).is_none_or(|mask| mask.is_empty()) &&
2432 branch_node_hash_masks.get(&path).is_none_or(|mask| mask.is_empty())
2433 {
2434 update_actions.push(SparseTrieUpdatesAction::RemoveUpdated(path));
2437 }
2438
2439 store_in_db_trie
2440 } else {
2441 false
2442 };
2443 *store_in_db_trie = Some(store_in_db_trie_value);
2444
2445 (
2446 rlp_node,
2447 SparseNodeType::Branch { store_in_db_trie: Some(store_in_db_trie_value) },
2448 )
2449 }
2450 };
2451
2452 self.buffers.rlp_node_stack.push(RlpNodeStackItem { path, rlp_node, node_type });
2453 trace!(
2454 target: "trie::parallel_sparse",
2455 ?path,
2456 ?node_type,
2457 "Added node to RLP node stack"
2458 );
2459 }
2460
2461 fn clear(&mut self) {
2463 self.values.clear();
2464 self.buffers.clear();
2465 }
2466}
2467
2468#[derive(Clone, Debug, PartialEq, Eq, Default)]
2470pub enum LeafUpdateStep {
2471 Continue {
2473 next_node: Nibbles,
2475 },
2476 Complete {
2478 inserted_nodes: Vec<Nibbles>,
2480 reveal_path: Option<Nibbles>,
2482 },
2483 #[default]
2485 NodeNotFound,
2486}
2487
2488impl LeafUpdateStep {
2489 pub const fn continue_with(next_node: Nibbles) -> Self {
2491 Self::Continue { next_node }
2492 }
2493
2494 pub const fn complete_with_insertions(
2496 inserted_nodes: Vec<Nibbles>,
2497 reveal_path: Option<Nibbles>,
2498 ) -> Self {
2499 Self::Complete { inserted_nodes, reveal_path }
2500 }
2501}
2502
2503#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2512pub enum SparseSubtrieType {
2513 Upper,
2515 Lower(usize),
2518}
2519
2520impl SparseSubtrieType {
2521 pub const fn path_len_is_upper(len: usize) -> bool {
2526 len < UPPER_TRIE_MAX_DEPTH
2527 }
2528
2529 pub fn from_path(path: &Nibbles) -> Self {
2531 if Self::path_len_is_upper(path.len()) {
2532 Self::Upper
2533 } else {
2534 Self::Lower(path_subtrie_index_unchecked(path))
2535 }
2536 }
2537
2538 pub const fn lower_index(&self) -> Option<usize> {
2540 match self {
2541 Self::Upper => None,
2542 Self::Lower(index) => Some(*index),
2543 }
2544 }
2545}
2546
2547impl Ord for SparseSubtrieType {
2548 fn cmp(&self, other: &Self) -> Ordering {
2551 match (self, other) {
2552 (Self::Upper, Self::Upper) => Ordering::Equal,
2553 (Self::Upper, Self::Lower(_)) => Ordering::Less,
2554 (Self::Lower(_), Self::Upper) => Ordering::Greater,
2555 (Self::Lower(idx_a), Self::Lower(idx_b)) if idx_a == idx_b => Ordering::Equal,
2556 (Self::Lower(idx_a), Self::Lower(idx_b)) => idx_a.cmp(idx_b),
2557 }
2558 }
2559}
2560
2561impl PartialOrd for SparseSubtrieType {
2562 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2563 Some(self.cmp(other))
2564 }
2565}
2566
2567#[derive(Clone, PartialEq, Eq, Debug, Default)]
2571pub struct SparseSubtrieBuffers {
2572 path_stack: Vec<RlpNodePathStackItem>,
2574 rlp_node_stack: Vec<RlpNodeStackItem>,
2576 branch_child_buf: SmallVec<[Nibbles; 16]>,
2578 branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
2580 rlp_buf: Vec<u8>,
2582}
2583
2584impl SparseSubtrieBuffers {
2585 fn clear(&mut self) {
2587 self.path_stack.clear();
2588 self.path_stack.shrink_to_fit();
2589
2590 self.rlp_node_stack.clear();
2591 self.rlp_node_stack.shrink_to_fit();
2592
2593 self.branch_child_buf.clear();
2594 self.branch_child_buf.shrink_to_fit();
2595
2596 self.branch_value_stack_buf.clear();
2597 self.branch_value_stack_buf.shrink_to_fit();
2598
2599 self.rlp_buf.clear();
2600 self.rlp_buf.shrink_to_fit();
2601 }
2602}
2603
2604#[derive(Clone, PartialEq, Eq, Debug)]
2606pub struct RlpNodePathStackItem {
2607 pub path: Nibbles,
2609 pub is_in_prefix_set: Option<bool>,
2611}
2612
2613#[derive(Debug)]
2615struct ChangedSubtrie {
2616 index: usize,
2618 subtrie: Box<SparseSubtrie>,
2620 prefix_set: PrefixSet,
2622 update_actions_buf: Option<Vec<SparseTrieUpdatesAction>>,
2625}
2626
2627fn path_subtrie_index_unchecked(path: &Nibbles) -> usize {
2634 debug_assert_eq!(UPPER_TRIE_MAX_DEPTH, 2);
2635 path.get_byte_unchecked(0) as usize
2636}
2637
2638#[derive(Clone, Debug, Eq, PartialEq)]
2640enum SparseTrieUpdatesAction {
2641 InsertRemoved(Nibbles),
2643 RemoveUpdated(Nibbles),
2646 InsertUpdated(Nibbles, BranchNodeCompact),
2648}
2649
2650#[cfg(test)]
2651mod tests {
2652 use super::{
2653 path_subtrie_index_unchecked, LowerSparseSubtrie, ParallelSparseTrie, SparseSubtrie,
2654 SparseSubtrieType,
2655 };
2656 use crate::trie::ChangedSubtrie;
2657 use alloy_primitives::{
2658 b256, hex,
2659 map::{B256Set, DefaultHashBuilder, HashMap},
2660 B256, U256,
2661 };
2662 use alloy_rlp::{Decodable, Encodable};
2663 use alloy_trie::{BranchNodeCompact, Nibbles};
2664 use assert_matches::assert_matches;
2665 use itertools::Itertools;
2666 use proptest::{prelude::*, sample::SizeRange};
2667 use proptest_arbitrary_interop::arb;
2668 use reth_execution_errors::{SparseTrieError, SparseTrieErrorKind};
2669 use reth_primitives_traits::Account;
2670 use reth_provider::{test_utils::create_test_provider_factory, TrieWriter};
2671 use reth_trie::{
2672 hashed_cursor::{noop::NoopHashedCursor, HashedPostStateCursor},
2673 node_iter::{TrieElement, TrieNodeIter},
2674 trie_cursor::{noop::NoopAccountTrieCursor, TrieCursor, TrieCursorFactory},
2675 walker::TrieWalker,
2676 HashedPostState,
2677 };
2678 use reth_trie_common::{
2679 prefix_set::PrefixSetMut,
2680 proof::{ProofNodes, ProofRetainer},
2681 updates::TrieUpdates,
2682 BranchNode, ExtensionNode, HashBuilder, LeafNode, ProofTrieNode, RlpNode, TrieMask,
2683 TrieMasks, TrieNode, EMPTY_ROOT_HASH,
2684 };
2685 use reth_trie_db::DatabaseTrieCursorFactory;
2686 use reth_trie_sparse::{
2687 provider::{DefaultTrieNodeProvider, RevealedNode, TrieNodeProvider},
2688 LeafLookup, LeafLookupError, SerialSparseTrie, SparseNode, SparseTrieInterface,
2689 SparseTrieUpdates,
2690 };
2691 use std::collections::{BTreeMap, BTreeSet};
2692
2693 fn pad_nibbles_right(mut nibbles: Nibbles) -> Nibbles {
2695 nibbles.extend(&Nibbles::from_nibbles_unchecked(vec![
2696 0;
2697 B256::len_bytes() * 2 - nibbles.len()
2698 ]));
2699 nibbles
2700 }
2701
2702 #[derive(Debug, Clone)]
2707 struct MockTrieNodeProvider {
2708 nodes: HashMap<Nibbles, RevealedNode, DefaultHashBuilder>,
2710 }
2711
2712 impl MockTrieNodeProvider {
2713 fn new() -> Self {
2715 Self { nodes: HashMap::default() }
2716 }
2717
2718 fn add_revealed_node(&mut self, path: Nibbles, node: RevealedNode) {
2720 self.nodes.insert(path, node);
2721 }
2722 }
2723
2724 impl TrieNodeProvider for MockTrieNodeProvider {
2725 fn trie_node(&self, path: &Nibbles) -> Result<Option<RevealedNode>, SparseTrieError> {
2726 Ok(self.nodes.get(path).cloned())
2727 }
2728 }
2729
2730 fn create_account(nonce: u64) -> Account {
2731 Account { nonce, ..Default::default() }
2732 }
2733
2734 fn encode_account_value(nonce: u64) -> Vec<u8> {
2735 let account = Account { nonce, ..Default::default() };
2736 let trie_account = account.into_trie_account(EMPTY_ROOT_HASH);
2737 let mut buf = Vec::new();
2738 trie_account.encode(&mut buf);
2739 buf
2740 }
2741
2742 #[derive(Default)]
2744 struct ParallelSparseTrieTestContext;
2745
2746 impl ParallelSparseTrieTestContext {
2747 fn assert_subtrie_exists(&self, trie: &ParallelSparseTrie, path: &Nibbles) {
2749 let idx = path_subtrie_index_unchecked(path);
2750 assert!(
2751 trie.lower_subtries[idx].as_revealed_ref().is_some(),
2752 "Expected lower subtrie at path {path:?} to exist",
2753 );
2754 }
2755
2756 fn get_subtrie<'a>(
2758 &self,
2759 trie: &'a ParallelSparseTrie,
2760 path: &Nibbles,
2761 ) -> &'a SparseSubtrie {
2762 let idx = path_subtrie_index_unchecked(path);
2763 trie.lower_subtries[idx]
2764 .as_revealed_ref()
2765 .unwrap_or_else(|| panic!("Lower subtrie at path {path:?} should exist"))
2766 }
2767
2768 fn assert_subtrie_path(
2770 &self,
2771 trie: &ParallelSparseTrie,
2772 subtrie_prefix: impl AsRef<[u8]>,
2773 expected_path: impl AsRef<[u8]>,
2774 ) {
2775 let subtrie_prefix = Nibbles::from_nibbles(subtrie_prefix);
2776 let expected_path = Nibbles::from_nibbles(expected_path);
2777 let idx = path_subtrie_index_unchecked(&subtrie_prefix);
2778
2779 let subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap_or_else(|| {
2780 panic!("Lower subtrie at prefix {subtrie_prefix:?} should exist")
2781 });
2782
2783 assert_eq!(
2784 subtrie.path, expected_path,
2785 "Subtrie at prefix {subtrie_prefix:?} should have path {expected_path:?}, but has {:?}",
2786 subtrie.path
2787 );
2788 }
2789
2790 fn create_test_leaves(&self, paths: &[&[u8]]) -> Vec<(Nibbles, Vec<u8>)> {
2792 paths
2793 .iter()
2794 .enumerate()
2795 .map(|(i, path)| (Nibbles::from_nibbles(path), encode_account_value(i as u64 + 1)))
2796 .collect()
2797 }
2798
2799 fn create_test_leaf(&self, path: impl AsRef<[u8]>, value_nonce: u64) -> (Nibbles, Vec<u8>) {
2801 (Nibbles::from_nibbles(path), encode_account_value(value_nonce))
2802 }
2803
2804 fn update_leaves(
2806 &self,
2807 trie: &mut ParallelSparseTrie,
2808 leaves: impl IntoIterator<Item = (Nibbles, Vec<u8>)>,
2809 ) {
2810 for (path, value) in leaves {
2811 trie.update_leaf(path, value, DefaultTrieNodeProvider).unwrap();
2812 }
2813 }
2814
2815 fn assert_subtrie<'a>(
2817 &self,
2818 trie: &'a ParallelSparseTrie,
2819 path: Nibbles,
2820 ) -> SubtrieAssertion<'a> {
2821 self.assert_subtrie_exists(trie, &path);
2822 let subtrie = self.get_subtrie(trie, &path);
2823 SubtrieAssertion::new(subtrie)
2824 }
2825
2826 fn assert_upper_subtrie<'a>(&self, trie: &'a ParallelSparseTrie) -> SubtrieAssertion<'a> {
2828 SubtrieAssertion::new(&trie.upper_subtrie)
2829 }
2830
2831 fn assert_with_hash_builder(
2833 &self,
2834 trie: &mut ParallelSparseTrie,
2835 hash_builder_root: B256,
2836 hash_builder_updates: TrieUpdates,
2837 hash_builder_proof_nodes: ProofNodes,
2838 ) {
2839 assert_eq!(trie.root(), hash_builder_root);
2840 pretty_assertions::assert_eq!(
2841 BTreeMap::from_iter(trie.updates_ref().updated_nodes.clone()),
2842 BTreeMap::from_iter(hash_builder_updates.account_nodes)
2843 );
2844 assert_eq_parallel_sparse_trie_proof_nodes(trie, hash_builder_proof_nodes);
2845 }
2846 }
2847
2848 struct SubtrieAssertion<'a> {
2850 subtrie: &'a SparseSubtrie,
2851 }
2852
2853 impl<'a> SubtrieAssertion<'a> {
2854 fn new(subtrie: &'a SparseSubtrie) -> Self {
2855 Self { subtrie }
2856 }
2857
2858 fn has_branch(self, path: &Nibbles, expected_mask_bits: &[u8]) -> Self {
2859 match self.subtrie.nodes.get(path) {
2860 Some(SparseNode::Branch { state_mask, .. }) => {
2861 for bit in expected_mask_bits {
2862 assert!(
2863 state_mask.is_bit_set(*bit),
2864 "Expected branch at {path:?} to have bit {bit} set, instead mask is: {state_mask:?}",
2865 );
2866 }
2867 }
2868 node => panic!("Expected branch node at {path:?}, found {node:?}"),
2869 }
2870 self
2871 }
2872
2873 fn has_leaf(self, path: &Nibbles, expected_key: &Nibbles) -> Self {
2874 match self.subtrie.nodes.get(path) {
2875 Some(SparseNode::Leaf { key, .. }) => {
2876 assert_eq!(
2877 *key, *expected_key,
2878 "Expected leaf at {path:?} to have key {expected_key:?}, found {key:?}",
2879 );
2880 }
2881 node => panic!("Expected leaf node at {path:?}, found {node:?}"),
2882 }
2883 self
2884 }
2885
2886 fn has_extension(self, path: &Nibbles, expected_key: &Nibbles) -> Self {
2887 match self.subtrie.nodes.get(path) {
2888 Some(SparseNode::Extension { key, .. }) => {
2889 assert_eq!(
2890 *key, *expected_key,
2891 "Expected extension at {path:?} to have key {expected_key:?}, found {key:?}",
2892 );
2893 }
2894 node => panic!("Expected extension node at {path:?}, found {node:?}"),
2895 }
2896 self
2897 }
2898
2899 fn has_hash(self, path: &Nibbles, expected_hash: &B256) -> Self {
2900 match self.subtrie.nodes.get(path) {
2901 Some(SparseNode::Hash(hash)) => {
2902 assert_eq!(
2903 *hash, *expected_hash,
2904 "Expected hash at {path:?} to be {expected_hash:?}, found {hash:?}",
2905 );
2906 }
2907 node => panic!("Expected hash node at {path:?}, found {node:?}"),
2908 }
2909 self
2910 }
2911
2912 fn has_value(self, path: &Nibbles, expected_value: &[u8]) -> Self {
2913 let actual = self.subtrie.inner.values.get(path);
2914 assert_eq!(
2915 actual.map(|v| v.as_slice()),
2916 Some(expected_value),
2917 "Expected value at {path:?} to be {expected_value:?}, found {actual:?}",
2918 );
2919 self
2920 }
2921
2922 fn has_no_value(self, path: &Nibbles) -> Self {
2923 let actual = self.subtrie.inner.values.get(path);
2924 assert!(actual.is_none(), "Expected no value at {path:?}, but found {actual:?}");
2925 self
2926 }
2927 }
2928
2929 fn create_leaf_node(key: impl AsRef<[u8]>, value_nonce: u64) -> TrieNode {
2930 TrieNode::Leaf(LeafNode::new(Nibbles::from_nibbles(key), encode_account_value(value_nonce)))
2931 }
2932
2933 fn create_extension_node(key: impl AsRef<[u8]>, child_hash: B256) -> TrieNode {
2934 TrieNode::Extension(ExtensionNode::new(
2935 Nibbles::from_nibbles(key),
2936 RlpNode::word_rlp(&child_hash),
2937 ))
2938 }
2939
2940 fn create_branch_node_with_children(
2941 children_indices: &[u8],
2942 child_hashes: impl IntoIterator<Item = RlpNode>,
2943 ) -> TrieNode {
2944 let mut stack = Vec::new();
2945 let mut state_mask = TrieMask::default();
2946
2947 for (&idx, hash) in children_indices.iter().zip(child_hashes.into_iter()) {
2948 state_mask.set_bit(idx);
2949 stack.push(hash);
2950 }
2951
2952 TrieNode::Branch(BranchNode::new(stack, state_mask))
2953 }
2954
2955 fn run_hash_builder(
2960 state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
2961 trie_cursor: impl TrieCursor,
2962 destroyed_accounts: B256Set,
2963 proof_targets: impl IntoIterator<Item = Nibbles>,
2964 ) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>, HashMap<Nibbles, TrieMask>)
2965 {
2966 let mut account_rlp = Vec::new();
2967
2968 let mut hash_builder = HashBuilder::default()
2969 .with_updates(true)
2970 .with_proof_retainer(ProofRetainer::from_iter(proof_targets));
2971
2972 let mut prefix_set = PrefixSetMut::default();
2973 prefix_set.extend_keys(state.clone().into_iter().map(|(nibbles, _)| nibbles));
2974 prefix_set.extend_keys(destroyed_accounts.iter().map(Nibbles::unpack));
2975 let walker = TrieWalker::<_>::state_trie(trie_cursor, prefix_set.freeze())
2976 .with_deletions_retained(true);
2977 let hashed_post_state = HashedPostState::default()
2978 .with_accounts(state.into_iter().map(|(nibbles, account)| {
2979 (nibbles.pack().into_inner().unwrap().into(), Some(account))
2980 }))
2981 .into_sorted();
2982 let mut node_iter = TrieNodeIter::state_trie(
2983 walker,
2984 HashedPostStateCursor::new_account(
2985 NoopHashedCursor::<Account>::default(),
2986 &hashed_post_state,
2987 ),
2988 );
2989
2990 while let Some(node) = node_iter.try_next().unwrap() {
2991 match node {
2992 TrieElement::Branch(branch) => {
2993 hash_builder.add_branch(branch.key, branch.value, branch.children_are_in_trie);
2994 }
2995 TrieElement::Leaf(key, account) => {
2996 let account = account.into_trie_account(EMPTY_ROOT_HASH);
2997 account.encode(&mut account_rlp);
2998
2999 hash_builder.add_leaf(Nibbles::unpack(key), &account_rlp);
3000 account_rlp.clear();
3001 }
3002 }
3003 }
3004 let root = hash_builder.root();
3005 let proof_nodes = hash_builder.take_proof_nodes();
3006 let branch_node_hash_masks = hash_builder
3007 .updated_branch_nodes
3008 .clone()
3009 .unwrap_or_default()
3010 .iter()
3011 .map(|(path, node)| (*path, node.hash_mask))
3012 .collect();
3013 let branch_node_tree_masks = hash_builder
3014 .updated_branch_nodes
3015 .clone()
3016 .unwrap_or_default()
3017 .iter()
3018 .map(|(path, node)| (*path, node.tree_mask))
3019 .collect();
3020
3021 let mut trie_updates = TrieUpdates::default();
3022 let removed_keys = node_iter.walker.take_removed_keys();
3023 trie_updates.finalize(hash_builder, removed_keys, destroyed_accounts);
3024
3025 (root, trie_updates, proof_nodes, branch_node_hash_masks, branch_node_tree_masks)
3026 }
3027
3028 fn new_test_trie<Nodes>(nodes: Nodes) -> ParallelSparseTrie
3031 where
3032 Nodes: Iterator<Item = (Nibbles, SparseNode)>,
3033 {
3034 let mut trie = ParallelSparseTrie::default().with_updates(true);
3035
3036 for (path, node) in nodes {
3037 let subtrie = trie.subtrie_for_path_mut(&path);
3038 if let SparseNode::Leaf { key, .. } = &node {
3039 let mut full_key = path;
3040 full_key.extend(key);
3041 subtrie.inner.values.insert(full_key, "LEAF VALUE".into());
3042 }
3043 subtrie.nodes.insert(path, node);
3044 }
3045 trie
3046 }
3047
3048 fn parallel_sparse_trie_nodes(
3049 sparse_trie: &ParallelSparseTrie,
3050 ) -> impl IntoIterator<Item = (&Nibbles, &SparseNode)> {
3051 let lower_sparse_nodes = sparse_trie
3052 .lower_subtries
3053 .iter()
3054 .filter_map(|subtrie| subtrie.as_revealed_ref())
3055 .flat_map(|subtrie| subtrie.nodes.iter());
3056
3057 let upper_sparse_nodes = sparse_trie.upper_subtrie.nodes.iter();
3058
3059 lower_sparse_nodes.chain(upper_sparse_nodes).sorted_by_key(|(path, _)| *path)
3060 }
3061
3062 fn assert_eq_parallel_sparse_trie_proof_nodes(
3065 sparse_trie: &ParallelSparseTrie,
3066 proof_nodes: ProofNodes,
3067 ) {
3068 let proof_nodes = proof_nodes
3069 .into_nodes_sorted()
3070 .into_iter()
3071 .map(|(path, node)| (path, TrieNode::decode(&mut node.as_ref()).unwrap()));
3072
3073 let all_sparse_nodes = parallel_sparse_trie_nodes(sparse_trie);
3074
3075 for ((proof_node_path, proof_node), (sparse_node_path, sparse_node)) in
3076 proof_nodes.zip(all_sparse_nodes)
3077 {
3078 assert_eq!(&proof_node_path, sparse_node_path);
3079
3080 let equals = match (&proof_node, &sparse_node) {
3081 (TrieNode::EmptyRoot, SparseNode::Empty) => true,
3083 (
3085 TrieNode::Branch(BranchNode { state_mask: proof_state_mask, .. }),
3086 SparseNode::Branch { state_mask: sparse_state_mask, .. },
3087 ) => proof_state_mask == sparse_state_mask,
3088 (
3090 TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
3091 SparseNode::Extension { key: sparse_key, .. },
3092 ) |
3093 (
3095 TrieNode::Leaf(LeafNode { key: proof_key, .. }),
3096 SparseNode::Leaf { key: sparse_key, .. },
3097 ) => proof_key == sparse_key,
3098 (_, SparseNode::Empty | SparseNode::Hash(_)) => continue,
3100 _ => false,
3101 };
3102 assert!(
3103 equals,
3104 "path: {proof_node_path:?}\nproof node: {proof_node:?}\nsparse node: {sparse_node:?}"
3105 );
3106 }
3107 }
3108
3109 #[test]
3110 fn test_get_changed_subtries_empty() {
3111 let mut trie = ParallelSparseTrie::default();
3112 let mut prefix_set = PrefixSetMut::from([Nibbles::default()]).freeze();
3113
3114 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3115 assert!(subtries.is_empty());
3116 assert_eq!(unchanged_prefix_set, PrefixSetMut::from(prefix_set.iter().copied()));
3117 }
3118
3119 #[test]
3120 fn test_get_changed_subtries() {
3121 let mut trie = ParallelSparseTrie::default();
3123 let subtrie_1 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3124 let subtrie_1_index = path_subtrie_index_unchecked(&subtrie_1.path);
3125 let subtrie_2 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x1, 0x0])));
3126 let subtrie_2_index = path_subtrie_index_unchecked(&subtrie_2.path);
3127 let subtrie_3 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x3, 0x0])));
3128 let subtrie_3_index = path_subtrie_index_unchecked(&subtrie_3.path);
3129
3130 trie.lower_subtries[subtrie_1_index] = LowerSparseSubtrie::Revealed(subtrie_1.clone());
3132 trie.lower_subtries[subtrie_2_index] = LowerSparseSubtrie::Revealed(subtrie_2.clone());
3133 trie.lower_subtries[subtrie_3_index] = LowerSparseSubtrie::Revealed(subtrie_3);
3134
3135 let unchanged_prefix_set = PrefixSetMut::from([
3136 Nibbles::from_nibbles([0x0]),
3137 Nibbles::from_nibbles([0x2, 0x0, 0x0]),
3138 ]);
3139 let mut prefix_set = PrefixSetMut::from([
3141 Nibbles::from_nibbles([0x1, 0x0, 0x0]),
3143 Nibbles::from_nibbles([0x1, 0x0, 0x1, 0x0]),
3144 ]);
3145 prefix_set.extend(unchanged_prefix_set);
3146 let mut prefix_set = prefix_set.freeze();
3147
3148 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3150 assert_eq!(
3151 subtries
3152 .into_iter()
3153 .map(|ChangedSubtrie { index, subtrie, prefix_set, .. }| {
3154 (index, subtrie, prefix_set.iter().copied().collect::<Vec<_>>())
3155 })
3156 .collect::<Vec<_>>(),
3157 vec![(
3158 subtrie_2_index,
3159 subtrie_2,
3160 vec![
3161 Nibbles::from_nibbles([0x1, 0x0, 0x0]),
3162 Nibbles::from_nibbles([0x1, 0x0, 0x1, 0x0])
3163 ]
3164 )]
3165 );
3166 assert_eq!(unchanged_prefix_set, unchanged_prefix_set);
3167 assert!(trie.lower_subtries[subtrie_2_index].as_revealed_ref().is_none());
3168
3169 assert_eq!(trie.lower_subtries[subtrie_1_index], LowerSparseSubtrie::Revealed(subtrie_1));
3171 }
3172
3173 #[test]
3174 fn test_get_changed_subtries_all() {
3175 let mut trie = ParallelSparseTrie::default();
3177 let subtrie_1 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3178 let subtrie_1_index = path_subtrie_index_unchecked(&subtrie_1.path);
3179 let subtrie_2 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x1, 0x0])));
3180 let subtrie_2_index = path_subtrie_index_unchecked(&subtrie_2.path);
3181 let subtrie_3 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x3, 0x0])));
3182 let subtrie_3_index = path_subtrie_index_unchecked(&subtrie_3.path);
3183
3184 trie.lower_subtries[subtrie_1_index] = LowerSparseSubtrie::Revealed(subtrie_1.clone());
3186 trie.lower_subtries[subtrie_2_index] = LowerSparseSubtrie::Revealed(subtrie_2.clone());
3187 trie.lower_subtries[subtrie_3_index] = LowerSparseSubtrie::Revealed(subtrie_3.clone());
3188
3189 let mut prefix_set = PrefixSetMut::all().freeze();
3191
3192 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3194 assert_eq!(
3195 subtries
3196 .into_iter()
3197 .map(|ChangedSubtrie { index, subtrie, prefix_set, .. }| {
3198 (index, subtrie, prefix_set.all())
3199 })
3200 .collect::<Vec<_>>(),
3201 vec![
3202 (subtrie_1_index, subtrie_1, true),
3203 (subtrie_2_index, subtrie_2, true),
3204 (subtrie_3_index, subtrie_3, true)
3205 ]
3206 );
3207 assert_eq!(unchanged_prefix_set, PrefixSetMut::all());
3208
3209 assert!(trie.lower_subtries.iter().all(|subtrie| subtrie.as_revealed_ref().is_none()));
3210 }
3211
3212 #[test]
3213 fn test_sparse_subtrie_type() {
3214 assert_eq!(SparseSubtrieType::from_path(&Nibbles::new()), SparseSubtrieType::Upper);
3215 assert_eq!(
3216 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0])),
3217 SparseSubtrieType::Upper
3218 );
3219 assert_eq!(
3220 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15])),
3221 SparseSubtrieType::Upper
3222 );
3223 assert_eq!(
3224 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 0])),
3225 SparseSubtrieType::Lower(0)
3226 );
3227 assert_eq!(
3228 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 0, 0])),
3229 SparseSubtrieType::Lower(0)
3230 );
3231 assert_eq!(
3232 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 1])),
3233 SparseSubtrieType::Lower(1)
3234 );
3235 assert_eq!(
3236 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 1, 0])),
3237 SparseSubtrieType::Lower(1)
3238 );
3239 assert_eq!(
3240 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 15])),
3241 SparseSubtrieType::Lower(15)
3242 );
3243 assert_eq!(
3244 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 0])),
3245 SparseSubtrieType::Lower(240)
3246 );
3247 assert_eq!(
3248 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 1])),
3249 SparseSubtrieType::Lower(241)
3250 );
3251 assert_eq!(
3252 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 15])),
3253 SparseSubtrieType::Lower(255)
3254 );
3255 assert_eq!(
3256 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 15, 15])),
3257 SparseSubtrieType::Lower(255)
3258 );
3259 }
3260
3261 #[test]
3262 fn test_reveal_node_leaves() {
3263 let mut trie = ParallelSparseTrie::default();
3264
3265 {
3267 let path = Nibbles::from_nibbles([0x1]);
3268 let node = create_leaf_node([0x2, 0x3], 42);
3269 let masks = TrieMasks::none();
3270
3271 trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
3272
3273 assert_matches!(
3274 trie.upper_subtrie.nodes.get(&path),
3275 Some(SparseNode::Leaf { key, hash: None })
3276 if key == &Nibbles::from_nibbles([0x2, 0x3])
3277 );
3278
3279 let full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3280 assert_eq!(
3281 trie.upper_subtrie.inner.values.get(&full_path),
3282 Some(&encode_account_value(42))
3283 );
3284 }
3285
3286 {
3288 let path = Nibbles::from_nibbles([0x1, 0x2]);
3289 let node = create_leaf_node([0x3, 0x4], 42);
3290 let masks = TrieMasks::none();
3291
3292 trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
3293
3294 let idx = path_subtrie_index_unchecked(&path);
3296 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3297
3298 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3300 assert_eq!(lower_subtrie.path, path);
3301
3302 assert_matches!(
3303 lower_subtrie.nodes.get(&path),
3304 Some(SparseNode::Leaf { key, hash: None })
3305 if key == &Nibbles::from_nibbles([0x3, 0x4])
3306 );
3307 }
3308
3309 {
3312 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3313 let node = create_leaf_node([0x4, 0x5], 42);
3314 let masks = TrieMasks::none();
3315
3316 trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
3317
3318 let idx = path_subtrie_index_unchecked(&path);
3320 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3321 assert_eq!(lower_subtrie.path, Nibbles::from_nibbles([0x1, 0x2]));
3322 }
3323 }
3324
3325 #[test]
3326 fn test_reveal_node_extension_all_upper() {
3327 let path = Nibbles::new();
3328 let child_hash = B256::repeat_byte(0xab);
3329 let node = create_extension_node([0x1], child_hash);
3330 let masks = TrieMasks::none();
3331 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3332
3333 assert_matches!(
3334 trie.upper_subtrie.nodes.get(&path),
3335 Some(SparseNode::Extension { key, hash: None, .. })
3336 if key == &Nibbles::from_nibbles([0x1])
3337 );
3338
3339 let child_path = Nibbles::from_nibbles([0x1]);
3341 assert_eq!(trie.upper_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3342 }
3343
3344 #[test]
3345 fn test_reveal_node_extension_cross_level() {
3346 let path = Nibbles::new();
3347 let child_hash = B256::repeat_byte(0xcd);
3348 let node = create_extension_node([0x1, 0x2, 0x3], child_hash);
3349 let masks = TrieMasks::none();
3350 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3351
3352 assert_matches!(
3354 trie.upper_subtrie.nodes.get(&path),
3355 Some(SparseNode::Extension { key, hash: None, .. })
3356 if key == &Nibbles::from_nibbles([0x1, 0x2, 0x3])
3357 );
3358
3359 let child_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3361 let idx = path_subtrie_index_unchecked(&child_path);
3362 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3363
3364 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3365 assert_eq!(lower_subtrie.path, child_path);
3366 assert_eq!(lower_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3367 }
3368
3369 #[test]
3370 fn test_reveal_node_extension_cross_level_boundary() {
3371 let mut trie = ParallelSparseTrie::default();
3372 let path = Nibbles::from_nibbles([0x1]);
3373 let child_hash = B256::repeat_byte(0xcd);
3374 let node = create_extension_node([0x2], child_hash);
3375 let masks = TrieMasks::none();
3376
3377 trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
3378
3379 assert_matches!(
3381 trie.upper_subtrie.nodes.get(&path),
3382 Some(SparseNode::Extension { key, hash: None, .. })
3383 if key == &Nibbles::from_nibbles([0x2])
3384 );
3385
3386 let child_path = Nibbles::from_nibbles([0x1, 0x2]);
3388 let idx = path_subtrie_index_unchecked(&child_path);
3389 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3390
3391 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3392 assert_eq!(lower_subtrie.path, child_path);
3393 assert_eq!(lower_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3394 }
3395
3396 #[test]
3397 fn test_reveal_node_branch_all_upper() {
3398 let path = Nibbles::new();
3399 let child_hashes = [
3400 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
3401 RlpNode::word_rlp(&B256::repeat_byte(0x22)),
3402 ];
3403 let node = create_branch_node_with_children(&[0x0, 0x5], child_hashes.clone());
3404 let masks = TrieMasks::none();
3405 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3406
3407 assert_matches!(
3409 trie.upper_subtrie.nodes.get(&path),
3410 Some(SparseNode::Branch { state_mask, hash: None, .. })
3411 if *state_mask == 0b0000000000100001.into()
3412 );
3413
3414 let child_path_0 = Nibbles::from_nibbles([0x0]);
3416 let child_path_5 = Nibbles::from_nibbles([0x5]);
3417 assert_eq!(
3418 trie.upper_subtrie.nodes.get(&child_path_0),
3419 Some(&SparseNode::Hash(child_hashes[0].as_hash().unwrap()))
3420 );
3421 assert_eq!(
3422 trie.upper_subtrie.nodes.get(&child_path_5),
3423 Some(&SparseNode::Hash(child_hashes[1].as_hash().unwrap()))
3424 );
3425 }
3426
3427 #[test]
3428 fn test_reveal_node_branch_cross_level() {
3429 let mut trie = ParallelSparseTrie::default();
3430 let path = Nibbles::from_nibbles([0x1]); let child_hashes = [
3432 RlpNode::word_rlp(&B256::repeat_byte(0x33)),
3433 RlpNode::word_rlp(&B256::repeat_byte(0x44)),
3434 RlpNode::word_rlp(&B256::repeat_byte(0x55)),
3435 ];
3436 let node = create_branch_node_with_children(&[0x0, 0x7, 0xf], child_hashes.clone());
3437 let masks = TrieMasks::none();
3438
3439 trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
3440
3441 assert_matches!(
3443 trie.upper_subtrie.nodes.get(&path),
3444 Some(SparseNode::Branch { state_mask, hash: None, .. })
3445 if *state_mask == 0b1000000010000001.into()
3446 );
3447
3448 let child_paths = [
3450 Nibbles::from_nibbles([0x1, 0x0]),
3451 Nibbles::from_nibbles([0x1, 0x7]),
3452 Nibbles::from_nibbles([0x1, 0xf]),
3453 ];
3454
3455 for (i, child_path) in child_paths.iter().enumerate() {
3456 let idx = path_subtrie_index_unchecked(child_path);
3457 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3458 assert_eq!(&lower_subtrie.path, child_path);
3459 assert_eq!(
3460 lower_subtrie.nodes.get(child_path),
3461 Some(&SparseNode::Hash(child_hashes[i].as_hash().unwrap())),
3462 );
3463 }
3464 }
3465
3466 #[test]
3467 fn test_update_subtrie_hashes_prefix_set_matching() {
3468 let mut trie = ParallelSparseTrie::default();
3470
3471 let leaf_1_full_path = Nibbles::from_nibbles([0; 64]);
3473 let leaf_1_path = leaf_1_full_path.slice(..2);
3474 let leaf_1_key = leaf_1_full_path.slice(2..);
3475 let leaf_2_full_path = Nibbles::from_nibbles([vec![0, 1], vec![0; 62]].concat());
3476 let leaf_2_path = leaf_2_full_path.slice(..2);
3477 let leaf_2_key = leaf_2_full_path.slice(2..);
3478 let leaf_3_full_path = Nibbles::from_nibbles([vec![0, 2], vec![0; 62]].concat());
3479 let leaf_3_path = leaf_3_full_path.slice(..2);
3480 let leaf_3_key = leaf_3_full_path.slice(2..);
3481 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), 1);
3482 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), 2);
3483 let leaf_3 = create_leaf_node(leaf_3_key.to_vec(), 3);
3484
3485 let child_hashes = [
3487 RlpNode::word_rlp(&B256::repeat_byte(0x00)),
3488 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
3489 ];
3491 let branch_path = Nibbles::from_nibbles([0x0]);
3492 let branch_node = create_branch_node_with_children(&[0x0, 0x1, 0x2], child_hashes);
3493
3494 trie.reveal_nodes(vec![
3496 ProofTrieNode { path: branch_path, node: branch_node, masks: TrieMasks::none() },
3497 ProofTrieNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
3498 ProofTrieNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
3499 ProofTrieNode { path: leaf_3_path, node: leaf_3, masks: TrieMasks::none() },
3500 ])
3501 .unwrap();
3502
3503 let subtrie_1_index = SparseSubtrieType::from_path(&leaf_1_path).lower_index().unwrap();
3505 let subtrie_2_index = SparseSubtrieType::from_path(&leaf_2_path).lower_index().unwrap();
3506 let subtrie_3_index = SparseSubtrieType::from_path(&leaf_3_path).lower_index().unwrap();
3507
3508 let mut unchanged_prefix_set = PrefixSetMut::from([
3509 Nibbles::from_nibbles([0x0]),
3510 leaf_2_full_path,
3511 Nibbles::from_nibbles([0x3, 0x0, 0x0]),
3512 ]);
3513 let mut prefix_set = PrefixSetMut::from([
3515 Nibbles::from_nibbles([0x0, 0x1, 0x0]),
3517 Nibbles::from_nibbles([0x0, 0x1, 0x1, 0x0]),
3518 ]);
3519 prefix_set.extend(unchanged_prefix_set.clone());
3520 trie.prefix_set = prefix_set;
3521
3522 trie.update_subtrie_hashes();
3524
3525 unchanged_prefix_set.insert(leaf_3_full_path);
3529
3530 assert_eq!(
3532 trie.prefix_set.clone().freeze().into_iter().collect::<Vec<_>>(),
3533 unchanged_prefix_set.freeze().into_iter().collect::<Vec<_>>()
3534 );
3535 assert!(trie.lower_subtries[subtrie_1_index].as_revealed_ref().is_some());
3537 assert!(trie.lower_subtries[subtrie_2_index].as_revealed_ref().is_some());
3538 assert!(trie.lower_subtries[subtrie_3_index].as_revealed_ref().is_some());
3539 }
3540
3541 #[test]
3542 fn test_subtrie_update_hashes() {
3543 let mut subtrie = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3544
3545 let leaf_1_full_path = Nibbles::from_nibbles([0; 64]);
3547 let leaf_1_path = leaf_1_full_path.slice(..5);
3548 let leaf_1_key = leaf_1_full_path.slice(5..);
3549 let leaf_2_full_path = Nibbles::from_nibbles([vec![0, 0, 0, 0, 1], vec![0; 59]].concat());
3550 let leaf_2_path = leaf_2_full_path.slice(..5);
3551 let leaf_2_key = leaf_2_full_path.slice(5..);
3552 let leaf_3_full_path = Nibbles::from_nibbles([vec![0, 0, 1], vec![0; 61]].concat());
3553 let leaf_3_path = leaf_3_full_path.slice(..3);
3554 let leaf_3_key = leaf_3_full_path.slice(3..);
3555
3556 let account_1 = create_account(1);
3557 let account_2 = create_account(2);
3558 let account_3 = create_account(3);
3559 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), account_1.nonce);
3560 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), account_2.nonce);
3561 let leaf_3 = create_leaf_node(leaf_3_key.to_vec(), account_3.nonce);
3562
3563 let branch_1_path = Nibbles::from_nibbles([0, 0, 0, 0]);
3565 let branch_1 = create_branch_node_with_children(
3566 &[0, 1],
3567 vec![
3568 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_1)),
3569 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_2)),
3570 ],
3571 );
3572
3573 let extension_path = Nibbles::from_nibbles([0, 0, 0]);
3575 let extension_key = Nibbles::from_nibbles([0]);
3576 let extension = create_extension_node(
3577 extension_key.to_vec(),
3578 RlpNode::from_rlp(&alloy_rlp::encode(&branch_1)).as_hash().unwrap(),
3579 );
3580
3581 let branch_2_path = Nibbles::from_nibbles([0, 0]);
3583 let branch_2 = create_branch_node_with_children(
3584 &[0, 1],
3585 vec![
3586 RlpNode::from_rlp(&alloy_rlp::encode(&extension)),
3587 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_3)),
3588 ],
3589 );
3590
3591 subtrie.reveal_node(branch_2_path, &branch_2, TrieMasks::none()).unwrap();
3593 subtrie.reveal_node(leaf_1_path, &leaf_1, TrieMasks::none()).unwrap();
3594 subtrie.reveal_node(extension_path, &extension, TrieMasks::none()).unwrap();
3595 subtrie.reveal_node(branch_1_path, &branch_1, TrieMasks::none()).unwrap();
3596 subtrie.reveal_node(leaf_2_path, &leaf_2, TrieMasks::none()).unwrap();
3597 subtrie.reveal_node(leaf_3_path, &leaf_3, TrieMasks::none()).unwrap();
3598
3599 let (_, _, proof_nodes, _, _) = run_hash_builder(
3601 [
3602 (leaf_1_full_path, account_1),
3603 (leaf_2_full_path, account_2),
3604 (leaf_3_full_path, account_3),
3605 ],
3606 NoopAccountTrieCursor::default(),
3607 Default::default(),
3608 [
3609 branch_1_path,
3610 extension_path,
3611 branch_2_path,
3612 leaf_1_full_path,
3613 leaf_2_full_path,
3614 leaf_3_full_path,
3615 ],
3616 );
3617
3618 subtrie.update_hashes(
3620 &mut PrefixSetMut::from([leaf_1_full_path, leaf_2_full_path, leaf_3_full_path])
3621 .freeze(),
3622 &mut None,
3623 &HashMap::default(),
3624 &HashMap::default(),
3625 );
3626
3627 let hash_builder_branch_1_hash =
3629 RlpNode::from_rlp(proof_nodes.get(&branch_1_path).unwrap().as_ref()).as_hash().unwrap();
3630 let subtrie_branch_1_hash = subtrie.nodes.get(&branch_1_path).unwrap().hash().unwrap();
3631 assert_eq!(hash_builder_branch_1_hash, subtrie_branch_1_hash);
3632
3633 let hash_builder_extension_hash =
3634 RlpNode::from_rlp(proof_nodes.get(&extension_path).unwrap().as_ref())
3635 .as_hash()
3636 .unwrap();
3637 let subtrie_extension_hash = subtrie.nodes.get(&extension_path).unwrap().hash().unwrap();
3638 assert_eq!(hash_builder_extension_hash, subtrie_extension_hash);
3639
3640 let hash_builder_branch_2_hash =
3641 RlpNode::from_rlp(proof_nodes.get(&branch_2_path).unwrap().as_ref()).as_hash().unwrap();
3642 let subtrie_branch_2_hash = subtrie.nodes.get(&branch_2_path).unwrap().hash().unwrap();
3643 assert_eq!(hash_builder_branch_2_hash, subtrie_branch_2_hash);
3644
3645 let subtrie_leaf_1_hash = subtrie.nodes.get(&leaf_1_path).unwrap().hash().unwrap();
3646 let hash_builder_leaf_1_hash =
3647 RlpNode::from_rlp(proof_nodes.get(&leaf_1_path).unwrap().as_ref()).as_hash().unwrap();
3648 assert_eq!(hash_builder_leaf_1_hash, subtrie_leaf_1_hash);
3649
3650 let hash_builder_leaf_2_hash =
3651 RlpNode::from_rlp(proof_nodes.get(&leaf_2_path).unwrap().as_ref()).as_hash().unwrap();
3652 let subtrie_leaf_2_hash = subtrie.nodes.get(&leaf_2_path).unwrap().hash().unwrap();
3653 assert_eq!(hash_builder_leaf_2_hash, subtrie_leaf_2_hash);
3654
3655 let hash_builder_leaf_3_hash =
3656 RlpNode::from_rlp(proof_nodes.get(&leaf_3_path).unwrap().as_ref()).as_hash().unwrap();
3657 let subtrie_leaf_3_hash = subtrie.nodes.get(&leaf_3_path).unwrap().hash().unwrap();
3658 assert_eq!(hash_builder_leaf_3_hash, subtrie_leaf_3_hash);
3659 }
3660
3661 #[test]
3662 fn test_remove_leaf_branch_becomes_extension() {
3663 let mut trie = new_test_trie(
3675 [
3676 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
3677 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(TrieMask::new(0b1001))),
3678 (
3679 Nibbles::from_nibbles([0x5, 0x0]),
3680 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3])),
3681 ),
3682 (
3683 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
3684 SparseNode::new_branch(TrieMask::new(0b0101)),
3685 ),
3686 (
3687 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
3688 SparseNode::new_leaf(Nibbles::new()),
3689 ),
3690 (
3691 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
3692 SparseNode::new_leaf(Nibbles::new()),
3693 ),
3694 (
3695 Nibbles::from_nibbles([0x5, 0x3]),
3696 SparseNode::new_leaf(Nibbles::from_nibbles([0x7])),
3697 ),
3698 ]
3699 .into_iter(),
3700 );
3701
3702 let provider = MockTrieNodeProvider::new();
3703
3704 let leaf_full_path = Nibbles::from_nibbles([0x5, 0x3, 0x7]);
3706 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3707
3708 let upper_subtrie = &trie.upper_subtrie;
3709 let lower_subtrie_50 = trie.lower_subtries[0x50].as_revealed_ref().unwrap();
3710
3711 assert_matches!(trie.lower_subtries[0x53].as_revealed_ref(), None);
3714
3715 assert_matches!(
3718 upper_subtrie.nodes.get(&Nibbles::from_nibbles([])),
3719 Some(SparseNode::Extension{ key, ..})
3720 if key == &Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3])
3721 );
3722 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x5])), None);
3723 assert_matches!(lower_subtrie_50.nodes.get(&Nibbles::from_nibbles([0x5, 0x0])), None);
3724 assert_matches!(
3725 lower_subtrie_50.nodes.get(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3])),
3726 Some(SparseNode::Branch{ state_mask, .. })
3727 if *state_mask == 0b0101.into()
3728 );
3729 }
3730
3731 #[test]
3732 fn test_remove_leaf_branch_becomes_leaf() {
3733 let mut trie = new_test_trie(
3741 [
3742 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0011))),
3743 (
3744 Nibbles::from_nibbles([0x0]),
3745 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3746 ),
3747 (
3748 Nibbles::from_nibbles([0x1]),
3749 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3750 ),
3751 ]
3752 .into_iter(),
3753 );
3754
3755 if let Some(updates) = trie.updates.as_mut() {
3757 updates
3758 .updated_nodes
3759 .insert(Nibbles::default(), BranchNodeCompact::new(0b11, 0, 0, vec![], None));
3760 }
3761
3762 let provider = MockTrieNodeProvider::new();
3763
3764 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2]);
3766 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3767
3768 let upper_subtrie = &trie.upper_subtrie;
3769
3770 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
3772
3773 assert_matches!(
3775 upper_subtrie.nodes.get(&Nibbles::default()),
3776 Some(SparseNode::Leaf{ key, ..})
3777 if key == &Nibbles::from_nibbles([0x1, 0x3, 0x4])
3778 );
3779
3780 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])), None);
3782 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x0])), None);
3784
3785 let updates = trie.updates.as_ref().unwrap();
3787
3788 assert!(updates.removed_nodes.contains(&Nibbles::default()));
3790
3791 assert!(!updates.updated_nodes.contains_key(&Nibbles::default()));
3793 }
3794
3795 #[test]
3796 fn test_remove_leaf_extension_becomes_leaf() {
3797 let mut trie = new_test_trie(
3806 [
3807 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
3808 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(TrieMask::new(0b0011))),
3809 (
3810 Nibbles::from_nibbles([0x5, 0x0]),
3811 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3812 ),
3813 (
3814 Nibbles::from_nibbles([0x5, 0x1]),
3815 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3816 ),
3817 ]
3818 .into_iter(),
3819 );
3820
3821 let provider = MockTrieNodeProvider::new();
3822
3823 let leaf_full_path = Nibbles::from_nibbles([0x5, 0x0, 0x1, 0x2]);
3825 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3826
3827 let upper_subtrie = &trie.upper_subtrie;
3828
3829 assert_matches!(trie.lower_subtries[0x50].as_revealed_ref(), None);
3833 assert_matches!(trie.lower_subtries[0x51].as_revealed_ref(), None);
3834
3835 let other_leaf_full_value = Nibbles::from_nibbles([0x5, 0x1, 0x3, 0x4]);
3837 assert_matches!(upper_subtrie.inner.values.get(&other_leaf_full_value), Some(_));
3838
3839 assert_matches!(
3841 upper_subtrie.nodes.get(&Nibbles::default()),
3842 Some(SparseNode::Leaf{ key, ..})
3843 if key == &Nibbles::from_nibbles([0x5, 0x1, 0x3, 0x4])
3844 );
3845
3846 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x5])), None);
3848 }
3849
3850 #[test]
3851 fn test_remove_leaf_branch_on_branch() {
3852 let mut trie = new_test_trie(
3862 [
3863 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0101))),
3864 (
3865 Nibbles::from_nibbles([0x0]),
3866 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3867 ),
3868 (Nibbles::from_nibbles([0x2]), SparseNode::new_branch(TrieMask::new(0b0011))),
3869 (
3870 Nibbles::from_nibbles([0x2, 0x0]),
3871 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3872 ),
3873 (
3874 Nibbles::from_nibbles([0x2, 0x1]),
3875 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x6])),
3876 ),
3877 ]
3878 .into_iter(),
3879 );
3880
3881 let provider = MockTrieNodeProvider::new();
3882
3883 let leaf_full_path = Nibbles::from_nibbles([0x2, 0x0, 0x3, 0x4]);
3885 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3886
3887 let upper_subtrie = &trie.upper_subtrie;
3888
3889 assert_matches!(trie.lower_subtries[0x20].as_revealed_ref(), None);
3893 assert_matches!(trie.lower_subtries[0x21].as_revealed_ref(), None);
3894
3895 let other_leaf_full_value = Nibbles::from_nibbles([0x2, 0x1, 0x5, 0x6]);
3897 assert_matches!(upper_subtrie.inner.values.get(&other_leaf_full_value), Some(_));
3898
3899 assert_matches!(
3901 upper_subtrie.nodes.get(&Nibbles::default()),
3902 Some(SparseNode::Branch{ state_mask, .. })
3903 if *state_mask == 0b0101.into()
3904 );
3905
3906 assert_matches!(
3908 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x2])),
3909 Some(SparseNode::Leaf{ key, ..})
3910 if key == &Nibbles::from_nibbles([0x1, 0x5, 0x6])
3911 );
3912 }
3913
3914 #[test]
3915 fn test_remove_leaf_lower_subtrie_root_path_update() {
3916 let mut trie = new_test_trie(
3930 [
3931 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x1, 0x2, 0x3]))),
3932 (
3933 Nibbles::from_nibbles([0x1, 0x2, 0x3]),
3934 SparseNode::new_branch(TrieMask::new(0b0011000)),
3935 ),
3936 (
3937 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x3]),
3938 SparseNode::new_leaf(Nibbles::default()),
3939 ),
3940 (
3941 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]),
3942 SparseNode::new_ext(Nibbles::from_nibbles([0x5])),
3943 ),
3944 (
3945 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]),
3946 SparseNode::new_branch(TrieMask::new(0b0011)),
3947 ),
3948 (
3949 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5, 0x0]),
3950 SparseNode::new_leaf(Nibbles::default()),
3951 ),
3952 (
3953 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5, 0x1]),
3954 SparseNode::new_leaf(Nibbles::default()),
3955 ),
3956 ]
3957 .into_iter(),
3958 );
3959
3960 let provider = MockTrieNodeProvider::new();
3961
3962 let lower_subtrie_root_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3964 assert_matches!(
3965 trie.lower_subtrie_for_path_mut(&lower_subtrie_root_path),
3966 Some(subtrie)
3967 if subtrie.path == lower_subtrie_root_path
3968 );
3969
3970 let leaf_full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x3]);
3972 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3973
3974 let lower_subtrie = trie.lower_subtries[0x12].as_revealed_ref().unwrap();
3979 assert_eq!(lower_subtrie.path, Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]));
3980
3981 assert_matches!(
3983 trie.upper_subtrie.nodes.get(&Nibbles::default()),
3984 Some(SparseNode::Extension { key, .. })
3985 if key == &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5])
3986 );
3987
3988 assert_matches!(
3990 lower_subtrie.nodes.get(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5])),
3991 Some(SparseNode::Branch { state_mask, .. })
3992 if state_mask == &TrieMask::new(0b0011)
3993 );
3994 }
3995
3996 #[test]
3997 fn test_remove_leaf_remaining_child_needs_reveal() {
3998 let mut trie = new_test_trie(
4006 [
4007 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0011))),
4008 (
4009 Nibbles::from_nibbles([0x0]),
4010 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
4011 ),
4012 (Nibbles::from_nibbles([0x1]), SparseNode::Hash(B256::repeat_byte(0xab))),
4013 ]
4014 .into_iter(),
4015 );
4016
4017 let mut provider = MockTrieNodeProvider::new();
4019 let revealed_leaf = create_leaf_node([0x3, 0x4], 42);
4020 let mut encoded = Vec::new();
4021 revealed_leaf.encode(&mut encoded);
4022 provider.add_revealed_node(
4023 Nibbles::from_nibbles([0x1]),
4024 RevealedNode { node: encoded.into(), tree_mask: None, hash_mask: None },
4025 );
4026
4027 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2]);
4029 trie.remove_leaf(&leaf_full_path, provider).unwrap();
4030
4031 let upper_subtrie = &trie.upper_subtrie;
4032
4033 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
4035
4036 assert_matches!(
4038 upper_subtrie.nodes.get(&Nibbles::default()),
4039 Some(SparseNode::Leaf{ key, ..})
4040 if key == &Nibbles::from_nibbles([0x1, 0x3, 0x4])
4041 );
4042
4043 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])), None);
4045 }
4046
4047 #[test]
4048 fn test_remove_leaf_root() {
4049 let mut trie = new_test_trie(std::iter::once((
4055 Nibbles::default(),
4056 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2, 0x3])),
4057 )));
4058
4059 let provider = MockTrieNodeProvider::new();
4060
4061 let leaf_full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
4063 trie.remove_leaf(&leaf_full_path, provider).unwrap();
4064
4065 let upper_subtrie = &trie.upper_subtrie;
4066
4067 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
4069
4070 assert_matches!(upper_subtrie.nodes.get(&Nibbles::default()), Some(SparseNode::Empty));
4072 }
4073
4074 #[test]
4075 fn test_remove_leaf_unsets_hash_along_path() {
4076 let mut trie = new_test_trie(
4091 [
4092 (
4093 Nibbles::default(),
4094 SparseNode::Branch {
4095 state_mask: TrieMask::new(0b0011),
4096 hash: Some(B256::repeat_byte(0x10)),
4097 store_in_db_trie: None,
4098 },
4099 ),
4100 (
4101 Nibbles::from_nibbles([0x0]),
4102 SparseNode::Extension {
4103 key: Nibbles::from_nibbles([0x1]),
4104 hash: Some(B256::repeat_byte(0x20)),
4105 store_in_db_trie: None,
4106 },
4107 ),
4108 (
4109 Nibbles::from_nibbles([0x0, 0x1]),
4110 SparseNode::Branch {
4111 state_mask: TrieMask::new(0b11100),
4112 hash: Some(B256::repeat_byte(0x30)),
4113 store_in_db_trie: None,
4114 },
4115 ),
4116 (
4117 Nibbles::from_nibbles([0x0, 0x1, 0x2]),
4118 SparseNode::Leaf {
4119 key: Nibbles::from_nibbles([0x3, 0x4]),
4120 hash: Some(B256::repeat_byte(0x40)),
4121 },
4122 ),
4123 (
4124 Nibbles::from_nibbles([0x0, 0x1, 0x3]),
4125 SparseNode::Leaf {
4126 key: Nibbles::from_nibbles([0x5, 0x6]),
4127 hash: Some(B256::repeat_byte(0x50)),
4128 },
4129 ),
4130 (
4131 Nibbles::from_nibbles([0x0, 0x1, 0x4]),
4132 SparseNode::Leaf {
4133 key: Nibbles::from_nibbles([0x6, 0x7]),
4134 hash: Some(B256::repeat_byte(0x60)),
4135 },
4136 ),
4137 (
4138 Nibbles::from_nibbles([0x1]),
4139 SparseNode::Leaf {
4140 key: Nibbles::from_nibbles([0x7, 0x8]),
4141 hash: Some(B256::repeat_byte(0x70)),
4142 },
4143 ),
4144 ]
4145 .into_iter(),
4146 );
4147
4148 let provider = MockTrieNodeProvider::new();
4149
4150 trie.remove_leaf(&Nibbles::from_nibbles([0x0, 0x1, 0x2, 0x3, 0x4, 0xF]), &provider)
4152 .unwrap();
4153 for (path, node) in trie.all_nodes() {
4154 assert!(node.hash().is_some(), "path {path:?} should still have a hash");
4155 }
4156
4157 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2, 0x3, 0x4]);
4159 trie.remove_leaf(&leaf_full_path, &provider).unwrap();
4160
4161 let upper_subtrie = &trie.upper_subtrie;
4162 let lower_subtrie_10 = trie.lower_subtries[0x01].as_revealed_ref().unwrap();
4163
4164 assert_matches!(
4166 upper_subtrie.nodes.get(&Nibbles::default()),
4167 Some(SparseNode::Branch { hash: None, .. })
4168 );
4169 assert_matches!(
4170 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x0])),
4171 Some(SparseNode::Extension { hash: None, .. })
4172 );
4173 assert_matches!(
4174 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1])),
4175 Some(SparseNode::Branch { hash: None, .. })
4176 );
4177
4178 assert_matches!(
4180 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])),
4181 Some(SparseNode::Leaf { hash: Some(_), .. })
4182 );
4183 assert_matches!(
4184 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1, 0x3])),
4185 Some(SparseNode::Leaf { hash: Some(_), .. })
4186 );
4187 assert_matches!(
4188 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1, 0x4])),
4189 Some(SparseNode::Leaf { hash: Some(_), .. })
4190 );
4191 }
4192
4193 #[test]
4194 fn test_remove_leaf_remaining_extension_node_child_is_revealed() {
4195 let branch_path = Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7]);
4196 let removed_branch_path = Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2]);
4197
4198 let nodes = vec![
4200 ProofTrieNode {
4202 path: branch_path,
4203 node: {
4204 TrieNode::Branch(BranchNode::new(
4205 vec![
4206 RlpNode::word_rlp(&B256::from(hex!(
4207 "dede882d52f0e0eddfb5b89293a10c87468b4a73acd0d4ae550054a92353f6d5"
4208 ))),
4209 RlpNode::word_rlp(&B256::from(hex!(
4210 "8746f18e465e2eed16117306b6f2eef30bc9d2978aee4a7838255e39c41a3222"
4211 ))),
4212 RlpNode::word_rlp(&B256::from(hex!(
4213 "35a4ea861548af5f0262a9b6d619b4fc88fce6531cbd004eab1530a73f34bbb1"
4214 ))),
4215 RlpNode::word_rlp(&B256::from(hex!(
4216 "47d5c2bf9eea5c1ee027e4740c2b86159074a27d52fd2f6a8a8c86c77e48006f"
4217 ))),
4218 RlpNode::word_rlp(&B256::from(hex!(
4219 "eb76a359b216e1d86b1f2803692a9fe8c3d3f97a9fe6a82b396e30344febc0c1"
4220 ))),
4221 RlpNode::word_rlp(&B256::from(hex!(
4222 "437656f2697f167b23e33cb94acc8550128cfd647fc1579d61e982cb7616b8bc"
4223 ))),
4224 RlpNode::word_rlp(&B256::from(hex!(
4225 "45a1ac2faf15ea8a4da6f921475974e0379f39c3d08166242255a567fa88ce6c"
4226 ))),
4227 RlpNode::word_rlp(&B256::from(hex!(
4228 "7dbb299d714d3dfa593f53bc1b8c66d5c401c30a0b5587b01254a56330361395"
4229 ))),
4230 RlpNode::word_rlp(&B256::from(hex!(
4231 "ae407eb14a74ed951c9949c1867fb9ee9ba5d5b7e03769eaf3f29c687d080429"
4232 ))),
4233 RlpNode::word_rlp(&B256::from(hex!(
4234 "768d0fe1003f0e85d3bc76e4a1fa0827f63b10ca9bca52d56c2b1cceb8eb8b08"
4235 ))),
4236 RlpNode::word_rlp(&B256::from(hex!(
4237 "e5127935143493d5094f4da6e4f7f5a0f62d524fbb61e7bb9fb63d8a166db0f3"
4238 ))),
4239 RlpNode::word_rlp(&B256::from(hex!(
4240 "7f3698297308664fbc1b9e2c41d097fbd57d8f364c394f6ad7c71b10291fbf42"
4241 ))),
4242 RlpNode::word_rlp(&B256::from(hex!(
4243 "4a2bc7e19cec63cb5ef5754add0208959b50bcc79f13a22a370f77b277dbe6db"
4244 ))),
4245 RlpNode::word_rlp(&B256::from(hex!(
4246 "40764b8c48de59258e62a3371909a107e76e1b5e847cfa94dbc857e9fd205103"
4247 ))),
4248 RlpNode::word_rlp(&B256::from(hex!(
4249 "2985dca29a7616920d95c43ab62eb013a40e6a0c88c284471e4c3bd22f3b9b25"
4250 ))),
4251 RlpNode::word_rlp(&B256::from(hex!(
4252 "1b6511f7a385e79477239f7dd4a49f52082ecac05aa5bd0de18b1d55fe69d10c"
4253 ))),
4254 ],
4255 TrieMask::new(0b1111111111111111),
4256 ))
4257 },
4258 masks: TrieMasks {
4259 hash_mask: Some(TrieMask::new(0b1111111111111111)),
4260 tree_mask: Some(TrieMask::new(0b0011110100100101)),
4261 },
4262 },
4263 ProofTrieNode {
4265 path: removed_branch_path,
4266 node: {
4267 let stack = vec![
4268 RlpNode::word_rlp(&B256::from(hex!(
4269 "15fd4993a41feff1af3b629b32572ab05acddd97c681d82ec2eb89c8a8e3ab9e"
4270 ))),
4271 RlpNode::word_rlp(&B256::from(hex!(
4272 "a272b0b94ced4e6ec7adb41719850cf4a167ad8711d0dda6a810d129258a0d94"
4273 ))),
4274 ];
4275 let branch_node = BranchNode::new(stack, TrieMask::new(0b0001000000000100));
4276 TrieNode::Branch(branch_node)
4277 },
4278 masks: TrieMasks {
4279 hash_mask: Some(TrieMask::new(0b0000000000000000)),
4280 tree_mask: Some(TrieMask::new(0b0000000000000100)),
4281 },
4282 },
4283 ProofTrieNode {
4285 path: Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0x2]),
4286 node: {
4287 let extension_node = ExtensionNode::new(
4288 Nibbles::from_nibbles([0x6]),
4289 RlpNode::word_rlp(&B256::from(hex!(
4290 "56fab2b106a97eae9c7197f86d03bca292da6e0ac725b783082f7d950cc4e0fc"
4291 ))),
4292 );
4293 TrieNode::Extension(extension_node)
4294 },
4295 masks: TrieMasks { hash_mask: None, tree_mask: None },
4296 },
4297 ProofTrieNode {
4299 path: Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0xc]),
4300 node: {
4301 let leaf_node = LeafNode::new(
4302 Nibbles::from_nibbles([
4303 0x0, 0x7, 0x7, 0xf, 0x8, 0x6, 0x6, 0x1, 0x3, 0x0, 0x8, 0x8, 0xd, 0xf,
4304 0xc, 0xa, 0xe, 0x6, 0x4, 0x8, 0xa, 0xb, 0xe, 0x8, 0x3, 0x1, 0xf, 0xa,
4305 0xd, 0xc, 0xa, 0x5, 0x5, 0xa, 0xd, 0x4, 0x3, 0xa, 0xb, 0x1, 0x6, 0x5,
4306 0xd, 0x1, 0x6, 0x8, 0x0, 0xd, 0xd, 0x5, 0x6, 0x7, 0xb, 0x5, 0xd, 0x6,
4307 ]),
4308 hex::decode("8468d3971d").unwrap(),
4309 );
4310 TrieNode::Leaf(leaf_node)
4311 },
4312 masks: TrieMasks { hash_mask: None, tree_mask: None },
4313 },
4314 ];
4315
4316 let mut trie = ParallelSparseTrie::from_root(
4318 TrieNode::Extension(ExtensionNode::new(
4319 Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7]),
4320 RlpNode::word_rlp(&B256::from(hex!(
4321 "56fab2b106a97eae9c7197f86d03bca292da6e0ac725b783082f7d950cc4e0fc"
4322 ))),
4323 )),
4324 TrieMasks::none(),
4325 true,
4326 )
4327 .unwrap();
4328
4329 trie.reveal_nodes(nodes).unwrap();
4331
4332 let leaf_key = Nibbles::from_nibbles([
4334 0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0xc, 0x0, 0x7, 0x7, 0xf, 0x8, 0x6, 0x6, 0x1, 0x3,
4335 0x0, 0x8, 0x8, 0xd, 0xf, 0xc, 0xa, 0xe, 0x6, 0x4, 0x8, 0xa, 0xb, 0xe, 0x8, 0x3, 0x1,
4336 0xf, 0xa, 0xd, 0xc, 0xa, 0x5, 0x5, 0xa, 0xd, 0x4, 0x3, 0xa, 0xb, 0x1, 0x6, 0x5, 0xd,
4337 0x1, 0x6, 0x8, 0x0, 0xd, 0xd, 0x5, 0x6, 0x7, 0xb, 0x5, 0xd, 0x6,
4338 ]);
4339
4340 let mut provider = MockTrieNodeProvider::new();
4341 let revealed_branch = create_branch_node_with_children(&[], []);
4342 let mut encoded = Vec::new();
4343 revealed_branch.encode(&mut encoded);
4344 provider.add_revealed_node(
4345 Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0x2, 0x6]),
4346 RevealedNode {
4347 node: encoded.into(),
4348 tree_mask: None,
4349 hash_mask: Some(TrieMask::new(0b1111)),
4351 },
4352 );
4353
4354 trie.remove_leaf(&leaf_key, provider).unwrap();
4355
4356 trie.root();
4358
4359 let updates = trie.take_updates();
4361 assert_eq!(
4362 updates.removed_nodes.into_iter().collect::<Vec<_>>(),
4363 vec![removed_branch_path]
4364 );
4365 assert_eq!(updates.updated_nodes.len(), 1);
4366 let updated_node = updates.updated_nodes.get(&branch_path).unwrap();
4367
4368 assert_eq!(updated_node.tree_mask, TrieMask::new(0b011110100100101),)
4370 }
4371
4372 #[test]
4373 fn test_parallel_sparse_trie_root() {
4374 let extension_path = Nibbles::new();
4377 let extension_key = Nibbles::from_nibbles([0x2]);
4378
4379 let branch_path = Nibbles::from_nibbles([0x2]);
4381
4382 let leaf_1_path = Nibbles::from_nibbles([0x2, 0x0]);
4384 let leaf_1_key = Nibbles::from_nibbles(vec![0; 62]); let leaf_1_full_path = Nibbles::from_nibbles([vec![0x2, 0x0], vec![0; 62]].concat());
4386
4387 let leaf_2_path = Nibbles::from_nibbles([0x2, 0x1]);
4388 let leaf_2_key = Nibbles::from_nibbles(vec![0; 62]); let leaf_2_full_path = Nibbles::from_nibbles([vec![0x2, 0x1], vec![0; 62]].concat());
4390
4391 let account_1 = create_account(1);
4393 let account_2 = create_account(2);
4394
4395 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), account_1.nonce);
4397 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), account_2.nonce);
4398
4399 let branch = create_branch_node_with_children(
4401 &[0, 1],
4402 vec![
4403 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_1)),
4404 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_2)),
4405 ],
4406 );
4407
4408 let extension = create_extension_node(
4410 extension_key.to_vec(),
4411 RlpNode::from_rlp(&alloy_rlp::encode(&branch)).as_hash().unwrap(),
4412 );
4413
4414 let mut trie = ParallelSparseTrie::from_root(extension, TrieMasks::none(), true).unwrap();
4416 trie.reveal_nodes(vec![
4417 ProofTrieNode { path: branch_path, node: branch, masks: TrieMasks::none() },
4418 ProofTrieNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
4419 ProofTrieNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
4420 ])
4421 .unwrap();
4422
4423 trie.upper_subtrie.nodes.get_mut(&extension_path).unwrap().set_hash(None);
4426 trie.upper_subtrie.nodes.get_mut(&branch_path).unwrap().set_hash(None);
4427
4428 let leaf_1_subtrie_idx = path_subtrie_index_unchecked(&leaf_1_path);
4430 let leaf_2_subtrie_idx = path_subtrie_index_unchecked(&leaf_2_path);
4431
4432 trie.lower_subtries[leaf_1_subtrie_idx]
4433 .as_revealed_mut()
4434 .unwrap()
4435 .nodes
4436 .get_mut(&leaf_1_path)
4437 .unwrap()
4438 .set_hash(None);
4439 trie.lower_subtries[leaf_2_subtrie_idx]
4440 .as_revealed_mut()
4441 .unwrap()
4442 .nodes
4443 .get_mut(&leaf_2_path)
4444 .unwrap()
4445 .set_hash(None);
4446
4447 trie.prefix_set.insert(leaf_1_full_path);
4449 trie.prefix_set.insert(leaf_2_full_path);
4450
4451 let root = trie.root();
4453
4454 let (hash_builder_root, _, _proof_nodes, _, _) = run_hash_builder(
4456 [(leaf_1_full_path, account_1), (leaf_2_full_path, account_2)],
4457 NoopAccountTrieCursor::default(),
4458 Default::default(),
4459 [extension_path, branch_path, leaf_1_full_path, leaf_2_full_path],
4460 );
4461
4462 assert_eq!(root, hash_builder_root);
4464
4465 let leaf_1_subtrie = trie.lower_subtries[leaf_1_subtrie_idx].as_revealed_ref().unwrap();
4467 let leaf_2_subtrie = trie.lower_subtries[leaf_2_subtrie_idx].as_revealed_ref().unwrap();
4468 assert!(trie.upper_subtrie.nodes.get(&extension_path).unwrap().hash().is_some());
4469 assert!(trie.upper_subtrie.nodes.get(&branch_path).unwrap().hash().is_some());
4470 assert!(leaf_1_subtrie.nodes.get(&leaf_1_path).unwrap().hash().is_some());
4471 assert!(leaf_2_subtrie.nodes.get(&leaf_2_path).unwrap().hash().is_some());
4472 }
4473
4474 #[test]
4475 fn sparse_trie_empty_update_one() {
4476 let ctx = ParallelSparseTrieTestContext;
4477
4478 let key = Nibbles::unpack(B256::with_last_byte(42));
4479 let value = || Account::default();
4480 let value_encoded = || {
4481 let mut account_rlp = Vec::new();
4482 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4483 account_rlp
4484 };
4485
4486 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4487 run_hash_builder(
4488 [(key, value())],
4489 NoopAccountTrieCursor::default(),
4490 Default::default(),
4491 [key],
4492 );
4493
4494 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4495 ctx.update_leaves(&mut sparse, [(key, value_encoded())]);
4496 ctx.assert_with_hash_builder(
4497 &mut sparse,
4498 hash_builder_root,
4499 hash_builder_updates,
4500 hash_builder_proof_nodes,
4501 );
4502 }
4503
4504 #[test]
4505 fn sparse_trie_empty_update_multiple_lower_nibbles() {
4506 let ctx = ParallelSparseTrieTestContext;
4507
4508 let paths = (0..=16).map(|b| Nibbles::unpack(B256::with_last_byte(b))).collect::<Vec<_>>();
4509 let value = || Account::default();
4510 let value_encoded = || {
4511 let mut account_rlp = Vec::new();
4512 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4513 account_rlp
4514 };
4515
4516 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4517 run_hash_builder(
4518 paths.iter().copied().zip(std::iter::repeat_with(value)),
4519 NoopAccountTrieCursor::default(),
4520 Default::default(),
4521 paths.clone(),
4522 );
4523
4524 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4525 ctx.update_leaves(
4526 &mut sparse,
4527 paths.into_iter().zip(std::iter::repeat_with(value_encoded)),
4528 );
4529
4530 ctx.assert_with_hash_builder(
4531 &mut sparse,
4532 hash_builder_root,
4533 hash_builder_updates,
4534 hash_builder_proof_nodes,
4535 );
4536 }
4537
4538 #[test]
4539 fn sparse_trie_empty_update_multiple_upper_nibbles() {
4540 let paths = (239..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
4541 let value = || Account::default();
4542 let value_encoded = || {
4543 let mut account_rlp = Vec::new();
4544 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4545 account_rlp
4546 };
4547
4548 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4549 run_hash_builder(
4550 paths.iter().copied().zip(std::iter::repeat_with(value)),
4551 NoopAccountTrieCursor::default(),
4552 Default::default(),
4553 paths.clone(),
4554 );
4555
4556 let provider = DefaultTrieNodeProvider;
4557 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4558 for path in &paths {
4559 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
4560 }
4561 let sparse_root = sparse.root();
4562 let sparse_updates = sparse.take_updates();
4563
4564 assert_eq!(sparse_root, hash_builder_root);
4565 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
4566 assert_eq_parallel_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
4567 }
4568
4569 #[test]
4570 fn sparse_trie_empty_update_multiple() {
4571 let ctx = ParallelSparseTrieTestContext;
4572
4573 let paths = (0..=255)
4574 .map(|b| {
4575 Nibbles::unpack(if b % 2 == 0 {
4576 B256::repeat_byte(b)
4577 } else {
4578 B256::with_last_byte(b)
4579 })
4580 })
4581 .collect::<Vec<_>>();
4582 let value = || Account::default();
4583 let value_encoded = || {
4584 let mut account_rlp = Vec::new();
4585 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4586 account_rlp
4587 };
4588
4589 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4590 run_hash_builder(
4591 paths.iter().sorted_unstable().copied().zip(std::iter::repeat_with(value)),
4592 NoopAccountTrieCursor::default(),
4593 Default::default(),
4594 paths.clone(),
4595 );
4596
4597 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4598 ctx.update_leaves(
4599 &mut sparse,
4600 paths.iter().copied().zip(std::iter::repeat_with(value_encoded)),
4601 );
4602 ctx.assert_with_hash_builder(
4603 &mut sparse,
4604 hash_builder_root,
4605 hash_builder_updates,
4606 hash_builder_proof_nodes,
4607 );
4608 }
4609
4610 #[test]
4611 fn sparse_trie_empty_update_repeated() {
4612 let ctx = ParallelSparseTrieTestContext;
4613
4614 let paths = (0..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
4615 let old_value = Account { nonce: 1, ..Default::default() };
4616 let old_value_encoded = {
4617 let mut account_rlp = Vec::new();
4618 old_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4619 account_rlp
4620 };
4621 let new_value = Account { nonce: 2, ..Default::default() };
4622 let new_value_encoded = {
4623 let mut account_rlp = Vec::new();
4624 new_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4625 account_rlp
4626 };
4627
4628 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4629 run_hash_builder(
4630 paths.iter().copied().zip(std::iter::repeat_with(|| old_value)),
4631 NoopAccountTrieCursor::default(),
4632 Default::default(),
4633 paths.clone(),
4634 );
4635
4636 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4637 ctx.update_leaves(
4638 &mut sparse,
4639 paths.iter().copied().zip(std::iter::repeat(old_value_encoded)),
4640 );
4641 ctx.assert_with_hash_builder(
4642 &mut sparse,
4643 hash_builder_root,
4644 hash_builder_updates,
4645 hash_builder_proof_nodes,
4646 );
4647
4648 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4649 run_hash_builder(
4650 paths.iter().copied().zip(std::iter::repeat(new_value)),
4651 NoopAccountTrieCursor::default(),
4652 Default::default(),
4653 paths.clone(),
4654 );
4655
4656 ctx.update_leaves(
4657 &mut sparse,
4658 paths.iter().copied().zip(std::iter::repeat(new_value_encoded)),
4659 );
4660 ctx.assert_with_hash_builder(
4661 &mut sparse,
4662 hash_builder_root,
4663 hash_builder_updates,
4664 hash_builder_proof_nodes,
4665 );
4666 }
4667
4668 #[test]
4669 fn sparse_trie_remove_leaf() {
4670 let ctx = ParallelSparseTrieTestContext;
4671 let provider = DefaultTrieNodeProvider;
4672 let mut sparse = ParallelSparseTrie::default();
4673
4674 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
4675
4676 ctx.update_leaves(
4677 &mut sparse,
4678 [
4679 (Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone()),
4680 (Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone()),
4681 (Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone()),
4682 (Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone()),
4683 (Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone()),
4684 (Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value),
4685 ],
4686 );
4687
4688 pretty_assertions::assert_eq!(
4701 parallel_sparse_trie_nodes(&sparse)
4702 .into_iter()
4703 .map(|(k, v)| (*k, v.clone()))
4704 .collect::<BTreeMap<_, _>>(),
4705 BTreeMap::from_iter([
4706 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4707 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1101.into())),
4708 (
4709 Nibbles::from_nibbles([0x5, 0x0]),
4710 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
4711 ),
4712 (
4713 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
4714 SparseNode::new_branch(0b1010.into())
4715 ),
4716 (
4717 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
4718 SparseNode::new_leaf(Nibbles::default())
4719 ),
4720 (
4721 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
4722 SparseNode::new_leaf(Nibbles::default())
4723 ),
4724 (
4725 Nibbles::from_nibbles([0x5, 0x2]),
4726 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x1, 0x3]))
4727 ),
4728 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4729 (
4730 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4731 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4732 ),
4733 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4734 (
4735 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4736 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4737 ),
4738 (
4739 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4740 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4741 )
4742 ])
4743 );
4744
4745 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), &provider).unwrap();
4746
4747 pretty_assertions::assert_eq!(
4759 parallel_sparse_trie_nodes(&sparse)
4760 .into_iter()
4761 .map(|(k, v)| (*k, v.clone()))
4762 .collect::<BTreeMap<_, _>>(),
4763 BTreeMap::from_iter([
4764 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4765 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4766 (
4767 Nibbles::from_nibbles([0x5, 0x0]),
4768 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
4769 ),
4770 (
4771 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
4772 SparseNode::new_branch(0b1010.into())
4773 ),
4774 (
4775 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
4776 SparseNode::new_leaf(Nibbles::default())
4777 ),
4778 (
4779 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
4780 SparseNode::new_leaf(Nibbles::default())
4781 ),
4782 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4783 (
4784 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4785 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4786 ),
4787 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4788 (
4789 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4790 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4791 ),
4792 (
4793 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4794 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4795 )
4796 ])
4797 );
4798
4799 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), &provider).unwrap();
4800
4801 pretty_assertions::assert_eq!(
4810 parallel_sparse_trie_nodes(&sparse)
4811 .into_iter()
4812 .map(|(k, v)| (*k, v.clone()))
4813 .collect::<BTreeMap<_, _>>(),
4814 BTreeMap::from_iter([
4815 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4816 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4817 (
4818 Nibbles::from_nibbles([0x5, 0x0]),
4819 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4820 ),
4821 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4822 (
4823 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4824 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4825 ),
4826 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4827 (
4828 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4829 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4830 ),
4831 (
4832 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4833 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4834 )
4835 ])
4836 );
4837
4838 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), &provider).unwrap();
4839
4840 pretty_assertions::assert_eq!(
4847 parallel_sparse_trie_nodes(&sparse)
4848 .into_iter()
4849 .map(|(k, v)| (*k, v.clone()))
4850 .collect::<BTreeMap<_, _>>(),
4851 BTreeMap::from_iter([
4852 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4853 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4854 (
4855 Nibbles::from_nibbles([0x5, 0x0]),
4856 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4857 ),
4858 (
4859 Nibbles::from_nibbles([0x5, 0x3]),
4860 SparseNode::new_ext(Nibbles::from_nibbles([0x3]))
4861 ),
4862 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4863 (
4864 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4865 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4866 ),
4867 (
4868 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4869 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4870 )
4871 ])
4872 );
4873
4874 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), &provider).unwrap();
4875
4876 pretty_assertions::assert_eq!(
4881 parallel_sparse_trie_nodes(&sparse)
4882 .into_iter()
4883 .map(|(k, v)| (*k, v.clone()))
4884 .collect::<BTreeMap<_, _>>(),
4885 BTreeMap::from_iter([
4886 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4887 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4888 (
4889 Nibbles::from_nibbles([0x5, 0x0]),
4890 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4891 ),
4892 (
4893 Nibbles::from_nibbles([0x5, 0x3]),
4894 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x0, 0x2]))
4895 ),
4896 ])
4897 );
4898
4899 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), &provider).unwrap();
4900
4901 pretty_assertions::assert_eq!(
4903 parallel_sparse_trie_nodes(&sparse)
4904 .into_iter()
4905 .map(|(k, v)| (*k, v.clone()))
4906 .collect::<BTreeMap<_, _>>(),
4907 BTreeMap::from_iter([(
4908 Nibbles::default(),
4909 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]))
4910 ),])
4911 );
4912
4913 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), &provider).unwrap();
4914
4915 pretty_assertions::assert_eq!(
4917 parallel_sparse_trie_nodes(&sparse)
4918 .into_iter()
4919 .map(|(k, v)| (*k, v.clone()))
4920 .collect::<BTreeMap<_, _>>(),
4921 BTreeMap::from_iter([(Nibbles::default(), SparseNode::Empty)])
4922 );
4923 }
4924
4925 #[test]
4926 fn sparse_trie_remove_leaf_blinded() {
4927 let leaf = LeafNode::new(
4928 Nibbles::default(),
4929 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
4930 );
4931 let branch = TrieNode::Branch(BranchNode::new(
4932 vec![
4933 RlpNode::word_rlp(&B256::repeat_byte(1)),
4934 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
4935 ],
4936 TrieMask::new(0b11),
4937 ));
4938
4939 let provider = DefaultTrieNodeProvider;
4940 let mut sparse = ParallelSparseTrie::from_root(
4941 branch.clone(),
4942 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
4943 false,
4944 )
4945 .unwrap();
4946
4947 sparse
4953 .reveal_nodes(vec![
4954 ProofTrieNode {
4955 path: Nibbles::default(),
4956 node: branch,
4957 masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
4958 },
4959 ProofTrieNode {
4960 path: Nibbles::from_nibbles([0x1]),
4961 node: TrieNode::Leaf(leaf),
4962 masks: TrieMasks::none(),
4963 },
4964 ])
4965 .unwrap();
4966
4967 assert_matches!(
4969 sparse.remove_leaf(&Nibbles::from_nibbles([0x0]), &provider).map_err(|e| e.into_kind()),
4970 Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
4971 );
4972 }
4973
4974 #[test]
4975 fn sparse_trie_remove_leaf_non_existent() {
4976 let leaf = LeafNode::new(
4977 Nibbles::default(),
4978 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
4979 );
4980 let branch = TrieNode::Branch(BranchNode::new(
4981 vec![
4982 RlpNode::word_rlp(&B256::repeat_byte(1)),
4983 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
4984 ],
4985 TrieMask::new(0b11),
4986 ));
4987
4988 let provider = DefaultTrieNodeProvider;
4989 let mut sparse = ParallelSparseTrie::from_root(
4990 branch.clone(),
4991 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
4992 false,
4993 )
4994 .unwrap();
4995
4996 sparse
5002 .reveal_nodes(vec![
5003 ProofTrieNode {
5004 path: Nibbles::default(),
5005 node: branch,
5006 masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
5007 },
5008 ProofTrieNode {
5009 path: Nibbles::from_nibbles([0x1]),
5010 node: TrieNode::Leaf(leaf),
5011 masks: TrieMasks::none(),
5012 },
5013 ])
5014 .unwrap();
5015
5016 let sparse_old = sparse.clone();
5018 assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2]), &provider), Ok(()));
5019 assert_eq!(sparse, sparse_old);
5020 }
5021
5022 #[test]
5023 fn sparse_trie_fuzz() {
5024 const KEY_NIBBLES_LEN: usize = 3;
5028
5029 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
5030 {
5031 let mut state = BTreeMap::default();
5032 let default_provider = DefaultTrieNodeProvider;
5033 let provider_factory = create_test_provider_factory();
5034 let mut sparse = ParallelSparseTrie::default().with_updates(true);
5035
5036 for (update, keys_to_delete) in updates {
5037 for (key, account) in update.clone() {
5039 let account = account.into_trie_account(EMPTY_ROOT_HASH);
5040 let mut account_rlp = Vec::new();
5041 account.encode(&mut account_rlp);
5042 sparse.update_leaf(key, account_rlp, &default_provider).unwrap();
5043 }
5044 let mut updated_sparse = sparse.clone();
5048 let sparse_root = updated_sparse.root();
5049 let sparse_updates = updated_sparse.take_updates();
5050
5051 state.extend(update);
5053 let provider = provider_factory.provider().unwrap();
5054 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
5055 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
5056 run_hash_builder(
5057 state.clone(),
5058 trie_cursor.account_trie_cursor().unwrap(),
5059 Default::default(),
5060 state.keys().copied(),
5061 );
5062
5063 let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
5065
5066 let provider_rw = provider_factory.provider_rw().unwrap();
5068 provider_rw.write_trie_updates(hash_builder_updates).unwrap();
5069 provider_rw.commit().unwrap();
5070
5071 assert_eq!(sparse_root, hash_builder_root);
5073 pretty_assertions::assert_eq!(
5075 BTreeMap::from_iter(sparse_updates.updated_nodes),
5076 BTreeMap::from_iter(hash_builder_account_nodes)
5077 );
5078 assert_eq_parallel_sparse_trie_proof_nodes(
5080 &updated_sparse,
5081 hash_builder_proof_nodes,
5082 );
5083
5084 for key in &keys_to_delete {
5087 state.remove(key).unwrap();
5088 sparse.remove_leaf(key, &default_provider).unwrap();
5089 }
5090
5091 let mut updated_sparse = sparse.clone();
5095 let sparse_root = updated_sparse.root();
5096 let sparse_updates = updated_sparse.take_updates();
5097
5098 let provider = provider_factory.provider().unwrap();
5099 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
5100 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
5101 run_hash_builder(
5102 state.clone(),
5103 trie_cursor.account_trie_cursor().unwrap(),
5104 keys_to_delete
5105 .iter()
5106 .map(|nibbles| B256::from_slice(&nibbles.pack()))
5107 .collect(),
5108 state.keys().copied(),
5109 );
5110
5111 let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
5113
5114 let provider_rw = provider_factory.provider_rw().unwrap();
5116 provider_rw.write_trie_updates(hash_builder_updates).unwrap();
5117 provider_rw.commit().unwrap();
5118
5119 assert_eq!(sparse_root, hash_builder_root);
5121 pretty_assertions::assert_eq!(
5123 BTreeMap::from_iter(sparse_updates.updated_nodes),
5124 BTreeMap::from_iter(hash_builder_account_nodes)
5125 );
5126 assert_eq_parallel_sparse_trie_proof_nodes(
5128 &updated_sparse,
5129 hash_builder_proof_nodes,
5130 );
5131 }
5132 }
5133 }
5134
5135 fn transform_updates(
5136 updates: Vec<BTreeMap<Nibbles, Account>>,
5137 mut rng: impl rand::Rng,
5138 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
5139 let mut keys = BTreeSet::new();
5140 updates
5141 .into_iter()
5142 .map(|update| {
5143 keys.extend(update.keys().copied());
5144
5145 let keys_to_delete_len = update.len() / 2;
5146 let keys_to_delete = (0..keys_to_delete_len)
5147 .map(|_| {
5148 let key =
5149 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
5150 keys.take(&key).unwrap()
5151 })
5152 .collect();
5153
5154 (update, keys_to_delete)
5155 })
5156 .collect::<Vec<_>>()
5157 }
5158
5159 proptest!(ProptestConfig::with_cases(10), |(
5160 updates in proptest::collection::vec(
5161 proptest::collection::btree_map(
5162 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
5163 arb::<Account>(),
5164 1..50,
5165 ),
5166 1..50,
5167 ).prop_perturb(transform_updates)
5168 )| {
5169 test(updates)
5170 });
5171 }
5172
5173 #[test]
5174 fn sparse_trie_fuzz_vs_serial() {
5175 const KEY_NIBBLES_LEN: usize = 3;
5179
5180 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
5181 let default_provider = DefaultTrieNodeProvider;
5182 let mut serial = SerialSparseTrie::default().with_updates(true);
5183 let mut parallel = ParallelSparseTrie::default().with_updates(true);
5184
5185 for (update, keys_to_delete) in updates {
5186 for (key, account) in update.clone() {
5188 let account = account.into_trie_account(EMPTY_ROOT_HASH);
5189 let mut account_rlp = Vec::new();
5190 account.encode(&mut account_rlp);
5191 serial.update_leaf(key, account_rlp.clone(), &default_provider).unwrap();
5192 parallel.update_leaf(key, account_rlp, &default_provider).unwrap();
5193 }
5194
5195 let serial_root = serial.root();
5197 let parallel_root = parallel.root();
5198 assert_eq!(parallel_root, serial_root);
5199
5200 let serial_updates = serial.take_updates();
5202 let parallel_updates = parallel.take_updates();
5203 pretty_assertions::assert_eq!(
5204 BTreeMap::from_iter(parallel_updates.updated_nodes),
5205 BTreeMap::from_iter(serial_updates.updated_nodes),
5206 );
5207 pretty_assertions::assert_eq!(
5208 BTreeSet::from_iter(parallel_updates.removed_nodes),
5209 BTreeSet::from_iter(serial_updates.removed_nodes),
5210 );
5211
5212 for key in &keys_to_delete {
5214 parallel.remove_leaf(key, &default_provider).unwrap();
5215 serial.remove_leaf(key, &default_provider).unwrap();
5216 }
5217
5218 let serial_root = serial.root();
5220 let parallel_root = parallel.root();
5221 assert_eq!(parallel_root, serial_root);
5222
5223 let serial_updates = serial.take_updates();
5225 let parallel_updates = parallel.take_updates();
5226 pretty_assertions::assert_eq!(
5227 BTreeMap::from_iter(parallel_updates.updated_nodes),
5228 BTreeMap::from_iter(serial_updates.updated_nodes),
5229 );
5230 pretty_assertions::assert_eq!(
5231 BTreeSet::from_iter(parallel_updates.removed_nodes),
5232 BTreeSet::from_iter(serial_updates.removed_nodes),
5233 );
5234 }
5235 }
5236
5237 fn transform_updates(
5238 updates: Vec<BTreeMap<Nibbles, Account>>,
5239 mut rng: impl rand::Rng,
5240 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
5241 let mut keys = BTreeSet::new();
5242 updates
5243 .into_iter()
5244 .map(|update| {
5245 keys.extend(update.keys().copied());
5246
5247 let keys_to_delete_len = update.len() / 2;
5248 let keys_to_delete = (0..keys_to_delete_len)
5249 .map(|_| {
5250 let key =
5251 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
5252 keys.take(&key).unwrap()
5253 })
5254 .collect();
5255
5256 (update, keys_to_delete)
5257 })
5258 .collect::<Vec<_>>()
5259 }
5260
5261 proptest!(ProptestConfig::with_cases(10), |(
5262 updates in proptest::collection::vec(
5263 proptest::collection::btree_map(
5264 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
5265 arb::<Account>(),
5266 1..50,
5267 ),
5268 1..50,
5269 ).prop_perturb(transform_updates)
5270 )| {
5271 test(updates)
5272 });
5273 }
5274
5275 #[test]
5276 fn sparse_trie_two_leaves_at_lower_roots() {
5277 let provider = DefaultTrieNodeProvider;
5278 let mut trie = ParallelSparseTrie::default().with_updates(true);
5279 let key_50 = Nibbles::unpack(hex!(
5280 "0x5000000000000000000000000000000000000000000000000000000000000000"
5281 ));
5282 let key_51 = Nibbles::unpack(hex!(
5283 "0x5100000000000000000000000000000000000000000000000000000000000000"
5284 ));
5285
5286 let account = Account::default().into_trie_account(EMPTY_ROOT_HASH);
5287 let mut account_rlp = Vec::new();
5288 account.encode(&mut account_rlp);
5289
5290 trie.update_leaf(key_50, account_rlp.clone(), &provider).unwrap();
5292 trie.root();
5293
5294 trie.update_leaf(key_51, account_rlp.clone(), &provider).unwrap();
5296
5297 let expected_root =
5298 hex!("0xdaf0ef9f91a2f179bb74501209effdb5301db1697bcab041eca2234b126e25de");
5299 let root = trie.root();
5300 assert_eq!(root, expected_root);
5301 assert_eq!(SparseTrieUpdates::default(), trie.take_updates());
5302 }
5303
5304 #[test]
5316 fn sparse_trie_reveal_node_1() {
5317 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00]));
5318 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01]));
5319 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x02]));
5320 let value = || Account::default();
5321 let value_encoded = || {
5322 let mut account_rlp = Vec::new();
5323 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
5324 account_rlp
5325 };
5326
5327 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5329 run_hash_builder(
5330 [(key1(), value()), (key3(), value())],
5331 NoopAccountTrieCursor::default(),
5332 Default::default(),
5333 [Nibbles::default()],
5334 );
5335
5336 let provider = DefaultTrieNodeProvider;
5337 let mut sparse = ParallelSparseTrie::from_root(
5338 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5339 TrieMasks {
5340 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5341 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5342 },
5343 false,
5344 )
5345 .unwrap();
5346
5347 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5349 run_hash_builder(
5350 [(key1(), value()), (key3(), value())],
5351 NoopAccountTrieCursor::default(),
5352 Default::default(),
5353 [key1()],
5354 );
5355 let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
5356 .nodes_sorted()
5357 .into_iter()
5358 .map(|(path, node)| {
5359 let hash_mask = branch_node_hash_masks.get(&path).copied();
5360 let tree_mask = branch_node_tree_masks.get(&path).copied();
5361 ProofTrieNode {
5362 path,
5363 node: TrieNode::decode(&mut &node[..]).unwrap(),
5364 masks: TrieMasks { hash_mask, tree_mask },
5365 }
5366 })
5367 .collect();
5368 sparse.reveal_nodes(revealed_nodes).unwrap();
5369
5370 assert_eq!(
5372 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5373 Some(&SparseNode::new_branch(0b101.into()))
5374 );
5375
5376 sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
5378
5379 assert_eq!(
5381 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5382 Some(&SparseNode::new_branch(0b111.into()))
5383 );
5384
5385 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5387 run_hash_builder(
5388 [(key1(), value()), (key3(), value())],
5389 NoopAccountTrieCursor::default(),
5390 Default::default(),
5391 [key3()],
5392 );
5393 let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
5394 .nodes_sorted()
5395 .into_iter()
5396 .map(|(path, node)| {
5397 let hash_mask = branch_node_hash_masks.get(&path).copied();
5398 let tree_mask = branch_node_tree_masks.get(&path).copied();
5399 ProofTrieNode {
5400 path,
5401 node: TrieNode::decode(&mut &node[..]).unwrap(),
5402 masks: TrieMasks { hash_mask, tree_mask },
5403 }
5404 })
5405 .collect();
5406 sparse.reveal_nodes(revealed_nodes).unwrap();
5407
5408 assert_eq!(
5410 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5411 Some(&SparseNode::new_branch(0b111.into()))
5412 );
5413
5414 let (_, _, hash_builder_proof_nodes, _, _) = run_hash_builder(
5417 [(key1(), value()), (key2(), value()), (key3(), value())],
5418 NoopAccountTrieCursor::default(),
5419 Default::default(),
5420 [key1(), key2(), key3()],
5421 );
5422
5423 assert_eq_parallel_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
5424 }
5425
5426 #[test]
5437 fn sparse_trie_reveal_node_2() {
5438 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x00]));
5439 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x01]));
5440 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x02]));
5441 let value = || Account::default();
5442
5443 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5445 run_hash_builder(
5446 [(key1(), value()), (key2(), value()), (key3(), value())],
5447 NoopAccountTrieCursor::default(),
5448 Default::default(),
5449 [Nibbles::default()],
5450 );
5451
5452 let provider = DefaultTrieNodeProvider;
5453 let mut sparse = ParallelSparseTrie::from_root(
5454 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5455 TrieMasks {
5456 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5457 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5458 },
5459 false,
5460 )
5461 .unwrap();
5462
5463 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5466 run_hash_builder(
5467 [(key1(), value()), (key2(), value()), (key3(), value())],
5468 NoopAccountTrieCursor::default(),
5469 Default::default(),
5470 [key1(), Nibbles::from_nibbles_unchecked([0x01])],
5471 );
5472 let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
5473 .nodes_sorted()
5474 .into_iter()
5475 .map(|(path, node)| {
5476 let hash_mask = branch_node_hash_masks.get(&path).copied();
5477 let tree_mask = branch_node_tree_masks.get(&path).copied();
5478 ProofTrieNode {
5479 path,
5480 node: TrieNode::decode(&mut &node[..]).unwrap(),
5481 masks: TrieMasks { hash_mask, tree_mask },
5482 }
5483 })
5484 .collect();
5485 sparse.reveal_nodes(revealed_nodes).unwrap();
5486
5487 assert_eq!(
5489 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5490 Some(&SparseNode::new_branch(0b11.into()))
5491 );
5492
5493 sparse.remove_leaf(&key1(), &provider).unwrap();
5495
5496 assert_eq!(
5498 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5499 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
5500 );
5501
5502 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5504 run_hash_builder(
5505 [(key1(), value()), (key2(), value()), (key3(), value())],
5506 NoopAccountTrieCursor::default(),
5507 Default::default(),
5508 [key2()],
5509 );
5510 let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
5511 .nodes_sorted()
5512 .into_iter()
5513 .map(|(path, node)| {
5514 let hash_mask = branch_node_hash_masks.get(&path).copied();
5515 let tree_mask = branch_node_tree_masks.get(&path).copied();
5516 ProofTrieNode {
5517 path,
5518 node: TrieNode::decode(&mut &node[..]).unwrap(),
5519 masks: TrieMasks { hash_mask, tree_mask },
5520 }
5521 })
5522 .collect();
5523 sparse.reveal_nodes(revealed_nodes).unwrap();
5524
5525 assert_eq!(
5527 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5528 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
5529 );
5530 }
5531
5532 #[test]
5541 fn sparse_trie_reveal_node_3() {
5542 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x01]));
5543 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x02]));
5544 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x00]));
5545 let value = || Account::default();
5546 let value_encoded = || {
5547 let mut account_rlp = Vec::new();
5548 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
5549 account_rlp
5550 };
5551
5552 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5554 run_hash_builder(
5555 [(key1(), value()), (key2(), value())],
5556 NoopAccountTrieCursor::default(),
5557 Default::default(),
5558 [Nibbles::default()],
5559 );
5560
5561 let provider = DefaultTrieNodeProvider;
5562 let mut sparse = ParallelSparseTrie::from_root(
5563 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5564 TrieMasks {
5565 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5566 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5567 },
5568 false,
5569 )
5570 .unwrap();
5571
5572 assert_matches!(
5574 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5575 Some(SparseNode::Extension { key, hash: None, store_in_db_trie: None }) if *key == Nibbles::from_nibbles([0x00])
5576 );
5577
5578 sparse.update_leaf(key3(), value_encoded(), &provider).unwrap();
5580
5581 assert_matches!(
5583 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5584 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
5585 );
5586
5587 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5589 run_hash_builder(
5590 [(key1(), value()), (key2(), value())],
5591 NoopAccountTrieCursor::default(),
5592 Default::default(),
5593 [key1()],
5594 );
5595 let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
5596 .nodes_sorted()
5597 .into_iter()
5598 .map(|(path, node)| {
5599 let hash_mask = branch_node_hash_masks.get(&path).copied();
5600 let tree_mask = branch_node_tree_masks.get(&path).copied();
5601 ProofTrieNode {
5602 path,
5603 node: TrieNode::decode(&mut &node[..]).unwrap(),
5604 masks: TrieMasks { hash_mask, tree_mask },
5605 }
5606 })
5607 .collect();
5608 sparse.reveal_nodes(revealed_nodes).unwrap();
5609
5610 assert_matches!(
5612 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5613 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
5614 );
5615 }
5616
5617 #[test]
5618 fn test_update_leaf_cross_level() {
5619 let ctx = ParallelSparseTrieTestContext;
5620 let mut trie =
5621 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5622
5623 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x3, 0x4, 0x5], 1);
5645 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
5646
5647 ctx.assert_upper_subtrie(&trie)
5649 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x3, 0x4, 0x5]))
5650 .has_value(&leaf1_path, &value1);
5651
5652 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 2);
5654 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
5655
5656 ctx.assert_upper_subtrie(&trie)
5658 .has_branch(&Nibbles::from_nibbles([0x1]), &[0x2, 0x3])
5659 .has_no_value(&leaf1_path)
5660 .has_no_value(&leaf2_path);
5661
5662 let (leaf3_path, value3) = ctx.create_test_leaf([0x1, 0x2, 0x4, 0x5], 3);
5664 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
5665
5666 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5668 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5669 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5670 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::from_nibbles([0x5]))
5671 .has_value(&leaf2_path, &value2)
5672 .has_value(&leaf3_path, &value3);
5673
5674 let (leaf4_path, value4) = ctx.create_test_leaf([0x1, 0x3, 0x3, 0x4], 4);
5676 trie.update_leaf(leaf4_path, value4.clone(), DefaultTrieNodeProvider).unwrap();
5677
5678 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x3]))
5680 .has_value(&leaf1_path, &value1)
5681 .has_value(&leaf4_path, &value4);
5682
5683 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5685 .has_value(&leaf2_path, &value2)
5686 .has_value(&leaf3_path, &value3);
5687
5688 ctx.assert_upper_subtrie(&trie)
5690 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1]))
5691 .has_branch(&Nibbles::from_nibbles([0x1]), &[0x2, 0x3])
5692 .has_no_value(&leaf1_path)
5693 .has_no_value(&leaf2_path)
5694 .has_no_value(&leaf3_path)
5695 .has_no_value(&leaf4_path);
5696 }
5697
5698 #[test]
5699 fn test_update_leaf_split_at_level_boundary() {
5700 let ctx = ParallelSparseTrieTestContext;
5701 let mut trie =
5702 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5703
5704 let (first_leaf_path, first_value) = ctx.create_test_leaf([0x1, 0x2, 0x2, 0x4], 1);
5719
5720 trie.update_leaf(first_leaf_path, first_value.clone(), DefaultTrieNodeProvider).unwrap();
5721
5722 ctx.assert_upper_subtrie(&trie)
5724 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x2, 0x4]))
5725 .has_value(&first_leaf_path, &first_value);
5726
5727 let (second_leaf_path, second_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 2);
5729
5730 trie.update_leaf(second_leaf_path, second_value.clone(), DefaultTrieNodeProvider).unwrap();
5731
5732 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5734 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x2, 0x3])
5735 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x2]), &Nibbles::from_nibbles([0x4]))
5736 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5737 .has_value(&first_leaf_path, &first_value)
5738 .has_value(&second_leaf_path, &second_value);
5739
5740 ctx.assert_upper_subtrie(&trie)
5742 .has_no_value(&first_leaf_path)
5743 .has_no_value(&second_leaf_path);
5744 }
5745
5746 #[test]
5747 fn test_update_subtrie_with_multiple_leaves() {
5748 let ctx = ParallelSparseTrieTestContext;
5749 let mut trie =
5750 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5751
5752 let leaves = ctx.create_test_leaves(&[
5766 &[0x1, 0x2, 0x3, 0x4],
5767 &[0x1, 0x2, 0x3, 0x5],
5768 &[0x1, 0x2, 0x4, 0x6],
5769 &[0x1, 0x2, 0x4, 0x7],
5770 ]);
5771
5772 ctx.update_leaves(&mut trie, leaves.clone());
5774
5775 ctx.assert_upper_subtrie(&trie)
5777 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
5778
5779 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5781 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5782 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
5783 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &[0x6, 0x7])
5784 .has_value(&leaves[0].0, &leaves[0].1)
5785 .has_value(&leaves[1].0, &leaves[1].1)
5786 .has_value(&leaves[2].0, &leaves[2].1)
5787 .has_value(&leaves[3].0, &leaves[3].1);
5788
5789 let updated_path = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]);
5791 let (_, updated_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 100);
5792
5793 trie.update_leaf(updated_path, updated_value.clone(), DefaultTrieNodeProvider).unwrap();
5794
5795 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5798 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5799 .has_value(&updated_path, &updated_value)
5800 .has_value(&leaves[1].0, &leaves[1].1)
5801 .has_value(&leaves[2].0, &leaves[2].1)
5802 .has_value(&leaves[3].0, &leaves[3].1);
5803
5804 let (new_leaf_path, new_leaf_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x6], 200);
5806
5807 trie.update_leaf(new_leaf_path, new_leaf_value.clone(), DefaultTrieNodeProvider).unwrap();
5808
5809 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5811 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5, 0x6])
5812 .has_value(&new_leaf_path, &new_leaf_value);
5813 }
5814
5815 #[test]
5816 fn test_update_subtrie_extension_node_subtrie() {
5817 let ctx = ParallelSparseTrieTestContext;
5818 let mut trie =
5819 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5820
5821 let leaves = ctx.create_test_leaves(&[&[0x1, 0x2, 0x3, 0x4], &[0x1, 0x2, 0x3, 0x5]]);
5830
5831 ctx.update_leaves(&mut trie, leaves.clone());
5833
5834 ctx.assert_upper_subtrie(&trie)
5836 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
5837
5838 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5840 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
5841 .has_value(&leaves[0].0, &leaves[0].1)
5842 .has_value(&leaves[1].0, &leaves[1].1);
5843 }
5844
5845 #[test]
5846 fn update_subtrie_extension_node_cross_level() {
5847 let ctx = ParallelSparseTrieTestContext;
5848 let mut trie =
5849 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5850
5851 let leaves = ctx.create_test_leaves(&[&[0x1, 0x2, 0x3, 0x4], &[0x1, 0x2, 0x4, 0x5]]);
5861
5862 ctx.update_leaves(&mut trie, leaves.clone());
5864
5865 ctx.assert_upper_subtrie(&trie)
5867 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
5868
5869 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5871 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5872 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5873 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::from_nibbles([0x5]))
5874 .has_value(&leaves[0].0, &leaves[0].1)
5875 .has_value(&leaves[1].0, &leaves[1].1);
5876 }
5877
5878 #[test]
5879 fn test_update_single_nibble_paths() {
5880 let ctx = ParallelSparseTrieTestContext;
5881 let mut trie =
5882 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5883
5884 let (leaf1_path, value1) = ctx.create_test_leaf([0x0], 1);
5896 let (leaf2_path, value2) = ctx.create_test_leaf([0x1], 2);
5897 let (leaf3_path, value3) = ctx.create_test_leaf([0x2], 3);
5898 let (leaf4_path, value4) = ctx.create_test_leaf([0x3], 4);
5899
5900 ctx.update_leaves(
5901 &mut trie,
5902 [
5903 (leaf1_path, value1.clone()),
5904 (leaf2_path, value2.clone()),
5905 (leaf3_path, value3.clone()),
5906 (leaf4_path, value4.clone()),
5907 ],
5908 );
5909
5910 ctx.assert_upper_subtrie(&trie)
5912 .has_branch(&Nibbles::default(), &[0x0, 0x1, 0x2, 0x3])
5913 .has_leaf(&Nibbles::from_nibbles([0x0]), &Nibbles::default())
5914 .has_leaf(&Nibbles::from_nibbles([0x1]), &Nibbles::default())
5915 .has_leaf(&Nibbles::from_nibbles([0x2]), &Nibbles::default())
5916 .has_leaf(&Nibbles::from_nibbles([0x3]), &Nibbles::default())
5917 .has_value(&leaf1_path, &value1)
5918 .has_value(&leaf2_path, &value2)
5919 .has_value(&leaf3_path, &value3)
5920 .has_value(&leaf4_path, &value4);
5921 }
5922
5923 #[test]
5924 fn test_update_deep_extension_chain() {
5925 let ctx = ParallelSparseTrieTestContext;
5926 let mut trie =
5927 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5928
5929 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0], 1);
5943 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1], 2);
5944
5945 ctx.update_leaves(&mut trie, [(leaf1_path, value1.clone()), (leaf2_path, value2.clone())]);
5946
5947 ctx.assert_upper_subtrie(&trie).has_extension(
5949 &Nibbles::default(),
5950 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1]),
5951 );
5952
5953 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x1]))
5955 .has_branch(&Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1]), &[0x0, 0x1])
5956 .has_leaf(
5957 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0]),
5958 &Nibbles::default(),
5959 )
5960 .has_leaf(
5961 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1]),
5962 &Nibbles::default(),
5963 )
5964 .has_value(&leaf1_path, &value1)
5965 .has_value(&leaf2_path, &value2);
5966 }
5967
5968 #[test]
5969 fn test_update_branch_with_all_nibbles() {
5970 let ctx = ParallelSparseTrieTestContext;
5971 let mut trie =
5972 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5973
5974 let mut leaves = Vec::new();
5991 for nibble in 0x0..=0xF {
5992 let (path, value) = ctx.create_test_leaf([0xA, 0x0, nibble], nibble as u64 + 1);
5993 leaves.push((path, value));
5994 }
5995
5996 ctx.update_leaves(&mut trie, leaves.iter().cloned());
5998
5999 ctx.assert_upper_subtrie(&trie)
6001 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA, 0x0]));
6002
6003 let mut subtrie_assert =
6005 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0x0])).has_branch(
6006 &Nibbles::from_nibbles([0xA, 0x0]),
6007 &[0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
6008 );
6009
6010 for (i, (path, value)) in leaves.iter().enumerate() {
6012 subtrie_assert = subtrie_assert
6013 .has_leaf(&Nibbles::from_nibbles([0xA, 0x0, i as u8]), &Nibbles::default())
6014 .has_value(path, value);
6015 }
6016 }
6017
6018 #[test]
6019 fn test_update_creates_multiple_subtries() {
6020 let ctx = ParallelSparseTrieTestContext;
6021 let mut trie =
6022 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6023
6024 let leaves = [
6040 ctx.create_test_leaf([0x0, 0x0, 0x1, 0x2], 1),
6041 ctx.create_test_leaf([0x0, 0x1, 0x3, 0x4], 2),
6042 ctx.create_test_leaf([0x0, 0x2, 0x5, 0x6], 3),
6043 ctx.create_test_leaf([0x0, 0x3, 0x7, 0x8], 4),
6044 ];
6045
6046 ctx.update_leaves(&mut trie, leaves.iter().cloned());
6048
6049 ctx.assert_upper_subtrie(&trie)
6051 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x0]))
6052 .has_branch(&Nibbles::from_nibbles([0x0]), &[0x0, 0x1, 0x2, 0x3]);
6053
6054 for (i, (leaf_path, leaf_value)) in leaves.iter().enumerate() {
6056 let subtrie_path = Nibbles::from_nibbles([0x0, i as u8]);
6057 ctx.assert_subtrie(&trie, subtrie_path)
6058 .has_leaf(
6059 &subtrie_path,
6060 &Nibbles::from_nibbles(match i {
6061 0 => vec![0x1, 0x2],
6062 1 => vec![0x3, 0x4],
6063 2 => vec![0x5, 0x6],
6064 3 => vec![0x7, 0x8],
6065 _ => unreachable!(),
6066 }),
6067 )
6068 .has_value(leaf_path, leaf_value);
6069 }
6070 }
6071
6072 #[test]
6073 fn test_update_extension_to_branch_transformation() {
6074 let ctx = ParallelSparseTrieTestContext;
6075 let mut trie =
6076 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6077
6078 let (leaf1_path, value1) = ctx.create_test_leaf([0xF, 0xF, 0x0, 0x1], 1);
6094 let (leaf2_path, value2) = ctx.create_test_leaf([0xF, 0xF, 0x0, 0x2], 2);
6095 let (leaf3_path, value3) = ctx.create_test_leaf([0xF, 0x0, 0x0, 0x3], 3);
6096
6097 ctx.update_leaves(&mut trie, [(leaf1_path, value1.clone()), (leaf2_path, value2.clone())]);
6098
6099 ctx.assert_upper_subtrie(&trie)
6101 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xF, 0xF, 0x0]));
6102
6103 ctx.update_leaves(&mut trie, [(leaf3_path, value3.clone())]);
6105
6106 ctx.assert_upper_subtrie(&trie)
6108 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xF]))
6109 .has_branch(&Nibbles::from_nibbles([0xF]), &[0x0, 0xF]);
6110
6111 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0xF]))
6113 .has_branch(&Nibbles::from_nibbles([0xF, 0xF, 0x0]), &[0x1, 0x2])
6114 .has_leaf(&Nibbles::from_nibbles([0xF, 0xF, 0x0, 0x1]), &Nibbles::default())
6115 .has_leaf(&Nibbles::from_nibbles([0xF, 0xF, 0x0, 0x2]), &Nibbles::default())
6116 .has_value(&leaf1_path, &value1)
6117 .has_value(&leaf2_path, &value2);
6118
6119 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0x0]))
6120 .has_leaf(&Nibbles::from_nibbles([0xF, 0x0]), &Nibbles::from_nibbles([0x0, 0x3]))
6121 .has_value(&leaf3_path, &value3);
6122 }
6123
6124 #[test]
6125 fn test_update_upper_extension_reveal_lower_hash_node() {
6126 let ctx = ParallelSparseTrieTestContext;
6127
6128 let mut provider = MockTrieNodeProvider::new();
6151
6152 let child_hashes = [
6154 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
6155 RlpNode::word_rlp(&B256::repeat_byte(0x22)),
6156 ];
6157 let revealed_branch = create_branch_node_with_children(&[0x1, 0x2], child_hashes);
6158 let mut encoded = Vec::new();
6159 revealed_branch.encode(&mut encoded);
6160 provider.add_revealed_node(
6161 Nibbles::from_nibbles([0xA, 0xB]),
6162 RevealedNode { node: encoded.into(), tree_mask: None, hash_mask: None },
6163 );
6164
6165 let mut trie = new_test_trie(
6166 [
6167 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0xA, 0xB]))),
6168 (Nibbles::from_nibbles([0xA, 0xB]), SparseNode::Hash(B256::repeat_byte(0x42))),
6169 ]
6170 .into_iter(),
6171 );
6172
6173 let (leaf_path, value) = ctx.create_test_leaf([0xA, 0x0], 1);
6175 trie.update_leaf(leaf_path, value, provider).unwrap();
6176
6177 ctx.assert_upper_subtrie(&trie)
6179 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA]))
6180 .has_branch(&Nibbles::from_nibbles([0xA]), &[0x0, 0xB]);
6181
6182 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0xB]))
6184 .has_branch(&Nibbles::from_nibbles([0xA, 0xB]), &[0x1, 0x2])
6185 .has_hash(&Nibbles::from_nibbles([0xA, 0xB, 0x1]), &B256::repeat_byte(0x11))
6186 .has_hash(&Nibbles::from_nibbles([0xA, 0xB, 0x2]), &B256::repeat_byte(0x22));
6187 }
6188
6189 #[test]
6190 fn test_update_long_shared_prefix_at_boundary() {
6191 let ctx = ParallelSparseTrieTestContext;
6192 let mut trie =
6193 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6194
6195 let (leaf1_path, value1) = ctx.create_test_leaf([0xA, 0xB, 0xC, 0xD, 0xE, 0xF], 1);
6209 let (leaf2_path, value2) = ctx.create_test_leaf([0xA, 0xB, 0xD, 0xE, 0xF, 0x0], 2);
6210
6211 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6212 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6213
6214 ctx.assert_upper_subtrie(&trie)
6216 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA, 0xB]));
6217
6218 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0xB]))
6220 .has_branch(&Nibbles::from_nibbles([0xA, 0xB]), &[0xC, 0xD])
6221 .has_leaf(
6222 &Nibbles::from_nibbles([0xA, 0xB, 0xC]),
6223 &Nibbles::from_nibbles([0xD, 0xE, 0xF]),
6224 )
6225 .has_leaf(
6226 &Nibbles::from_nibbles([0xA, 0xB, 0xD]),
6227 &Nibbles::from_nibbles([0xE, 0xF, 0x0]),
6228 )
6229 .has_value(&leaf1_path, &value1)
6230 .has_value(&leaf2_path, &value2);
6231 }
6232
6233 #[test]
6234 fn test_update_branch_to_extension_collapse() {
6235 let ctx = ParallelSparseTrieTestContext;
6236 let mut trie =
6237 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6238
6239 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 1);
6265 let (leaf2_path, value2) = ctx.create_test_leaf([0x2, 0x3, 0x4, 0x5], 2);
6266 let (leaf3_path, value3) = ctx.create_test_leaf([0x2, 0x3, 0x5, 0x6], 3);
6267
6268 trie.update_leaf(leaf1_path, value1, DefaultTrieNodeProvider).unwrap();
6269 trie.update_leaf(leaf2_path, value2, DefaultTrieNodeProvider).unwrap();
6270 trie.update_leaf(leaf3_path, value3, DefaultTrieNodeProvider).unwrap();
6271
6272 ctx.assert_upper_subtrie(&trie).has_branch(&Nibbles::default(), &[0x1, 0x2]);
6274
6275 let (new_leaf1_path, new_value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 10);
6278 let (new_leaf2_path, new_value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x5], 11);
6279 let (new_leaf3_path, new_value3) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x6], 12);
6280
6281 let mut trie =
6283 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6284 trie.update_leaf(new_leaf1_path, new_value1.clone(), DefaultTrieNodeProvider).unwrap();
6285 trie.update_leaf(new_leaf2_path, new_value2.clone(), DefaultTrieNodeProvider).unwrap();
6286 trie.update_leaf(new_leaf3_path, new_value3.clone(), DefaultTrieNodeProvider).unwrap();
6287
6288 ctx.assert_upper_subtrie(&trie)
6290 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
6291
6292 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3]);
6294
6295 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6297 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5, 0x6]) .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &Nibbles::default())
6299 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x5]), &Nibbles::default())
6300 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x6]), &Nibbles::default())
6301 .has_value(&new_leaf1_path, &new_value1)
6302 .has_value(&new_leaf2_path, &new_value2)
6303 .has_value(&new_leaf3_path, &new_value3);
6304 }
6305
6306 #[test]
6307 fn test_update_shared_prefix_patterns() {
6308 let ctx = ParallelSparseTrieTestContext;
6309 let mut trie =
6310 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6311
6312 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 1);
6328 let (leaf2_path, value2) = ctx.create_test_leaf([0x2, 0x3, 0x4, 0x5], 2);
6329 let (leaf3_path, value3) = ctx.create_test_leaf([0x2, 0x3, 0x5, 0x6], 3);
6330
6331 trie.update_leaf(leaf1_path, value1, DefaultTrieNodeProvider).unwrap();
6332 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6333 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
6334
6335 ctx.assert_upper_subtrie(&trie)
6337 .has_branch(&Nibbles::default(), &[0x1, 0x2])
6338 .has_leaf(&Nibbles::from_nibbles([0x1]), &Nibbles::from_nibbles([0x2, 0x3, 0x4]))
6339 .has_extension(&Nibbles::from_nibbles([0x2]), &Nibbles::from_nibbles([0x3]));
6340
6341 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x2, 0x3]))
6343 .has_branch(&Nibbles::from_nibbles([0x2, 0x3]), &[0x4, 0x5])
6344 .has_leaf(&Nibbles::from_nibbles([0x2, 0x3, 0x4]), &Nibbles::from_nibbles([0x5]))
6345 .has_leaf(&Nibbles::from_nibbles([0x2, 0x3, 0x5]), &Nibbles::from_nibbles([0x6]))
6346 .has_value(&leaf2_path, &value2)
6347 .has_value(&leaf3_path, &value3);
6348 }
6349
6350 #[test]
6351 fn test_progressive_branch_creation() {
6352 let ctx = ParallelSparseTrieTestContext;
6353 let mut trie =
6354 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6355
6356 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4, 0x5], 1);
6392 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6393
6394 ctx.assert_upper_subtrie(&trie)
6396 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]))
6397 .has_value(&leaf1_path, &value1);
6398
6399 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4, 0x6], 2);
6401 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6402
6403 ctx.assert_upper_subtrie(&trie)
6405 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]));
6406
6407 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3, 0x4]);
6409
6410 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6411 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6412 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]), &Nibbles::default())
6413 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x6]), &Nibbles::default())
6414 .has_value(&leaf1_path, &value1)
6415 .has_value(&leaf2_path, &value2);
6416
6417 let (leaf3_path, value3) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x5], 3);
6419 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
6420
6421 ctx.assert_upper_subtrie(&trie)
6423 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
6424
6425 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3]);
6427
6428 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6429 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
6430 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6431 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x5]), &Nibbles::default())
6432 .has_value(&leaf1_path, &value1)
6433 .has_value(&leaf2_path, &value2)
6434 .has_value(&leaf3_path, &value3);
6435
6436 let (leaf4_path, value4) = ctx.create_test_leaf([0x1, 0x2, 0x4], 4);
6438 trie.update_leaf(leaf4_path, value4.clone(), DefaultTrieNodeProvider).unwrap();
6439
6440 ctx.assert_upper_subtrie(&trie)
6442 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
6443
6444 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2]);
6446
6447 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6449 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
6450 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
6451 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6452 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::default())
6453 .has_value(&leaf1_path, &value1)
6454 .has_value(&leaf2_path, &value2)
6455 .has_value(&leaf3_path, &value3)
6456 .has_value(&leaf4_path, &value4);
6457 }
6458
6459 #[test]
6460 fn test_update_max_depth_paths() {
6461 let ctx = ParallelSparseTrieTestContext;
6462 let mut trie =
6463 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6464
6465 let mut path1_nibbles = vec![0xF; 63];
6477 path1_nibbles.push(0x0);
6478 let mut path2_nibbles = vec![0xF; 63];
6479 path2_nibbles.push(0x1);
6480
6481 let (leaf1_path, value1) = ctx.create_test_leaf(&path1_nibbles, 1);
6482 let (leaf2_path, value2) = ctx.create_test_leaf(&path2_nibbles, 2);
6483
6484 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6485 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6486
6487 let extension_key = vec![0xF; 63];
6489 ctx.assert_upper_subtrie(&trie)
6490 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles(&extension_key));
6491
6492 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0xF]))
6494 .has_branch(&Nibbles::from_nibbles(&path1_nibbles[..63]), &[0x0, 0x1])
6495 .has_value(&leaf1_path, &value1)
6496 .has_value(&leaf2_path, &value2);
6497 }
6498
6499 #[test]
6500 fn test_hoodie_block_1_data() {
6501 let root_branch_stack = vec![
6503 hex!("a0550b6aba4dd4582a2434d2cbdad8d3007d09f622d7a6e6eaa7a49385823c2fa2"),
6504 hex!("a04788a4975a9e1efd29b834fd80fdfe8a57cc1b1c5ace6d30ce5a36a15e0092b3"),
6505 hex!("a093aeccf87da304e6f7d09edc5d7bd3a552808866d2149dd0940507a8f9bfa910"),
6506 hex!("a08b5b423ba68d0dec2eca1f408076f9170678505eb4a5db2abbbd83bb37666949"),
6507 hex!("a08592f62216af4218098a78acad7cf472a727fb55e6c27d3cfdf2774d4518eb83"),
6508 hex!("a0ef02aeee845cb64c11f85edc1a3094227c26445952554b8a9248915d80c746c3"),
6509 hex!("a0df2529ee3a1ce4df5a758cf17e6a86d0fb5ea22ab7071cf60af6412e9b0a428a"),
6510 hex!("a0acaa1092db69cd5a63676685827b3484c4b80dc1d3361f6073bbb9240101e144"),
6511 hex!("a09c3f2bb2a729d71f246a833353ade65667716bb330e0127a3299a42d11200f93"),
6512 hex!("a0ce978470f4c0b1f8069570563a14d2b79d709add2db4bf22dd9b6aed3271c566"),
6513 hex!("a095f783cd1d464a60e3c8adcadc28c6eb9fec7306664df39553be41dccc909606"),
6514 hex!("a0a9083f5fb914b255e1feb5d951a4dfddacf3c8003ef1d1ec6a13bb6ba5b2ac62"),
6515 hex!("a0fec113d537d8577cd361e0cabf5e95ef58f1cc34318292fdecce9fae57c3e094"),
6516 hex!("a08b7465f5fe8b3e3c0d087cb7521310d4065ef2a0ee43bf73f68dee8a5742b3dd"),
6517 hex!("a0c589aa1ae3d5fd87d8640957f7d5184a4ac06f393b453a8e8ed7e8fba0d385c8"),
6518 hex!("a0b516d6f3352f87beab4ed6e7322f191fc7a147686500ef4de7dd290ad784ef51"),
6519 ];
6520
6521 let root_branch_rlp_stack: Vec<RlpNode> = root_branch_stack
6522 .iter()
6523 .map(|hex_str| RlpNode::from_raw_rlp(&hex_str[..]).unwrap())
6524 .collect();
6525
6526 let root_branch_node = BranchNode::new(
6527 root_branch_rlp_stack,
6528 TrieMask::new(0b1111111111111111), );
6530
6531 let root_branch_masks = TrieMasks {
6532 hash_mask: Some(TrieMask::new(0b1111111111111111)),
6533 tree_mask: Some(TrieMask::new(0b1111111111111111)),
6534 };
6535
6536 let mut trie = ParallelSparseTrie::from_root(
6537 TrieNode::Branch(root_branch_node),
6538 root_branch_masks,
6539 true,
6540 )
6541 .unwrap();
6542
6543 let branch_0x3_stack = vec![
6545 hex!("a09da7d9755fe0c558b3c3de9fdcdf9f28ae641f38c9787b05b73ab22ae53af3e2"),
6546 hex!("a0d9990bf0b810d1145ecb2b011fd68c63cc85564e6724166fd4a9520180706e5f"),
6547 hex!("a0f60eb4b12132a40df05d9bbdb88bbde0185a3f097f3c76bf4200c23eda26cf86"),
6548 hex!("a0ca976997ddaf06f18992f6207e4f6a05979d07acead96568058789017cc6d06b"),
6549 hex!("a04d78166b48044fdc28ed22d2fd39c8df6f8aaa04cb71d3a17286856f6893ff83"),
6550 hex!("a021d4f90c34d3f1706e78463b6482bca77a3aa1cd059a3f326c42a1cfd30b9b60"),
6551 hex!("a0fc3b71c33e2e6b77c5e494c1db7fdbb447473f003daf378c7a63ba9bf3f0049d"),
6552 hex!("a0e33ed2be194a3d93d343e85642447c93a9d0cfc47a016c2c23d14c083be32a7c"),
6553 hex!("a07b8e7a21c1178d28074f157b50fca85ee25c12568ff8e9706dcbcdacb77bf854"),
6554 hex!("a0973274526811393ea0bf4811ca9077531db00d06b86237a2ecd683f55ba4bcb0"),
6555 hex!("a03a93d726d7487874e51b52d8d534c63aa2a689df18e3b307c0d6cb0a388b00f3"),
6556 hex!("a06aa67101d011d1c22fe739ef83b04b5214a3e2f8e1a2625d8bfdb116b447e86f"),
6557 hex!("a02dd545b33c62d33a183e127a08a4767fba891d9f3b94fc20a2ca02600d6d1fff"),
6558 hex!("a0fe6db87d00f06d53bff8169fa497571ff5af1addfb715b649b4d79dd3e394b04"),
6559 hex!("a0d9240a9d2d5851d05a97ff3305334dfdb0101e1e321fc279d2bb3cad6afa8fc8"),
6560 hex!("a01b69c6ab5173de8a8ec53a6ebba965713a4cc7feb86cb3e230def37c230ca2b2"),
6561 ];
6562
6563 let branch_0x3_rlp_stack: Vec<RlpNode> = branch_0x3_stack
6564 .iter()
6565 .map(|hex_str| RlpNode::from_raw_rlp(&hex_str[..]).unwrap())
6566 .collect();
6567
6568 let branch_0x3_node = BranchNode::new(
6569 branch_0x3_rlp_stack,
6570 TrieMask::new(0b1111111111111111), );
6572
6573 let branch_0x3_masks = TrieMasks {
6574 hash_mask: Some(TrieMask::new(0b0100010000010101)),
6575 tree_mask: Some(TrieMask::new(0b0100000000000000)),
6576 };
6577
6578 let leaf_path = Nibbles::from_nibbles([0x3, 0x7]);
6580 let leaf_key = Nibbles::unpack(
6581 &hex!("d65eaa92c6bc4c13a5ec45527f0c18ea8932588728769ec7aecfe6d9f32e42")[..],
6582 );
6583 let leaf_value = hex!("f8440180a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c").to_vec();
6584
6585 let leaf_node = LeafNode::new(leaf_key, leaf_value);
6586 let leaf_masks = TrieMasks::none();
6587
6588 trie.reveal_nodes(vec![
6589 ProofTrieNode {
6590 path: Nibbles::from_nibbles([0x3]),
6591 node: TrieNode::Branch(branch_0x3_node),
6592 masks: branch_0x3_masks,
6593 },
6594 ProofTrieNode { path: leaf_path, node: TrieNode::Leaf(leaf_node), masks: leaf_masks },
6595 ])
6596 .unwrap();
6597
6598 let mut leaf_full_path = leaf_path;
6600 leaf_full_path.extend(&leaf_key);
6601
6602 let leaf_new_value = vec![
6603 248, 68, 1, 128, 160, 224, 163, 152, 169, 122, 160, 155, 102, 53, 41, 0, 47, 28, 205,
6604 190, 199, 5, 215, 108, 202, 22, 138, 70, 196, 178, 193, 208, 18, 96, 95, 63, 238, 160,
6605 245, 122, 205, 64, 37, 152, 114, 96, 109, 118, 25, 126, 240, 82, 243, 211, 85, 136,
6606 218, 223, 145, 158, 225, 240, 227, 203, 155, 98, 211, 244, 176, 44,
6607 ];
6608
6609 trie.update_leaf(leaf_full_path, leaf_new_value.clone(), DefaultTrieNodeProvider).unwrap();
6610
6611 assert_eq!(
6613 Some(&leaf_new_value),
6614 trie.lower_subtrie_for_path(&leaf_path).unwrap().inner.values.get(&leaf_full_path)
6615 );
6616 assert!(trie.upper_subtrie.inner.values.is_empty());
6617
6618 let expected_root =
6620 b256!("0x29b07de8376e9ce7b3a69e9b102199869514d3f42590b5abc6f7d48ec9b8665c");
6621 assert_eq!(trie.root(), expected_root);
6622 }
6623
6624 #[test]
6625 fn find_leaf_existing_leaf() {
6626 let provider = DefaultTrieNodeProvider;
6628 let mut sparse = ParallelSparseTrie::default();
6629 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6630 let value = b"test_value".to_vec();
6631
6632 sparse.update_leaf(path, value.clone(), &provider).unwrap();
6633
6634 let result = sparse.find_leaf(&path, None);
6636 assert_matches!(result, Ok(LeafLookup::Exists));
6637
6638 let result = sparse.find_leaf(&path, Some(&value));
6640 assert_matches!(result, Ok(LeafLookup::Exists));
6641 }
6642
6643 #[test]
6644 fn find_leaf_value_mismatch() {
6645 let provider = DefaultTrieNodeProvider;
6647 let mut sparse = ParallelSparseTrie::default();
6648 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6649 let value = b"test_value".to_vec();
6650 let wrong_value = b"wrong_value".to_vec();
6651
6652 sparse.update_leaf(path, value, &provider).unwrap();
6653
6654 let result = sparse.find_leaf(&path, Some(&wrong_value));
6656 assert_matches!(
6657 result,
6658 Err(LeafLookupError::ValueMismatch { path: p, expected: Some(e), actual: _a }) if p == path && e == wrong_value
6659 );
6660 }
6661
6662 #[test]
6663 fn find_leaf_not_found_empty_trie() {
6664 let sparse = ParallelSparseTrie::default();
6666 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6667
6668 let result = sparse.find_leaf(&path, None);
6670 assert_matches!(result, Ok(LeafLookup::NonExistent));
6671 }
6672
6673 #[test]
6674 fn find_leaf_empty_trie() {
6675 let sparse = ParallelSparseTrie::default();
6676 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6677
6678 let result = sparse.find_leaf(&path, None);
6679 assert_matches!(result, Ok(LeafLookup::NonExistent));
6680 }
6681
6682 #[test]
6683 fn find_leaf_exists_no_value_check() {
6684 let provider = DefaultTrieNodeProvider;
6685 let mut sparse = ParallelSparseTrie::default();
6686 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6687 sparse.update_leaf(path, encode_account_value(0), &provider).unwrap();
6688
6689 let result = sparse.find_leaf(&path, None);
6690 assert_matches!(result, Ok(LeafLookup::Exists));
6691 }
6692
6693 #[test]
6694 fn find_leaf_exists_with_value_check_ok() {
6695 let provider = DefaultTrieNodeProvider;
6696 let mut sparse = ParallelSparseTrie::default();
6697 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6698 let value = encode_account_value(0);
6699 sparse.update_leaf(path, value.clone(), &provider).unwrap();
6700
6701 let result = sparse.find_leaf(&path, Some(&value));
6702 assert_matches!(result, Ok(LeafLookup::Exists));
6703 }
6704
6705 #[test]
6706 fn find_leaf_exclusion_branch_divergence() {
6707 let provider = DefaultTrieNodeProvider;
6708 let mut sparse = ParallelSparseTrie::default();
6709 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]); let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]); sparse.update_leaf(path1, encode_account_value(0), &provider).unwrap();
6714 sparse.update_leaf(path2, encode_account_value(1), &provider).unwrap();
6715
6716 let result = sparse.find_leaf(&search_path, None);
6717 assert_matches!(result, Ok(LeafLookup::NonExistent))
6718 }
6719
6720 #[test]
6721 fn find_leaf_exclusion_extension_divergence() {
6722 let provider = DefaultTrieNodeProvider;
6723 let mut sparse = ParallelSparseTrie::default();
6724 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
6726 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]);
6728
6729 sparse.update_leaf(path1, encode_account_value(0), &provider).unwrap();
6730
6731 let result = sparse.find_leaf(&search_path, None);
6732 assert_matches!(result, Ok(LeafLookup::NonExistent))
6733 }
6734
6735 #[test]
6736 fn find_leaf_exclusion_leaf_divergence() {
6737 let provider = DefaultTrieNodeProvider;
6738 let mut sparse = ParallelSparseTrie::default();
6739 let existing_leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6740 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
6741
6742 sparse.update_leaf(existing_leaf_path, encode_account_value(0), &provider).unwrap();
6743
6744 let result = sparse.find_leaf(&search_path, None);
6745 assert_matches!(result, Ok(LeafLookup::NonExistent))
6746 }
6747
6748 #[test]
6749 fn find_leaf_exclusion_path_ends_at_branch() {
6750 let provider = DefaultTrieNodeProvider;
6751 let mut sparse = ParallelSparseTrie::default();
6752 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]);
6754 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2]); sparse.update_leaf(path1, encode_account_value(0), &provider).unwrap();
6757 sparse.update_leaf(path2, encode_account_value(1), &provider).unwrap();
6758
6759 let result = sparse.find_leaf(&search_path, None);
6760 assert_matches!(result, Ok(LeafLookup::NonExistent));
6761 }
6762
6763 #[test]
6764 fn find_leaf_error_blinded_node_at_leaf_path() {
6765 let blinded_hash = B256::repeat_byte(0xBB);
6767 let leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6768
6769 let sparse = new_test_trie(
6770 [
6771 (
6772 Nibbles::default(),
6774 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x1, 0x2])),
6775 ),
6776 (
6777 Nibbles::from_nibbles_unchecked([0x1, 0x2]),
6779 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x3])),
6780 ),
6781 (
6782 Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3]),
6784 SparseNode::new_branch(TrieMask::new(0b10000)),
6785 ),
6786 (
6787 leaf_path,
6789 SparseNode::Hash(blinded_hash),
6790 ),
6791 ]
6792 .into_iter(),
6793 );
6794
6795 let result = sparse.find_leaf(&leaf_path, None);
6796
6797 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
6799 if path == leaf_path && hash == blinded_hash
6800 );
6801 }
6802
6803 #[test]
6804 fn find_leaf_error_blinded_node() {
6805 let blinded_hash = B256::repeat_byte(0xAA);
6806 let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]);
6807 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6808
6809 let sparse = new_test_trie(
6810 [
6811 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b100010))),
6814 (path_to_blind, SparseNode::Hash(blinded_hash)),
6815 (
6816 Nibbles::from_nibbles_unchecked([0x5]),
6817 SparseNode::new_leaf(Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8])),
6818 ),
6819 ]
6820 .into_iter(),
6821 );
6822
6823 let result = sparse.find_leaf(&search_path, None);
6824
6825 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
6827 if path == path_to_blind && hash == blinded_hash
6828 );
6829 }
6830}