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, RlpNode, TrieNode, CHILD_INDEX_RANGE,
13};
14use reth_trie_sparse::{
15 provider::{RevealedNode, TrieNodeProvider},
16 LeafLookup, LeafLookupError, RevealedSparseNode, RlpNodeStackItem, SparseNode, SparseNodeType,
17 SparseTrieInterface, SparseTrieUpdates, TrieMasks,
18};
19use smallvec::SmallVec;
20use std::{
21 cmp::{Ord, Ordering, PartialOrd},
22 sync::mpsc,
23};
24use tracing::{debug, instrument, trace};
25
26pub const UPPER_TRIE_MAX_DEPTH: usize = 2;
29
30pub const NUM_LOWER_SUBTRIES: usize = 16usize.pow(UPPER_TRIE_MAX_DEPTH as u32);
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
35pub struct ParallelismThresholds {
36 pub min_revealed_nodes: usize,
39 pub min_updated_nodes: usize,
43}
44
45#[derive(Clone, PartialEq, Eq, Debug)]
107pub struct ParallelSparseTrie {
108 upper_subtrie: Box<SparseSubtrie>,
110 lower_subtries: [LowerSparseSubtrie; NUM_LOWER_SUBTRIES],
112 prefix_set: PrefixSetMut,
115 updates: Option<SparseTrieUpdates>,
117 branch_node_tree_masks: HashMap<Nibbles, TrieMask>,
119 branch_node_hash_masks: HashMap<Nibbles, TrieMask>,
121 update_actions_buffers: Vec<Vec<SparseTrieUpdatesAction>>,
124 parallelism_thresholds: ParallelismThresholds,
126 #[cfg(feature = "metrics")]
128 metrics: crate::metrics::ParallelSparseTrieMetrics,
129}
130
131impl Default for ParallelSparseTrie {
132 fn default() -> Self {
133 Self {
134 upper_subtrie: Box::new(SparseSubtrie {
135 nodes: HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]),
136 ..Default::default()
137 }),
138 lower_subtries: [const { LowerSparseSubtrie::Blind(None) }; NUM_LOWER_SUBTRIES],
139 prefix_set: PrefixSetMut::default(),
140 updates: None,
141 branch_node_tree_masks: HashMap::default(),
142 branch_node_hash_masks: HashMap::default(),
143 update_actions_buffers: Vec::default(),
144 parallelism_thresholds: Default::default(),
145 #[cfg(feature = "metrics")]
146 metrics: Default::default(),
147 }
148 }
149}
150
151impl SparseTrieInterface for ParallelSparseTrie {
152 fn with_root(
153 mut self,
154 root: TrieNode,
155 masks: TrieMasks,
156 retain_updates: bool,
157 ) -> SparseTrieResult<Self> {
158 let path = Nibbles::default();
161 let _removed_root = self.upper_subtrie.nodes.remove(&path).expect("root node should exist");
162 debug_assert_eq!(_removed_root, SparseNode::Empty);
163
164 self = self.with_updates(retain_updates);
165
166 self.reveal_upper_node(Nibbles::default(), &root, masks)?;
167 Ok(self)
168 }
169
170 fn with_updates(mut self, retain_updates: bool) -> Self {
171 self.updates = retain_updates.then(Default::default);
172 self
173 }
174
175 fn reveal_nodes(&mut self, mut nodes: Vec<RevealedSparseNode>) -> SparseTrieResult<()> {
176 if nodes.is_empty() {
177 return Ok(())
178 }
179
180 nodes.sort_unstable_by(
183 |RevealedSparseNode { path: path_a, .. }, RevealedSparseNode { path: path_b, .. }| {
184 let subtrie_type_a = SparseSubtrieType::from_path(path_a);
185 let subtrie_type_b = SparseSubtrieType::from_path(path_b);
186 subtrie_type_a.cmp(&subtrie_type_b).then(path_a.cmp(path_b))
187 },
188 );
189
190 for RevealedSparseNode { path, masks, .. } in &nodes {
192 if let Some(tree_mask) = masks.tree_mask {
193 self.branch_node_tree_masks.insert(*path, tree_mask);
194 }
195 if let Some(hash_mask) = masks.hash_mask {
196 self.branch_node_hash_masks.insert(*path, hash_mask);
197 }
198 }
199
200 let num_upper_nodes = nodes
204 .iter()
205 .position(|n| !SparseSubtrieType::path_len_is_upper(n.path.len()))
206 .unwrap_or(nodes.len());
207
208 let upper_nodes = &nodes[..num_upper_nodes];
209 let lower_nodes = &nodes[num_upper_nodes..];
210
211 self.upper_subtrie.nodes.reserve(upper_nodes.len());
214 for node in upper_nodes {
215 self.reveal_upper_node(node.path, &node.node, node.masks)?;
216 }
217
218 if !self.is_reveal_parallelism_enabled(lower_nodes.len()) {
219 for node in lower_nodes {
220 if let Some(subtrie) = self.lower_subtrie_for_path_mut(&node.path) {
221 subtrie.reveal_node(node.path, &node.node, node.masks)?;
222 } else {
223 panic!("upper subtrie node {node:?} found amongst lower nodes");
224 }
225 }
226 return Ok(())
227 }
228
229 #[cfg(not(feature = "std"))]
230 unreachable!("nostd is checked by is_reveal_parallelism_enabled");
231
232 #[cfg(feature = "std")]
233 {
235 use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
236
237 let node_groups: Vec<_> = lower_nodes
240 .chunk_by(|node_a, node_b| {
241 SparseSubtrieType::from_path(&node_a.path) ==
242 SparseSubtrieType::from_path(&node_b.path)
243 })
244 .collect();
245
246 let lower_subtries: Vec<_> = node_groups
250 .iter()
251 .map(|nodes| {
252 let node = &nodes[0];
254 let idx =
255 SparseSubtrieType::from_path(&node.path).lower_index().unwrap_or_else(
256 || panic!("upper subtrie node {node:?} found amongst lower nodes"),
257 );
258 self.lower_subtries[idx].reveal(&node.path);
263 (idx, self.lower_subtries[idx].take_revealed().expect("just revealed"))
264 })
265 .collect();
266
267 let (tx, rx) = mpsc::channel();
268
269 lower_subtries
272 .into_par_iter()
273 .zip(node_groups.into_par_iter())
274 .map(|((subtrie_idx, mut subtrie), nodes)| {
275 subtrie.nodes.reserve(nodes.len());
278
279 for node in nodes {
280 let res = subtrie.reveal_node(node.path, &node.node, node.masks);
282 if res.is_err() {
283 return (subtrie_idx, subtrie, res)
284 }
285 }
286 (subtrie_idx, subtrie, Ok(()))
287 })
288 .for_each_init(|| tx.clone(), |tx, result| tx.send(result).unwrap());
289
290 drop(tx);
291
292 let mut any_err = Ok(());
297 for (subtrie_idx, subtrie, res) in rx {
298 self.lower_subtries[subtrie_idx] = LowerSparseSubtrie::Revealed(subtrie);
299 if res.is_err() {
300 any_err = res;
301 }
302 }
303
304 any_err
305 }
306 }
307
308 fn update_leaf<P: TrieNodeProvider>(
309 &mut self,
310 full_path: Nibbles,
311 value: Vec<u8>,
312 provider: P,
313 ) -> SparseTrieResult<()> {
314 self.prefix_set.insert(full_path);
315 let existing = self.upper_subtrie.inner.values.insert(full_path, value.clone());
316 if existing.is_some() {
317 return Ok(())
319 }
320
321 let retain_updates = self.updates_enabled();
322
323 let mut new_nodes = Vec::new();
332 let mut next = Some(Nibbles::default());
333
334 while let Some(current) =
339 next.filter(|next| SparseSubtrieType::path_len_is_upper(next.len()))
340 {
341 match self.upper_subtrie.update_next_node(current, &full_path, retain_updates)? {
344 LeafUpdateStep::Continue { next_node } => {
345 next = Some(next_node);
346 }
347 LeafUpdateStep::Complete { inserted_nodes, reveal_path } => {
348 new_nodes.extend(inserted_nodes);
349
350 if let Some(reveal_path) = reveal_path {
351 let subtrie = self.subtrie_for_path_mut(&reveal_path);
352 if subtrie.nodes.get(&reveal_path).expect("node must exist").is_hash() {
353 debug!(
354 target: "trie::parallel_sparse",
355 child_path = ?reveal_path,
356 leaf_full_path = ?full_path,
357 "Extension node child not revealed in update_leaf, falling back to db",
358 );
359 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
360 provider.trie_node(&reveal_path)?
361 {
362 let decoded = TrieNode::decode(&mut &node[..])?;
363 trace!(
364 target: "trie::parallel_sparse",
365 ?reveal_path,
366 ?decoded,
367 ?tree_mask,
368 ?hash_mask,
369 "Revealing child (from upper)",
370 );
371 subtrie.reveal_node(
372 reveal_path,
373 &decoded,
374 TrieMasks { hash_mask, tree_mask },
375 )?;
376 } else {
377 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
378 path: reveal_path,
379 }
380 .into())
381 }
382 }
383 }
384
385 next = None;
386 }
387 LeafUpdateStep::NodeNotFound => {
388 next = None;
389 }
390 }
391 }
392
393 for node_path in &new_nodes {
395 if SparseSubtrieType::path_len_is_upper(node_path.len()) {
397 continue
398 }
399
400 let node =
401 self.upper_subtrie.nodes.remove(node_path).expect("node belongs to upper subtrie");
402
403 let leaf_value = if let SparseNode::Leaf { key, .. } = &node {
405 let mut leaf_full_path = *node_path;
406 leaf_full_path.extend(key);
407 Some((
408 leaf_full_path,
409 self.upper_subtrie
410 .inner
411 .values
412 .remove(&leaf_full_path)
413 .expect("leaf nodes have associated values entries"),
414 ))
415 } else {
416 None
417 };
418
419 let subtrie = self.subtrie_for_path_mut(node_path);
421
422 if let Some((leaf_full_path, value)) = leaf_value {
424 subtrie.inner.values.insert(leaf_full_path, value);
425 }
426
427 subtrie.nodes.insert(*node_path, node);
429 }
430
431 if let Some(next_path) = next.filter(|n| !SparseSubtrieType::path_len_is_upper(n.len())) {
433 self.upper_subtrie.inner.values.remove(&full_path);
438
439 let subtrie = self.subtrie_for_path_mut(&next_path);
444
445 if subtrie.nodes.is_empty() {
447 subtrie.nodes.insert(subtrie.path, SparseNode::Empty);
448 }
449
450 subtrie.update_leaf(full_path, value, provider, retain_updates)?;
453 }
454
455 Ok(())
456 }
457
458 fn remove_leaf<P: TrieNodeProvider>(
459 &mut self,
460 full_path: &Nibbles,
461 provider: P,
462 ) -> SparseTrieResult<()> {
463 let leaf_path;
479 let leaf_subtrie;
480
481 let mut branch_parent_path: Option<Nibbles> = None;
482 let mut branch_parent_node: Option<SparseNode> = None;
483
484 let mut ext_grandparent_path: Option<Nibbles> = None;
485 let mut ext_grandparent_node: Option<SparseNode> = None;
486
487 let mut curr_path = Nibbles::new(); let mut curr_subtrie = self.upper_subtrie.as_mut();
489 let mut curr_subtrie_is_upper = true;
490
491 let mut paths_to_reset_hashes = Vec::new();
493
494 loop {
495 let curr_node = curr_subtrie.nodes.get_mut(&curr_path).unwrap();
496
497 match Self::find_next_to_leaf(&curr_path, curr_node, full_path) {
498 FindNextToLeafOutcome::NotFound => return Ok(()), FindNextToLeafOutcome::BlindedNode(hash) => {
500 return Err(SparseTrieErrorKind::BlindedNode { path: curr_path, hash }.into())
501 }
502 FindNextToLeafOutcome::Found => {
503 leaf_path = curr_path;
505 leaf_subtrie = curr_subtrie;
506 break;
507 }
508 FindNextToLeafOutcome::ContinueFrom(next_path) => {
509 match curr_node {
512 SparseNode::Branch { hash, .. } => {
513 if hash.is_some() {
514 paths_to_reset_hashes
515 .push((SparseSubtrieType::from_path(&curr_path), curr_path));
516 }
517
518 match (&branch_parent_path, &ext_grandparent_path) {
521 (Some(branch), Some(ext)) if branch.len() > ext.len() => {
522 ext_grandparent_path = None;
523 ext_grandparent_node = None;
524 }
525 _ => (),
526 };
527 branch_parent_path = Some(curr_path);
528 branch_parent_node = Some(curr_node.clone());
529 }
530 SparseNode::Extension { hash, .. } => {
531 if hash.is_some() {
532 paths_to_reset_hashes
533 .push((SparseSubtrieType::from_path(&curr_path), curr_path));
534 }
535
536 ext_grandparent_path = Some(curr_path);
540 ext_grandparent_node = Some(curr_node.clone());
541 }
542 SparseNode::Empty | SparseNode::Hash(_) | SparseNode::Leaf { .. } => {
543 unreachable!(
544 "find_next_to_leaf only continues to a branch or extension"
545 )
546 }
547 }
548
549 curr_path = next_path;
550
551 if curr_subtrie_is_upper &&
554 let SparseSubtrieType::Lower(idx) =
555 SparseSubtrieType::from_path(&curr_path)
556 {
557 curr_subtrie = self.lower_subtries[idx]
558 .as_revealed_mut()
559 .expect("lower subtrie is revealed");
560 curr_subtrie_is_upper = false;
561 }
562 }
563 };
564 }
565
566 self.prefix_set.insert(*full_path);
569 leaf_subtrie.inner.values.remove(full_path);
570 for (subtrie_type, path) in paths_to_reset_hashes {
571 let node = match subtrie_type {
572 SparseSubtrieType::Upper => self.upper_subtrie.nodes.get_mut(&path),
573 SparseSubtrieType::Lower(idx) => self.lower_subtries[idx]
574 .as_revealed_mut()
575 .expect("lower subtrie is revealed")
576 .nodes
577 .get_mut(&path),
578 }
579 .expect("node exists");
580
581 match node {
582 SparseNode::Extension { hash, .. } | SparseNode::Branch { hash, .. } => {
583 *hash = None
584 }
585 SparseNode::Empty | SparseNode::Hash(_) | SparseNode::Leaf { .. } => {
586 unreachable!("only branch and extension node hashes can be reset")
587 }
588 }
589 }
590 self.remove_node(&leaf_path);
591
592 if leaf_path.is_empty() {
595 self.upper_subtrie.nodes.insert(leaf_path, SparseNode::Empty);
596 return Ok(())
597 }
598
599 if let (Some(branch_path), &Some(SparseNode::Branch { mut state_mask, .. })) =
602 (&branch_parent_path, &branch_parent_node)
603 {
604 let child_nibble = leaf_path.get_unchecked(branch_path.len());
605 state_mask.unset_bit(child_nibble);
606
607 let new_branch_node = if state_mask.count_bits() == 1 {
608 let remaining_child_path = {
611 let mut p = *branch_path;
612 p.push_unchecked(
613 state_mask.first_set_bit_index().expect("state mask is not empty"),
614 );
615 p
616 };
617
618 trace!(
619 target: "trie::parallel_sparse",
620 ?leaf_path,
621 ?branch_path,
622 ?remaining_child_path,
623 "Branch node has only one child",
624 );
625
626 let remaining_child_node = self.reveal_remaining_child_on_leaf_removal(
629 provider,
630 full_path,
631 &remaining_child_path,
632 true, )?;
634
635 let (new_branch_node, remove_child) = Self::branch_changes_on_leaf_removal(
636 branch_path,
637 &remaining_child_path,
638 &remaining_child_node,
639 );
640
641 if remove_child {
642 self.move_value_on_leaf_removal(
643 branch_path,
644 &new_branch_node,
645 &remaining_child_path,
646 );
647 self.remove_node(&remaining_child_path);
648 }
649
650 if let Some(updates) = self.updates.as_mut() {
651 updates.updated_nodes.remove(branch_path);
652 updates.removed_nodes.insert(*branch_path);
653 }
654
655 new_branch_node
656 } else {
657 SparseNode::new_branch(state_mask)
660 };
661
662 let branch_subtrie = self.subtrie_for_path_mut(branch_path);
663 branch_subtrie.nodes.insert(*branch_path, new_branch_node.clone());
664 branch_parent_node = Some(new_branch_node);
665 };
666
667 if let (Some(ext_path), Some(SparseNode::Extension { key: shortkey, .. })) =
671 (ext_grandparent_path, &ext_grandparent_node)
672 {
673 let ext_subtrie = self.subtrie_for_path_mut(&ext_path);
674 let branch_path = branch_parent_path.as_ref().unwrap();
675
676 if let Some(new_ext_node) = Self::extension_changes_on_leaf_removal(
677 &ext_path,
678 shortkey,
679 branch_path,
680 branch_parent_node.as_ref().unwrap(),
681 ) {
682 ext_subtrie.nodes.insert(ext_path, new_ext_node.clone());
683 self.move_value_on_leaf_removal(&ext_path, &new_ext_node, branch_path);
684 self.remove_node(branch_path);
685 }
686 }
687
688 Ok(())
689 }
690
691 #[instrument(level = "trace", target = "trie::sparse::parallel", skip(self))]
692 fn root(&mut self) -> B256 {
693 trace!(target: "trie::parallel_sparse", "Calculating trie root hash");
694
695 self.update_subtrie_hashes();
697
698 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
701 let root_rlp = self.update_upper_subtrie_hashes(&mut prefix_set);
702
703 root_rlp.as_hash().unwrap_or(EMPTY_ROOT_HASH)
705 }
706
707 #[instrument(level = "trace", target = "trie::sparse::parallel", skip(self))]
708 fn update_subtrie_hashes(&mut self) {
709 trace!(target: "trie::parallel_sparse", "Updating subtrie hashes");
710
711 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
713 let num_changed_keys = prefix_set.len();
714 let (mut changed_subtries, unchanged_prefix_set) =
715 self.take_changed_lower_subtries(&mut prefix_set);
716
717 #[cfg(feature = "metrics")]
719 self.metrics.subtries_updated.record(changed_subtries.len() as f64);
720
721 self.prefix_set = unchanged_prefix_set;
723
724 if !self.is_update_parallelism_enabled(num_changed_keys) {
726 for changed_subtrie in &mut changed_subtries {
727 changed_subtrie.subtrie.update_hashes(
728 &mut changed_subtrie.prefix_set,
729 &mut changed_subtrie.update_actions_buf,
730 &self.branch_node_tree_masks,
731 &self.branch_node_hash_masks,
732 );
733 }
734
735 self.insert_changed_subtries(changed_subtries);
736 return
737 }
738
739 #[cfg(not(feature = "std"))]
740 unreachable!("nostd is checked by is_update_parallelism_enabled");
741
742 #[cfg(feature = "std")]
743 {
745 use rayon::iter::{IntoParallelIterator, ParallelIterator};
746 use tracing::debug_span;
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 let span = tracing::Span::current();
753 changed_subtries
754 .into_par_iter()
755 .map(|mut changed_subtrie| {
756 let _enter = debug_span!(
757 target: "trie::parallel_sparse",
758 parent: span.clone(),
759 "subtrie",
760 index = changed_subtrie.index
761 )
762 .entered();
763
764 #[cfg(feature = "metrics")]
765 let start = std::time::Instant::now();
766 changed_subtrie.subtrie.update_hashes(
767 &mut changed_subtrie.prefix_set,
768 &mut changed_subtrie.update_actions_buf,
769 branch_node_tree_masks,
770 branch_node_hash_masks,
771 );
772 #[cfg(feature = "metrics")]
773 self.metrics.subtrie_hash_update_latency.record(start.elapsed());
774 changed_subtrie
775 })
776 .for_each_init(|| tx.clone(), |tx, result| tx.send(result).unwrap());
777
778 drop(tx);
779 self.insert_changed_subtries(rx);
780 }
781 }
782
783 fn get_leaf_value(&self, full_path: &Nibbles) -> Option<&Vec<u8>> {
784 self.subtrie_for_path(full_path).and_then(|subtrie| subtrie.inner.values.get(full_path))
785 }
786
787 fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
788 self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
789 }
790
791 fn take_updates(&mut self) -> SparseTrieUpdates {
792 self.updates.take().unwrap_or_default()
793 }
794
795 fn wipe(&mut self) {
796 self.upper_subtrie.wipe();
797 self.lower_subtries = [const { LowerSparseSubtrie::Blind(None) }; NUM_LOWER_SUBTRIES];
798 self.prefix_set = PrefixSetMut::all();
799 self.updates = self.updates.is_some().then(SparseTrieUpdates::wiped);
800 }
801
802 fn clear(&mut self) {
803 self.upper_subtrie.clear();
804 self.upper_subtrie.nodes.insert(Nibbles::default(), SparseNode::Empty);
805 for subtrie in &mut self.lower_subtries {
806 subtrie.clear();
807 }
808 self.prefix_set.clear();
809 self.updates = None;
810 self.branch_node_tree_masks.clear();
811 self.branch_node_hash_masks.clear();
812 }
815
816 fn find_leaf(
817 &self,
818 full_path: &Nibbles,
819 expected_value: Option<&Vec<u8>>,
820 ) -> Result<LeafLookup, LeafLookupError> {
821 if let Some(actual_value) = std::iter::once(self.upper_subtrie.as_ref())
827 .chain(self.lower_subtrie_for_path(full_path))
828 .filter_map(|subtrie| subtrie.inner.values.get(full_path))
829 .next()
830 {
831 return expected_value
833 .is_none_or(|v| v == actual_value)
834 .then_some(LeafLookup::Exists)
835 .ok_or_else(|| LeafLookupError::ValueMismatch {
836 path: *full_path,
837 expected: expected_value.cloned(),
838 actual: actual_value.clone(),
839 })
840 }
841
842 let mut curr_path = Nibbles::new(); let mut curr_subtrie = self.upper_subtrie.as_ref();
850 let mut curr_subtrie_is_upper = true;
851
852 loop {
853 let curr_node = curr_subtrie.nodes.get(&curr_path).unwrap();
854
855 match Self::find_next_to_leaf(&curr_path, curr_node, full_path) {
856 FindNextToLeafOutcome::NotFound => return Ok(LeafLookup::NonExistent),
857 FindNextToLeafOutcome::BlindedNode(hash) => {
858 return Err(LeafLookupError::BlindedNode { path: curr_path, hash });
860 }
861 FindNextToLeafOutcome::Found => {
862 panic!("target leaf {full_path:?} found at path {curr_path:?}, even though value wasn't in values hashmap");
863 }
864 FindNextToLeafOutcome::ContinueFrom(next_path) => {
865 curr_path = next_path;
866 if curr_subtrie_is_upper &&
869 let Some(lower_subtrie) = self.lower_subtrie_for_path(&curr_path)
870 {
871 curr_subtrie = lower_subtrie;
872 curr_subtrie_is_upper = false;
873 }
874 }
875 }
876 }
877 }
878
879 fn shrink_nodes_to(&mut self, size: usize) {
880 let total_subtries = 1 + NUM_LOWER_SUBTRIES;
884 let size_per_subtrie = size / total_subtries;
885
886 self.upper_subtrie.shrink_nodes_to(size_per_subtrie);
888
889 for subtrie in &mut self.lower_subtries {
891 subtrie.shrink_nodes_to(size_per_subtrie);
892 }
893
894 self.branch_node_hash_masks.shrink_to(size);
896 self.branch_node_tree_masks.shrink_to(size);
897 }
898
899 fn shrink_values_to(&mut self, size: usize) {
900 let total_subtries = 1 + NUM_LOWER_SUBTRIES;
904 let size_per_subtrie = size / total_subtries;
905
906 self.upper_subtrie.shrink_values_to(size_per_subtrie);
908
909 for subtrie in &mut self.lower_subtries {
911 subtrie.shrink_values_to(size_per_subtrie);
912 }
913 }
914}
915
916impl ParallelSparseTrie {
917 pub const fn with_parallelism_thresholds(mut self, thresholds: ParallelismThresholds) -> Self {
919 self.parallelism_thresholds = thresholds;
920 self
921 }
922
923 const fn updates_enabled(&self) -> bool {
925 self.updates.is_some()
926 }
927
928 const fn is_reveal_parallelism_enabled(&self, num_nodes: usize) -> bool {
931 #[cfg(not(feature = "std"))]
932 return false;
933
934 num_nodes >= self.parallelism_thresholds.min_revealed_nodes
935 }
936
937 const fn is_update_parallelism_enabled(&self, num_changed_keys: usize) -> bool {
940 #[cfg(not(feature = "std"))]
941 return false;
942
943 num_changed_keys >= self.parallelism_thresholds.min_updated_nodes
944 }
945
946 pub fn from_root(
961 root: TrieNode,
962 masks: TrieMasks,
963 retain_updates: bool,
964 ) -> SparseTrieResult<Self> {
965 Self::default().with_root(root, masks, retain_updates)
966 }
967
968 fn lower_subtrie_for_path(&self, path: &Nibbles) -> Option<&SparseSubtrie> {
972 match SparseSubtrieType::from_path(path) {
973 SparseSubtrieType::Upper => None,
974 SparseSubtrieType::Lower(idx) => self.lower_subtries[idx].as_revealed_ref(),
975 }
976 }
977
978 fn lower_subtrie_for_path_mut(&mut self, path: &Nibbles) -> Option<&mut SparseSubtrie> {
985 match SparseSubtrieType::from_path(path) {
986 SparseSubtrieType::Upper => None,
987 SparseSubtrieType::Lower(idx) => {
988 self.lower_subtries[idx].reveal(path);
989 Some(self.lower_subtries[idx].as_revealed_mut().expect("just revealed"))
990 }
991 }
992 }
993
994 fn subtrie_for_path(&self, path: &Nibbles) -> Option<&SparseSubtrie> {
999 if SparseSubtrieType::path_len_is_upper(path.len()) {
1002 Some(&self.upper_subtrie)
1003 } else {
1004 self.lower_subtrie_for_path(path)
1005 }
1006 }
1007
1008 fn subtrie_for_path_mut(&mut self, path: &Nibbles) -> &mut SparseSubtrie {
1015 if SparseSubtrieType::path_len_is_upper(path.len()) {
1018 &mut self.upper_subtrie
1019 } else {
1020 self.lower_subtrie_for_path_mut(path).unwrap()
1021 }
1022 }
1023
1024 fn find_next_to_leaf(
1032 from_path: &Nibbles,
1033 from_node: &SparseNode,
1034 leaf_full_path: &Nibbles,
1035 ) -> FindNextToLeafOutcome {
1036 debug_assert!(leaf_full_path.len() >= from_path.len());
1037 debug_assert!(leaf_full_path.starts_with(from_path));
1038
1039 match from_node {
1040 SparseNode::Empty => FindNextToLeafOutcome::NotFound,
1043 SparseNode::Hash(hash) => FindNextToLeafOutcome::BlindedNode(*hash),
1044 SparseNode::Leaf { key, .. } => {
1045 let mut found_full_path = *from_path;
1046 found_full_path.extend(key);
1047
1048 if &found_full_path == leaf_full_path {
1049 return FindNextToLeafOutcome::Found
1050 }
1051 FindNextToLeafOutcome::NotFound
1052 }
1053 SparseNode::Extension { key, .. } => {
1054 if leaf_full_path.len() == from_path.len() {
1055 return FindNextToLeafOutcome::NotFound
1056 }
1057
1058 let mut child_path = *from_path;
1059 child_path.extend(key);
1060
1061 if !leaf_full_path.starts_with(&child_path) {
1062 return FindNextToLeafOutcome::NotFound
1063 }
1064 FindNextToLeafOutcome::ContinueFrom(child_path)
1065 }
1066 SparseNode::Branch { state_mask, .. } => {
1067 if leaf_full_path.len() == from_path.len() {
1068 return FindNextToLeafOutcome::NotFound
1069 }
1070
1071 let nibble = leaf_full_path.get_unchecked(from_path.len());
1072 if !state_mask.is_bit_set(nibble) {
1073 return FindNextToLeafOutcome::NotFound
1074 }
1075
1076 let mut child_path = *from_path;
1077 child_path.push_unchecked(nibble);
1078
1079 FindNextToLeafOutcome::ContinueFrom(child_path)
1080 }
1081 }
1082 }
1083
1084 fn move_value_on_leaf_removal(
1089 &mut self,
1090 parent_path: &Nibbles,
1091 new_parent_node: &SparseNode,
1092 prev_child_path: &Nibbles,
1093 ) {
1094 if SparseSubtrieType::from_path(parent_path).lower_index().is_some() {
1097 return;
1098 }
1099
1100 if let SparseNode::Leaf { key, .. } = new_parent_node {
1101 let Some(prev_child_subtrie) = self.lower_subtrie_for_path_mut(prev_child_path) else {
1102 return;
1103 };
1104
1105 let mut leaf_full_path = *parent_path;
1106 leaf_full_path.extend(key);
1107
1108 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");
1109 self.upper_subtrie.inner.values.insert(leaf_full_path, val);
1110 }
1111 }
1112
1113 fn remove_node(&mut self, path: &Nibbles) {
1125 let subtrie = self.subtrie_for_path_mut(path);
1126 let node = subtrie.nodes.remove(path);
1127
1128 let Some(idx) = SparseSubtrieType::from_path(path).lower_index() else {
1129 return;
1132 };
1133
1134 match node {
1135 Some(SparseNode::Leaf { .. }) => {
1136 if subtrie.nodes.is_empty() {
1139 self.lower_subtries[idx].clear();
1140 }
1141 }
1142 Some(SparseNode::Extension { key, .. }) => {
1143 if &subtrie.path == path {
1147 subtrie.path.extend(&key);
1148 }
1149 }
1150 _ => panic!("Expected to remove a leaf or extension, but removed {node:?}"),
1151 }
1152 }
1153
1154 fn branch_changes_on_leaf_removal(
1163 parent_path: &Nibbles,
1164 remaining_child_path: &Nibbles,
1165 remaining_child_node: &SparseNode,
1166 ) -> (SparseNode, bool) {
1167 debug_assert!(remaining_child_path.len() > parent_path.len());
1168 debug_assert!(remaining_child_path.starts_with(parent_path));
1169
1170 let remaining_child_nibble = remaining_child_path.get_unchecked(parent_path.len());
1171
1172 match remaining_child_node {
1175 SparseNode::Empty | SparseNode::Hash(_) => {
1176 panic!("remaining child must have been revealed already")
1177 }
1178 SparseNode::Leaf { key, .. } => {
1182 let mut new_key = Nibbles::from_nibbles_unchecked([remaining_child_nibble]);
1183 new_key.extend(key);
1184 (SparseNode::new_leaf(new_key), true)
1185 }
1186 SparseNode::Extension { key, .. } => {
1190 let mut new_key = Nibbles::from_nibbles_unchecked([remaining_child_nibble]);
1191 new_key.extend(key);
1192 (SparseNode::new_ext(new_key), true)
1193 }
1194 SparseNode::Branch { .. } => (
1197 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([remaining_child_nibble])),
1198 false,
1199 ),
1200 }
1201 }
1202
1203 fn extension_changes_on_leaf_removal(
1212 parent_path: &Nibbles,
1213 parent_key: &Nibbles,
1214 child_path: &Nibbles,
1215 child: &SparseNode,
1216 ) -> Option<SparseNode> {
1217 debug_assert!(child_path.len() > parent_path.len());
1218 debug_assert!(child_path.starts_with(parent_path));
1219
1220 match child {
1223 SparseNode::Empty | SparseNode::Hash(_) => {
1224 panic!("child must be revealed")
1225 }
1226 SparseNode::Leaf { key, .. } => {
1232 let mut new_key = *parent_key;
1233 new_key.extend(key);
1234 Some(SparseNode::new_leaf(new_key))
1235 }
1236 SparseNode::Extension { key, .. } => {
1239 let mut new_key = *parent_key;
1240 new_key.extend(key);
1241 Some(SparseNode::new_ext(new_key))
1242 }
1243 SparseNode::Branch { .. } => None,
1245 }
1246 }
1247
1248 fn reveal_remaining_child_on_leaf_removal<P: TrieNodeProvider>(
1258 &mut self,
1259 provider: P,
1260 full_path: &Nibbles, remaining_child_path: &Nibbles,
1262 recurse_into_extension: bool,
1263 ) -> SparseTrieResult<SparseNode> {
1264 let remaining_child_subtrie = self.subtrie_for_path_mut(remaining_child_path);
1265
1266 let remaining_child_node =
1267 match remaining_child_subtrie.nodes.get(remaining_child_path).unwrap() {
1268 SparseNode::Hash(_) => {
1269 debug!(
1270 target: "trie::parallel_sparse",
1271 child_path = ?remaining_child_path,
1272 leaf_full_path = ?full_path,
1273 "Node child not revealed in remove_leaf, falling back to db",
1274 );
1275 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1276 provider.trie_node(remaining_child_path)?
1277 {
1278 let decoded = TrieNode::decode(&mut &node[..])?;
1279 trace!(
1280 target: "trie::parallel_sparse",
1281 ?remaining_child_path,
1282 ?decoded,
1283 ?tree_mask,
1284 ?hash_mask,
1285 "Revealing remaining blinded branch child"
1286 );
1287 remaining_child_subtrie.reveal_node(
1288 *remaining_child_path,
1289 &decoded,
1290 TrieMasks { hash_mask, tree_mask },
1291 )?;
1292 remaining_child_subtrie.nodes.get(remaining_child_path).unwrap().clone()
1293 } else {
1294 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1295 path: *remaining_child_path,
1296 }
1297 .into())
1298 }
1299 }
1300 node => node.clone(),
1301 };
1302
1303 if let SparseNode::Extension { key, .. } = &remaining_child_node &&
1308 recurse_into_extension
1309 {
1310 let mut remaining_grandchild_path = *remaining_child_path;
1311 remaining_grandchild_path.extend(key);
1312
1313 trace!(
1314 target: "trie::parallel_sparse",
1315 remaining_grandchild_path = ?remaining_grandchild_path,
1316 child_path = ?remaining_child_path,
1317 leaf_full_path = ?full_path,
1318 "Revealing child of extension node, which is the last remaining child of the branch"
1319 );
1320
1321 self.reveal_remaining_child_on_leaf_removal(
1322 provider,
1323 full_path,
1324 &remaining_grandchild_path,
1325 false, )?;
1327 }
1328
1329 Ok(remaining_child_node)
1330 }
1331
1332 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all)]
1335 fn apply_subtrie_update_actions(
1336 &mut self,
1337 update_actions: impl Iterator<Item = SparseTrieUpdatesAction>,
1338 ) {
1339 if let Some(updates) = self.updates.as_mut() {
1340 for action in update_actions {
1341 match action {
1342 SparseTrieUpdatesAction::InsertRemoved(path) => {
1343 updates.updated_nodes.remove(&path);
1344 updates.removed_nodes.insert(path);
1345 }
1346 SparseTrieUpdatesAction::RemoveUpdated(path) => {
1347 updates.updated_nodes.remove(&path);
1348 }
1349 SparseTrieUpdatesAction::InsertUpdated(path, branch_node) => {
1350 updates.updated_nodes.insert(path, branch_node);
1351 }
1352 }
1353 }
1354 };
1355 }
1356
1357 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, ret)]
1359 fn update_upper_subtrie_hashes(&mut self, prefix_set: &mut PrefixSet) -> RlpNode {
1360 trace!(target: "trie::parallel_sparse", "Updating upper subtrie hashes");
1361
1362 debug_assert!(self.upper_subtrie.inner.buffers.path_stack.is_empty());
1363 self.upper_subtrie.inner.buffers.path_stack.push(RlpNodePathStackItem {
1364 path: Nibbles::default(), is_in_prefix_set: None,
1366 });
1367
1368 #[cfg(feature = "metrics")]
1369 let start = std::time::Instant::now();
1370
1371 let mut update_actions_buf =
1372 self.updates_enabled().then(|| self.update_actions_buffers.pop().unwrap_or_default());
1373
1374 while let Some(stack_item) = self.upper_subtrie.inner.buffers.path_stack.pop() {
1375 let path = stack_item.path;
1376 let node = if path.len() < UPPER_TRIE_MAX_DEPTH {
1377 self.upper_subtrie.nodes.get_mut(&path).expect("upper subtrie node must exist")
1378 } else {
1379 let index = path_subtrie_index_unchecked(&path);
1380 let node = self.lower_subtries[index]
1381 .as_revealed_mut()
1382 .expect("lower subtrie must exist")
1383 .nodes
1384 .get_mut(&path)
1385 .expect("lower subtrie node must exist");
1386 debug_assert!(
1389 node.hash().is_some(),
1390 "Lower subtrie root node at path {path:?} has no hash"
1391 );
1392 node
1393 };
1394
1395 self.upper_subtrie.inner.rlp_node(
1397 prefix_set,
1398 &mut update_actions_buf,
1399 stack_item,
1400 node,
1401 &self.branch_node_tree_masks,
1402 &self.branch_node_hash_masks,
1403 );
1404 }
1405
1406 if let Some(mut update_actions_buf) = update_actions_buf {
1409 self.apply_subtrie_update_actions(
1410 #[allow(clippy::iter_with_drain)]
1411 update_actions_buf.drain(..),
1412 );
1413 self.update_actions_buffers.push(update_actions_buf);
1414 }
1415
1416 #[cfg(feature = "metrics")]
1417 self.metrics.subtrie_upper_hash_latency.record(start.elapsed());
1418
1419 debug_assert_eq!(self.upper_subtrie.inner.buffers.rlp_node_stack.len(), 1);
1420 self.upper_subtrie.inner.buffers.rlp_node_stack.pop().unwrap().rlp_node
1421 }
1422
1423 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, fields(prefix_set_len = prefix_set.len()))]
1437 fn take_changed_lower_subtries(
1438 &mut self,
1439 prefix_set: &mut PrefixSet,
1440 ) -> (Vec<ChangedSubtrie>, PrefixSetMut) {
1441 if prefix_set.is_empty() && !prefix_set.all() {
1444 return Default::default();
1445 }
1446
1447 let prefix_set_clone = prefix_set.clone();
1449 let mut prefix_set_iter = prefix_set_clone.into_iter().copied().peekable();
1450 let mut changed_subtries = Vec::new();
1451 let mut unchanged_prefix_set = PrefixSetMut::default();
1452 let updates_enabled = self.updates_enabled();
1453
1454 for (index, subtrie) in self.lower_subtries.iter_mut().enumerate() {
1455 if let Some(subtrie) = subtrie.take_revealed_if(|subtrie| {
1456 prefix_set.contains(&subtrie.path) ||
1457 subtrie.nodes.get(&subtrie.path).is_some_and(|n| n.hash().is_none())
1458 }) {
1459 let prefix_set = if prefix_set.all() {
1460 unchanged_prefix_set = PrefixSetMut::all();
1461 PrefixSetMut::all()
1462 } else {
1463 let mut new_prefix_set = Vec::new();
1468 while let Some(key) = prefix_set_iter.peek() {
1469 if key.starts_with(&subtrie.path) {
1470 new_prefix_set.push(prefix_set_iter.next().unwrap());
1472 } else if new_prefix_set.is_empty() && key < &subtrie.path {
1473 unchanged_prefix_set.insert(prefix_set_iter.next().unwrap());
1477 } else {
1478 break
1482 }
1483 }
1484 PrefixSetMut::from(new_prefix_set)
1485 }
1486 .freeze();
1487
1488 match subtrie.nodes.get(&subtrie.path) {
1491 Some(SparseNode::Extension { key, .. } | SparseNode::Leaf { key, .. }) => {
1492 unchanged_prefix_set.insert(subtrie.path.join(key));
1493 }
1494 Some(SparseNode::Branch { .. }) => {
1495 unchanged_prefix_set.insert(subtrie.path);
1496 }
1497 _ => {}
1498 }
1499
1500 let update_actions_buf =
1501 updates_enabled.then(|| self.update_actions_buffers.pop().unwrap_or_default());
1502
1503 changed_subtries.push(ChangedSubtrie {
1504 index,
1505 subtrie,
1506 prefix_set,
1507 update_actions_buf,
1508 });
1509 }
1510 }
1511
1512 unchanged_prefix_set.extend_keys(prefix_set_iter);
1514
1515 (changed_subtries, unchanged_prefix_set)
1516 }
1517
1518 #[cfg(test)]
1520 fn all_nodes(&self) -> impl IntoIterator<Item = (&Nibbles, &SparseNode)> {
1521 let mut nodes = vec![];
1522 for subtrie in self.lower_subtries.iter().filter_map(LowerSparseSubtrie::as_revealed_ref) {
1523 nodes.extend(subtrie.nodes.iter())
1524 }
1525 nodes.extend(self.upper_subtrie.nodes.iter());
1526 nodes
1527 }
1528
1529 fn reveal_upper_node(
1546 &mut self,
1547 path: Nibbles,
1548 node: &TrieNode,
1549 masks: TrieMasks,
1550 ) -> SparseTrieResult<()> {
1551 self.upper_subtrie.reveal_node(path, node, masks)?;
1554
1555 match node {
1560 TrieNode::Branch(branch) => {
1561 if !SparseSubtrieType::path_len_is_upper(path.len() + 1) {
1565 let mut stack_ptr = branch.as_ref().first_child_index();
1566 for idx in CHILD_INDEX_RANGE {
1567 if branch.state_mask.is_bit_set(idx) {
1568 let mut child_path = path;
1569 child_path.push_unchecked(idx);
1570 self.lower_subtrie_for_path_mut(&child_path)
1571 .expect("child_path must have a lower subtrie")
1572 .reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
1573 stack_ptr += 1;
1574 }
1575 }
1576 }
1577 }
1578 TrieNode::Extension(ext) => {
1579 let mut child_path = path;
1580 child_path.extend(&ext.key);
1581 if let Some(subtrie) = self.lower_subtrie_for_path_mut(&child_path) {
1582 subtrie.reveal_node_or_hash(child_path, &ext.child)?;
1583 }
1584 }
1585 TrieNode::EmptyRoot | TrieNode::Leaf(_) => (),
1586 }
1587
1588 Ok(())
1589 }
1590
1591 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all)]
1594 fn insert_changed_subtries(
1595 &mut self,
1596 changed_subtries: impl IntoIterator<Item = ChangedSubtrie>,
1597 ) {
1598 for ChangedSubtrie { index, subtrie, update_actions_buf, .. } in changed_subtries {
1599 if let Some(mut update_actions_buf) = update_actions_buf {
1600 self.apply_subtrie_update_actions(
1601 #[allow(clippy::iter_with_drain)]
1602 update_actions_buf.drain(..),
1603 );
1604 self.update_actions_buffers.push(update_actions_buf);
1605 }
1606
1607 self.lower_subtries[index] = LowerSparseSubtrie::Revealed(subtrie);
1608 }
1609 }
1610}
1611
1612#[derive(Clone, PartialEq, Eq, Debug, Default)]
1615pub struct SparseSubtrie {
1616 pub(crate) path: Nibbles,
1624 nodes: HashMap<Nibbles, SparseNode>,
1626 inner: SparseSubtrieInner,
1628}
1629
1630enum FindNextToLeafOutcome {
1633 Found,
1635 ContinueFrom(Nibbles),
1637 NotFound,
1640 BlindedNode(B256),
1643}
1644
1645impl SparseSubtrie {
1646 pub(crate) fn new(path: Nibbles) -> Self {
1648 Self { path, ..Default::default() }
1649 }
1650
1651 pub(crate) fn is_empty(&self) -> bool {
1653 self.nodes.is_empty()
1654 }
1655
1656 fn is_child_same_level(current_path: &Nibbles, child_path: &Nibbles) -> bool {
1658 let current_level = core::mem::discriminant(&SparseSubtrieType::from_path(current_path));
1659 let child_level = core::mem::discriminant(&SparseSubtrieType::from_path(child_path));
1660 current_level == child_level
1661 }
1662
1663 pub fn update_leaf(
1676 &mut self,
1677 full_path: Nibbles,
1678 value: Vec<u8>,
1679 provider: impl TrieNodeProvider,
1680 retain_updates: bool,
1681 ) -> SparseTrieResult<()> {
1682 debug_assert!(full_path.starts_with(&self.path));
1683 let existing = self.inner.values.insert(full_path, value);
1684 if existing.is_some() {
1685 return Ok(())
1687 }
1688
1689 let mut current = Some(self.path);
1691 while let Some(current_path) = current {
1692 match self.update_next_node(current_path, &full_path, retain_updates)? {
1693 LeafUpdateStep::Continue { next_node } => {
1694 current = Some(next_node);
1695 }
1696 LeafUpdateStep::Complete { reveal_path, .. } => {
1697 if let Some(reveal_path) = reveal_path &&
1698 self.nodes.get(&reveal_path).expect("node must exist").is_hash()
1699 {
1700 debug!(
1701 target: "trie::parallel_sparse",
1702 child_path = ?reveal_path,
1703 leaf_full_path = ?full_path,
1704 "Extension node child not revealed in update_leaf, falling back to db",
1705 );
1706 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1707 provider.trie_node(&reveal_path)?
1708 {
1709 let decoded = TrieNode::decode(&mut &node[..])?;
1710 trace!(
1711 target: "trie::parallel_sparse",
1712 ?reveal_path,
1713 ?decoded,
1714 ?tree_mask,
1715 ?hash_mask,
1716 "Revealing child (from lower)",
1717 );
1718 self.reveal_node(
1719 reveal_path,
1720 &decoded,
1721 TrieMasks { hash_mask, tree_mask },
1722 )?;
1723 } else {
1724 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1725 path: reveal_path,
1726 }
1727 .into())
1728 }
1729 }
1730
1731 current = None;
1732 }
1733 LeafUpdateStep::NodeNotFound => {
1734 current = None;
1735 }
1736 }
1737 }
1738
1739 Ok(())
1740 }
1741
1742 fn update_next_node(
1749 &mut self,
1750 mut current: Nibbles,
1751 path: &Nibbles,
1752 retain_updates: bool,
1753 ) -> SparseTrieResult<LeafUpdateStep> {
1754 debug_assert!(path.starts_with(&self.path));
1755 debug_assert!(current.starts_with(&self.path));
1756 debug_assert!(path.starts_with(¤t));
1757 let Some(node) = self.nodes.get_mut(¤t) else {
1758 return Ok(LeafUpdateStep::NodeNotFound);
1759 };
1760 match node {
1761 SparseNode::Empty => {
1762 let path = path.slice(self.path.len()..);
1765 *node = SparseNode::new_leaf(path);
1766 Ok(LeafUpdateStep::complete_with_insertions(vec![current], None))
1767 }
1768 SparseNode::Hash(hash) => {
1769 Err(SparseTrieErrorKind::BlindedNode { path: current, hash: *hash }.into())
1770 }
1771 SparseNode::Leaf { key: current_key, .. } => {
1772 current.extend(current_key);
1773
1774 debug_assert!(
1776 ¤t != path,
1777 "we already checked leaf presence in the beginning"
1778 );
1779
1780 let common = current.common_prefix_length(path);
1782
1783 let new_ext_key = current.slice(current.len() - current_key.len()..common);
1785 *node = SparseNode::new_ext(new_ext_key);
1786
1787 self.nodes.reserve(3);
1789 let branch_path = current.slice(..common);
1790 let new_leaf_path = path.slice(..=common);
1791 let existing_leaf_path = current.slice(..=common);
1792
1793 self.nodes.insert(
1794 branch_path,
1795 SparseNode::new_split_branch(
1796 current.get_unchecked(common),
1797 path.get_unchecked(common),
1798 ),
1799 );
1800 self.nodes.insert(new_leaf_path, SparseNode::new_leaf(path.slice(common + 1..)));
1801 self.nodes
1802 .insert(existing_leaf_path, SparseNode::new_leaf(current.slice(common + 1..)));
1803
1804 Ok(LeafUpdateStep::complete_with_insertions(
1805 vec![branch_path, new_leaf_path, existing_leaf_path],
1806 None,
1807 ))
1808 }
1809 SparseNode::Extension { key, .. } => {
1810 current.extend(key);
1811
1812 if !path.starts_with(¤t) {
1813 let common = current.common_prefix_length(path);
1815 *key = current.slice(current.len() - key.len()..common);
1816
1817 let reveal_path = retain_updates.then_some(current);
1821
1822 self.nodes.reserve(3);
1825 let branch_path = current.slice(..common);
1826 let new_leaf_path = path.slice(..=common);
1827 let branch = SparseNode::new_split_branch(
1828 current.get_unchecked(common),
1829 path.get_unchecked(common),
1830 );
1831
1832 self.nodes.insert(branch_path, branch);
1833
1834 let new_leaf = SparseNode::new_leaf(path.slice(common + 1..));
1836 self.nodes.insert(new_leaf_path, new_leaf);
1837
1838 let mut inserted_nodes = vec![branch_path, new_leaf_path];
1839
1840 let key = current.slice(common + 1..);
1842 if !key.is_empty() {
1843 let ext_path = current.slice(..=common);
1844 self.nodes.insert(ext_path, SparseNode::new_ext(key));
1845 inserted_nodes.push(ext_path);
1846 }
1847
1848 return Ok(LeafUpdateStep::complete_with_insertions(inserted_nodes, reveal_path))
1849 }
1850
1851 Ok(LeafUpdateStep::continue_with(current))
1852 }
1853 SparseNode::Branch { state_mask, .. } => {
1854 let nibble = path.get_unchecked(current.len());
1855 current.push_unchecked(nibble);
1856 if !state_mask.is_bit_set(nibble) {
1857 state_mask.set_bit(nibble);
1858 let new_leaf = SparseNode::new_leaf(path.slice(current.len()..));
1859 self.nodes.insert(current, new_leaf);
1860 return Ok(LeafUpdateStep::complete_with_insertions(vec![current], None))
1861 }
1862
1863 Ok(LeafUpdateStep::continue_with(current))
1865 }
1866 }
1867 }
1868
1869 fn reveal_node(
1871 &mut self,
1872 path: Nibbles,
1873 node: &TrieNode,
1874 masks: TrieMasks,
1875 ) -> SparseTrieResult<()> {
1876 debug_assert!(path.starts_with(&self.path));
1877
1878 if self.nodes.get(&path).is_some_and(|node| !node.is_hash()) {
1880 return Ok(())
1881 }
1882
1883 match node {
1884 TrieNode::EmptyRoot => {
1885 debug_assert!(path.is_empty());
1887 debug_assert!(self.path.is_empty());
1888 self.nodes.insert(path, SparseNode::Empty);
1889 }
1890 TrieNode::Branch(branch) => {
1891 let mut stack_ptr = branch.as_ref().first_child_index();
1893 for idx in CHILD_INDEX_RANGE {
1894 if branch.state_mask.is_bit_set(idx) {
1895 let mut child_path = path;
1896 child_path.push_unchecked(idx);
1897 if Self::is_child_same_level(&path, &child_path) {
1898 self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
1901 }
1902 stack_ptr += 1;
1903 }
1904 }
1905 match self.nodes.entry(path) {
1908 Entry::Occupied(mut entry) => match entry.get() {
1909 SparseNode::Hash(hash) => {
1911 entry.insert(SparseNode::Branch {
1912 state_mask: branch.state_mask,
1913 hash: Some(*hash),
1916 store_in_db_trie: Some(
1917 masks.hash_mask.is_some_and(|mask| !mask.is_empty()) ||
1918 masks.tree_mask.is_some_and(|mask| !mask.is_empty()),
1919 ),
1920 });
1921 }
1922 SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
1925 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
1927 return Err(SparseTrieErrorKind::Reveal {
1928 path: *entry.key(),
1929 node: Box::new(node.clone()),
1930 }
1931 .into())
1932 }
1933 },
1934 Entry::Vacant(entry) => {
1935 entry.insert(SparseNode::new_branch(branch.state_mask));
1936 }
1937 }
1938 }
1939 TrieNode::Extension(ext) => match self.nodes.entry(path) {
1940 Entry::Occupied(mut entry) => match entry.get() {
1941 SparseNode::Hash(hash) => {
1943 let mut child_path = *entry.key();
1944 child_path.extend(&ext.key);
1945 entry.insert(SparseNode::Extension {
1946 key: ext.key,
1947 hash: Some(*hash),
1950 store_in_db_trie: None,
1951 });
1952 if Self::is_child_same_level(&path, &child_path) {
1953 self.reveal_node_or_hash(child_path, &ext.child)?;
1954 }
1955 }
1956 SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
1959 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
1961 return Err(SparseTrieErrorKind::Reveal {
1962 path: *entry.key(),
1963 node: Box::new(node.clone()),
1964 }
1965 .into())
1966 }
1967 },
1968 Entry::Vacant(entry) => {
1969 let mut child_path = *entry.key();
1970 child_path.extend(&ext.key);
1971 entry.insert(SparseNode::new_ext(ext.key));
1972 if Self::is_child_same_level(&path, &child_path) {
1973 self.reveal_node_or_hash(child_path, &ext.child)?;
1974 }
1975 }
1976 },
1977 TrieNode::Leaf(leaf) => match self.nodes.entry(path) {
1978 Entry::Occupied(mut entry) => match entry.get() {
1979 SparseNode::Hash(hash) => {
1981 let mut full = *entry.key();
1982 full.extend(&leaf.key);
1983 self.inner.values.insert(full, leaf.value.clone());
1984 entry.insert(SparseNode::Leaf {
1985 key: leaf.key,
1986 hash: Some(*hash),
1989 });
1990 }
1991 SparseNode::Leaf { .. } => {}
1993 node @ (SparseNode::Empty |
1995 SparseNode::Extension { .. } |
1996 SparseNode::Branch { .. }) => {
1997 return Err(SparseTrieErrorKind::Reveal {
1998 path: *entry.key(),
1999 node: Box::new(node.clone()),
2000 }
2001 .into())
2002 }
2003 },
2004 Entry::Vacant(entry) => {
2005 let mut full = *entry.key();
2006 full.extend(&leaf.key);
2007 entry.insert(SparseNode::new_leaf(leaf.key));
2008 self.inner.values.insert(full, leaf.value.clone());
2009 }
2010 },
2011 }
2012
2013 Ok(())
2014 }
2015
2016 fn reveal_node_or_hash(&mut self, path: Nibbles, child: &[u8]) -> SparseTrieResult<()> {
2035 if child.len() == B256::len_bytes() + 1 {
2036 let hash = B256::from_slice(&child[1..]);
2037 match self.nodes.entry(path) {
2038 Entry::Occupied(entry) => match entry.get() {
2039 SparseNode::Hash(previous_hash) if previous_hash != &hash => {
2041 return Err(SparseTrieErrorKind::Reveal {
2042 path: *entry.key(),
2043 node: Box::new(SparseNode::Hash(hash)),
2044 }
2045 .into())
2046 }
2047 _ => {}
2048 },
2049 Entry::Vacant(entry) => {
2050 entry.insert(SparseNode::Hash(hash));
2051 }
2052 }
2053 return Ok(())
2054 }
2055
2056 self.reveal_node(path, &TrieNode::decode(&mut &child[..])?, TrieMasks::none())
2057 }
2058
2059 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, fields(root = ?self.path), ret)]
2082 fn update_hashes(
2083 &mut self,
2084 prefix_set: &mut PrefixSet,
2085 update_actions: &mut Option<Vec<SparseTrieUpdatesAction>>,
2086 branch_node_tree_masks: &HashMap<Nibbles, TrieMask>,
2087 branch_node_hash_masks: &HashMap<Nibbles, TrieMask>,
2088 ) -> RlpNode {
2089 trace!(target: "trie::parallel_sparse", "Updating subtrie hashes");
2090
2091 debug_assert!(prefix_set.iter().all(|path| path.starts_with(&self.path)));
2092
2093 debug_assert!(self.inner.buffers.path_stack.is_empty());
2094 self.inner
2095 .buffers
2096 .path_stack
2097 .push(RlpNodePathStackItem { path: self.path, is_in_prefix_set: None });
2098
2099 while let Some(stack_item) = self.inner.buffers.path_stack.pop() {
2100 let path = stack_item.path;
2101 let node = self
2102 .nodes
2103 .get_mut(&path)
2104 .unwrap_or_else(|| panic!("node at path {path:?} does not exist"));
2105
2106 self.inner.rlp_node(
2107 prefix_set,
2108 update_actions,
2109 stack_item,
2110 node,
2111 branch_node_tree_masks,
2112 branch_node_hash_masks,
2113 );
2114 }
2115
2116 debug_assert_eq!(self.inner.buffers.rlp_node_stack.len(), 1);
2117 self.inner.buffers.rlp_node_stack.pop().unwrap().rlp_node
2118 }
2119
2120 fn wipe(&mut self) {
2123 self.nodes = HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]);
2124 self.inner.clear();
2125 }
2126
2127 pub(crate) fn clear(&mut self) {
2129 self.nodes.clear();
2130 self.inner.clear();
2131 }
2132
2133 pub(crate) fn shrink_nodes_to(&mut self, size: usize) {
2135 self.nodes.shrink_to(size);
2136 }
2137
2138 pub(crate) fn shrink_values_to(&mut self, size: usize) {
2140 self.inner.values.shrink_to(size);
2141 }
2142}
2143
2144#[derive(Clone, PartialEq, Eq, Debug, Default)]
2147struct SparseSubtrieInner {
2148 values: HashMap<Nibbles, Vec<u8>>,
2151 buffers: SparseSubtrieBuffers,
2153}
2154
2155impl SparseSubtrieInner {
2156 fn rlp_node(
2187 &mut self,
2188 prefix_set: &mut PrefixSet,
2189 update_actions: &mut Option<Vec<SparseTrieUpdatesAction>>,
2190 mut stack_item: RlpNodePathStackItem,
2191 node: &mut SparseNode,
2192 branch_node_tree_masks: &HashMap<Nibbles, TrieMask>,
2193 branch_node_hash_masks: &HashMap<Nibbles, TrieMask>,
2194 ) {
2195 let path = stack_item.path;
2196 trace!(
2197 target: "trie::parallel_sparse",
2198 ?path,
2199 ?node,
2200 "Calculating node RLP"
2201 );
2202
2203 let mut prefix_set_contains = |path: &Nibbles| {
2207 *stack_item.is_in_prefix_set.get_or_insert_with(|| prefix_set.contains(path))
2208 };
2209
2210 let (rlp_node, node_type) = match node {
2211 SparseNode::Empty => (RlpNode::word_rlp(&EMPTY_ROOT_HASH), SparseNodeType::Empty),
2212 SparseNode::Hash(hash) => {
2213 (RlpNode::word_rlp(hash), SparseNodeType::Hash)
2215 }
2216 SparseNode::Leaf { key, hash } => {
2217 let mut path = path;
2218 path.extend(key);
2219 let value = self.values.get(&path);
2220 if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path) || value.is_none())
2221 {
2222 (RlpNode::word_rlp(&hash), SparseNodeType::Leaf)
2226 } else {
2227 let value = self.values.get(&path).unwrap();
2229 self.buffers.rlp_buf.clear();
2230 let rlp_node = LeafNodeRef { key, value }.rlp(&mut self.buffers.rlp_buf);
2231 *hash = rlp_node.as_hash();
2232 (rlp_node, SparseNodeType::Leaf)
2233 }
2234 }
2235 SparseNode::Extension { key, hash, store_in_db_trie } => {
2236 let mut child_path = path;
2237 child_path.extend(key);
2238 if let Some((hash, store_in_db_trie)) =
2239 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
2240 {
2241 (
2244 RlpNode::word_rlp(&hash),
2245 SparseNodeType::Extension { store_in_db_trie: Some(store_in_db_trie) },
2246 )
2247 } else if self.buffers.rlp_node_stack.last().is_some_and(|e| e.path == child_path) {
2248 let RlpNodeStackItem { path: _, rlp_node: child, node_type: child_node_type } =
2251 self.buffers.rlp_node_stack.pop().unwrap();
2252 self.buffers.rlp_buf.clear();
2253 let rlp_node =
2254 ExtensionNodeRef::new(key, &child).rlp(&mut self.buffers.rlp_buf);
2255 *hash = rlp_node.as_hash();
2256
2257 let store_in_db_trie_value = child_node_type.store_in_db_trie();
2258
2259 trace!(
2260 target: "trie::parallel_sparse",
2261 ?path,
2262 ?child_path,
2263 ?child_node_type,
2264 "Extension node"
2265 );
2266
2267 *store_in_db_trie = store_in_db_trie_value;
2268
2269 (
2270 rlp_node,
2271 SparseNodeType::Extension {
2272 store_in_db_trie: store_in_db_trie_value,
2275 },
2276 )
2277 } else {
2278 self.buffers.path_stack.extend([
2281 RlpNodePathStackItem {
2282 path,
2283 is_in_prefix_set: Some(prefix_set_contains(&path)),
2284 },
2285 RlpNodePathStackItem { path: child_path, is_in_prefix_set: None },
2286 ]);
2287 return
2288 }
2289 }
2290 SparseNode::Branch { state_mask, hash, store_in_db_trie } => {
2291 if let Some((hash, store_in_db_trie)) =
2292 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
2293 {
2294 self.buffers.rlp_node_stack.push(RlpNodeStackItem {
2297 path,
2298 rlp_node: RlpNode::word_rlp(&hash),
2299 node_type: SparseNodeType::Branch {
2300 store_in_db_trie: Some(store_in_db_trie),
2301 },
2302 });
2303 return
2304 }
2305
2306 let retain_updates = update_actions.is_some() && prefix_set_contains(&path);
2307
2308 self.buffers.branch_child_buf.clear();
2309 for bit in CHILD_INDEX_RANGE.rev() {
2312 if state_mask.is_bit_set(bit) {
2313 let mut child = path;
2314 child.push_unchecked(bit);
2315 self.buffers.branch_child_buf.push(child);
2316 }
2317 }
2318
2319 self.buffers
2320 .branch_value_stack_buf
2321 .resize(self.buffers.branch_child_buf.len(), Default::default());
2322 let mut added_children = false;
2323
2324 let mut tree_mask = TrieMask::default();
2325 let mut hash_mask = TrieMask::default();
2326 let mut hashes = Vec::new();
2327 for (i, child_path) in self.buffers.branch_child_buf.iter().enumerate() {
2328 if self.buffers.rlp_node_stack.last().is_some_and(|e| &e.path == child_path) {
2329 let RlpNodeStackItem {
2330 path: _,
2331 rlp_node: child,
2332 node_type: child_node_type,
2333 } = self.buffers.rlp_node_stack.pop().unwrap();
2334
2335 if retain_updates {
2337 let last_child_nibble = child_path.last().unwrap();
2339
2340 let should_set_tree_mask_bit = if let Some(store_in_db_trie) =
2342 child_node_type.store_in_db_trie()
2343 {
2344 store_in_db_trie
2347 } else {
2348 child_node_type.is_hash() &&
2350 branch_node_tree_masks
2351 .get(&path)
2352 .is_some_and(|mask| mask.is_bit_set(last_child_nibble))
2353 };
2354 if should_set_tree_mask_bit {
2355 tree_mask.set_bit(last_child_nibble);
2356 }
2357
2358 let hash = child.as_hash().filter(|_| {
2362 child_node_type.is_branch() ||
2363 (child_node_type.is_hash() &&
2364 branch_node_hash_masks.get(&path).is_some_and(
2365 |mask| mask.is_bit_set(last_child_nibble),
2366 ))
2367 });
2368 if let Some(hash) = hash {
2369 hash_mask.set_bit(last_child_nibble);
2370 hashes.push(hash);
2371 }
2372 }
2373
2374 let original_idx = self.buffers.branch_child_buf.len() - i - 1;
2378 self.buffers.branch_value_stack_buf[original_idx] = child;
2379 added_children = true;
2380 } else {
2381 debug_assert!(!added_children);
2384 self.buffers.path_stack.push(RlpNodePathStackItem {
2385 path,
2386 is_in_prefix_set: Some(prefix_set_contains(&path)),
2387 });
2388 self.buffers.path_stack.extend(
2389 self.buffers
2390 .branch_child_buf
2391 .drain(..)
2392 .map(|path| RlpNodePathStackItem { path, is_in_prefix_set: None }),
2393 );
2394 return
2395 }
2396 }
2397
2398 trace!(
2399 target: "trie::parallel_sparse",
2400 ?path,
2401 ?tree_mask,
2402 ?hash_mask,
2403 "Branch node masks"
2404 );
2405
2406 self.buffers.rlp_buf.clear();
2409 let branch_node_ref =
2410 BranchNodeRef::new(&self.buffers.branch_value_stack_buf, *state_mask);
2411 let rlp_node = branch_node_ref.rlp(&mut self.buffers.rlp_buf);
2412 *hash = rlp_node.as_hash();
2413
2414 let store_in_db_trie_value = if let Some(update_actions) =
2417 update_actions.as_mut().filter(|_| retain_updates && !path.is_empty())
2418 {
2419 let store_in_db_trie = !tree_mask.is_empty() || !hash_mask.is_empty();
2420 if store_in_db_trie {
2421 hashes.reverse();
2424 let branch_node = BranchNodeCompact::new(
2425 *state_mask,
2426 tree_mask,
2427 hash_mask,
2428 hashes,
2429 hash.filter(|_| path.is_empty()),
2430 );
2431 update_actions
2432 .push(SparseTrieUpdatesAction::InsertUpdated(path, branch_node));
2433 } else if branch_node_tree_masks.get(&path).is_some_and(|mask| !mask.is_empty()) ||
2434 branch_node_hash_masks.get(&path).is_some_and(|mask| !mask.is_empty())
2435 {
2436 update_actions.push(SparseTrieUpdatesAction::InsertRemoved(path));
2440 } else if branch_node_tree_masks.get(&path).is_none_or(|mask| mask.is_empty()) &&
2441 branch_node_hash_masks.get(&path).is_none_or(|mask| mask.is_empty())
2442 {
2443 update_actions.push(SparseTrieUpdatesAction::RemoveUpdated(path));
2446 }
2447
2448 store_in_db_trie
2449 } else {
2450 false
2451 };
2452 *store_in_db_trie = Some(store_in_db_trie_value);
2453
2454 (
2455 rlp_node,
2456 SparseNodeType::Branch { store_in_db_trie: Some(store_in_db_trie_value) },
2457 )
2458 }
2459 };
2460
2461 self.buffers.rlp_node_stack.push(RlpNodeStackItem { path, rlp_node, node_type });
2462 trace!(
2463 target: "trie::parallel_sparse",
2464 ?path,
2465 ?node_type,
2466 "Added node to RLP node stack"
2467 );
2468 }
2469
2470 fn clear(&mut self) {
2472 self.values.clear();
2473 self.buffers.clear();
2474 }
2475}
2476
2477#[derive(Clone, Debug, PartialEq, Eq, Default)]
2479pub enum LeafUpdateStep {
2480 Continue {
2482 next_node: Nibbles,
2484 },
2485 Complete {
2487 inserted_nodes: Vec<Nibbles>,
2489 reveal_path: Option<Nibbles>,
2491 },
2492 #[default]
2494 NodeNotFound,
2495}
2496
2497impl LeafUpdateStep {
2498 pub const fn continue_with(next_node: Nibbles) -> Self {
2500 Self::Continue { next_node }
2501 }
2502
2503 pub const fn complete_with_insertions(
2505 inserted_nodes: Vec<Nibbles>,
2506 reveal_path: Option<Nibbles>,
2507 ) -> Self {
2508 Self::Complete { inserted_nodes, reveal_path }
2509 }
2510}
2511
2512#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2521pub enum SparseSubtrieType {
2522 Upper,
2524 Lower(usize),
2527}
2528
2529impl SparseSubtrieType {
2530 pub const fn path_len_is_upper(len: usize) -> bool {
2535 len < UPPER_TRIE_MAX_DEPTH
2536 }
2537
2538 pub fn from_path(path: &Nibbles) -> Self {
2540 if Self::path_len_is_upper(path.len()) {
2541 Self::Upper
2542 } else {
2543 Self::Lower(path_subtrie_index_unchecked(path))
2544 }
2545 }
2546
2547 pub const fn lower_index(&self) -> Option<usize> {
2549 match self {
2550 Self::Upper => None,
2551 Self::Lower(index) => Some(*index),
2552 }
2553 }
2554}
2555
2556impl Ord for SparseSubtrieType {
2557 fn cmp(&self, other: &Self) -> Ordering {
2560 match (self, other) {
2561 (Self::Upper, Self::Upper) => Ordering::Equal,
2562 (Self::Upper, Self::Lower(_)) => Ordering::Less,
2563 (Self::Lower(_), Self::Upper) => Ordering::Greater,
2564 (Self::Lower(idx_a), Self::Lower(idx_b)) if idx_a == idx_b => Ordering::Equal,
2565 (Self::Lower(idx_a), Self::Lower(idx_b)) => idx_a.cmp(idx_b),
2566 }
2567 }
2568}
2569
2570impl PartialOrd for SparseSubtrieType {
2571 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2572 Some(self.cmp(other))
2573 }
2574}
2575
2576#[derive(Clone, PartialEq, Eq, Debug, Default)]
2580pub struct SparseSubtrieBuffers {
2581 path_stack: Vec<RlpNodePathStackItem>,
2583 rlp_node_stack: Vec<RlpNodeStackItem>,
2585 branch_child_buf: SmallVec<[Nibbles; 16]>,
2587 branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
2589 rlp_buf: Vec<u8>,
2591}
2592
2593impl SparseSubtrieBuffers {
2594 fn clear(&mut self) {
2596 self.path_stack.clear();
2597 self.path_stack.shrink_to_fit();
2598
2599 self.rlp_node_stack.clear();
2600 self.rlp_node_stack.shrink_to_fit();
2601
2602 self.branch_child_buf.clear();
2603 self.branch_child_buf.shrink_to_fit();
2604
2605 self.branch_value_stack_buf.clear();
2606 self.branch_value_stack_buf.shrink_to_fit();
2607
2608 self.rlp_buf.clear();
2609 self.rlp_buf.shrink_to_fit();
2610 }
2611}
2612
2613#[derive(Clone, PartialEq, Eq, Debug)]
2615pub struct RlpNodePathStackItem {
2616 pub path: Nibbles,
2618 pub is_in_prefix_set: Option<bool>,
2620}
2621
2622#[derive(Debug)]
2624struct ChangedSubtrie {
2625 index: usize,
2627 subtrie: Box<SparseSubtrie>,
2629 prefix_set: PrefixSet,
2631 update_actions_buf: Option<Vec<SparseTrieUpdatesAction>>,
2634}
2635
2636fn path_subtrie_index_unchecked(path: &Nibbles) -> usize {
2643 debug_assert_eq!(UPPER_TRIE_MAX_DEPTH, 2);
2644 path.get_byte_unchecked(0) as usize
2645}
2646
2647#[derive(Clone, Debug, Eq, PartialEq)]
2649enum SparseTrieUpdatesAction {
2650 InsertRemoved(Nibbles),
2652 RemoveUpdated(Nibbles),
2655 InsertUpdated(Nibbles, BranchNodeCompact),
2657}
2658
2659#[cfg(test)]
2660mod tests {
2661 use super::{
2662 path_subtrie_index_unchecked, LowerSparseSubtrie, ParallelSparseTrie, SparseSubtrie,
2663 SparseSubtrieType,
2664 };
2665 use crate::trie::ChangedSubtrie;
2666 use alloy_primitives::{
2667 b256, hex,
2668 map::{B256Set, DefaultHashBuilder, HashMap},
2669 B256, U256,
2670 };
2671 use alloy_rlp::{Decodable, Encodable};
2672 use alloy_trie::{BranchNodeCompact, Nibbles};
2673 use assert_matches::assert_matches;
2674 use itertools::Itertools;
2675 use proptest::{prelude::*, sample::SizeRange};
2676 use proptest_arbitrary_interop::arb;
2677 use reth_execution_errors::{SparseTrieError, SparseTrieErrorKind};
2678 use reth_primitives_traits::Account;
2679 use reth_provider::{test_utils::create_test_provider_factory, TrieWriter};
2680 use reth_trie::{
2681 hashed_cursor::{noop::NoopHashedAccountCursor, HashedPostStateAccountCursor},
2682 node_iter::{TrieElement, TrieNodeIter},
2683 trie_cursor::{noop::NoopAccountTrieCursor, TrieCursor, TrieCursorFactory},
2684 walker::TrieWalker,
2685 HashedPostState,
2686 };
2687 use reth_trie_common::{
2688 prefix_set::PrefixSetMut,
2689 proof::{ProofNodes, ProofRetainer},
2690 updates::TrieUpdates,
2691 BranchNode, ExtensionNode, HashBuilder, LeafNode, RlpNode, TrieMask, TrieNode,
2692 EMPTY_ROOT_HASH,
2693 };
2694 use reth_trie_db::DatabaseTrieCursorFactory;
2695 use reth_trie_sparse::{
2696 provider::{DefaultTrieNodeProvider, RevealedNode, TrieNodeProvider},
2697 LeafLookup, LeafLookupError, RevealedSparseNode, SerialSparseTrie, SparseNode,
2698 SparseTrieInterface, SparseTrieUpdates, TrieMasks,
2699 };
2700 use std::collections::{BTreeMap, BTreeSet};
2701
2702 fn pad_nibbles_right(mut nibbles: Nibbles) -> Nibbles {
2704 nibbles.extend(&Nibbles::from_nibbles_unchecked(vec![
2705 0;
2706 B256::len_bytes() * 2 - nibbles.len()
2707 ]));
2708 nibbles
2709 }
2710
2711 #[derive(Debug, Clone)]
2716 struct MockTrieNodeProvider {
2717 nodes: HashMap<Nibbles, RevealedNode, DefaultHashBuilder>,
2719 }
2720
2721 impl MockTrieNodeProvider {
2722 fn new() -> Self {
2724 Self { nodes: HashMap::default() }
2725 }
2726
2727 fn add_revealed_node(&mut self, path: Nibbles, node: RevealedNode) {
2729 self.nodes.insert(path, node);
2730 }
2731 }
2732
2733 impl TrieNodeProvider for MockTrieNodeProvider {
2734 fn trie_node(&self, path: &Nibbles) -> Result<Option<RevealedNode>, SparseTrieError> {
2735 Ok(self.nodes.get(path).cloned())
2736 }
2737 }
2738
2739 fn create_account(nonce: u64) -> Account {
2740 Account { nonce, ..Default::default() }
2741 }
2742
2743 fn encode_account_value(nonce: u64) -> Vec<u8> {
2744 let account = Account { nonce, ..Default::default() };
2745 let trie_account = account.into_trie_account(EMPTY_ROOT_HASH);
2746 let mut buf = Vec::new();
2747 trie_account.encode(&mut buf);
2748 buf
2749 }
2750
2751 #[derive(Default)]
2753 struct ParallelSparseTrieTestContext;
2754
2755 impl ParallelSparseTrieTestContext {
2756 fn assert_subtrie_exists(&self, trie: &ParallelSparseTrie, path: &Nibbles) {
2758 let idx = path_subtrie_index_unchecked(path);
2759 assert!(
2760 trie.lower_subtries[idx].as_revealed_ref().is_some(),
2761 "Expected lower subtrie at path {path:?} to exist",
2762 );
2763 }
2764
2765 fn get_subtrie<'a>(
2767 &self,
2768 trie: &'a ParallelSparseTrie,
2769 path: &Nibbles,
2770 ) -> &'a SparseSubtrie {
2771 let idx = path_subtrie_index_unchecked(path);
2772 trie.lower_subtries[idx]
2773 .as_revealed_ref()
2774 .unwrap_or_else(|| panic!("Lower subtrie at path {path:?} should exist"))
2775 }
2776
2777 fn assert_subtrie_path(
2779 &self,
2780 trie: &ParallelSparseTrie,
2781 subtrie_prefix: impl AsRef<[u8]>,
2782 expected_path: impl AsRef<[u8]>,
2783 ) {
2784 let subtrie_prefix = Nibbles::from_nibbles(subtrie_prefix);
2785 let expected_path = Nibbles::from_nibbles(expected_path);
2786 let idx = path_subtrie_index_unchecked(&subtrie_prefix);
2787
2788 let subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap_or_else(|| {
2789 panic!("Lower subtrie at prefix {subtrie_prefix:?} should exist")
2790 });
2791
2792 assert_eq!(
2793 subtrie.path, expected_path,
2794 "Subtrie at prefix {subtrie_prefix:?} should have path {expected_path:?}, but has {:?}",
2795 subtrie.path
2796 );
2797 }
2798
2799 fn create_test_leaves(&self, paths: &[&[u8]]) -> Vec<(Nibbles, Vec<u8>)> {
2801 paths
2802 .iter()
2803 .enumerate()
2804 .map(|(i, path)| (Nibbles::from_nibbles(path), encode_account_value(i as u64 + 1)))
2805 .collect()
2806 }
2807
2808 fn create_test_leaf(&self, path: impl AsRef<[u8]>, value_nonce: u64) -> (Nibbles, Vec<u8>) {
2810 (Nibbles::from_nibbles(path), encode_account_value(value_nonce))
2811 }
2812
2813 fn update_leaves(
2815 &self,
2816 trie: &mut ParallelSparseTrie,
2817 leaves: impl IntoIterator<Item = (Nibbles, Vec<u8>)>,
2818 ) {
2819 for (path, value) in leaves {
2820 trie.update_leaf(path, value, DefaultTrieNodeProvider).unwrap();
2821 }
2822 }
2823
2824 fn assert_subtrie<'a>(
2826 &self,
2827 trie: &'a ParallelSparseTrie,
2828 path: Nibbles,
2829 ) -> SubtrieAssertion<'a> {
2830 self.assert_subtrie_exists(trie, &path);
2831 let subtrie = self.get_subtrie(trie, &path);
2832 SubtrieAssertion::new(subtrie)
2833 }
2834
2835 fn assert_upper_subtrie<'a>(&self, trie: &'a ParallelSparseTrie) -> SubtrieAssertion<'a> {
2837 SubtrieAssertion::new(&trie.upper_subtrie)
2838 }
2839
2840 fn assert_with_hash_builder(
2842 &self,
2843 trie: &mut ParallelSparseTrie,
2844 hash_builder_root: B256,
2845 hash_builder_updates: TrieUpdates,
2846 hash_builder_proof_nodes: ProofNodes,
2847 ) {
2848 assert_eq!(trie.root(), hash_builder_root);
2849 pretty_assertions::assert_eq!(
2850 BTreeMap::from_iter(trie.updates_ref().updated_nodes.clone()),
2851 BTreeMap::from_iter(hash_builder_updates.account_nodes)
2852 );
2853 assert_eq_parallel_sparse_trie_proof_nodes(trie, hash_builder_proof_nodes);
2854 }
2855 }
2856
2857 struct SubtrieAssertion<'a> {
2859 subtrie: &'a SparseSubtrie,
2860 }
2861
2862 impl<'a> SubtrieAssertion<'a> {
2863 fn new(subtrie: &'a SparseSubtrie) -> Self {
2864 Self { subtrie }
2865 }
2866
2867 fn has_branch(self, path: &Nibbles, expected_mask_bits: &[u8]) -> Self {
2868 match self.subtrie.nodes.get(path) {
2869 Some(SparseNode::Branch { state_mask, .. }) => {
2870 for bit in expected_mask_bits {
2871 assert!(
2872 state_mask.is_bit_set(*bit),
2873 "Expected branch at {path:?} to have bit {bit} set, instead mask is: {state_mask:?}",
2874 );
2875 }
2876 }
2877 node => panic!("Expected branch node at {path:?}, found {node:?}"),
2878 }
2879 self
2880 }
2881
2882 fn has_leaf(self, path: &Nibbles, expected_key: &Nibbles) -> Self {
2883 match self.subtrie.nodes.get(path) {
2884 Some(SparseNode::Leaf { key, .. }) => {
2885 assert_eq!(
2886 *key, *expected_key,
2887 "Expected leaf at {path:?} to have key {expected_key:?}, found {key:?}",
2888 );
2889 }
2890 node => panic!("Expected leaf node at {path:?}, found {node:?}"),
2891 }
2892 self
2893 }
2894
2895 fn has_extension(self, path: &Nibbles, expected_key: &Nibbles) -> Self {
2896 match self.subtrie.nodes.get(path) {
2897 Some(SparseNode::Extension { key, .. }) => {
2898 assert_eq!(
2899 *key, *expected_key,
2900 "Expected extension at {path:?} to have key {expected_key:?}, found {key:?}",
2901 );
2902 }
2903 node => panic!("Expected extension node at {path:?}, found {node:?}"),
2904 }
2905 self
2906 }
2907
2908 fn has_hash(self, path: &Nibbles, expected_hash: &B256) -> Self {
2909 match self.subtrie.nodes.get(path) {
2910 Some(SparseNode::Hash(hash)) => {
2911 assert_eq!(
2912 *hash, *expected_hash,
2913 "Expected hash at {path:?} to be {expected_hash:?}, found {hash:?}",
2914 );
2915 }
2916 node => panic!("Expected hash node at {path:?}, found {node:?}"),
2917 }
2918 self
2919 }
2920
2921 fn has_value(self, path: &Nibbles, expected_value: &[u8]) -> Self {
2922 let actual = self.subtrie.inner.values.get(path);
2923 assert_eq!(
2924 actual.map(|v| v.as_slice()),
2925 Some(expected_value),
2926 "Expected value at {path:?} to be {expected_value:?}, found {actual:?}",
2927 );
2928 self
2929 }
2930
2931 fn has_no_value(self, path: &Nibbles) -> Self {
2932 let actual = self.subtrie.inner.values.get(path);
2933 assert!(actual.is_none(), "Expected no value at {path:?}, but found {actual:?}");
2934 self
2935 }
2936 }
2937
2938 fn create_leaf_node(key: impl AsRef<[u8]>, value_nonce: u64) -> TrieNode {
2939 TrieNode::Leaf(LeafNode::new(Nibbles::from_nibbles(key), encode_account_value(value_nonce)))
2940 }
2941
2942 fn create_extension_node(key: impl AsRef<[u8]>, child_hash: B256) -> TrieNode {
2943 TrieNode::Extension(ExtensionNode::new(
2944 Nibbles::from_nibbles(key),
2945 RlpNode::word_rlp(&child_hash),
2946 ))
2947 }
2948
2949 fn create_branch_node_with_children(
2950 children_indices: &[u8],
2951 child_hashes: impl IntoIterator<Item = RlpNode>,
2952 ) -> TrieNode {
2953 let mut stack = Vec::new();
2954 let mut state_mask = TrieMask::default();
2955
2956 for (&idx, hash) in children_indices.iter().zip(child_hashes.into_iter()) {
2957 state_mask.set_bit(idx);
2958 stack.push(hash);
2959 }
2960
2961 TrieNode::Branch(BranchNode::new(stack, state_mask))
2962 }
2963
2964 fn run_hash_builder(
2969 state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
2970 trie_cursor: impl TrieCursor,
2971 destroyed_accounts: B256Set,
2972 proof_targets: impl IntoIterator<Item = Nibbles>,
2973 ) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>, HashMap<Nibbles, TrieMask>)
2974 {
2975 let mut account_rlp = Vec::new();
2976
2977 let mut hash_builder = HashBuilder::default()
2978 .with_updates(true)
2979 .with_proof_retainer(ProofRetainer::from_iter(proof_targets));
2980
2981 let mut prefix_set = PrefixSetMut::default();
2982 prefix_set.extend_keys(state.clone().into_iter().map(|(nibbles, _)| nibbles));
2983 prefix_set.extend_keys(destroyed_accounts.iter().map(Nibbles::unpack));
2984 let walker = TrieWalker::<_>::state_trie(trie_cursor, prefix_set.freeze())
2985 .with_deletions_retained(true);
2986 let hashed_post_state = HashedPostState::default()
2987 .with_accounts(state.into_iter().map(|(nibbles, account)| {
2988 (nibbles.pack().into_inner().unwrap().into(), Some(account))
2989 }))
2990 .into_sorted();
2991 let mut node_iter = TrieNodeIter::state_trie(
2992 walker,
2993 HashedPostStateAccountCursor::new(
2994 NoopHashedAccountCursor::default(),
2995 hashed_post_state.accounts(),
2996 ),
2997 );
2998
2999 while let Some(node) = node_iter.try_next().unwrap() {
3000 match node {
3001 TrieElement::Branch(branch) => {
3002 hash_builder.add_branch(branch.key, branch.value, branch.children_are_in_trie);
3003 }
3004 TrieElement::Leaf(key, account) => {
3005 let account = account.into_trie_account(EMPTY_ROOT_HASH);
3006 account.encode(&mut account_rlp);
3007
3008 hash_builder.add_leaf(Nibbles::unpack(key), &account_rlp);
3009 account_rlp.clear();
3010 }
3011 }
3012 }
3013 let root = hash_builder.root();
3014 let proof_nodes = hash_builder.take_proof_nodes();
3015 let branch_node_hash_masks = hash_builder
3016 .updated_branch_nodes
3017 .clone()
3018 .unwrap_or_default()
3019 .iter()
3020 .map(|(path, node)| (*path, node.hash_mask))
3021 .collect();
3022 let branch_node_tree_masks = hash_builder
3023 .updated_branch_nodes
3024 .clone()
3025 .unwrap_or_default()
3026 .iter()
3027 .map(|(path, node)| (*path, node.tree_mask))
3028 .collect();
3029
3030 let mut trie_updates = TrieUpdates::default();
3031 let removed_keys = node_iter.walker.take_removed_keys();
3032 trie_updates.finalize(hash_builder, removed_keys, destroyed_accounts);
3033
3034 (root, trie_updates, proof_nodes, branch_node_hash_masks, branch_node_tree_masks)
3035 }
3036
3037 fn new_test_trie<Nodes>(nodes: Nodes) -> ParallelSparseTrie
3040 where
3041 Nodes: Iterator<Item = (Nibbles, SparseNode)>,
3042 {
3043 let mut trie = ParallelSparseTrie::default().with_updates(true);
3044
3045 for (path, node) in nodes {
3046 let subtrie = trie.subtrie_for_path_mut(&path);
3047 if let SparseNode::Leaf { key, .. } = &node {
3048 let mut full_key = path;
3049 full_key.extend(key);
3050 subtrie.inner.values.insert(full_key, "LEAF VALUE".into());
3051 }
3052 subtrie.nodes.insert(path, node);
3053 }
3054 trie
3055 }
3056
3057 fn parallel_sparse_trie_nodes(
3058 sparse_trie: &ParallelSparseTrie,
3059 ) -> impl IntoIterator<Item = (&Nibbles, &SparseNode)> {
3060 let lower_sparse_nodes = sparse_trie
3061 .lower_subtries
3062 .iter()
3063 .filter_map(|subtrie| subtrie.as_revealed_ref())
3064 .flat_map(|subtrie| subtrie.nodes.iter());
3065
3066 let upper_sparse_nodes = sparse_trie.upper_subtrie.nodes.iter();
3067
3068 lower_sparse_nodes.chain(upper_sparse_nodes).sorted_by_key(|(path, _)| *path)
3069 }
3070
3071 fn assert_eq_parallel_sparse_trie_proof_nodes(
3074 sparse_trie: &ParallelSparseTrie,
3075 proof_nodes: ProofNodes,
3076 ) {
3077 let proof_nodes = proof_nodes
3078 .into_nodes_sorted()
3079 .into_iter()
3080 .map(|(path, node)| (path, TrieNode::decode(&mut node.as_ref()).unwrap()));
3081
3082 let all_sparse_nodes = parallel_sparse_trie_nodes(sparse_trie);
3083
3084 for ((proof_node_path, proof_node), (sparse_node_path, sparse_node)) in
3085 proof_nodes.zip(all_sparse_nodes)
3086 {
3087 assert_eq!(&proof_node_path, sparse_node_path);
3088
3089 let equals = match (&proof_node, &sparse_node) {
3090 (TrieNode::EmptyRoot, SparseNode::Empty) => true,
3092 (
3094 TrieNode::Branch(BranchNode { state_mask: proof_state_mask, .. }),
3095 SparseNode::Branch { state_mask: sparse_state_mask, .. },
3096 ) => proof_state_mask == sparse_state_mask,
3097 (
3099 TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
3100 SparseNode::Extension { key: sparse_key, .. },
3101 ) |
3102 (
3104 TrieNode::Leaf(LeafNode { key: proof_key, .. }),
3105 SparseNode::Leaf { key: sparse_key, .. },
3106 ) => proof_key == sparse_key,
3107 (_, SparseNode::Empty | SparseNode::Hash(_)) => continue,
3109 _ => false,
3110 };
3111 assert!(
3112 equals,
3113 "path: {proof_node_path:?}\nproof node: {proof_node:?}\nsparse node: {sparse_node:?}"
3114 );
3115 }
3116 }
3117
3118 #[test]
3119 fn test_get_changed_subtries_empty() {
3120 let mut trie = ParallelSparseTrie::default();
3121 let mut prefix_set = PrefixSetMut::from([Nibbles::default()]).freeze();
3122
3123 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3124 assert!(subtries.is_empty());
3125 assert_eq!(unchanged_prefix_set, PrefixSetMut::from(prefix_set.iter().copied()));
3126 }
3127
3128 #[test]
3129 fn test_get_changed_subtries() {
3130 let mut trie = ParallelSparseTrie::default();
3132 let subtrie_1 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3133 let subtrie_1_index = path_subtrie_index_unchecked(&subtrie_1.path);
3134 let subtrie_2 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x1, 0x0])));
3135 let subtrie_2_index = path_subtrie_index_unchecked(&subtrie_2.path);
3136 let subtrie_3 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x3, 0x0])));
3137 let subtrie_3_index = path_subtrie_index_unchecked(&subtrie_3.path);
3138
3139 trie.lower_subtries[subtrie_1_index] = LowerSparseSubtrie::Revealed(subtrie_1.clone());
3141 trie.lower_subtries[subtrie_2_index] = LowerSparseSubtrie::Revealed(subtrie_2.clone());
3142 trie.lower_subtries[subtrie_3_index] = LowerSparseSubtrie::Revealed(subtrie_3);
3143
3144 let unchanged_prefix_set = PrefixSetMut::from([
3145 Nibbles::from_nibbles([0x0]),
3146 Nibbles::from_nibbles([0x2, 0x0, 0x0]),
3147 ]);
3148 let mut prefix_set = PrefixSetMut::from([
3150 Nibbles::from_nibbles([0x1, 0x0, 0x0]),
3152 Nibbles::from_nibbles([0x1, 0x0, 0x1, 0x0]),
3153 ]);
3154 prefix_set.extend(unchanged_prefix_set);
3155 let mut prefix_set = prefix_set.freeze();
3156
3157 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3159 assert_eq!(
3160 subtries
3161 .into_iter()
3162 .map(|ChangedSubtrie { index, subtrie, prefix_set, .. }| {
3163 (index, subtrie, prefix_set.iter().copied().collect::<Vec<_>>())
3164 })
3165 .collect::<Vec<_>>(),
3166 vec![(
3167 subtrie_2_index,
3168 subtrie_2,
3169 vec![
3170 Nibbles::from_nibbles([0x1, 0x0, 0x0]),
3171 Nibbles::from_nibbles([0x1, 0x0, 0x1, 0x0])
3172 ]
3173 )]
3174 );
3175 assert_eq!(unchanged_prefix_set, unchanged_prefix_set);
3176 assert!(trie.lower_subtries[subtrie_2_index].as_revealed_ref().is_none());
3177
3178 assert_eq!(trie.lower_subtries[subtrie_1_index], LowerSparseSubtrie::Revealed(subtrie_1));
3180 }
3181
3182 #[test]
3183 fn test_get_changed_subtries_all() {
3184 let mut trie = ParallelSparseTrie::default();
3186 let subtrie_1 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3187 let subtrie_1_index = path_subtrie_index_unchecked(&subtrie_1.path);
3188 let subtrie_2 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x1, 0x0])));
3189 let subtrie_2_index = path_subtrie_index_unchecked(&subtrie_2.path);
3190 let subtrie_3 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x3, 0x0])));
3191 let subtrie_3_index = path_subtrie_index_unchecked(&subtrie_3.path);
3192
3193 trie.lower_subtries[subtrie_1_index] = LowerSparseSubtrie::Revealed(subtrie_1.clone());
3195 trie.lower_subtries[subtrie_2_index] = LowerSparseSubtrie::Revealed(subtrie_2.clone());
3196 trie.lower_subtries[subtrie_3_index] = LowerSparseSubtrie::Revealed(subtrie_3.clone());
3197
3198 let mut prefix_set = PrefixSetMut::all().freeze();
3200
3201 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3203 assert_eq!(
3204 subtries
3205 .into_iter()
3206 .map(|ChangedSubtrie { index, subtrie, prefix_set, .. }| {
3207 (index, subtrie, prefix_set.all())
3208 })
3209 .collect::<Vec<_>>(),
3210 vec![
3211 (subtrie_1_index, subtrie_1, true),
3212 (subtrie_2_index, subtrie_2, true),
3213 (subtrie_3_index, subtrie_3, true)
3214 ]
3215 );
3216 assert_eq!(unchanged_prefix_set, PrefixSetMut::all());
3217
3218 assert!(trie.lower_subtries.iter().all(|subtrie| subtrie.as_revealed_ref().is_none()));
3219 }
3220
3221 #[test]
3222 fn test_sparse_subtrie_type() {
3223 assert_eq!(SparseSubtrieType::from_path(&Nibbles::new()), SparseSubtrieType::Upper);
3224 assert_eq!(
3225 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0])),
3226 SparseSubtrieType::Upper
3227 );
3228 assert_eq!(
3229 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15])),
3230 SparseSubtrieType::Upper
3231 );
3232 assert_eq!(
3233 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 0])),
3234 SparseSubtrieType::Lower(0)
3235 );
3236 assert_eq!(
3237 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 0, 0])),
3238 SparseSubtrieType::Lower(0)
3239 );
3240 assert_eq!(
3241 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 1])),
3242 SparseSubtrieType::Lower(1)
3243 );
3244 assert_eq!(
3245 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 1, 0])),
3246 SparseSubtrieType::Lower(1)
3247 );
3248 assert_eq!(
3249 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 15])),
3250 SparseSubtrieType::Lower(15)
3251 );
3252 assert_eq!(
3253 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 0])),
3254 SparseSubtrieType::Lower(240)
3255 );
3256 assert_eq!(
3257 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 1])),
3258 SparseSubtrieType::Lower(241)
3259 );
3260 assert_eq!(
3261 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 15])),
3262 SparseSubtrieType::Lower(255)
3263 );
3264 assert_eq!(
3265 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 15, 15])),
3266 SparseSubtrieType::Lower(255)
3267 );
3268 }
3269
3270 #[test]
3271 fn test_reveal_node_leaves() {
3272 let mut trie = ParallelSparseTrie::default();
3273
3274 {
3276 let path = Nibbles::from_nibbles([0x1]);
3277 let node = create_leaf_node([0x2, 0x3], 42);
3278 let masks = TrieMasks::none();
3279
3280 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3281
3282 assert_matches!(
3283 trie.upper_subtrie.nodes.get(&path),
3284 Some(SparseNode::Leaf { key, hash: None })
3285 if key == &Nibbles::from_nibbles([0x2, 0x3])
3286 );
3287
3288 let full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3289 assert_eq!(
3290 trie.upper_subtrie.inner.values.get(&full_path),
3291 Some(&encode_account_value(42))
3292 );
3293 }
3294
3295 {
3297 let path = Nibbles::from_nibbles([0x1, 0x2]);
3298 let node = create_leaf_node([0x3, 0x4], 42);
3299 let masks = TrieMasks::none();
3300
3301 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3302
3303 let idx = path_subtrie_index_unchecked(&path);
3305 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3306
3307 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3309 assert_eq!(lower_subtrie.path, path);
3310
3311 assert_matches!(
3312 lower_subtrie.nodes.get(&path),
3313 Some(SparseNode::Leaf { key, hash: None })
3314 if key == &Nibbles::from_nibbles([0x3, 0x4])
3315 );
3316 }
3317
3318 {
3321 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3322 let node = create_leaf_node([0x4, 0x5], 42);
3323 let masks = TrieMasks::none();
3324
3325 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3326
3327 let idx = path_subtrie_index_unchecked(&path);
3329 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3330 assert_eq!(lower_subtrie.path, Nibbles::from_nibbles([0x1, 0x2]));
3331 }
3332 }
3333
3334 #[test]
3335 fn test_reveal_node_extension_all_upper() {
3336 let path = Nibbles::new();
3337 let child_hash = B256::repeat_byte(0xab);
3338 let node = create_extension_node([0x1], child_hash);
3339 let masks = TrieMasks::none();
3340 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3341
3342 assert_matches!(
3343 trie.upper_subtrie.nodes.get(&path),
3344 Some(SparseNode::Extension { key, hash: None, .. })
3345 if key == &Nibbles::from_nibbles([0x1])
3346 );
3347
3348 let child_path = Nibbles::from_nibbles([0x1]);
3350 assert_eq!(trie.upper_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3351 }
3352
3353 #[test]
3354 fn test_reveal_node_extension_cross_level() {
3355 let path = Nibbles::new();
3356 let child_hash = B256::repeat_byte(0xcd);
3357 let node = create_extension_node([0x1, 0x2, 0x3], child_hash);
3358 let masks = TrieMasks::none();
3359 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3360
3361 assert_matches!(
3363 trie.upper_subtrie.nodes.get(&path),
3364 Some(SparseNode::Extension { key, hash: None, .. })
3365 if key == &Nibbles::from_nibbles([0x1, 0x2, 0x3])
3366 );
3367
3368 let child_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3370 let idx = path_subtrie_index_unchecked(&child_path);
3371 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3372
3373 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3374 assert_eq!(lower_subtrie.path, child_path);
3375 assert_eq!(lower_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3376 }
3377
3378 #[test]
3379 fn test_reveal_node_extension_cross_level_boundary() {
3380 let mut trie = ParallelSparseTrie::default();
3381 let path = Nibbles::from_nibbles([0x1]);
3382 let child_hash = B256::repeat_byte(0xcd);
3383 let node = create_extension_node([0x2], child_hash);
3384 let masks = TrieMasks::none();
3385
3386 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3387
3388 assert_matches!(
3390 trie.upper_subtrie.nodes.get(&path),
3391 Some(SparseNode::Extension { key, hash: None, .. })
3392 if key == &Nibbles::from_nibbles([0x2])
3393 );
3394
3395 let child_path = Nibbles::from_nibbles([0x1, 0x2]);
3397 let idx = path_subtrie_index_unchecked(&child_path);
3398 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3399
3400 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3401 assert_eq!(lower_subtrie.path, child_path);
3402 assert_eq!(lower_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3403 }
3404
3405 #[test]
3406 fn test_reveal_node_branch_all_upper() {
3407 let path = Nibbles::new();
3408 let child_hashes = [
3409 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
3410 RlpNode::word_rlp(&B256::repeat_byte(0x22)),
3411 ];
3412 let node = create_branch_node_with_children(&[0x0, 0x5], child_hashes.clone());
3413 let masks = TrieMasks::none();
3414 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3415
3416 assert_matches!(
3418 trie.upper_subtrie.nodes.get(&path),
3419 Some(SparseNode::Branch { state_mask, hash: None, .. })
3420 if *state_mask == 0b0000000000100001.into()
3421 );
3422
3423 let child_path_0 = Nibbles::from_nibbles([0x0]);
3425 let child_path_5 = Nibbles::from_nibbles([0x5]);
3426 assert_eq!(
3427 trie.upper_subtrie.nodes.get(&child_path_0),
3428 Some(&SparseNode::Hash(child_hashes[0].as_hash().unwrap()))
3429 );
3430 assert_eq!(
3431 trie.upper_subtrie.nodes.get(&child_path_5),
3432 Some(&SparseNode::Hash(child_hashes[1].as_hash().unwrap()))
3433 );
3434 }
3435
3436 #[test]
3437 fn test_reveal_node_branch_cross_level() {
3438 let mut trie = ParallelSparseTrie::default();
3439 let path = Nibbles::from_nibbles([0x1]); let child_hashes = [
3441 RlpNode::word_rlp(&B256::repeat_byte(0x33)),
3442 RlpNode::word_rlp(&B256::repeat_byte(0x44)),
3443 RlpNode::word_rlp(&B256::repeat_byte(0x55)),
3444 ];
3445 let node = create_branch_node_with_children(&[0x0, 0x7, 0xf], child_hashes.clone());
3446 let masks = TrieMasks::none();
3447
3448 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3449
3450 assert_matches!(
3452 trie.upper_subtrie.nodes.get(&path),
3453 Some(SparseNode::Branch { state_mask, hash: None, .. })
3454 if *state_mask == 0b1000000010000001.into()
3455 );
3456
3457 let child_paths = [
3459 Nibbles::from_nibbles([0x1, 0x0]),
3460 Nibbles::from_nibbles([0x1, 0x7]),
3461 Nibbles::from_nibbles([0x1, 0xf]),
3462 ];
3463
3464 for (i, child_path) in child_paths.iter().enumerate() {
3465 let idx = path_subtrie_index_unchecked(child_path);
3466 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3467 assert_eq!(&lower_subtrie.path, child_path);
3468 assert_eq!(
3469 lower_subtrie.nodes.get(child_path),
3470 Some(&SparseNode::Hash(child_hashes[i].as_hash().unwrap())),
3471 );
3472 }
3473 }
3474
3475 #[test]
3476 fn test_update_subtrie_hashes_prefix_set_matching() {
3477 let mut trie = ParallelSparseTrie::default();
3479
3480 let leaf_1_full_path = Nibbles::from_nibbles([0; 64]);
3482 let leaf_1_path = leaf_1_full_path.slice(..2);
3483 let leaf_1_key = leaf_1_full_path.slice(2..);
3484 let leaf_2_full_path = Nibbles::from_nibbles([vec![0, 1], vec![0; 62]].concat());
3485 let leaf_2_path = leaf_2_full_path.slice(..2);
3486 let leaf_2_key = leaf_2_full_path.slice(2..);
3487 let leaf_3_full_path = Nibbles::from_nibbles([vec![0, 2], vec![0; 62]].concat());
3488 let leaf_3_path = leaf_3_full_path.slice(..2);
3489 let leaf_3_key = leaf_3_full_path.slice(2..);
3490 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), 1);
3491 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), 2);
3492 let leaf_3 = create_leaf_node(leaf_3_key.to_vec(), 3);
3493
3494 let child_hashes = [
3496 RlpNode::word_rlp(&B256::repeat_byte(0x00)),
3497 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
3498 ];
3500 let branch_path = Nibbles::from_nibbles([0x0]);
3501 let branch_node = create_branch_node_with_children(&[0x0, 0x1, 0x2], child_hashes);
3502
3503 trie.reveal_nodes(vec![
3505 RevealedSparseNode { path: branch_path, node: branch_node, masks: TrieMasks::none() },
3506 RevealedSparseNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
3507 RevealedSparseNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
3508 RevealedSparseNode { path: leaf_3_path, node: leaf_3, masks: TrieMasks::none() },
3509 ])
3510 .unwrap();
3511
3512 let subtrie_1_index = SparseSubtrieType::from_path(&leaf_1_path).lower_index().unwrap();
3514 let subtrie_2_index = SparseSubtrieType::from_path(&leaf_2_path).lower_index().unwrap();
3515 let subtrie_3_index = SparseSubtrieType::from_path(&leaf_3_path).lower_index().unwrap();
3516
3517 let mut unchanged_prefix_set = PrefixSetMut::from([
3518 Nibbles::from_nibbles([0x0]),
3519 leaf_2_full_path,
3520 Nibbles::from_nibbles([0x3, 0x0, 0x0]),
3521 ]);
3522 let mut prefix_set = PrefixSetMut::from([
3524 Nibbles::from_nibbles([0x0, 0x1, 0x0]),
3526 Nibbles::from_nibbles([0x0, 0x1, 0x1, 0x0]),
3527 ]);
3528 prefix_set.extend(unchanged_prefix_set.clone());
3529 trie.prefix_set = prefix_set;
3530
3531 trie.update_subtrie_hashes();
3533
3534 unchanged_prefix_set.insert(leaf_3_full_path);
3538
3539 assert_eq!(
3541 trie.prefix_set.clone().freeze().into_iter().collect::<Vec<_>>(),
3542 unchanged_prefix_set.freeze().into_iter().collect::<Vec<_>>()
3543 );
3544 assert!(trie.lower_subtries[subtrie_1_index].as_revealed_ref().is_some());
3546 assert!(trie.lower_subtries[subtrie_2_index].as_revealed_ref().is_some());
3547 assert!(trie.lower_subtries[subtrie_3_index].as_revealed_ref().is_some());
3548 }
3549
3550 #[test]
3551 fn test_subtrie_update_hashes() {
3552 let mut subtrie = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3553
3554 let leaf_1_full_path = Nibbles::from_nibbles([0; 64]);
3556 let leaf_1_path = leaf_1_full_path.slice(..5);
3557 let leaf_1_key = leaf_1_full_path.slice(5..);
3558 let leaf_2_full_path = Nibbles::from_nibbles([vec![0, 0, 0, 0, 1], vec![0; 59]].concat());
3559 let leaf_2_path = leaf_2_full_path.slice(..5);
3560 let leaf_2_key = leaf_2_full_path.slice(5..);
3561 let leaf_3_full_path = Nibbles::from_nibbles([vec![0, 0, 1], vec![0; 61]].concat());
3562 let leaf_3_path = leaf_3_full_path.slice(..3);
3563 let leaf_3_key = leaf_3_full_path.slice(3..);
3564
3565 let account_1 = create_account(1);
3566 let account_2 = create_account(2);
3567 let account_3 = create_account(3);
3568 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), account_1.nonce);
3569 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), account_2.nonce);
3570 let leaf_3 = create_leaf_node(leaf_3_key.to_vec(), account_3.nonce);
3571
3572 let branch_1_path = Nibbles::from_nibbles([0, 0, 0, 0]);
3574 let branch_1 = create_branch_node_with_children(
3575 &[0, 1],
3576 vec![
3577 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_1)),
3578 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_2)),
3579 ],
3580 );
3581
3582 let extension_path = Nibbles::from_nibbles([0, 0, 0]);
3584 let extension_key = Nibbles::from_nibbles([0]);
3585 let extension = create_extension_node(
3586 extension_key.to_vec(),
3587 RlpNode::from_rlp(&alloy_rlp::encode(&branch_1)).as_hash().unwrap(),
3588 );
3589
3590 let branch_2_path = Nibbles::from_nibbles([0, 0]);
3592 let branch_2 = create_branch_node_with_children(
3593 &[0, 1],
3594 vec![
3595 RlpNode::from_rlp(&alloy_rlp::encode(&extension)),
3596 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_3)),
3597 ],
3598 );
3599
3600 subtrie.reveal_node(branch_2_path, &branch_2, TrieMasks::none()).unwrap();
3602 subtrie.reveal_node(leaf_1_path, &leaf_1, TrieMasks::none()).unwrap();
3603 subtrie.reveal_node(extension_path, &extension, TrieMasks::none()).unwrap();
3604 subtrie.reveal_node(branch_1_path, &branch_1, TrieMasks::none()).unwrap();
3605 subtrie.reveal_node(leaf_2_path, &leaf_2, TrieMasks::none()).unwrap();
3606 subtrie.reveal_node(leaf_3_path, &leaf_3, TrieMasks::none()).unwrap();
3607
3608 let (_, _, proof_nodes, _, _) = run_hash_builder(
3610 [
3611 (leaf_1_full_path, account_1),
3612 (leaf_2_full_path, account_2),
3613 (leaf_3_full_path, account_3),
3614 ],
3615 NoopAccountTrieCursor::default(),
3616 Default::default(),
3617 [
3618 branch_1_path,
3619 extension_path,
3620 branch_2_path,
3621 leaf_1_full_path,
3622 leaf_2_full_path,
3623 leaf_3_full_path,
3624 ],
3625 );
3626
3627 subtrie.update_hashes(
3629 &mut PrefixSetMut::from([leaf_1_full_path, leaf_2_full_path, leaf_3_full_path])
3630 .freeze(),
3631 &mut None,
3632 &HashMap::default(),
3633 &HashMap::default(),
3634 );
3635
3636 let hash_builder_branch_1_hash =
3638 RlpNode::from_rlp(proof_nodes.get(&branch_1_path).unwrap().as_ref()).as_hash().unwrap();
3639 let subtrie_branch_1_hash = subtrie.nodes.get(&branch_1_path).unwrap().hash().unwrap();
3640 assert_eq!(hash_builder_branch_1_hash, subtrie_branch_1_hash);
3641
3642 let hash_builder_extension_hash =
3643 RlpNode::from_rlp(proof_nodes.get(&extension_path).unwrap().as_ref())
3644 .as_hash()
3645 .unwrap();
3646 let subtrie_extension_hash = subtrie.nodes.get(&extension_path).unwrap().hash().unwrap();
3647 assert_eq!(hash_builder_extension_hash, subtrie_extension_hash);
3648
3649 let hash_builder_branch_2_hash =
3650 RlpNode::from_rlp(proof_nodes.get(&branch_2_path).unwrap().as_ref()).as_hash().unwrap();
3651 let subtrie_branch_2_hash = subtrie.nodes.get(&branch_2_path).unwrap().hash().unwrap();
3652 assert_eq!(hash_builder_branch_2_hash, subtrie_branch_2_hash);
3653
3654 let subtrie_leaf_1_hash = subtrie.nodes.get(&leaf_1_path).unwrap().hash().unwrap();
3655 let hash_builder_leaf_1_hash =
3656 RlpNode::from_rlp(proof_nodes.get(&leaf_1_path).unwrap().as_ref()).as_hash().unwrap();
3657 assert_eq!(hash_builder_leaf_1_hash, subtrie_leaf_1_hash);
3658
3659 let hash_builder_leaf_2_hash =
3660 RlpNode::from_rlp(proof_nodes.get(&leaf_2_path).unwrap().as_ref()).as_hash().unwrap();
3661 let subtrie_leaf_2_hash = subtrie.nodes.get(&leaf_2_path).unwrap().hash().unwrap();
3662 assert_eq!(hash_builder_leaf_2_hash, subtrie_leaf_2_hash);
3663
3664 let hash_builder_leaf_3_hash =
3665 RlpNode::from_rlp(proof_nodes.get(&leaf_3_path).unwrap().as_ref()).as_hash().unwrap();
3666 let subtrie_leaf_3_hash = subtrie.nodes.get(&leaf_3_path).unwrap().hash().unwrap();
3667 assert_eq!(hash_builder_leaf_3_hash, subtrie_leaf_3_hash);
3668 }
3669
3670 #[test]
3671 fn test_remove_leaf_branch_becomes_extension() {
3672 let mut trie = new_test_trie(
3684 [
3685 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
3686 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(TrieMask::new(0b1001))),
3687 (
3688 Nibbles::from_nibbles([0x5, 0x0]),
3689 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3])),
3690 ),
3691 (
3692 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
3693 SparseNode::new_branch(TrieMask::new(0b0101)),
3694 ),
3695 (
3696 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
3697 SparseNode::new_leaf(Nibbles::new()),
3698 ),
3699 (
3700 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
3701 SparseNode::new_leaf(Nibbles::new()),
3702 ),
3703 (
3704 Nibbles::from_nibbles([0x5, 0x3]),
3705 SparseNode::new_leaf(Nibbles::from_nibbles([0x7])),
3706 ),
3707 ]
3708 .into_iter(),
3709 );
3710
3711 let provider = MockTrieNodeProvider::new();
3712
3713 let leaf_full_path = Nibbles::from_nibbles([0x5, 0x3, 0x7]);
3715 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3716
3717 let upper_subtrie = &trie.upper_subtrie;
3718 let lower_subtrie_50 = trie.lower_subtries[0x50].as_revealed_ref().unwrap();
3719
3720 assert_matches!(trie.lower_subtries[0x53].as_revealed_ref(), None);
3723
3724 assert_matches!(
3727 upper_subtrie.nodes.get(&Nibbles::from_nibbles([])),
3728 Some(SparseNode::Extension{ key, ..})
3729 if key == &Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3])
3730 );
3731 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x5])), None);
3732 assert_matches!(lower_subtrie_50.nodes.get(&Nibbles::from_nibbles([0x5, 0x0])), None);
3733 assert_matches!(
3734 lower_subtrie_50.nodes.get(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3])),
3735 Some(SparseNode::Branch{ state_mask, .. })
3736 if *state_mask == 0b0101.into()
3737 );
3738 }
3739
3740 #[test]
3741 fn test_remove_leaf_branch_becomes_leaf() {
3742 let mut trie = new_test_trie(
3750 [
3751 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0011))),
3752 (
3753 Nibbles::from_nibbles([0x0]),
3754 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3755 ),
3756 (
3757 Nibbles::from_nibbles([0x1]),
3758 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3759 ),
3760 ]
3761 .into_iter(),
3762 );
3763
3764 if let Some(updates) = trie.updates.as_mut() {
3766 updates
3767 .updated_nodes
3768 .insert(Nibbles::default(), BranchNodeCompact::new(0b11, 0, 0, vec![], None));
3769 }
3770
3771 let provider = MockTrieNodeProvider::new();
3772
3773 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2]);
3775 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3776
3777 let upper_subtrie = &trie.upper_subtrie;
3778
3779 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
3781
3782 assert_matches!(
3784 upper_subtrie.nodes.get(&Nibbles::default()),
3785 Some(SparseNode::Leaf{ key, ..})
3786 if key == &Nibbles::from_nibbles([0x1, 0x3, 0x4])
3787 );
3788
3789 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])), None);
3791 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x0])), None);
3793
3794 let updates = trie.updates.as_ref().unwrap();
3796
3797 assert!(updates.removed_nodes.contains(&Nibbles::default()));
3799
3800 assert!(!updates.updated_nodes.contains_key(&Nibbles::default()));
3802 }
3803
3804 #[test]
3805 fn test_remove_leaf_extension_becomes_leaf() {
3806 let mut trie = new_test_trie(
3815 [
3816 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
3817 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(TrieMask::new(0b0011))),
3818 (
3819 Nibbles::from_nibbles([0x5, 0x0]),
3820 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3821 ),
3822 (
3823 Nibbles::from_nibbles([0x5, 0x1]),
3824 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3825 ),
3826 ]
3827 .into_iter(),
3828 );
3829
3830 let provider = MockTrieNodeProvider::new();
3831
3832 let leaf_full_path = Nibbles::from_nibbles([0x5, 0x0, 0x1, 0x2]);
3834 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3835
3836 let upper_subtrie = &trie.upper_subtrie;
3837
3838 assert_matches!(trie.lower_subtries[0x50].as_revealed_ref(), None);
3842 assert_matches!(trie.lower_subtries[0x51].as_revealed_ref(), None);
3843
3844 let other_leaf_full_value = Nibbles::from_nibbles([0x5, 0x1, 0x3, 0x4]);
3846 assert_matches!(upper_subtrie.inner.values.get(&other_leaf_full_value), Some(_));
3847
3848 assert_matches!(
3850 upper_subtrie.nodes.get(&Nibbles::default()),
3851 Some(SparseNode::Leaf{ key, ..})
3852 if key == &Nibbles::from_nibbles([0x5, 0x1, 0x3, 0x4])
3853 );
3854
3855 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x5])), None);
3857 }
3858
3859 #[test]
3860 fn test_remove_leaf_branch_on_branch() {
3861 let mut trie = new_test_trie(
3871 [
3872 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0101))),
3873 (
3874 Nibbles::from_nibbles([0x0]),
3875 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3876 ),
3877 (Nibbles::from_nibbles([0x2]), SparseNode::new_branch(TrieMask::new(0b0011))),
3878 (
3879 Nibbles::from_nibbles([0x2, 0x0]),
3880 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3881 ),
3882 (
3883 Nibbles::from_nibbles([0x2, 0x1]),
3884 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x6])),
3885 ),
3886 ]
3887 .into_iter(),
3888 );
3889
3890 let provider = MockTrieNodeProvider::new();
3891
3892 let leaf_full_path = Nibbles::from_nibbles([0x2, 0x0, 0x3, 0x4]);
3894 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3895
3896 let upper_subtrie = &trie.upper_subtrie;
3897
3898 assert_matches!(trie.lower_subtries[0x20].as_revealed_ref(), None);
3902 assert_matches!(trie.lower_subtries[0x21].as_revealed_ref(), None);
3903
3904 let other_leaf_full_value = Nibbles::from_nibbles([0x2, 0x1, 0x5, 0x6]);
3906 assert_matches!(upper_subtrie.inner.values.get(&other_leaf_full_value), Some(_));
3907
3908 assert_matches!(
3910 upper_subtrie.nodes.get(&Nibbles::default()),
3911 Some(SparseNode::Branch{ state_mask, .. })
3912 if *state_mask == 0b0101.into()
3913 );
3914
3915 assert_matches!(
3917 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x2])),
3918 Some(SparseNode::Leaf{ key, ..})
3919 if key == &Nibbles::from_nibbles([0x1, 0x5, 0x6])
3920 );
3921 }
3922
3923 #[test]
3924 fn test_remove_leaf_lower_subtrie_root_path_update() {
3925 let mut trie = new_test_trie(
3939 [
3940 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x1, 0x2, 0x3]))),
3941 (
3942 Nibbles::from_nibbles([0x1, 0x2, 0x3]),
3943 SparseNode::new_branch(TrieMask::new(0b0011000)),
3944 ),
3945 (
3946 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x3]),
3947 SparseNode::new_leaf(Nibbles::default()),
3948 ),
3949 (
3950 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]),
3951 SparseNode::new_ext(Nibbles::from_nibbles([0x5])),
3952 ),
3953 (
3954 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]),
3955 SparseNode::new_branch(TrieMask::new(0b0011)),
3956 ),
3957 (
3958 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5, 0x0]),
3959 SparseNode::new_leaf(Nibbles::default()),
3960 ),
3961 (
3962 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5, 0x1]),
3963 SparseNode::new_leaf(Nibbles::default()),
3964 ),
3965 ]
3966 .into_iter(),
3967 );
3968
3969 let provider = MockTrieNodeProvider::new();
3970
3971 let lower_subtrie_root_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3973 assert_matches!(
3974 trie.lower_subtrie_for_path_mut(&lower_subtrie_root_path),
3975 Some(subtrie)
3976 if subtrie.path == lower_subtrie_root_path
3977 );
3978
3979 let leaf_full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x3]);
3981 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3982
3983 let lower_subtrie = trie.lower_subtries[0x12].as_revealed_ref().unwrap();
3988 assert_eq!(lower_subtrie.path, Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]));
3989
3990 assert_matches!(
3992 trie.upper_subtrie.nodes.get(&Nibbles::default()),
3993 Some(SparseNode::Extension { key, .. })
3994 if key == &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5])
3995 );
3996
3997 assert_matches!(
3999 lower_subtrie.nodes.get(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5])),
4000 Some(SparseNode::Branch { state_mask, .. })
4001 if state_mask == &TrieMask::new(0b0011)
4002 );
4003 }
4004
4005 #[test]
4006 fn test_remove_leaf_remaining_child_needs_reveal() {
4007 let mut trie = new_test_trie(
4015 [
4016 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0011))),
4017 (
4018 Nibbles::from_nibbles([0x0]),
4019 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
4020 ),
4021 (Nibbles::from_nibbles([0x1]), SparseNode::Hash(B256::repeat_byte(0xab))),
4022 ]
4023 .into_iter(),
4024 );
4025
4026 let mut provider = MockTrieNodeProvider::new();
4028 let revealed_leaf = create_leaf_node([0x3, 0x4], 42);
4029 let mut encoded = Vec::new();
4030 revealed_leaf.encode(&mut encoded);
4031 provider.add_revealed_node(
4032 Nibbles::from_nibbles([0x1]),
4033 RevealedNode { node: encoded.into(), tree_mask: None, hash_mask: None },
4034 );
4035
4036 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2]);
4038 trie.remove_leaf(&leaf_full_path, provider).unwrap();
4039
4040 let upper_subtrie = &trie.upper_subtrie;
4041
4042 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
4044
4045 assert_matches!(
4047 upper_subtrie.nodes.get(&Nibbles::default()),
4048 Some(SparseNode::Leaf{ key, ..})
4049 if key == &Nibbles::from_nibbles([0x1, 0x3, 0x4])
4050 );
4051
4052 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])), None);
4054 }
4055
4056 #[test]
4057 fn test_remove_leaf_root() {
4058 let mut trie = new_test_trie(std::iter::once((
4064 Nibbles::default(),
4065 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2, 0x3])),
4066 )));
4067
4068 let provider = MockTrieNodeProvider::new();
4069
4070 let leaf_full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
4072 trie.remove_leaf(&leaf_full_path, provider).unwrap();
4073
4074 let upper_subtrie = &trie.upper_subtrie;
4075
4076 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
4078
4079 assert_matches!(upper_subtrie.nodes.get(&Nibbles::default()), Some(SparseNode::Empty));
4081 }
4082
4083 #[test]
4084 fn test_remove_leaf_unsets_hash_along_path() {
4085 let mut trie = new_test_trie(
4100 [
4101 (
4102 Nibbles::default(),
4103 SparseNode::Branch {
4104 state_mask: TrieMask::new(0b0011),
4105 hash: Some(B256::repeat_byte(0x10)),
4106 store_in_db_trie: None,
4107 },
4108 ),
4109 (
4110 Nibbles::from_nibbles([0x0]),
4111 SparseNode::Extension {
4112 key: Nibbles::from_nibbles([0x1]),
4113 hash: Some(B256::repeat_byte(0x20)),
4114 store_in_db_trie: None,
4115 },
4116 ),
4117 (
4118 Nibbles::from_nibbles([0x0, 0x1]),
4119 SparseNode::Branch {
4120 state_mask: TrieMask::new(0b11100),
4121 hash: Some(B256::repeat_byte(0x30)),
4122 store_in_db_trie: None,
4123 },
4124 ),
4125 (
4126 Nibbles::from_nibbles([0x0, 0x1, 0x2]),
4127 SparseNode::Leaf {
4128 key: Nibbles::from_nibbles([0x3, 0x4]),
4129 hash: Some(B256::repeat_byte(0x40)),
4130 },
4131 ),
4132 (
4133 Nibbles::from_nibbles([0x0, 0x1, 0x3]),
4134 SparseNode::Leaf {
4135 key: Nibbles::from_nibbles([0x5, 0x6]),
4136 hash: Some(B256::repeat_byte(0x50)),
4137 },
4138 ),
4139 (
4140 Nibbles::from_nibbles([0x0, 0x1, 0x4]),
4141 SparseNode::Leaf {
4142 key: Nibbles::from_nibbles([0x6, 0x7]),
4143 hash: Some(B256::repeat_byte(0x60)),
4144 },
4145 ),
4146 (
4147 Nibbles::from_nibbles([0x1]),
4148 SparseNode::Leaf {
4149 key: Nibbles::from_nibbles([0x7, 0x8]),
4150 hash: Some(B256::repeat_byte(0x70)),
4151 },
4152 ),
4153 ]
4154 .into_iter(),
4155 );
4156
4157 let provider = MockTrieNodeProvider::new();
4158
4159 trie.remove_leaf(&Nibbles::from_nibbles([0x0, 0x1, 0x2, 0x3, 0x4, 0xF]), &provider)
4161 .unwrap();
4162 for (path, node) in trie.all_nodes() {
4163 assert!(node.hash().is_some(), "path {path:?} should still have a hash");
4164 }
4165
4166 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2, 0x3, 0x4]);
4168 trie.remove_leaf(&leaf_full_path, &provider).unwrap();
4169
4170 let upper_subtrie = &trie.upper_subtrie;
4171 let lower_subtrie_10 = trie.lower_subtries[0x01].as_revealed_ref().unwrap();
4172
4173 assert_matches!(
4175 upper_subtrie.nodes.get(&Nibbles::default()),
4176 Some(SparseNode::Branch { hash: None, .. })
4177 );
4178 assert_matches!(
4179 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x0])),
4180 Some(SparseNode::Extension { hash: None, .. })
4181 );
4182 assert_matches!(
4183 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1])),
4184 Some(SparseNode::Branch { hash: None, .. })
4185 );
4186
4187 assert_matches!(
4189 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])),
4190 Some(SparseNode::Leaf { hash: Some(_), .. })
4191 );
4192 assert_matches!(
4193 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1, 0x3])),
4194 Some(SparseNode::Leaf { hash: Some(_), .. })
4195 );
4196 assert_matches!(
4197 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1, 0x4])),
4198 Some(SparseNode::Leaf { hash: Some(_), .. })
4199 );
4200 }
4201
4202 #[test]
4203 fn test_remove_leaf_remaining_extension_node_child_is_revealed() {
4204 let branch_path = Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7]);
4205 let removed_branch_path = Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2]);
4206
4207 let nodes = vec![
4209 RevealedSparseNode {
4211 path: branch_path,
4212 node: {
4213 TrieNode::Branch(BranchNode::new(
4214 vec![
4215 RlpNode::word_rlp(&B256::from(hex!(
4216 "dede882d52f0e0eddfb5b89293a10c87468b4a73acd0d4ae550054a92353f6d5"
4217 ))),
4218 RlpNode::word_rlp(&B256::from(hex!(
4219 "8746f18e465e2eed16117306b6f2eef30bc9d2978aee4a7838255e39c41a3222"
4220 ))),
4221 RlpNode::word_rlp(&B256::from(hex!(
4222 "35a4ea861548af5f0262a9b6d619b4fc88fce6531cbd004eab1530a73f34bbb1"
4223 ))),
4224 RlpNode::word_rlp(&B256::from(hex!(
4225 "47d5c2bf9eea5c1ee027e4740c2b86159074a27d52fd2f6a8a8c86c77e48006f"
4226 ))),
4227 RlpNode::word_rlp(&B256::from(hex!(
4228 "eb76a359b216e1d86b1f2803692a9fe8c3d3f97a9fe6a82b396e30344febc0c1"
4229 ))),
4230 RlpNode::word_rlp(&B256::from(hex!(
4231 "437656f2697f167b23e33cb94acc8550128cfd647fc1579d61e982cb7616b8bc"
4232 ))),
4233 RlpNode::word_rlp(&B256::from(hex!(
4234 "45a1ac2faf15ea8a4da6f921475974e0379f39c3d08166242255a567fa88ce6c"
4235 ))),
4236 RlpNode::word_rlp(&B256::from(hex!(
4237 "7dbb299d714d3dfa593f53bc1b8c66d5c401c30a0b5587b01254a56330361395"
4238 ))),
4239 RlpNode::word_rlp(&B256::from(hex!(
4240 "ae407eb14a74ed951c9949c1867fb9ee9ba5d5b7e03769eaf3f29c687d080429"
4241 ))),
4242 RlpNode::word_rlp(&B256::from(hex!(
4243 "768d0fe1003f0e85d3bc76e4a1fa0827f63b10ca9bca52d56c2b1cceb8eb8b08"
4244 ))),
4245 RlpNode::word_rlp(&B256::from(hex!(
4246 "e5127935143493d5094f4da6e4f7f5a0f62d524fbb61e7bb9fb63d8a166db0f3"
4247 ))),
4248 RlpNode::word_rlp(&B256::from(hex!(
4249 "7f3698297308664fbc1b9e2c41d097fbd57d8f364c394f6ad7c71b10291fbf42"
4250 ))),
4251 RlpNode::word_rlp(&B256::from(hex!(
4252 "4a2bc7e19cec63cb5ef5754add0208959b50bcc79f13a22a370f77b277dbe6db"
4253 ))),
4254 RlpNode::word_rlp(&B256::from(hex!(
4255 "40764b8c48de59258e62a3371909a107e76e1b5e847cfa94dbc857e9fd205103"
4256 ))),
4257 RlpNode::word_rlp(&B256::from(hex!(
4258 "2985dca29a7616920d95c43ab62eb013a40e6a0c88c284471e4c3bd22f3b9b25"
4259 ))),
4260 RlpNode::word_rlp(&B256::from(hex!(
4261 "1b6511f7a385e79477239f7dd4a49f52082ecac05aa5bd0de18b1d55fe69d10c"
4262 ))),
4263 ],
4264 TrieMask::new(0b1111111111111111),
4265 ))
4266 },
4267 masks: TrieMasks {
4268 hash_mask: Some(TrieMask::new(0b1111111111111111)),
4269 tree_mask: Some(TrieMask::new(0b0011110100100101)),
4270 },
4271 },
4272 RevealedSparseNode {
4274 path: removed_branch_path,
4275 node: {
4276 let stack = vec![
4277 RlpNode::word_rlp(&B256::from(hex!(
4278 "15fd4993a41feff1af3b629b32572ab05acddd97c681d82ec2eb89c8a8e3ab9e"
4279 ))),
4280 RlpNode::word_rlp(&B256::from(hex!(
4281 "a272b0b94ced4e6ec7adb41719850cf4a167ad8711d0dda6a810d129258a0d94"
4282 ))),
4283 ];
4284 let branch_node = BranchNode::new(stack, TrieMask::new(0b0001000000000100));
4285 TrieNode::Branch(branch_node)
4286 },
4287 masks: TrieMasks {
4288 hash_mask: Some(TrieMask::new(0b0000000000000000)),
4289 tree_mask: Some(TrieMask::new(0b0000000000000100)),
4290 },
4291 },
4292 RevealedSparseNode {
4294 path: Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0x2]),
4295 node: {
4296 let extension_node = ExtensionNode::new(
4297 Nibbles::from_nibbles([0x6]),
4298 RlpNode::word_rlp(&B256::from(hex!(
4299 "56fab2b106a97eae9c7197f86d03bca292da6e0ac725b783082f7d950cc4e0fc"
4300 ))),
4301 );
4302 TrieNode::Extension(extension_node)
4303 },
4304 masks: TrieMasks { hash_mask: None, tree_mask: None },
4305 },
4306 RevealedSparseNode {
4308 path: Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0xc]),
4309 node: {
4310 let leaf_node = LeafNode::new(
4311 Nibbles::from_nibbles([
4312 0x0, 0x7, 0x7, 0xf, 0x8, 0x6, 0x6, 0x1, 0x3, 0x0, 0x8, 0x8, 0xd, 0xf,
4313 0xc, 0xa, 0xe, 0x6, 0x4, 0x8, 0xa, 0xb, 0xe, 0x8, 0x3, 0x1, 0xf, 0xa,
4314 0xd, 0xc, 0xa, 0x5, 0x5, 0xa, 0xd, 0x4, 0x3, 0xa, 0xb, 0x1, 0x6, 0x5,
4315 0xd, 0x1, 0x6, 0x8, 0x0, 0xd, 0xd, 0x5, 0x6, 0x7, 0xb, 0x5, 0xd, 0x6,
4316 ]),
4317 hex::decode("8468d3971d").unwrap(),
4318 );
4319 TrieNode::Leaf(leaf_node)
4320 },
4321 masks: TrieMasks { hash_mask: None, tree_mask: None },
4322 },
4323 ];
4324
4325 let mut trie = ParallelSparseTrie::from_root(
4327 TrieNode::Extension(ExtensionNode::new(
4328 Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7]),
4329 RlpNode::word_rlp(&B256::from(hex!(
4330 "56fab2b106a97eae9c7197f86d03bca292da6e0ac725b783082f7d950cc4e0fc"
4331 ))),
4332 )),
4333 TrieMasks::none(),
4334 true,
4335 )
4336 .unwrap();
4337
4338 trie.reveal_nodes(nodes).unwrap();
4340
4341 let leaf_key = Nibbles::from_nibbles([
4343 0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0xc, 0x0, 0x7, 0x7, 0xf, 0x8, 0x6, 0x6, 0x1, 0x3,
4344 0x0, 0x8, 0x8, 0xd, 0xf, 0xc, 0xa, 0xe, 0x6, 0x4, 0x8, 0xa, 0xb, 0xe, 0x8, 0x3, 0x1,
4345 0xf, 0xa, 0xd, 0xc, 0xa, 0x5, 0x5, 0xa, 0xd, 0x4, 0x3, 0xa, 0xb, 0x1, 0x6, 0x5, 0xd,
4346 0x1, 0x6, 0x8, 0x0, 0xd, 0xd, 0x5, 0x6, 0x7, 0xb, 0x5, 0xd, 0x6,
4347 ]);
4348
4349 let mut provider = MockTrieNodeProvider::new();
4350 let revealed_branch = create_branch_node_with_children(&[], []);
4351 let mut encoded = Vec::new();
4352 revealed_branch.encode(&mut encoded);
4353 provider.add_revealed_node(
4354 Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0x2, 0x6]),
4355 RevealedNode {
4356 node: encoded.into(),
4357 tree_mask: None,
4358 hash_mask: Some(TrieMask::new(0b1111)),
4360 },
4361 );
4362
4363 trie.remove_leaf(&leaf_key, provider).unwrap();
4364
4365 trie.root();
4367
4368 let updates = trie.take_updates();
4370 assert_eq!(
4371 updates.removed_nodes.into_iter().collect::<Vec<_>>(),
4372 vec![removed_branch_path]
4373 );
4374 assert_eq!(updates.updated_nodes.len(), 1);
4375 let updated_node = updates.updated_nodes.get(&branch_path).unwrap();
4376
4377 assert_eq!(updated_node.tree_mask, TrieMask::new(0b011110100100101),)
4379 }
4380
4381 #[test]
4382 fn test_parallel_sparse_trie_root() {
4383 let extension_path = Nibbles::new();
4386 let extension_key = Nibbles::from_nibbles([0x2]);
4387
4388 let branch_path = Nibbles::from_nibbles([0x2]);
4390
4391 let leaf_1_path = Nibbles::from_nibbles([0x2, 0x0]);
4393 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());
4395
4396 let leaf_2_path = Nibbles::from_nibbles([0x2, 0x1]);
4397 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());
4399
4400 let account_1 = create_account(1);
4402 let account_2 = create_account(2);
4403
4404 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), account_1.nonce);
4406 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), account_2.nonce);
4407
4408 let branch = create_branch_node_with_children(
4410 &[0, 1],
4411 vec![
4412 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_1)),
4413 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_2)),
4414 ],
4415 );
4416
4417 let extension = create_extension_node(
4419 extension_key.to_vec(),
4420 RlpNode::from_rlp(&alloy_rlp::encode(&branch)).as_hash().unwrap(),
4421 );
4422
4423 let mut trie = ParallelSparseTrie::from_root(extension, TrieMasks::none(), true).unwrap();
4425 trie.reveal_nodes(vec![
4426 RevealedSparseNode { path: branch_path, node: branch, masks: TrieMasks::none() },
4427 RevealedSparseNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
4428 RevealedSparseNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
4429 ])
4430 .unwrap();
4431
4432 trie.upper_subtrie.nodes.get_mut(&extension_path).unwrap().set_hash(None);
4435 trie.upper_subtrie.nodes.get_mut(&branch_path).unwrap().set_hash(None);
4436
4437 let leaf_1_subtrie_idx = path_subtrie_index_unchecked(&leaf_1_path);
4439 let leaf_2_subtrie_idx = path_subtrie_index_unchecked(&leaf_2_path);
4440
4441 trie.lower_subtries[leaf_1_subtrie_idx]
4442 .as_revealed_mut()
4443 .unwrap()
4444 .nodes
4445 .get_mut(&leaf_1_path)
4446 .unwrap()
4447 .set_hash(None);
4448 trie.lower_subtries[leaf_2_subtrie_idx]
4449 .as_revealed_mut()
4450 .unwrap()
4451 .nodes
4452 .get_mut(&leaf_2_path)
4453 .unwrap()
4454 .set_hash(None);
4455
4456 trie.prefix_set.insert(leaf_1_full_path);
4458 trie.prefix_set.insert(leaf_2_full_path);
4459
4460 let root = trie.root();
4462
4463 let (hash_builder_root, _, _proof_nodes, _, _) = run_hash_builder(
4465 [(leaf_1_full_path, account_1), (leaf_2_full_path, account_2)],
4466 NoopAccountTrieCursor::default(),
4467 Default::default(),
4468 [extension_path, branch_path, leaf_1_full_path, leaf_2_full_path],
4469 );
4470
4471 assert_eq!(root, hash_builder_root);
4473
4474 let leaf_1_subtrie = trie.lower_subtries[leaf_1_subtrie_idx].as_revealed_ref().unwrap();
4476 let leaf_2_subtrie = trie.lower_subtries[leaf_2_subtrie_idx].as_revealed_ref().unwrap();
4477 assert!(trie.upper_subtrie.nodes.get(&extension_path).unwrap().hash().is_some());
4478 assert!(trie.upper_subtrie.nodes.get(&branch_path).unwrap().hash().is_some());
4479 assert!(leaf_1_subtrie.nodes.get(&leaf_1_path).unwrap().hash().is_some());
4480 assert!(leaf_2_subtrie.nodes.get(&leaf_2_path).unwrap().hash().is_some());
4481 }
4482
4483 #[test]
4484 fn sparse_trie_empty_update_one() {
4485 let ctx = ParallelSparseTrieTestContext;
4486
4487 let key = Nibbles::unpack(B256::with_last_byte(42));
4488 let value = || Account::default();
4489 let value_encoded = || {
4490 let mut account_rlp = Vec::new();
4491 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4492 account_rlp
4493 };
4494
4495 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4496 run_hash_builder(
4497 [(key, value())],
4498 NoopAccountTrieCursor::default(),
4499 Default::default(),
4500 [key],
4501 );
4502
4503 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4504 ctx.update_leaves(&mut sparse, [(key, value_encoded())]);
4505 ctx.assert_with_hash_builder(
4506 &mut sparse,
4507 hash_builder_root,
4508 hash_builder_updates,
4509 hash_builder_proof_nodes,
4510 );
4511 }
4512
4513 #[test]
4514 fn sparse_trie_empty_update_multiple_lower_nibbles() {
4515 let ctx = ParallelSparseTrieTestContext;
4516
4517 let paths = (0..=16).map(|b| Nibbles::unpack(B256::with_last_byte(b))).collect::<Vec<_>>();
4518 let value = || Account::default();
4519 let value_encoded = || {
4520 let mut account_rlp = Vec::new();
4521 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4522 account_rlp
4523 };
4524
4525 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4526 run_hash_builder(
4527 paths.iter().copied().zip(std::iter::repeat_with(value)),
4528 NoopAccountTrieCursor::default(),
4529 Default::default(),
4530 paths.clone(),
4531 );
4532
4533 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4534 ctx.update_leaves(
4535 &mut sparse,
4536 paths.into_iter().zip(std::iter::repeat_with(value_encoded)),
4537 );
4538
4539 ctx.assert_with_hash_builder(
4540 &mut sparse,
4541 hash_builder_root,
4542 hash_builder_updates,
4543 hash_builder_proof_nodes,
4544 );
4545 }
4546
4547 #[test]
4548 fn sparse_trie_empty_update_multiple_upper_nibbles() {
4549 let paths = (239..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
4550 let value = || Account::default();
4551 let value_encoded = || {
4552 let mut account_rlp = Vec::new();
4553 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4554 account_rlp
4555 };
4556
4557 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4558 run_hash_builder(
4559 paths.iter().copied().zip(std::iter::repeat_with(value)),
4560 NoopAccountTrieCursor::default(),
4561 Default::default(),
4562 paths.clone(),
4563 );
4564
4565 let provider = DefaultTrieNodeProvider;
4566 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4567 for path in &paths {
4568 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
4569 }
4570 let sparse_root = sparse.root();
4571 let sparse_updates = sparse.take_updates();
4572
4573 assert_eq!(sparse_root, hash_builder_root);
4574 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
4575 assert_eq_parallel_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
4576 }
4577
4578 #[test]
4579 fn sparse_trie_empty_update_multiple() {
4580 let ctx = ParallelSparseTrieTestContext;
4581
4582 let paths = (0..=255)
4583 .map(|b| {
4584 Nibbles::unpack(if b % 2 == 0 {
4585 B256::repeat_byte(b)
4586 } else {
4587 B256::with_last_byte(b)
4588 })
4589 })
4590 .collect::<Vec<_>>();
4591 let value = || Account::default();
4592 let value_encoded = || {
4593 let mut account_rlp = Vec::new();
4594 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4595 account_rlp
4596 };
4597
4598 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4599 run_hash_builder(
4600 paths.iter().sorted_unstable().copied().zip(std::iter::repeat_with(value)),
4601 NoopAccountTrieCursor::default(),
4602 Default::default(),
4603 paths.clone(),
4604 );
4605
4606 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4607 ctx.update_leaves(
4608 &mut sparse,
4609 paths.iter().copied().zip(std::iter::repeat_with(value_encoded)),
4610 );
4611 ctx.assert_with_hash_builder(
4612 &mut sparse,
4613 hash_builder_root,
4614 hash_builder_updates,
4615 hash_builder_proof_nodes,
4616 );
4617 }
4618
4619 #[test]
4620 fn sparse_trie_empty_update_repeated() {
4621 let ctx = ParallelSparseTrieTestContext;
4622
4623 let paths = (0..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
4624 let old_value = Account { nonce: 1, ..Default::default() };
4625 let old_value_encoded = {
4626 let mut account_rlp = Vec::new();
4627 old_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4628 account_rlp
4629 };
4630 let new_value = Account { nonce: 2, ..Default::default() };
4631 let new_value_encoded = {
4632 let mut account_rlp = Vec::new();
4633 new_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4634 account_rlp
4635 };
4636
4637 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4638 run_hash_builder(
4639 paths.iter().copied().zip(std::iter::repeat_with(|| old_value)),
4640 NoopAccountTrieCursor::default(),
4641 Default::default(),
4642 paths.clone(),
4643 );
4644
4645 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4646 ctx.update_leaves(
4647 &mut sparse,
4648 paths.iter().copied().zip(std::iter::repeat(old_value_encoded)),
4649 );
4650 ctx.assert_with_hash_builder(
4651 &mut sparse,
4652 hash_builder_root,
4653 hash_builder_updates,
4654 hash_builder_proof_nodes,
4655 );
4656
4657 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4658 run_hash_builder(
4659 paths.iter().copied().zip(std::iter::repeat(new_value)),
4660 NoopAccountTrieCursor::default(),
4661 Default::default(),
4662 paths.clone(),
4663 );
4664
4665 ctx.update_leaves(
4666 &mut sparse,
4667 paths.iter().copied().zip(std::iter::repeat(new_value_encoded)),
4668 );
4669 ctx.assert_with_hash_builder(
4670 &mut sparse,
4671 hash_builder_root,
4672 hash_builder_updates,
4673 hash_builder_proof_nodes,
4674 );
4675 }
4676
4677 #[test]
4678 fn sparse_trie_remove_leaf() {
4679 let ctx = ParallelSparseTrieTestContext;
4680 let provider = DefaultTrieNodeProvider;
4681 let mut sparse = ParallelSparseTrie::default();
4682
4683 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
4684
4685 ctx.update_leaves(
4686 &mut sparse,
4687 [
4688 (Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone()),
4689 (Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone()),
4690 (Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone()),
4691 (Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone()),
4692 (Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone()),
4693 (Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value),
4694 ],
4695 );
4696
4697 pretty_assertions::assert_eq!(
4710 parallel_sparse_trie_nodes(&sparse)
4711 .into_iter()
4712 .map(|(k, v)| (*k, v.clone()))
4713 .collect::<BTreeMap<_, _>>(),
4714 BTreeMap::from_iter([
4715 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4716 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1101.into())),
4717 (
4718 Nibbles::from_nibbles([0x5, 0x0]),
4719 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
4720 ),
4721 (
4722 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
4723 SparseNode::new_branch(0b1010.into())
4724 ),
4725 (
4726 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
4727 SparseNode::new_leaf(Nibbles::default())
4728 ),
4729 (
4730 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
4731 SparseNode::new_leaf(Nibbles::default())
4732 ),
4733 (
4734 Nibbles::from_nibbles([0x5, 0x2]),
4735 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x1, 0x3]))
4736 ),
4737 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4738 (
4739 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4740 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4741 ),
4742 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4743 (
4744 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4745 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4746 ),
4747 (
4748 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4749 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4750 )
4751 ])
4752 );
4753
4754 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), &provider).unwrap();
4755
4756 pretty_assertions::assert_eq!(
4768 parallel_sparse_trie_nodes(&sparse)
4769 .into_iter()
4770 .map(|(k, v)| (*k, v.clone()))
4771 .collect::<BTreeMap<_, _>>(),
4772 BTreeMap::from_iter([
4773 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4774 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4775 (
4776 Nibbles::from_nibbles([0x5, 0x0]),
4777 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
4778 ),
4779 (
4780 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
4781 SparseNode::new_branch(0b1010.into())
4782 ),
4783 (
4784 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
4785 SparseNode::new_leaf(Nibbles::default())
4786 ),
4787 (
4788 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
4789 SparseNode::new_leaf(Nibbles::default())
4790 ),
4791 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4792 (
4793 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4794 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4795 ),
4796 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4797 (
4798 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4799 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4800 ),
4801 (
4802 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4803 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4804 )
4805 ])
4806 );
4807
4808 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), &provider).unwrap();
4809
4810 pretty_assertions::assert_eq!(
4819 parallel_sparse_trie_nodes(&sparse)
4820 .into_iter()
4821 .map(|(k, v)| (*k, v.clone()))
4822 .collect::<BTreeMap<_, _>>(),
4823 BTreeMap::from_iter([
4824 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4825 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4826 (
4827 Nibbles::from_nibbles([0x5, 0x0]),
4828 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4829 ),
4830 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4831 (
4832 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4833 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4834 ),
4835 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4836 (
4837 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4838 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4839 ),
4840 (
4841 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4842 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4843 )
4844 ])
4845 );
4846
4847 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), &provider).unwrap();
4848
4849 pretty_assertions::assert_eq!(
4856 parallel_sparse_trie_nodes(&sparse)
4857 .into_iter()
4858 .map(|(k, v)| (*k, v.clone()))
4859 .collect::<BTreeMap<_, _>>(),
4860 BTreeMap::from_iter([
4861 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4862 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4863 (
4864 Nibbles::from_nibbles([0x5, 0x0]),
4865 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4866 ),
4867 (
4868 Nibbles::from_nibbles([0x5, 0x3]),
4869 SparseNode::new_ext(Nibbles::from_nibbles([0x3]))
4870 ),
4871 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4872 (
4873 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4874 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4875 ),
4876 (
4877 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4878 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4879 )
4880 ])
4881 );
4882
4883 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), &provider).unwrap();
4884
4885 pretty_assertions::assert_eq!(
4890 parallel_sparse_trie_nodes(&sparse)
4891 .into_iter()
4892 .map(|(k, v)| (*k, v.clone()))
4893 .collect::<BTreeMap<_, _>>(),
4894 BTreeMap::from_iter([
4895 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4896 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4897 (
4898 Nibbles::from_nibbles([0x5, 0x0]),
4899 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4900 ),
4901 (
4902 Nibbles::from_nibbles([0x5, 0x3]),
4903 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x0, 0x2]))
4904 ),
4905 ])
4906 );
4907
4908 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), &provider).unwrap();
4909
4910 pretty_assertions::assert_eq!(
4912 parallel_sparse_trie_nodes(&sparse)
4913 .into_iter()
4914 .map(|(k, v)| (*k, v.clone()))
4915 .collect::<BTreeMap<_, _>>(),
4916 BTreeMap::from_iter([(
4917 Nibbles::default(),
4918 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]))
4919 ),])
4920 );
4921
4922 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), &provider).unwrap();
4923
4924 pretty_assertions::assert_eq!(
4926 parallel_sparse_trie_nodes(&sparse)
4927 .into_iter()
4928 .map(|(k, v)| (*k, v.clone()))
4929 .collect::<BTreeMap<_, _>>(),
4930 BTreeMap::from_iter([(Nibbles::default(), SparseNode::Empty)])
4931 );
4932 }
4933
4934 #[test]
4935 fn sparse_trie_remove_leaf_blinded() {
4936 let leaf = LeafNode::new(
4937 Nibbles::default(),
4938 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
4939 );
4940 let branch = TrieNode::Branch(BranchNode::new(
4941 vec![
4942 RlpNode::word_rlp(&B256::repeat_byte(1)),
4943 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
4944 ],
4945 TrieMask::new(0b11),
4946 ));
4947
4948 let provider = DefaultTrieNodeProvider;
4949 let mut sparse = ParallelSparseTrie::from_root(
4950 branch.clone(),
4951 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
4952 false,
4953 )
4954 .unwrap();
4955
4956 sparse
4962 .reveal_nodes(vec![
4963 RevealedSparseNode {
4964 path: Nibbles::default(),
4965 node: branch,
4966 masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
4967 },
4968 RevealedSparseNode {
4969 path: Nibbles::from_nibbles([0x1]),
4970 node: TrieNode::Leaf(leaf),
4971 masks: TrieMasks::none(),
4972 },
4973 ])
4974 .unwrap();
4975
4976 assert_matches!(
4978 sparse.remove_leaf(&Nibbles::from_nibbles([0x0]), &provider).map_err(|e| e.into_kind()),
4979 Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
4980 );
4981 }
4982
4983 #[test]
4984 fn sparse_trie_remove_leaf_non_existent() {
4985 let leaf = LeafNode::new(
4986 Nibbles::default(),
4987 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
4988 );
4989 let branch = TrieNode::Branch(BranchNode::new(
4990 vec![
4991 RlpNode::word_rlp(&B256::repeat_byte(1)),
4992 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
4993 ],
4994 TrieMask::new(0b11),
4995 ));
4996
4997 let provider = DefaultTrieNodeProvider;
4998 let mut sparse = ParallelSparseTrie::from_root(
4999 branch.clone(),
5000 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
5001 false,
5002 )
5003 .unwrap();
5004
5005 sparse
5011 .reveal_nodes(vec![
5012 RevealedSparseNode {
5013 path: Nibbles::default(),
5014 node: branch,
5015 masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
5016 },
5017 RevealedSparseNode {
5018 path: Nibbles::from_nibbles([0x1]),
5019 node: TrieNode::Leaf(leaf),
5020 masks: TrieMasks::none(),
5021 },
5022 ])
5023 .unwrap();
5024
5025 let sparse_old = sparse.clone();
5027 assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2]), &provider), Ok(()));
5028 assert_eq!(sparse, sparse_old);
5029 }
5030
5031 #[test]
5032 fn sparse_trie_fuzz() {
5033 const KEY_NIBBLES_LEN: usize = 3;
5037
5038 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
5039 {
5040 let mut state = BTreeMap::default();
5041 let default_provider = DefaultTrieNodeProvider;
5042 let provider_factory = create_test_provider_factory();
5043 let mut sparse = ParallelSparseTrie::default().with_updates(true);
5044
5045 for (update, keys_to_delete) in updates {
5046 for (key, account) in update.clone() {
5048 let account = account.into_trie_account(EMPTY_ROOT_HASH);
5049 let mut account_rlp = Vec::new();
5050 account.encode(&mut account_rlp);
5051 sparse.update_leaf(key, account_rlp, &default_provider).unwrap();
5052 }
5053 let mut updated_sparse = sparse.clone();
5057 let sparse_root = updated_sparse.root();
5058 let sparse_updates = updated_sparse.take_updates();
5059
5060 state.extend(update);
5062 let provider = provider_factory.provider().unwrap();
5063 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
5064 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
5065 run_hash_builder(
5066 state.clone(),
5067 trie_cursor.account_trie_cursor().unwrap(),
5068 Default::default(),
5069 state.keys().copied(),
5070 );
5071
5072 let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
5074
5075 let provider_rw = provider_factory.provider_rw().unwrap();
5077 provider_rw.write_trie_updates(hash_builder_updates).unwrap();
5078 provider_rw.commit().unwrap();
5079
5080 assert_eq!(sparse_root, hash_builder_root);
5082 pretty_assertions::assert_eq!(
5084 BTreeMap::from_iter(sparse_updates.updated_nodes),
5085 BTreeMap::from_iter(hash_builder_account_nodes)
5086 );
5087 assert_eq_parallel_sparse_trie_proof_nodes(
5089 &updated_sparse,
5090 hash_builder_proof_nodes,
5091 );
5092
5093 for key in &keys_to_delete {
5096 state.remove(key).unwrap();
5097 sparse.remove_leaf(key, &default_provider).unwrap();
5098 }
5099
5100 let mut updated_sparse = sparse.clone();
5104 let sparse_root = updated_sparse.root();
5105 let sparse_updates = updated_sparse.take_updates();
5106
5107 let provider = provider_factory.provider().unwrap();
5108 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
5109 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
5110 run_hash_builder(
5111 state.clone(),
5112 trie_cursor.account_trie_cursor().unwrap(),
5113 keys_to_delete
5114 .iter()
5115 .map(|nibbles| B256::from_slice(&nibbles.pack()))
5116 .collect(),
5117 state.keys().copied(),
5118 );
5119
5120 let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
5122
5123 let provider_rw = provider_factory.provider_rw().unwrap();
5125 provider_rw.write_trie_updates(hash_builder_updates).unwrap();
5126 provider_rw.commit().unwrap();
5127
5128 assert_eq!(sparse_root, hash_builder_root);
5130 pretty_assertions::assert_eq!(
5132 BTreeMap::from_iter(sparse_updates.updated_nodes),
5133 BTreeMap::from_iter(hash_builder_account_nodes)
5134 );
5135 assert_eq_parallel_sparse_trie_proof_nodes(
5137 &updated_sparse,
5138 hash_builder_proof_nodes,
5139 );
5140 }
5141 }
5142 }
5143
5144 fn transform_updates(
5145 updates: Vec<BTreeMap<Nibbles, Account>>,
5146 mut rng: impl rand::Rng,
5147 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
5148 let mut keys = BTreeSet::new();
5149 updates
5150 .into_iter()
5151 .map(|update| {
5152 keys.extend(update.keys().copied());
5153
5154 let keys_to_delete_len = update.len() / 2;
5155 let keys_to_delete = (0..keys_to_delete_len)
5156 .map(|_| {
5157 let key =
5158 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
5159 keys.take(&key).unwrap()
5160 })
5161 .collect();
5162
5163 (update, keys_to_delete)
5164 })
5165 .collect::<Vec<_>>()
5166 }
5167
5168 proptest!(ProptestConfig::with_cases(10), |(
5169 updates in proptest::collection::vec(
5170 proptest::collection::btree_map(
5171 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
5172 arb::<Account>(),
5173 1..50,
5174 ),
5175 1..50,
5176 ).prop_perturb(transform_updates)
5177 )| {
5178 test(updates)
5179 });
5180 }
5181
5182 #[test]
5183 fn sparse_trie_fuzz_vs_serial() {
5184 const KEY_NIBBLES_LEN: usize = 3;
5188
5189 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
5190 let default_provider = DefaultTrieNodeProvider;
5191 let mut serial = SerialSparseTrie::default().with_updates(true);
5192 let mut parallel = ParallelSparseTrie::default().with_updates(true);
5193
5194 for (update, keys_to_delete) in updates {
5195 for (key, account) in update.clone() {
5197 let account = account.into_trie_account(EMPTY_ROOT_HASH);
5198 let mut account_rlp = Vec::new();
5199 account.encode(&mut account_rlp);
5200 serial.update_leaf(key, account_rlp.clone(), &default_provider).unwrap();
5201 parallel.update_leaf(key, account_rlp, &default_provider).unwrap();
5202 }
5203
5204 let serial_root = serial.root();
5206 let parallel_root = parallel.root();
5207 assert_eq!(parallel_root, serial_root);
5208
5209 let serial_updates = serial.take_updates();
5211 let parallel_updates = parallel.take_updates();
5212 pretty_assertions::assert_eq!(
5213 BTreeMap::from_iter(parallel_updates.updated_nodes),
5214 BTreeMap::from_iter(serial_updates.updated_nodes),
5215 );
5216 pretty_assertions::assert_eq!(
5217 BTreeSet::from_iter(parallel_updates.removed_nodes),
5218 BTreeSet::from_iter(serial_updates.removed_nodes),
5219 );
5220
5221 for key in &keys_to_delete {
5223 parallel.remove_leaf(key, &default_provider).unwrap();
5224 serial.remove_leaf(key, &default_provider).unwrap();
5225 }
5226
5227 let serial_root = serial.root();
5229 let parallel_root = parallel.root();
5230 assert_eq!(parallel_root, serial_root);
5231
5232 let serial_updates = serial.take_updates();
5234 let parallel_updates = parallel.take_updates();
5235 pretty_assertions::assert_eq!(
5236 BTreeMap::from_iter(parallel_updates.updated_nodes),
5237 BTreeMap::from_iter(serial_updates.updated_nodes),
5238 );
5239 pretty_assertions::assert_eq!(
5240 BTreeSet::from_iter(parallel_updates.removed_nodes),
5241 BTreeSet::from_iter(serial_updates.removed_nodes),
5242 );
5243 }
5244 }
5245
5246 fn transform_updates(
5247 updates: Vec<BTreeMap<Nibbles, Account>>,
5248 mut rng: impl rand::Rng,
5249 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
5250 let mut keys = BTreeSet::new();
5251 updates
5252 .into_iter()
5253 .map(|update| {
5254 keys.extend(update.keys().copied());
5255
5256 let keys_to_delete_len = update.len() / 2;
5257 let keys_to_delete = (0..keys_to_delete_len)
5258 .map(|_| {
5259 let key =
5260 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
5261 keys.take(&key).unwrap()
5262 })
5263 .collect();
5264
5265 (update, keys_to_delete)
5266 })
5267 .collect::<Vec<_>>()
5268 }
5269
5270 proptest!(ProptestConfig::with_cases(10), |(
5271 updates in proptest::collection::vec(
5272 proptest::collection::btree_map(
5273 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
5274 arb::<Account>(),
5275 1..50,
5276 ),
5277 1..50,
5278 ).prop_perturb(transform_updates)
5279 )| {
5280 test(updates)
5281 });
5282 }
5283
5284 #[test]
5285 fn sparse_trie_two_leaves_at_lower_roots() {
5286 let provider = DefaultTrieNodeProvider;
5287 let mut trie = ParallelSparseTrie::default().with_updates(true);
5288 let key_50 = Nibbles::unpack(hex!(
5289 "0x5000000000000000000000000000000000000000000000000000000000000000"
5290 ));
5291 let key_51 = Nibbles::unpack(hex!(
5292 "0x5100000000000000000000000000000000000000000000000000000000000000"
5293 ));
5294
5295 let account = Account::default().into_trie_account(EMPTY_ROOT_HASH);
5296 let mut account_rlp = Vec::new();
5297 account.encode(&mut account_rlp);
5298
5299 trie.update_leaf(key_50, account_rlp.clone(), &provider).unwrap();
5301 trie.root();
5302
5303 trie.update_leaf(key_51, account_rlp.clone(), &provider).unwrap();
5305
5306 let expected_root =
5307 hex!("0xdaf0ef9f91a2f179bb74501209effdb5301db1697bcab041eca2234b126e25de");
5308 let root = trie.root();
5309 assert_eq!(root, expected_root);
5310 assert_eq!(SparseTrieUpdates::default(), trie.take_updates());
5311 }
5312
5313 #[test]
5325 fn sparse_trie_reveal_node_1() {
5326 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00]));
5327 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01]));
5328 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x02]));
5329 let value = || Account::default();
5330 let value_encoded = || {
5331 let mut account_rlp = Vec::new();
5332 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
5333 account_rlp
5334 };
5335
5336 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5338 run_hash_builder(
5339 [(key1(), value()), (key3(), value())],
5340 NoopAccountTrieCursor::default(),
5341 Default::default(),
5342 [Nibbles::default()],
5343 );
5344
5345 let provider = DefaultTrieNodeProvider;
5346 let mut sparse = ParallelSparseTrie::from_root(
5347 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5348 TrieMasks {
5349 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5350 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5351 },
5352 false,
5353 )
5354 .unwrap();
5355
5356 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5358 run_hash_builder(
5359 [(key1(), value()), (key3(), value())],
5360 NoopAccountTrieCursor::default(),
5361 Default::default(),
5362 [key1()],
5363 );
5364 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5365 .nodes_sorted()
5366 .into_iter()
5367 .map(|(path, node)| {
5368 let hash_mask = branch_node_hash_masks.get(&path).copied();
5369 let tree_mask = branch_node_tree_masks.get(&path).copied();
5370 RevealedSparseNode {
5371 path,
5372 node: TrieNode::decode(&mut &node[..]).unwrap(),
5373 masks: TrieMasks { hash_mask, tree_mask },
5374 }
5375 })
5376 .collect();
5377 sparse.reveal_nodes(revealed_nodes).unwrap();
5378
5379 assert_eq!(
5381 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5382 Some(&SparseNode::new_branch(0b101.into()))
5383 );
5384
5385 sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
5387
5388 assert_eq!(
5390 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5391 Some(&SparseNode::new_branch(0b111.into()))
5392 );
5393
5394 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5396 run_hash_builder(
5397 [(key1(), value()), (key3(), value())],
5398 NoopAccountTrieCursor::default(),
5399 Default::default(),
5400 [key3()],
5401 );
5402 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5403 .nodes_sorted()
5404 .into_iter()
5405 .map(|(path, node)| {
5406 let hash_mask = branch_node_hash_masks.get(&path).copied();
5407 let tree_mask = branch_node_tree_masks.get(&path).copied();
5408 RevealedSparseNode {
5409 path,
5410 node: TrieNode::decode(&mut &node[..]).unwrap(),
5411 masks: TrieMasks { hash_mask, tree_mask },
5412 }
5413 })
5414 .collect();
5415 sparse.reveal_nodes(revealed_nodes).unwrap();
5416
5417 assert_eq!(
5419 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5420 Some(&SparseNode::new_branch(0b111.into()))
5421 );
5422
5423 let (_, _, hash_builder_proof_nodes, _, _) = run_hash_builder(
5426 [(key1(), value()), (key2(), value()), (key3(), value())],
5427 NoopAccountTrieCursor::default(),
5428 Default::default(),
5429 [key1(), key2(), key3()],
5430 );
5431
5432 assert_eq_parallel_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
5433 }
5434
5435 #[test]
5446 fn sparse_trie_reveal_node_2() {
5447 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x00]));
5448 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x01]));
5449 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x02]));
5450 let value = || Account::default();
5451
5452 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5454 run_hash_builder(
5455 [(key1(), value()), (key2(), value()), (key3(), value())],
5456 NoopAccountTrieCursor::default(),
5457 Default::default(),
5458 [Nibbles::default()],
5459 );
5460
5461 let provider = DefaultTrieNodeProvider;
5462 let mut sparse = ParallelSparseTrie::from_root(
5463 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5464 TrieMasks {
5465 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5466 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5467 },
5468 false,
5469 )
5470 .unwrap();
5471
5472 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5475 run_hash_builder(
5476 [(key1(), value()), (key2(), value()), (key3(), value())],
5477 NoopAccountTrieCursor::default(),
5478 Default::default(),
5479 [key1(), Nibbles::from_nibbles_unchecked([0x01])],
5480 );
5481 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5482 .nodes_sorted()
5483 .into_iter()
5484 .map(|(path, node)| {
5485 let hash_mask = branch_node_hash_masks.get(&path).copied();
5486 let tree_mask = branch_node_tree_masks.get(&path).copied();
5487 RevealedSparseNode {
5488 path,
5489 node: TrieNode::decode(&mut &node[..]).unwrap(),
5490 masks: TrieMasks { hash_mask, tree_mask },
5491 }
5492 })
5493 .collect();
5494 sparse.reveal_nodes(revealed_nodes).unwrap();
5495
5496 assert_eq!(
5498 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5499 Some(&SparseNode::new_branch(0b11.into()))
5500 );
5501
5502 sparse.remove_leaf(&key1(), &provider).unwrap();
5504
5505 assert_eq!(
5507 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5508 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
5509 );
5510
5511 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5513 run_hash_builder(
5514 [(key1(), value()), (key2(), value()), (key3(), value())],
5515 NoopAccountTrieCursor::default(),
5516 Default::default(),
5517 [key2()],
5518 );
5519 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5520 .nodes_sorted()
5521 .into_iter()
5522 .map(|(path, node)| {
5523 let hash_mask = branch_node_hash_masks.get(&path).copied();
5524 let tree_mask = branch_node_tree_masks.get(&path).copied();
5525 RevealedSparseNode {
5526 path,
5527 node: TrieNode::decode(&mut &node[..]).unwrap(),
5528 masks: TrieMasks { hash_mask, tree_mask },
5529 }
5530 })
5531 .collect();
5532 sparse.reveal_nodes(revealed_nodes).unwrap();
5533
5534 assert_eq!(
5536 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5537 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
5538 );
5539 }
5540
5541 #[test]
5550 fn sparse_trie_reveal_node_3() {
5551 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x01]));
5552 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x02]));
5553 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x00]));
5554 let value = || Account::default();
5555 let value_encoded = || {
5556 let mut account_rlp = Vec::new();
5557 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
5558 account_rlp
5559 };
5560
5561 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5563 run_hash_builder(
5564 [(key1(), value()), (key2(), value())],
5565 NoopAccountTrieCursor::default(),
5566 Default::default(),
5567 [Nibbles::default()],
5568 );
5569
5570 let provider = DefaultTrieNodeProvider;
5571 let mut sparse = ParallelSparseTrie::from_root(
5572 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5573 TrieMasks {
5574 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5575 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5576 },
5577 false,
5578 )
5579 .unwrap();
5580
5581 assert_matches!(
5583 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5584 Some(SparseNode::Extension { key, hash: None, store_in_db_trie: None }) if *key == Nibbles::from_nibbles([0x00])
5585 );
5586
5587 sparse.update_leaf(key3(), value_encoded(), &provider).unwrap();
5589
5590 assert_matches!(
5592 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5593 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
5594 );
5595
5596 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5598 run_hash_builder(
5599 [(key1(), value()), (key2(), value())],
5600 NoopAccountTrieCursor::default(),
5601 Default::default(),
5602 [key1()],
5603 );
5604 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5605 .nodes_sorted()
5606 .into_iter()
5607 .map(|(path, node)| {
5608 let hash_mask = branch_node_hash_masks.get(&path).copied();
5609 let tree_mask = branch_node_tree_masks.get(&path).copied();
5610 RevealedSparseNode {
5611 path,
5612 node: TrieNode::decode(&mut &node[..]).unwrap(),
5613 masks: TrieMasks { hash_mask, tree_mask },
5614 }
5615 })
5616 .collect();
5617 sparse.reveal_nodes(revealed_nodes).unwrap();
5618
5619 assert_matches!(
5621 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5622 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
5623 );
5624 }
5625
5626 #[test]
5627 fn test_update_leaf_cross_level() {
5628 let ctx = ParallelSparseTrieTestContext;
5629 let mut trie =
5630 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5631
5632 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x3, 0x4, 0x5], 1);
5654 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
5655
5656 ctx.assert_upper_subtrie(&trie)
5658 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x3, 0x4, 0x5]))
5659 .has_value(&leaf1_path, &value1);
5660
5661 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 2);
5663 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
5664
5665 ctx.assert_upper_subtrie(&trie)
5667 .has_branch(&Nibbles::from_nibbles([0x1]), &[0x2, 0x3])
5668 .has_no_value(&leaf1_path)
5669 .has_no_value(&leaf2_path);
5670
5671 let (leaf3_path, value3) = ctx.create_test_leaf([0x1, 0x2, 0x4, 0x5], 3);
5673 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
5674
5675 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5677 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5678 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5679 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::from_nibbles([0x5]))
5680 .has_value(&leaf2_path, &value2)
5681 .has_value(&leaf3_path, &value3);
5682
5683 let (leaf4_path, value4) = ctx.create_test_leaf([0x1, 0x3, 0x3, 0x4], 4);
5685 trie.update_leaf(leaf4_path, value4.clone(), DefaultTrieNodeProvider).unwrap();
5686
5687 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x3]))
5689 .has_value(&leaf1_path, &value1)
5690 .has_value(&leaf4_path, &value4);
5691
5692 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5694 .has_value(&leaf2_path, &value2)
5695 .has_value(&leaf3_path, &value3);
5696
5697 ctx.assert_upper_subtrie(&trie)
5699 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1]))
5700 .has_branch(&Nibbles::from_nibbles([0x1]), &[0x2, 0x3])
5701 .has_no_value(&leaf1_path)
5702 .has_no_value(&leaf2_path)
5703 .has_no_value(&leaf3_path)
5704 .has_no_value(&leaf4_path);
5705 }
5706
5707 #[test]
5708 fn test_update_leaf_split_at_level_boundary() {
5709 let ctx = ParallelSparseTrieTestContext;
5710 let mut trie =
5711 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5712
5713 let (first_leaf_path, first_value) = ctx.create_test_leaf([0x1, 0x2, 0x2, 0x4], 1);
5728
5729 trie.update_leaf(first_leaf_path, first_value.clone(), DefaultTrieNodeProvider).unwrap();
5730
5731 ctx.assert_upper_subtrie(&trie)
5733 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x2, 0x4]))
5734 .has_value(&first_leaf_path, &first_value);
5735
5736 let (second_leaf_path, second_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 2);
5738
5739 trie.update_leaf(second_leaf_path, second_value.clone(), DefaultTrieNodeProvider).unwrap();
5740
5741 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5743 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x2, 0x3])
5744 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x2]), &Nibbles::from_nibbles([0x4]))
5745 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5746 .has_value(&first_leaf_path, &first_value)
5747 .has_value(&second_leaf_path, &second_value);
5748
5749 ctx.assert_upper_subtrie(&trie)
5751 .has_no_value(&first_leaf_path)
5752 .has_no_value(&second_leaf_path);
5753 }
5754
5755 #[test]
5756 fn test_update_subtrie_with_multiple_leaves() {
5757 let ctx = ParallelSparseTrieTestContext;
5758 let mut trie =
5759 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5760
5761 let leaves = ctx.create_test_leaves(&[
5775 &[0x1, 0x2, 0x3, 0x4],
5776 &[0x1, 0x2, 0x3, 0x5],
5777 &[0x1, 0x2, 0x4, 0x6],
5778 &[0x1, 0x2, 0x4, 0x7],
5779 ]);
5780
5781 ctx.update_leaves(&mut trie, leaves.clone());
5783
5784 ctx.assert_upper_subtrie(&trie)
5786 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
5787
5788 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5790 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5791 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
5792 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &[0x6, 0x7])
5793 .has_value(&leaves[0].0, &leaves[0].1)
5794 .has_value(&leaves[1].0, &leaves[1].1)
5795 .has_value(&leaves[2].0, &leaves[2].1)
5796 .has_value(&leaves[3].0, &leaves[3].1);
5797
5798 let updated_path = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]);
5800 let (_, updated_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 100);
5801
5802 trie.update_leaf(updated_path, updated_value.clone(), DefaultTrieNodeProvider).unwrap();
5803
5804 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5807 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5808 .has_value(&updated_path, &updated_value)
5809 .has_value(&leaves[1].0, &leaves[1].1)
5810 .has_value(&leaves[2].0, &leaves[2].1)
5811 .has_value(&leaves[3].0, &leaves[3].1);
5812
5813 let (new_leaf_path, new_leaf_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x6], 200);
5815
5816 trie.update_leaf(new_leaf_path, new_leaf_value.clone(), DefaultTrieNodeProvider).unwrap();
5817
5818 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5820 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5, 0x6])
5821 .has_value(&new_leaf_path, &new_leaf_value);
5822 }
5823
5824 #[test]
5825 fn test_update_subtrie_extension_node_subtrie() {
5826 let ctx = ParallelSparseTrieTestContext;
5827 let mut trie =
5828 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5829
5830 let leaves = ctx.create_test_leaves(&[&[0x1, 0x2, 0x3, 0x4], &[0x1, 0x2, 0x3, 0x5]]);
5839
5840 ctx.update_leaves(&mut trie, leaves.clone());
5842
5843 ctx.assert_upper_subtrie(&trie)
5845 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
5846
5847 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5849 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
5850 .has_value(&leaves[0].0, &leaves[0].1)
5851 .has_value(&leaves[1].0, &leaves[1].1);
5852 }
5853
5854 #[test]
5855 fn update_subtrie_extension_node_cross_level() {
5856 let ctx = ParallelSparseTrieTestContext;
5857 let mut trie =
5858 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5859
5860 let leaves = ctx.create_test_leaves(&[&[0x1, 0x2, 0x3, 0x4], &[0x1, 0x2, 0x4, 0x5]]);
5870
5871 ctx.update_leaves(&mut trie, leaves.clone());
5873
5874 ctx.assert_upper_subtrie(&trie)
5876 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
5877
5878 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5880 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5881 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5882 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::from_nibbles([0x5]))
5883 .has_value(&leaves[0].0, &leaves[0].1)
5884 .has_value(&leaves[1].0, &leaves[1].1);
5885 }
5886
5887 #[test]
5888 fn test_update_single_nibble_paths() {
5889 let ctx = ParallelSparseTrieTestContext;
5890 let mut trie =
5891 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5892
5893 let (leaf1_path, value1) = ctx.create_test_leaf([0x0], 1);
5905 let (leaf2_path, value2) = ctx.create_test_leaf([0x1], 2);
5906 let (leaf3_path, value3) = ctx.create_test_leaf([0x2], 3);
5907 let (leaf4_path, value4) = ctx.create_test_leaf([0x3], 4);
5908
5909 ctx.update_leaves(
5910 &mut trie,
5911 [
5912 (leaf1_path, value1.clone()),
5913 (leaf2_path, value2.clone()),
5914 (leaf3_path, value3.clone()),
5915 (leaf4_path, value4.clone()),
5916 ],
5917 );
5918
5919 ctx.assert_upper_subtrie(&trie)
5921 .has_branch(&Nibbles::default(), &[0x0, 0x1, 0x2, 0x3])
5922 .has_leaf(&Nibbles::from_nibbles([0x0]), &Nibbles::default())
5923 .has_leaf(&Nibbles::from_nibbles([0x1]), &Nibbles::default())
5924 .has_leaf(&Nibbles::from_nibbles([0x2]), &Nibbles::default())
5925 .has_leaf(&Nibbles::from_nibbles([0x3]), &Nibbles::default())
5926 .has_value(&leaf1_path, &value1)
5927 .has_value(&leaf2_path, &value2)
5928 .has_value(&leaf3_path, &value3)
5929 .has_value(&leaf4_path, &value4);
5930 }
5931
5932 #[test]
5933 fn test_update_deep_extension_chain() {
5934 let ctx = ParallelSparseTrieTestContext;
5935 let mut trie =
5936 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5937
5938 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0], 1);
5952 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1], 2);
5953
5954 ctx.update_leaves(&mut trie, [(leaf1_path, value1.clone()), (leaf2_path, value2.clone())]);
5955
5956 ctx.assert_upper_subtrie(&trie).has_extension(
5958 &Nibbles::default(),
5959 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1]),
5960 );
5961
5962 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x1]))
5964 .has_branch(&Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1]), &[0x0, 0x1])
5965 .has_leaf(
5966 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0]),
5967 &Nibbles::default(),
5968 )
5969 .has_leaf(
5970 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1]),
5971 &Nibbles::default(),
5972 )
5973 .has_value(&leaf1_path, &value1)
5974 .has_value(&leaf2_path, &value2);
5975 }
5976
5977 #[test]
5978 fn test_update_branch_with_all_nibbles() {
5979 let ctx = ParallelSparseTrieTestContext;
5980 let mut trie =
5981 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5982
5983 let mut leaves = Vec::new();
6000 for nibble in 0x0..=0xF {
6001 let (path, value) = ctx.create_test_leaf([0xA, 0x0, nibble], nibble as u64 + 1);
6002 leaves.push((path, value));
6003 }
6004
6005 ctx.update_leaves(&mut trie, leaves.iter().cloned());
6007
6008 ctx.assert_upper_subtrie(&trie)
6010 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA, 0x0]));
6011
6012 let mut subtrie_assert =
6014 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0x0])).has_branch(
6015 &Nibbles::from_nibbles([0xA, 0x0]),
6016 &[0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
6017 );
6018
6019 for (i, (path, value)) in leaves.iter().enumerate() {
6021 subtrie_assert = subtrie_assert
6022 .has_leaf(&Nibbles::from_nibbles([0xA, 0x0, i as u8]), &Nibbles::default())
6023 .has_value(path, value);
6024 }
6025 }
6026
6027 #[test]
6028 fn test_update_creates_multiple_subtries() {
6029 let ctx = ParallelSparseTrieTestContext;
6030 let mut trie =
6031 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6032
6033 let leaves = [
6049 ctx.create_test_leaf([0x0, 0x0, 0x1, 0x2], 1),
6050 ctx.create_test_leaf([0x0, 0x1, 0x3, 0x4], 2),
6051 ctx.create_test_leaf([0x0, 0x2, 0x5, 0x6], 3),
6052 ctx.create_test_leaf([0x0, 0x3, 0x7, 0x8], 4),
6053 ];
6054
6055 ctx.update_leaves(&mut trie, leaves.iter().cloned());
6057
6058 ctx.assert_upper_subtrie(&trie)
6060 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x0]))
6061 .has_branch(&Nibbles::from_nibbles([0x0]), &[0x0, 0x1, 0x2, 0x3]);
6062
6063 for (i, (leaf_path, leaf_value)) in leaves.iter().enumerate() {
6065 let subtrie_path = Nibbles::from_nibbles([0x0, i as u8]);
6066 ctx.assert_subtrie(&trie, subtrie_path)
6067 .has_leaf(
6068 &subtrie_path,
6069 &Nibbles::from_nibbles(match i {
6070 0 => vec![0x1, 0x2],
6071 1 => vec![0x3, 0x4],
6072 2 => vec![0x5, 0x6],
6073 3 => vec![0x7, 0x8],
6074 _ => unreachable!(),
6075 }),
6076 )
6077 .has_value(leaf_path, leaf_value);
6078 }
6079 }
6080
6081 #[test]
6082 fn test_update_extension_to_branch_transformation() {
6083 let ctx = ParallelSparseTrieTestContext;
6084 let mut trie =
6085 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6086
6087 let (leaf1_path, value1) = ctx.create_test_leaf([0xF, 0xF, 0x0, 0x1], 1);
6103 let (leaf2_path, value2) = ctx.create_test_leaf([0xF, 0xF, 0x0, 0x2], 2);
6104 let (leaf3_path, value3) = ctx.create_test_leaf([0xF, 0x0, 0x0, 0x3], 3);
6105
6106 ctx.update_leaves(&mut trie, [(leaf1_path, value1.clone()), (leaf2_path, value2.clone())]);
6107
6108 ctx.assert_upper_subtrie(&trie)
6110 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xF, 0xF, 0x0]));
6111
6112 ctx.update_leaves(&mut trie, [(leaf3_path, value3.clone())]);
6114
6115 ctx.assert_upper_subtrie(&trie)
6117 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xF]))
6118 .has_branch(&Nibbles::from_nibbles([0xF]), &[0x0, 0xF]);
6119
6120 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0xF]))
6122 .has_branch(&Nibbles::from_nibbles([0xF, 0xF, 0x0]), &[0x1, 0x2])
6123 .has_leaf(&Nibbles::from_nibbles([0xF, 0xF, 0x0, 0x1]), &Nibbles::default())
6124 .has_leaf(&Nibbles::from_nibbles([0xF, 0xF, 0x0, 0x2]), &Nibbles::default())
6125 .has_value(&leaf1_path, &value1)
6126 .has_value(&leaf2_path, &value2);
6127
6128 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0x0]))
6129 .has_leaf(&Nibbles::from_nibbles([0xF, 0x0]), &Nibbles::from_nibbles([0x0, 0x3]))
6130 .has_value(&leaf3_path, &value3);
6131 }
6132
6133 #[test]
6134 fn test_update_upper_extension_reveal_lower_hash_node() {
6135 let ctx = ParallelSparseTrieTestContext;
6136
6137 let mut provider = MockTrieNodeProvider::new();
6160
6161 let child_hashes = [
6163 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
6164 RlpNode::word_rlp(&B256::repeat_byte(0x22)),
6165 ];
6166 let revealed_branch = create_branch_node_with_children(&[0x1, 0x2], child_hashes);
6167 let mut encoded = Vec::new();
6168 revealed_branch.encode(&mut encoded);
6169 provider.add_revealed_node(
6170 Nibbles::from_nibbles([0xA, 0xB]),
6171 RevealedNode { node: encoded.into(), tree_mask: None, hash_mask: None },
6172 );
6173
6174 let mut trie = new_test_trie(
6175 [
6176 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0xA, 0xB]))),
6177 (Nibbles::from_nibbles([0xA, 0xB]), SparseNode::Hash(B256::repeat_byte(0x42))),
6178 ]
6179 .into_iter(),
6180 );
6181
6182 let (leaf_path, value) = ctx.create_test_leaf([0xA, 0x0], 1);
6184 trie.update_leaf(leaf_path, value, provider).unwrap();
6185
6186 ctx.assert_upper_subtrie(&trie)
6188 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA]))
6189 .has_branch(&Nibbles::from_nibbles([0xA]), &[0x0, 0xB]);
6190
6191 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0xB]))
6193 .has_branch(&Nibbles::from_nibbles([0xA, 0xB]), &[0x1, 0x2])
6194 .has_hash(&Nibbles::from_nibbles([0xA, 0xB, 0x1]), &B256::repeat_byte(0x11))
6195 .has_hash(&Nibbles::from_nibbles([0xA, 0xB, 0x2]), &B256::repeat_byte(0x22));
6196 }
6197
6198 #[test]
6199 fn test_update_long_shared_prefix_at_boundary() {
6200 let ctx = ParallelSparseTrieTestContext;
6201 let mut trie =
6202 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6203
6204 let (leaf1_path, value1) = ctx.create_test_leaf([0xA, 0xB, 0xC, 0xD, 0xE, 0xF], 1);
6218 let (leaf2_path, value2) = ctx.create_test_leaf([0xA, 0xB, 0xD, 0xE, 0xF, 0x0], 2);
6219
6220 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6221 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6222
6223 ctx.assert_upper_subtrie(&trie)
6225 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA, 0xB]));
6226
6227 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0xB]))
6229 .has_branch(&Nibbles::from_nibbles([0xA, 0xB]), &[0xC, 0xD])
6230 .has_leaf(
6231 &Nibbles::from_nibbles([0xA, 0xB, 0xC]),
6232 &Nibbles::from_nibbles([0xD, 0xE, 0xF]),
6233 )
6234 .has_leaf(
6235 &Nibbles::from_nibbles([0xA, 0xB, 0xD]),
6236 &Nibbles::from_nibbles([0xE, 0xF, 0x0]),
6237 )
6238 .has_value(&leaf1_path, &value1)
6239 .has_value(&leaf2_path, &value2);
6240 }
6241
6242 #[test]
6243 fn test_update_branch_to_extension_collapse() {
6244 let ctx = ParallelSparseTrieTestContext;
6245 let mut trie =
6246 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6247
6248 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 1);
6274 let (leaf2_path, value2) = ctx.create_test_leaf([0x2, 0x3, 0x4, 0x5], 2);
6275 let (leaf3_path, value3) = ctx.create_test_leaf([0x2, 0x3, 0x5, 0x6], 3);
6276
6277 trie.update_leaf(leaf1_path, value1, DefaultTrieNodeProvider).unwrap();
6278 trie.update_leaf(leaf2_path, value2, DefaultTrieNodeProvider).unwrap();
6279 trie.update_leaf(leaf3_path, value3, DefaultTrieNodeProvider).unwrap();
6280
6281 ctx.assert_upper_subtrie(&trie).has_branch(&Nibbles::default(), &[0x1, 0x2]);
6283
6284 let (new_leaf1_path, new_value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 10);
6287 let (new_leaf2_path, new_value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x5], 11);
6288 let (new_leaf3_path, new_value3) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x6], 12);
6289
6290 let mut trie =
6292 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6293 trie.update_leaf(new_leaf1_path, new_value1.clone(), DefaultTrieNodeProvider).unwrap();
6294 trie.update_leaf(new_leaf2_path, new_value2.clone(), DefaultTrieNodeProvider).unwrap();
6295 trie.update_leaf(new_leaf3_path, new_value3.clone(), DefaultTrieNodeProvider).unwrap();
6296
6297 ctx.assert_upper_subtrie(&trie)
6299 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
6300
6301 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3]);
6303
6304 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6306 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5, 0x6]) .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &Nibbles::default())
6308 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x5]), &Nibbles::default())
6309 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x6]), &Nibbles::default())
6310 .has_value(&new_leaf1_path, &new_value1)
6311 .has_value(&new_leaf2_path, &new_value2)
6312 .has_value(&new_leaf3_path, &new_value3);
6313 }
6314
6315 #[test]
6316 fn test_update_shared_prefix_patterns() {
6317 let ctx = ParallelSparseTrieTestContext;
6318 let mut trie =
6319 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6320
6321 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 1);
6337 let (leaf2_path, value2) = ctx.create_test_leaf([0x2, 0x3, 0x4, 0x5], 2);
6338 let (leaf3_path, value3) = ctx.create_test_leaf([0x2, 0x3, 0x5, 0x6], 3);
6339
6340 trie.update_leaf(leaf1_path, value1, DefaultTrieNodeProvider).unwrap();
6341 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6342 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
6343
6344 ctx.assert_upper_subtrie(&trie)
6346 .has_branch(&Nibbles::default(), &[0x1, 0x2])
6347 .has_leaf(&Nibbles::from_nibbles([0x1]), &Nibbles::from_nibbles([0x2, 0x3, 0x4]))
6348 .has_extension(&Nibbles::from_nibbles([0x2]), &Nibbles::from_nibbles([0x3]));
6349
6350 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x2, 0x3]))
6352 .has_branch(&Nibbles::from_nibbles([0x2, 0x3]), &[0x4, 0x5])
6353 .has_leaf(&Nibbles::from_nibbles([0x2, 0x3, 0x4]), &Nibbles::from_nibbles([0x5]))
6354 .has_leaf(&Nibbles::from_nibbles([0x2, 0x3, 0x5]), &Nibbles::from_nibbles([0x6]))
6355 .has_value(&leaf2_path, &value2)
6356 .has_value(&leaf3_path, &value3);
6357 }
6358
6359 #[test]
6360 fn test_progressive_branch_creation() {
6361 let ctx = ParallelSparseTrieTestContext;
6362 let mut trie =
6363 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6364
6365 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4, 0x5], 1);
6401 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6402
6403 ctx.assert_upper_subtrie(&trie)
6405 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]))
6406 .has_value(&leaf1_path, &value1);
6407
6408 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4, 0x6], 2);
6410 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6411
6412 ctx.assert_upper_subtrie(&trie)
6414 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]));
6415
6416 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3, 0x4]);
6418
6419 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6420 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6421 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]), &Nibbles::default())
6422 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x6]), &Nibbles::default())
6423 .has_value(&leaf1_path, &value1)
6424 .has_value(&leaf2_path, &value2);
6425
6426 let (leaf3_path, value3) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x5], 3);
6428 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
6429
6430 ctx.assert_upper_subtrie(&trie)
6432 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
6433
6434 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3]);
6436
6437 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6438 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
6439 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6440 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x5]), &Nibbles::default())
6441 .has_value(&leaf1_path, &value1)
6442 .has_value(&leaf2_path, &value2)
6443 .has_value(&leaf3_path, &value3);
6444
6445 let (leaf4_path, value4) = ctx.create_test_leaf([0x1, 0x2, 0x4], 4);
6447 trie.update_leaf(leaf4_path, value4.clone(), DefaultTrieNodeProvider).unwrap();
6448
6449 ctx.assert_upper_subtrie(&trie)
6451 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
6452
6453 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2]);
6455
6456 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6458 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
6459 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
6460 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6461 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::default())
6462 .has_value(&leaf1_path, &value1)
6463 .has_value(&leaf2_path, &value2)
6464 .has_value(&leaf3_path, &value3)
6465 .has_value(&leaf4_path, &value4);
6466 }
6467
6468 #[test]
6469 fn test_update_max_depth_paths() {
6470 let ctx = ParallelSparseTrieTestContext;
6471 let mut trie =
6472 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6473
6474 let mut path1_nibbles = vec![0xF; 63];
6486 path1_nibbles.push(0x0);
6487 let mut path2_nibbles = vec![0xF; 63];
6488 path2_nibbles.push(0x1);
6489
6490 let (leaf1_path, value1) = ctx.create_test_leaf(&path1_nibbles, 1);
6491 let (leaf2_path, value2) = ctx.create_test_leaf(&path2_nibbles, 2);
6492
6493 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6494 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6495
6496 let extension_key = vec![0xF; 63];
6498 ctx.assert_upper_subtrie(&trie)
6499 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles(&extension_key));
6500
6501 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0xF]))
6503 .has_branch(&Nibbles::from_nibbles(&path1_nibbles[..63]), &[0x0, 0x1])
6504 .has_value(&leaf1_path, &value1)
6505 .has_value(&leaf2_path, &value2);
6506 }
6507
6508 #[test]
6509 fn test_hoodie_block_1_data() {
6510 let root_branch_stack = vec![
6512 hex!("a0550b6aba4dd4582a2434d2cbdad8d3007d09f622d7a6e6eaa7a49385823c2fa2"),
6513 hex!("a04788a4975a9e1efd29b834fd80fdfe8a57cc1b1c5ace6d30ce5a36a15e0092b3"),
6514 hex!("a093aeccf87da304e6f7d09edc5d7bd3a552808866d2149dd0940507a8f9bfa910"),
6515 hex!("a08b5b423ba68d0dec2eca1f408076f9170678505eb4a5db2abbbd83bb37666949"),
6516 hex!("a08592f62216af4218098a78acad7cf472a727fb55e6c27d3cfdf2774d4518eb83"),
6517 hex!("a0ef02aeee845cb64c11f85edc1a3094227c26445952554b8a9248915d80c746c3"),
6518 hex!("a0df2529ee3a1ce4df5a758cf17e6a86d0fb5ea22ab7071cf60af6412e9b0a428a"),
6519 hex!("a0acaa1092db69cd5a63676685827b3484c4b80dc1d3361f6073bbb9240101e144"),
6520 hex!("a09c3f2bb2a729d71f246a833353ade65667716bb330e0127a3299a42d11200f93"),
6521 hex!("a0ce978470f4c0b1f8069570563a14d2b79d709add2db4bf22dd9b6aed3271c566"),
6522 hex!("a095f783cd1d464a60e3c8adcadc28c6eb9fec7306664df39553be41dccc909606"),
6523 hex!("a0a9083f5fb914b255e1feb5d951a4dfddacf3c8003ef1d1ec6a13bb6ba5b2ac62"),
6524 hex!("a0fec113d537d8577cd361e0cabf5e95ef58f1cc34318292fdecce9fae57c3e094"),
6525 hex!("a08b7465f5fe8b3e3c0d087cb7521310d4065ef2a0ee43bf73f68dee8a5742b3dd"),
6526 hex!("a0c589aa1ae3d5fd87d8640957f7d5184a4ac06f393b453a8e8ed7e8fba0d385c8"),
6527 hex!("a0b516d6f3352f87beab4ed6e7322f191fc7a147686500ef4de7dd290ad784ef51"),
6528 ];
6529
6530 let root_branch_rlp_stack: Vec<RlpNode> = root_branch_stack
6531 .iter()
6532 .map(|hex_str| RlpNode::from_raw_rlp(&hex_str[..]).unwrap())
6533 .collect();
6534
6535 let root_branch_node = BranchNode::new(
6536 root_branch_rlp_stack,
6537 TrieMask::new(0b1111111111111111), );
6539
6540 let root_branch_masks = TrieMasks {
6541 hash_mask: Some(TrieMask::new(0b1111111111111111)),
6542 tree_mask: Some(TrieMask::new(0b1111111111111111)),
6543 };
6544
6545 let mut trie = ParallelSparseTrie::from_root(
6546 TrieNode::Branch(root_branch_node),
6547 root_branch_masks,
6548 true,
6549 )
6550 .unwrap();
6551
6552 let branch_0x3_stack = vec![
6554 hex!("a09da7d9755fe0c558b3c3de9fdcdf9f28ae641f38c9787b05b73ab22ae53af3e2"),
6555 hex!("a0d9990bf0b810d1145ecb2b011fd68c63cc85564e6724166fd4a9520180706e5f"),
6556 hex!("a0f60eb4b12132a40df05d9bbdb88bbde0185a3f097f3c76bf4200c23eda26cf86"),
6557 hex!("a0ca976997ddaf06f18992f6207e4f6a05979d07acead96568058789017cc6d06b"),
6558 hex!("a04d78166b48044fdc28ed22d2fd39c8df6f8aaa04cb71d3a17286856f6893ff83"),
6559 hex!("a021d4f90c34d3f1706e78463b6482bca77a3aa1cd059a3f326c42a1cfd30b9b60"),
6560 hex!("a0fc3b71c33e2e6b77c5e494c1db7fdbb447473f003daf378c7a63ba9bf3f0049d"),
6561 hex!("a0e33ed2be194a3d93d343e85642447c93a9d0cfc47a016c2c23d14c083be32a7c"),
6562 hex!("a07b8e7a21c1178d28074f157b50fca85ee25c12568ff8e9706dcbcdacb77bf854"),
6563 hex!("a0973274526811393ea0bf4811ca9077531db00d06b86237a2ecd683f55ba4bcb0"),
6564 hex!("a03a93d726d7487874e51b52d8d534c63aa2a689df18e3b307c0d6cb0a388b00f3"),
6565 hex!("a06aa67101d011d1c22fe739ef83b04b5214a3e2f8e1a2625d8bfdb116b447e86f"),
6566 hex!("a02dd545b33c62d33a183e127a08a4767fba891d9f3b94fc20a2ca02600d6d1fff"),
6567 hex!("a0fe6db87d00f06d53bff8169fa497571ff5af1addfb715b649b4d79dd3e394b04"),
6568 hex!("a0d9240a9d2d5851d05a97ff3305334dfdb0101e1e321fc279d2bb3cad6afa8fc8"),
6569 hex!("a01b69c6ab5173de8a8ec53a6ebba965713a4cc7feb86cb3e230def37c230ca2b2"),
6570 ];
6571
6572 let branch_0x3_rlp_stack: Vec<RlpNode> = branch_0x3_stack
6573 .iter()
6574 .map(|hex_str| RlpNode::from_raw_rlp(&hex_str[..]).unwrap())
6575 .collect();
6576
6577 let branch_0x3_node = BranchNode::new(
6578 branch_0x3_rlp_stack,
6579 TrieMask::new(0b1111111111111111), );
6581
6582 let branch_0x3_masks = TrieMasks {
6583 hash_mask: Some(TrieMask::new(0b0100010000010101)),
6584 tree_mask: Some(TrieMask::new(0b0100000000000000)),
6585 };
6586
6587 let leaf_path = Nibbles::from_nibbles([0x3, 0x7]);
6589 let leaf_key = Nibbles::unpack(
6590 &hex!("d65eaa92c6bc4c13a5ec45527f0c18ea8932588728769ec7aecfe6d9f32e42")[..],
6591 );
6592 let leaf_value = hex!("f8440180a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c").to_vec();
6593
6594 let leaf_node = LeafNode::new(leaf_key, leaf_value);
6595 let leaf_masks = TrieMasks::none();
6596
6597 trie.reveal_nodes(vec![
6598 RevealedSparseNode {
6599 path: Nibbles::from_nibbles([0x3]),
6600 node: TrieNode::Branch(branch_0x3_node),
6601 masks: branch_0x3_masks,
6602 },
6603 RevealedSparseNode {
6604 path: leaf_path,
6605 node: TrieNode::Leaf(leaf_node),
6606 masks: leaf_masks,
6607 },
6608 ])
6609 .unwrap();
6610
6611 let mut leaf_full_path = leaf_path;
6613 leaf_full_path.extend(&leaf_key);
6614
6615 let leaf_new_value = vec![
6616 248, 68, 1, 128, 160, 224, 163, 152, 169, 122, 160, 155, 102, 53, 41, 0, 47, 28, 205,
6617 190, 199, 5, 215, 108, 202, 22, 138, 70, 196, 178, 193, 208, 18, 96, 95, 63, 238, 160,
6618 245, 122, 205, 64, 37, 152, 114, 96, 109, 118, 25, 126, 240, 82, 243, 211, 85, 136,
6619 218, 223, 145, 158, 225, 240, 227, 203, 155, 98, 211, 244, 176, 44,
6620 ];
6621
6622 trie.update_leaf(leaf_full_path, leaf_new_value.clone(), DefaultTrieNodeProvider).unwrap();
6623
6624 assert_eq!(
6626 Some(&leaf_new_value),
6627 trie.lower_subtrie_for_path(&leaf_path).unwrap().inner.values.get(&leaf_full_path)
6628 );
6629 assert!(trie.upper_subtrie.inner.values.is_empty());
6630
6631 let expected_root =
6633 b256!("0x29b07de8376e9ce7b3a69e9b102199869514d3f42590b5abc6f7d48ec9b8665c");
6634 assert_eq!(trie.root(), expected_root);
6635 }
6636
6637 #[test]
6638 fn find_leaf_existing_leaf() {
6639 let provider = DefaultTrieNodeProvider;
6641 let mut sparse = ParallelSparseTrie::default();
6642 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6643 let value = b"test_value".to_vec();
6644
6645 sparse.update_leaf(path, value.clone(), &provider).unwrap();
6646
6647 let result = sparse.find_leaf(&path, None);
6649 assert_matches!(result, Ok(LeafLookup::Exists));
6650
6651 let result = sparse.find_leaf(&path, Some(&value));
6653 assert_matches!(result, Ok(LeafLookup::Exists));
6654 }
6655
6656 #[test]
6657 fn find_leaf_value_mismatch() {
6658 let provider = DefaultTrieNodeProvider;
6660 let mut sparse = ParallelSparseTrie::default();
6661 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6662 let value = b"test_value".to_vec();
6663 let wrong_value = b"wrong_value".to_vec();
6664
6665 sparse.update_leaf(path, value, &provider).unwrap();
6666
6667 let result = sparse.find_leaf(&path, Some(&wrong_value));
6669 assert_matches!(
6670 result,
6671 Err(LeafLookupError::ValueMismatch { path: p, expected: Some(e), actual: _a }) if p == path && e == wrong_value
6672 );
6673 }
6674
6675 #[test]
6676 fn find_leaf_not_found_empty_trie() {
6677 let sparse = ParallelSparseTrie::default();
6679 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6680
6681 let result = sparse.find_leaf(&path, None);
6683 assert_matches!(result, Ok(LeafLookup::NonExistent));
6684 }
6685
6686 #[test]
6687 fn find_leaf_empty_trie() {
6688 let sparse = ParallelSparseTrie::default();
6689 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6690
6691 let result = sparse.find_leaf(&path, None);
6692 assert_matches!(result, Ok(LeafLookup::NonExistent));
6693 }
6694
6695 #[test]
6696 fn find_leaf_exists_no_value_check() {
6697 let provider = DefaultTrieNodeProvider;
6698 let mut sparse = ParallelSparseTrie::default();
6699 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6700 sparse.update_leaf(path, encode_account_value(0), &provider).unwrap();
6701
6702 let result = sparse.find_leaf(&path, None);
6703 assert_matches!(result, Ok(LeafLookup::Exists));
6704 }
6705
6706 #[test]
6707 fn find_leaf_exists_with_value_check_ok() {
6708 let provider = DefaultTrieNodeProvider;
6709 let mut sparse = ParallelSparseTrie::default();
6710 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6711 let value = encode_account_value(0);
6712 sparse.update_leaf(path, value.clone(), &provider).unwrap();
6713
6714 let result = sparse.find_leaf(&path, Some(&value));
6715 assert_matches!(result, Ok(LeafLookup::Exists));
6716 }
6717
6718 #[test]
6719 fn find_leaf_exclusion_branch_divergence() {
6720 let provider = DefaultTrieNodeProvider;
6721 let mut sparse = ParallelSparseTrie::default();
6722 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();
6727 sparse.update_leaf(path2, encode_account_value(1), &provider).unwrap();
6728
6729 let result = sparse.find_leaf(&search_path, None);
6730 assert_matches!(result, Ok(LeafLookup::NonExistent))
6731 }
6732
6733 #[test]
6734 fn find_leaf_exclusion_extension_divergence() {
6735 let provider = DefaultTrieNodeProvider;
6736 let mut sparse = ParallelSparseTrie::default();
6737 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
6739 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]);
6741
6742 sparse.update_leaf(path1, 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_leaf_divergence() {
6750 let provider = DefaultTrieNodeProvider;
6751 let mut sparse = ParallelSparseTrie::default();
6752 let existing_leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6753 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
6754
6755 sparse.update_leaf(existing_leaf_path, encode_account_value(0), &provider).unwrap();
6756
6757 let result = sparse.find_leaf(&search_path, None);
6758 assert_matches!(result, Ok(LeafLookup::NonExistent))
6759 }
6760
6761 #[test]
6762 fn find_leaf_exclusion_path_ends_at_branch() {
6763 let provider = DefaultTrieNodeProvider;
6764 let mut sparse = ParallelSparseTrie::default();
6765 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]);
6767 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2]); sparse.update_leaf(path1, encode_account_value(0), &provider).unwrap();
6770 sparse.update_leaf(path2, encode_account_value(1), &provider).unwrap();
6771
6772 let result = sparse.find_leaf(&search_path, None);
6773 assert_matches!(result, Ok(LeafLookup::NonExistent));
6774 }
6775
6776 #[test]
6777 fn find_leaf_error_blinded_node_at_leaf_path() {
6778 let blinded_hash = B256::repeat_byte(0xBB);
6780 let leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6781
6782 let sparse = new_test_trie(
6783 [
6784 (
6785 Nibbles::default(),
6787 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x1, 0x2])),
6788 ),
6789 (
6790 Nibbles::from_nibbles_unchecked([0x1, 0x2]),
6792 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x3])),
6793 ),
6794 (
6795 Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3]),
6797 SparseNode::new_branch(TrieMask::new(0b10000)),
6798 ),
6799 (
6800 leaf_path,
6802 SparseNode::Hash(blinded_hash),
6803 ),
6804 ]
6805 .into_iter(),
6806 );
6807
6808 let result = sparse.find_leaf(&leaf_path, None);
6809
6810 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
6812 if path == leaf_path && hash == blinded_hash
6813 );
6814 }
6815
6816 #[test]
6817 fn find_leaf_error_blinded_node() {
6818 let blinded_hash = B256::repeat_byte(0xAA);
6819 let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]);
6820 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6821
6822 let sparse = new_test_trie(
6823 [
6824 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b100010))),
6827 (path_to_blind, SparseNode::Hash(blinded_hash)),
6828 (
6829 Nibbles::from_nibbles_unchecked([0x5]),
6830 SparseNode::new_leaf(Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8])),
6831 ),
6832 ]
6833 .into_iter(),
6834 );
6835
6836 let result = sparse.find_leaf(&search_path, None);
6837
6838 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
6840 if path == path_to_blind && hash == blinded_hash
6841 );
6842 }
6843}