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 fn root(&mut self) -> B256 {
692 trace!(target: "trie::parallel_sparse", "Calculating trie root hash");
693
694 self.update_subtrie_hashes();
696
697 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
700 let root_rlp = self.update_upper_subtrie_hashes(&mut prefix_set);
701
702 root_rlp.as_hash().unwrap_or(EMPTY_ROOT_HASH)
704 }
705
706 fn update_subtrie_hashes(&mut self) {
707 trace!(target: "trie::parallel_sparse", "Updating subtrie hashes");
708
709 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
711 let num_changed_keys = prefix_set.len();
712 let (mut changed_subtries, unchanged_prefix_set) =
713 self.take_changed_lower_subtries(&mut prefix_set);
714
715 #[cfg(feature = "metrics")]
717 self.metrics.subtries_updated.record(changed_subtries.len() as f64);
718
719 self.prefix_set = unchanged_prefix_set;
721
722 if !self.is_update_parallelism_enabled(num_changed_keys) {
724 for changed_subtrie in &mut changed_subtries {
725 changed_subtrie.subtrie.update_hashes(
726 &mut changed_subtrie.prefix_set,
727 &mut changed_subtrie.update_actions_buf,
728 &self.branch_node_tree_masks,
729 &self.branch_node_hash_masks,
730 );
731 }
732
733 self.insert_changed_subtries(changed_subtries);
734 return
735 }
736
737 #[cfg(not(feature = "std"))]
738 unreachable!("nostd is checked by is_update_parallelism_enabled");
739
740 #[cfg(feature = "std")]
741 {
743 use rayon::iter::{IntoParallelIterator, ParallelIterator};
744 let (tx, rx) = mpsc::channel();
745
746 let branch_node_tree_masks = &self.branch_node_tree_masks;
747 let branch_node_hash_masks = &self.branch_node_hash_masks;
748 changed_subtries
749 .into_par_iter()
750 .map(|mut changed_subtrie| {
751 #[cfg(feature = "metrics")]
752 let start = std::time::Instant::now();
753 changed_subtrie.subtrie.update_hashes(
754 &mut changed_subtrie.prefix_set,
755 &mut changed_subtrie.update_actions_buf,
756 branch_node_tree_masks,
757 branch_node_hash_masks,
758 );
759 #[cfg(feature = "metrics")]
760 self.metrics.subtrie_hash_update_latency.record(start.elapsed());
761 changed_subtrie
762 })
763 .for_each_init(|| tx.clone(), |tx, result| tx.send(result).unwrap());
764
765 drop(tx);
766 self.insert_changed_subtries(rx);
767 }
768 }
769
770 fn get_leaf_value(&self, full_path: &Nibbles) -> Option<&Vec<u8>> {
771 self.subtrie_for_path(full_path).and_then(|subtrie| subtrie.inner.values.get(full_path))
772 }
773
774 fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
775 self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
776 }
777
778 fn take_updates(&mut self) -> SparseTrieUpdates {
779 self.updates.take().unwrap_or_default()
780 }
781
782 fn wipe(&mut self) {
783 self.upper_subtrie.wipe();
784 self.lower_subtries = [const { LowerSparseSubtrie::Blind(None) }; NUM_LOWER_SUBTRIES];
785 self.prefix_set = PrefixSetMut::all();
786 self.updates = self.updates.is_some().then(SparseTrieUpdates::wiped);
787 }
788
789 fn clear(&mut self) {
790 self.upper_subtrie.clear();
791 self.upper_subtrie.nodes.insert(Nibbles::default(), SparseNode::Empty);
792 for subtrie in &mut self.lower_subtries {
793 subtrie.clear();
794 }
795 self.prefix_set.clear();
796 self.updates = None;
797 self.branch_node_tree_masks.clear();
798 self.branch_node_hash_masks.clear();
799 }
802
803 fn find_leaf(
804 &self,
805 full_path: &Nibbles,
806 expected_value: Option<&Vec<u8>>,
807 ) -> Result<LeafLookup, LeafLookupError> {
808 if let Some(actual_value) = std::iter::once(self.upper_subtrie.as_ref())
814 .chain(self.lower_subtrie_for_path(full_path))
815 .filter_map(|subtrie| subtrie.inner.values.get(full_path))
816 .next()
817 {
818 return expected_value
820 .is_none_or(|v| v == actual_value)
821 .then_some(LeafLookup::Exists)
822 .ok_or_else(|| LeafLookupError::ValueMismatch {
823 path: *full_path,
824 expected: expected_value.cloned(),
825 actual: actual_value.clone(),
826 })
827 }
828
829 let mut curr_path = Nibbles::new(); let mut curr_subtrie = self.upper_subtrie.as_ref();
837 let mut curr_subtrie_is_upper = true;
838
839 loop {
840 let curr_node = curr_subtrie.nodes.get(&curr_path).unwrap();
841
842 match Self::find_next_to_leaf(&curr_path, curr_node, full_path) {
843 FindNextToLeafOutcome::NotFound => return Ok(LeafLookup::NonExistent),
844 FindNextToLeafOutcome::BlindedNode(hash) => {
845 return Err(LeafLookupError::BlindedNode { path: curr_path, hash });
847 }
848 FindNextToLeafOutcome::Found => {
849 panic!("target leaf {full_path:?} found at path {curr_path:?}, even though value wasn't in values hashmap");
850 }
851 FindNextToLeafOutcome::ContinueFrom(next_path) => {
852 curr_path = next_path;
853 if curr_subtrie_is_upper &&
856 let Some(lower_subtrie) = self.lower_subtrie_for_path(&curr_path)
857 {
858 curr_subtrie = lower_subtrie;
859 curr_subtrie_is_upper = false;
860 }
861 }
862 }
863 }
864 }
865}
866
867impl ParallelSparseTrie {
868 pub const fn with_parallelism_thresholds(mut self, thresholds: ParallelismThresholds) -> Self {
870 self.parallelism_thresholds = thresholds;
871 self
872 }
873
874 const fn updates_enabled(&self) -> bool {
876 self.updates.is_some()
877 }
878
879 const fn is_reveal_parallelism_enabled(&self, num_nodes: usize) -> bool {
882 #[cfg(not(feature = "std"))]
883 return false;
884
885 num_nodes >= self.parallelism_thresholds.min_revealed_nodes
886 }
887
888 const fn is_update_parallelism_enabled(&self, num_changed_keys: usize) -> bool {
891 #[cfg(not(feature = "std"))]
892 return false;
893
894 num_changed_keys >= self.parallelism_thresholds.min_updated_nodes
895 }
896
897 pub fn from_root(
912 root: TrieNode,
913 masks: TrieMasks,
914 retain_updates: bool,
915 ) -> SparseTrieResult<Self> {
916 Self::default().with_root(root, masks, retain_updates)
917 }
918
919 fn lower_subtrie_for_path(&self, path: &Nibbles) -> Option<&SparseSubtrie> {
923 match SparseSubtrieType::from_path(path) {
924 SparseSubtrieType::Upper => None,
925 SparseSubtrieType::Lower(idx) => self.lower_subtries[idx].as_revealed_ref(),
926 }
927 }
928
929 fn lower_subtrie_for_path_mut(&mut self, path: &Nibbles) -> Option<&mut SparseSubtrie> {
936 match SparseSubtrieType::from_path(path) {
937 SparseSubtrieType::Upper => None,
938 SparseSubtrieType::Lower(idx) => {
939 self.lower_subtries[idx].reveal(path);
940 Some(self.lower_subtries[idx].as_revealed_mut().expect("just revealed"))
941 }
942 }
943 }
944
945 fn subtrie_for_path(&self, path: &Nibbles) -> Option<&SparseSubtrie> {
950 if SparseSubtrieType::path_len_is_upper(path.len()) {
953 Some(&self.upper_subtrie)
954 } else {
955 self.lower_subtrie_for_path(path)
956 }
957 }
958
959 fn subtrie_for_path_mut(&mut self, path: &Nibbles) -> &mut SparseSubtrie {
966 if SparseSubtrieType::path_len_is_upper(path.len()) {
969 &mut self.upper_subtrie
970 } else {
971 self.lower_subtrie_for_path_mut(path).unwrap()
972 }
973 }
974
975 fn find_next_to_leaf(
983 from_path: &Nibbles,
984 from_node: &SparseNode,
985 leaf_full_path: &Nibbles,
986 ) -> FindNextToLeafOutcome {
987 debug_assert!(leaf_full_path.len() >= from_path.len());
988 debug_assert!(leaf_full_path.starts_with(from_path));
989
990 match from_node {
991 SparseNode::Empty => FindNextToLeafOutcome::NotFound,
994 SparseNode::Hash(hash) => FindNextToLeafOutcome::BlindedNode(*hash),
995 SparseNode::Leaf { key, .. } => {
996 let mut found_full_path = *from_path;
997 found_full_path.extend(key);
998
999 if &found_full_path == leaf_full_path {
1000 return FindNextToLeafOutcome::Found
1001 }
1002 FindNextToLeafOutcome::NotFound
1003 }
1004 SparseNode::Extension { key, .. } => {
1005 if leaf_full_path.len() == from_path.len() {
1006 return FindNextToLeafOutcome::NotFound
1007 }
1008
1009 let mut child_path = *from_path;
1010 child_path.extend(key);
1011
1012 if !leaf_full_path.starts_with(&child_path) {
1013 return FindNextToLeafOutcome::NotFound
1014 }
1015 FindNextToLeafOutcome::ContinueFrom(child_path)
1016 }
1017 SparseNode::Branch { state_mask, .. } => {
1018 if leaf_full_path.len() == from_path.len() {
1019 return FindNextToLeafOutcome::NotFound
1020 }
1021
1022 let nibble = leaf_full_path.get_unchecked(from_path.len());
1023 if !state_mask.is_bit_set(nibble) {
1024 return FindNextToLeafOutcome::NotFound
1025 }
1026
1027 let mut child_path = *from_path;
1028 child_path.push_unchecked(nibble);
1029
1030 FindNextToLeafOutcome::ContinueFrom(child_path)
1031 }
1032 }
1033 }
1034
1035 fn move_value_on_leaf_removal(
1040 &mut self,
1041 parent_path: &Nibbles,
1042 new_parent_node: &SparseNode,
1043 prev_child_path: &Nibbles,
1044 ) {
1045 if SparseSubtrieType::from_path(parent_path).lower_index().is_some() {
1048 return;
1049 }
1050
1051 if let SparseNode::Leaf { key, .. } = new_parent_node {
1052 let Some(prev_child_subtrie) = self.lower_subtrie_for_path_mut(prev_child_path) else {
1053 return;
1054 };
1055
1056 let mut leaf_full_path = *parent_path;
1057 leaf_full_path.extend(key);
1058
1059 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");
1060 self.upper_subtrie.inner.values.insert(leaf_full_path, val);
1061 }
1062 }
1063
1064 fn remove_node(&mut self, path: &Nibbles) {
1076 let subtrie = self.subtrie_for_path_mut(path);
1077 let node = subtrie.nodes.remove(path);
1078
1079 let Some(idx) = SparseSubtrieType::from_path(path).lower_index() else {
1080 return;
1083 };
1084
1085 match node {
1086 Some(SparseNode::Leaf { .. }) => {
1087 if subtrie.nodes.is_empty() {
1090 self.lower_subtries[idx].clear();
1091 }
1092 }
1093 Some(SparseNode::Extension { key, .. }) => {
1094 if &subtrie.path == path {
1098 subtrie.path.extend(&key);
1099 }
1100 }
1101 _ => panic!("Expected to remove a leaf or extension, but removed {node:?}"),
1102 }
1103 }
1104
1105 fn branch_changes_on_leaf_removal(
1114 parent_path: &Nibbles,
1115 remaining_child_path: &Nibbles,
1116 remaining_child_node: &SparseNode,
1117 ) -> (SparseNode, bool) {
1118 debug_assert!(remaining_child_path.len() > parent_path.len());
1119 debug_assert!(remaining_child_path.starts_with(parent_path));
1120
1121 let remaining_child_nibble = remaining_child_path.get_unchecked(parent_path.len());
1122
1123 match remaining_child_node {
1126 SparseNode::Empty | SparseNode::Hash(_) => {
1127 panic!("remaining child must have been revealed already")
1128 }
1129 SparseNode::Leaf { key, .. } => {
1133 let mut new_key = Nibbles::from_nibbles_unchecked([remaining_child_nibble]);
1134 new_key.extend(key);
1135 (SparseNode::new_leaf(new_key), true)
1136 }
1137 SparseNode::Extension { key, .. } => {
1141 let mut new_key = Nibbles::from_nibbles_unchecked([remaining_child_nibble]);
1142 new_key.extend(key);
1143 (SparseNode::new_ext(new_key), true)
1144 }
1145 SparseNode::Branch { .. } => (
1148 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([remaining_child_nibble])),
1149 false,
1150 ),
1151 }
1152 }
1153
1154 fn extension_changes_on_leaf_removal(
1163 parent_path: &Nibbles,
1164 parent_key: &Nibbles,
1165 child_path: &Nibbles,
1166 child: &SparseNode,
1167 ) -> Option<SparseNode> {
1168 debug_assert!(child_path.len() > parent_path.len());
1169 debug_assert!(child_path.starts_with(parent_path));
1170
1171 match child {
1174 SparseNode::Empty | SparseNode::Hash(_) => {
1175 panic!("child must be revealed")
1176 }
1177 SparseNode::Leaf { key, .. } => {
1183 let mut new_key = *parent_key;
1184 new_key.extend(key);
1185 Some(SparseNode::new_leaf(new_key))
1186 }
1187 SparseNode::Extension { key, .. } => {
1190 let mut new_key = *parent_key;
1191 new_key.extend(key);
1192 Some(SparseNode::new_ext(new_key))
1193 }
1194 SparseNode::Branch { .. } => None,
1196 }
1197 }
1198
1199 fn reveal_remaining_child_on_leaf_removal<P: TrieNodeProvider>(
1209 &mut self,
1210 provider: P,
1211 full_path: &Nibbles, remaining_child_path: &Nibbles,
1213 recurse_into_extension: bool,
1214 ) -> SparseTrieResult<SparseNode> {
1215 let remaining_child_subtrie = self.subtrie_for_path_mut(remaining_child_path);
1216
1217 let remaining_child_node =
1218 match remaining_child_subtrie.nodes.get(remaining_child_path).unwrap() {
1219 SparseNode::Hash(_) => {
1220 debug!(
1221 target: "trie::parallel_sparse",
1222 child_path = ?remaining_child_path,
1223 leaf_full_path = ?full_path,
1224 "Node child not revealed in remove_leaf, falling back to db",
1225 );
1226 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1227 provider.trie_node(remaining_child_path)?
1228 {
1229 let decoded = TrieNode::decode(&mut &node[..])?;
1230 trace!(
1231 target: "trie::parallel_sparse",
1232 ?remaining_child_path,
1233 ?decoded,
1234 ?tree_mask,
1235 ?hash_mask,
1236 "Revealing remaining blinded branch child"
1237 );
1238 remaining_child_subtrie.reveal_node(
1239 *remaining_child_path,
1240 &decoded,
1241 TrieMasks { hash_mask, tree_mask },
1242 )?;
1243 remaining_child_subtrie.nodes.get(remaining_child_path).unwrap().clone()
1244 } else {
1245 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1246 path: *remaining_child_path,
1247 }
1248 .into())
1249 }
1250 }
1251 node => node.clone(),
1252 };
1253
1254 if let SparseNode::Extension { key, .. } = &remaining_child_node &&
1259 recurse_into_extension
1260 {
1261 let mut remaining_grandchild_path = *remaining_child_path;
1262 remaining_grandchild_path.extend(key);
1263
1264 trace!(
1265 target: "trie::parallel_sparse",
1266 remaining_grandchild_path = ?remaining_grandchild_path,
1267 child_path = ?remaining_child_path,
1268 leaf_full_path = ?full_path,
1269 "Revealing child of extension node, which is the last remaining child of the branch"
1270 );
1271
1272 self.reveal_remaining_child_on_leaf_removal(
1273 provider,
1274 full_path,
1275 &remaining_grandchild_path,
1276 false, )?;
1278 }
1279
1280 Ok(remaining_child_node)
1281 }
1282
1283 fn apply_subtrie_update_actions(
1286 &mut self,
1287 update_actions: impl Iterator<Item = SparseTrieUpdatesAction>,
1288 ) {
1289 if let Some(updates) = self.updates.as_mut() {
1290 for action in update_actions {
1291 match action {
1292 SparseTrieUpdatesAction::InsertRemoved(path) => {
1293 updates.updated_nodes.remove(&path);
1294 updates.removed_nodes.insert(path);
1295 }
1296 SparseTrieUpdatesAction::RemoveUpdated(path) => {
1297 updates.updated_nodes.remove(&path);
1298 }
1299 SparseTrieUpdatesAction::InsertUpdated(path, branch_node) => {
1300 updates.updated_nodes.insert(path, branch_node);
1301 }
1302 }
1303 }
1304 };
1305 }
1306
1307 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, ret)]
1309 fn update_upper_subtrie_hashes(&mut self, prefix_set: &mut PrefixSet) -> RlpNode {
1310 trace!(target: "trie::parallel_sparse", "Updating upper subtrie hashes");
1311
1312 debug_assert!(self.upper_subtrie.inner.buffers.path_stack.is_empty());
1313 self.upper_subtrie.inner.buffers.path_stack.push(RlpNodePathStackItem {
1314 path: Nibbles::default(), is_in_prefix_set: None,
1316 });
1317
1318 #[cfg(feature = "metrics")]
1319 let start = std::time::Instant::now();
1320
1321 let mut update_actions_buf =
1322 self.updates_enabled().then(|| self.update_actions_buffers.pop().unwrap_or_default());
1323
1324 while let Some(stack_item) = self.upper_subtrie.inner.buffers.path_stack.pop() {
1325 let path = stack_item.path;
1326 let node = if path.len() < UPPER_TRIE_MAX_DEPTH {
1327 self.upper_subtrie.nodes.get_mut(&path).expect("upper subtrie node must exist")
1328 } else {
1329 let index = path_subtrie_index_unchecked(&path);
1330 let node = self.lower_subtries[index]
1331 .as_revealed_mut()
1332 .expect("lower subtrie must exist")
1333 .nodes
1334 .get_mut(&path)
1335 .expect("lower subtrie node must exist");
1336 debug_assert!(
1339 node.hash().is_some(),
1340 "Lower subtrie root node at path {path:?} has no hash"
1341 );
1342 node
1343 };
1344
1345 self.upper_subtrie.inner.rlp_node(
1347 prefix_set,
1348 &mut update_actions_buf,
1349 stack_item,
1350 node,
1351 &self.branch_node_tree_masks,
1352 &self.branch_node_hash_masks,
1353 );
1354 }
1355
1356 if let Some(mut update_actions_buf) = update_actions_buf {
1359 self.apply_subtrie_update_actions(
1360 #[allow(clippy::iter_with_drain)]
1361 update_actions_buf.drain(..),
1362 );
1363 self.update_actions_buffers.push(update_actions_buf);
1364 }
1365
1366 #[cfg(feature = "metrics")]
1367 self.metrics.subtrie_upper_hash_latency.record(start.elapsed());
1368
1369 debug_assert_eq!(self.upper_subtrie.inner.buffers.rlp_node_stack.len(), 1);
1370 self.upper_subtrie.inner.buffers.rlp_node_stack.pop().unwrap().rlp_node
1371 }
1372
1373 fn take_changed_lower_subtries(
1387 &mut self,
1388 prefix_set: &mut PrefixSet,
1389 ) -> (Vec<ChangedSubtrie>, PrefixSetMut) {
1390 if prefix_set.is_empty() && !prefix_set.all() {
1393 return Default::default();
1394 }
1395
1396 let prefix_set_clone = prefix_set.clone();
1398 let mut prefix_set_iter = prefix_set_clone.into_iter().copied().peekable();
1399 let mut changed_subtries = Vec::new();
1400 let mut unchanged_prefix_set = PrefixSetMut::default();
1401 let updates_enabled = self.updates_enabled();
1402
1403 for (index, subtrie) in self.lower_subtries.iter_mut().enumerate() {
1404 if let Some(subtrie) = subtrie.take_revealed_if(|subtrie| {
1405 prefix_set.contains(&subtrie.path) ||
1406 subtrie.nodes.get(&subtrie.path).is_some_and(|n| n.hash().is_none())
1407 }) {
1408 let prefix_set = if prefix_set.all() {
1409 unchanged_prefix_set = PrefixSetMut::all();
1410 PrefixSetMut::all()
1411 } else {
1412 let mut new_prefix_set = Vec::new();
1417 while let Some(key) = prefix_set_iter.peek() {
1418 if key.starts_with(&subtrie.path) {
1419 new_prefix_set.push(prefix_set_iter.next().unwrap());
1421 } else if new_prefix_set.is_empty() && key < &subtrie.path {
1422 unchanged_prefix_set.insert(prefix_set_iter.next().unwrap());
1426 } else {
1427 break
1431 }
1432 }
1433 PrefixSetMut::from(new_prefix_set)
1434 }
1435 .freeze();
1436
1437 match subtrie.nodes.get(&subtrie.path) {
1440 Some(SparseNode::Extension { key, .. } | SparseNode::Leaf { key, .. }) => {
1441 unchanged_prefix_set.insert(subtrie.path.join(key));
1442 }
1443 Some(SparseNode::Branch { .. }) => {
1444 unchanged_prefix_set.insert(subtrie.path);
1445 }
1446 _ => {}
1447 }
1448
1449 let update_actions_buf =
1450 updates_enabled.then(|| self.update_actions_buffers.pop().unwrap_or_default());
1451
1452 changed_subtries.push(ChangedSubtrie {
1453 index,
1454 subtrie,
1455 prefix_set,
1456 update_actions_buf,
1457 });
1458 }
1459 }
1460
1461 unchanged_prefix_set.extend_keys(prefix_set_iter);
1463
1464 (changed_subtries, unchanged_prefix_set)
1465 }
1466
1467 #[cfg(test)]
1469 fn all_nodes(&self) -> impl IntoIterator<Item = (&Nibbles, &SparseNode)> {
1470 let mut nodes = vec![];
1471 for subtrie in self.lower_subtries.iter().filter_map(LowerSparseSubtrie::as_revealed_ref) {
1472 nodes.extend(subtrie.nodes.iter())
1473 }
1474 nodes.extend(self.upper_subtrie.nodes.iter());
1475 nodes
1476 }
1477
1478 fn reveal_upper_node(
1495 &mut self,
1496 path: Nibbles,
1497 node: &TrieNode,
1498 masks: TrieMasks,
1499 ) -> SparseTrieResult<()> {
1500 self.upper_subtrie.reveal_node(path, node, masks)?;
1503
1504 match node {
1509 TrieNode::Branch(branch) => {
1510 if !SparseSubtrieType::path_len_is_upper(path.len() + 1) {
1514 let mut stack_ptr = branch.as_ref().first_child_index();
1515 for idx in CHILD_INDEX_RANGE {
1516 if branch.state_mask.is_bit_set(idx) {
1517 let mut child_path = path;
1518 child_path.push_unchecked(idx);
1519 self.lower_subtrie_for_path_mut(&child_path)
1520 .expect("child_path must have a lower subtrie")
1521 .reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
1522 stack_ptr += 1;
1523 }
1524 }
1525 }
1526 }
1527 TrieNode::Extension(ext) => {
1528 let mut child_path = path;
1529 child_path.extend(&ext.key);
1530 if let Some(subtrie) = self.lower_subtrie_for_path_mut(&child_path) {
1531 subtrie.reveal_node_or_hash(child_path, &ext.child)?;
1532 }
1533 }
1534 TrieNode::EmptyRoot | TrieNode::Leaf(_) => (),
1535 }
1536
1537 Ok(())
1538 }
1539
1540 fn insert_changed_subtries(
1543 &mut self,
1544 changed_subtries: impl IntoIterator<Item = ChangedSubtrie>,
1545 ) {
1546 for ChangedSubtrie { index, subtrie, update_actions_buf, .. } in changed_subtries {
1547 if let Some(mut update_actions_buf) = update_actions_buf {
1548 self.apply_subtrie_update_actions(
1549 #[allow(clippy::iter_with_drain)]
1550 update_actions_buf.drain(..),
1551 );
1552 self.update_actions_buffers.push(update_actions_buf);
1553 }
1554
1555 self.lower_subtries[index] = LowerSparseSubtrie::Revealed(subtrie);
1556 }
1557 }
1558}
1559
1560#[derive(Clone, PartialEq, Eq, Debug, Default)]
1563pub struct SparseSubtrie {
1564 pub(crate) path: Nibbles,
1572 nodes: HashMap<Nibbles, SparseNode>,
1574 inner: SparseSubtrieInner,
1576}
1577
1578enum FindNextToLeafOutcome {
1581 Found,
1583 ContinueFrom(Nibbles),
1585 NotFound,
1588 BlindedNode(B256),
1591}
1592
1593impl SparseSubtrie {
1594 pub(crate) fn new(path: Nibbles) -> Self {
1596 Self { path, ..Default::default() }
1597 }
1598
1599 pub(crate) fn is_empty(&self) -> bool {
1601 self.nodes.is_empty()
1602 }
1603
1604 fn is_child_same_level(current_path: &Nibbles, child_path: &Nibbles) -> bool {
1606 let current_level = core::mem::discriminant(&SparseSubtrieType::from_path(current_path));
1607 let child_level = core::mem::discriminant(&SparseSubtrieType::from_path(child_path));
1608 current_level == child_level
1609 }
1610
1611 pub fn update_leaf(
1624 &mut self,
1625 full_path: Nibbles,
1626 value: Vec<u8>,
1627 provider: impl TrieNodeProvider,
1628 retain_updates: bool,
1629 ) -> SparseTrieResult<()> {
1630 debug_assert!(full_path.starts_with(&self.path));
1631 let existing = self.inner.values.insert(full_path, value);
1632 if existing.is_some() {
1633 return Ok(())
1635 }
1636
1637 let mut current = Some(self.path);
1639 while let Some(current_path) = current {
1640 match self.update_next_node(current_path, &full_path, retain_updates)? {
1641 LeafUpdateStep::Continue { next_node } => {
1642 current = Some(next_node);
1643 }
1644 LeafUpdateStep::Complete { reveal_path, .. } => {
1645 if let Some(reveal_path) = reveal_path &&
1646 self.nodes.get(&reveal_path).expect("node must exist").is_hash()
1647 {
1648 debug!(
1649 target: "trie::parallel_sparse",
1650 child_path = ?reveal_path,
1651 leaf_full_path = ?full_path,
1652 "Extension node child not revealed in update_leaf, falling back to db",
1653 );
1654 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1655 provider.trie_node(&reveal_path)?
1656 {
1657 let decoded = TrieNode::decode(&mut &node[..])?;
1658 trace!(
1659 target: "trie::parallel_sparse",
1660 ?reveal_path,
1661 ?decoded,
1662 ?tree_mask,
1663 ?hash_mask,
1664 "Revealing child (from lower)",
1665 );
1666 self.reveal_node(
1667 reveal_path,
1668 &decoded,
1669 TrieMasks { hash_mask, tree_mask },
1670 )?;
1671 } else {
1672 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1673 path: reveal_path,
1674 }
1675 .into())
1676 }
1677 }
1678
1679 current = None;
1680 }
1681 LeafUpdateStep::NodeNotFound => {
1682 current = None;
1683 }
1684 }
1685 }
1686
1687 Ok(())
1688 }
1689
1690 fn update_next_node(
1697 &mut self,
1698 mut current: Nibbles,
1699 path: &Nibbles,
1700 retain_updates: bool,
1701 ) -> SparseTrieResult<LeafUpdateStep> {
1702 debug_assert!(path.starts_with(&self.path));
1703 debug_assert!(current.starts_with(&self.path));
1704 debug_assert!(path.starts_with(¤t));
1705 let Some(node) = self.nodes.get_mut(¤t) else {
1706 return Ok(LeafUpdateStep::NodeNotFound);
1707 };
1708 match node {
1709 SparseNode::Empty => {
1710 let path = path.slice(self.path.len()..);
1713 *node = SparseNode::new_leaf(path);
1714 Ok(LeafUpdateStep::complete_with_insertions(vec![current], None))
1715 }
1716 SparseNode::Hash(hash) => {
1717 Err(SparseTrieErrorKind::BlindedNode { path: current, hash: *hash }.into())
1718 }
1719 SparseNode::Leaf { key: current_key, .. } => {
1720 current.extend(current_key);
1721
1722 debug_assert!(
1724 ¤t != path,
1725 "we already checked leaf presence in the beginning"
1726 );
1727
1728 let common = current.common_prefix_length(path);
1730
1731 let new_ext_key = current.slice(current.len() - current_key.len()..common);
1733 *node = SparseNode::new_ext(new_ext_key);
1734
1735 self.nodes.reserve(3);
1737 let branch_path = current.slice(..common);
1738 let new_leaf_path = path.slice(..=common);
1739 let existing_leaf_path = current.slice(..=common);
1740
1741 self.nodes.insert(
1742 branch_path,
1743 SparseNode::new_split_branch(
1744 current.get_unchecked(common),
1745 path.get_unchecked(common),
1746 ),
1747 );
1748 self.nodes.insert(new_leaf_path, SparseNode::new_leaf(path.slice(common + 1..)));
1749 self.nodes
1750 .insert(existing_leaf_path, SparseNode::new_leaf(current.slice(common + 1..)));
1751
1752 Ok(LeafUpdateStep::complete_with_insertions(
1753 vec![branch_path, new_leaf_path, existing_leaf_path],
1754 None,
1755 ))
1756 }
1757 SparseNode::Extension { key, .. } => {
1758 current.extend(key);
1759
1760 if !path.starts_with(¤t) {
1761 let common = current.common_prefix_length(path);
1763 *key = current.slice(current.len() - key.len()..common);
1764
1765 let reveal_path = retain_updates.then_some(current);
1769
1770 self.nodes.reserve(3);
1773 let branch_path = current.slice(..common);
1774 let new_leaf_path = path.slice(..=common);
1775 let branch = SparseNode::new_split_branch(
1776 current.get_unchecked(common),
1777 path.get_unchecked(common),
1778 );
1779
1780 self.nodes.insert(branch_path, branch);
1781
1782 let new_leaf = SparseNode::new_leaf(path.slice(common + 1..));
1784 self.nodes.insert(new_leaf_path, new_leaf);
1785
1786 let mut inserted_nodes = vec![branch_path, new_leaf_path];
1787
1788 let key = current.slice(common + 1..);
1790 if !key.is_empty() {
1791 let ext_path = current.slice(..=common);
1792 self.nodes.insert(ext_path, SparseNode::new_ext(key));
1793 inserted_nodes.push(ext_path);
1794 }
1795
1796 return Ok(LeafUpdateStep::complete_with_insertions(inserted_nodes, reveal_path))
1797 }
1798
1799 Ok(LeafUpdateStep::continue_with(current))
1800 }
1801 SparseNode::Branch { state_mask, .. } => {
1802 let nibble = path.get_unchecked(current.len());
1803 current.push_unchecked(nibble);
1804 if !state_mask.is_bit_set(nibble) {
1805 state_mask.set_bit(nibble);
1806 let new_leaf = SparseNode::new_leaf(path.slice(current.len()..));
1807 self.nodes.insert(current, new_leaf);
1808 return Ok(LeafUpdateStep::complete_with_insertions(vec![current], None))
1809 }
1810
1811 Ok(LeafUpdateStep::continue_with(current))
1813 }
1814 }
1815 }
1816
1817 fn reveal_node(
1819 &mut self,
1820 path: Nibbles,
1821 node: &TrieNode,
1822 masks: TrieMasks,
1823 ) -> SparseTrieResult<()> {
1824 debug_assert!(path.starts_with(&self.path));
1825
1826 if self.nodes.get(&path).is_some_and(|node| !node.is_hash()) {
1828 return Ok(())
1829 }
1830
1831 match node {
1832 TrieNode::EmptyRoot => {
1833 debug_assert!(path.is_empty());
1835 debug_assert!(self.path.is_empty());
1836 self.nodes.insert(path, SparseNode::Empty);
1837 }
1838 TrieNode::Branch(branch) => {
1839 let mut stack_ptr = branch.as_ref().first_child_index();
1841 for idx in CHILD_INDEX_RANGE {
1842 if branch.state_mask.is_bit_set(idx) {
1843 let mut child_path = path;
1844 child_path.push_unchecked(idx);
1845 if Self::is_child_same_level(&path, &child_path) {
1846 self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
1849 }
1850 stack_ptr += 1;
1851 }
1852 }
1853 match self.nodes.entry(path) {
1856 Entry::Occupied(mut entry) => match entry.get() {
1857 SparseNode::Hash(hash) => {
1859 entry.insert(SparseNode::Branch {
1860 state_mask: branch.state_mask,
1861 hash: Some(*hash),
1864 store_in_db_trie: Some(
1865 masks.hash_mask.is_some_and(|mask| !mask.is_empty()) ||
1866 masks.tree_mask.is_some_and(|mask| !mask.is_empty()),
1867 ),
1868 });
1869 }
1870 SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
1873 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
1875 return Err(SparseTrieErrorKind::Reveal {
1876 path: *entry.key(),
1877 node: Box::new(node.clone()),
1878 }
1879 .into())
1880 }
1881 },
1882 Entry::Vacant(entry) => {
1883 entry.insert(SparseNode::new_branch(branch.state_mask));
1884 }
1885 }
1886 }
1887 TrieNode::Extension(ext) => match self.nodes.entry(path) {
1888 Entry::Occupied(mut entry) => match entry.get() {
1889 SparseNode::Hash(hash) => {
1891 let mut child_path = *entry.key();
1892 child_path.extend(&ext.key);
1893 entry.insert(SparseNode::Extension {
1894 key: ext.key,
1895 hash: Some(*hash),
1898 store_in_db_trie: None,
1899 });
1900 if Self::is_child_same_level(&path, &child_path) {
1901 self.reveal_node_or_hash(child_path, &ext.child)?;
1902 }
1903 }
1904 SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
1907 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
1909 return Err(SparseTrieErrorKind::Reveal {
1910 path: *entry.key(),
1911 node: Box::new(node.clone()),
1912 }
1913 .into())
1914 }
1915 },
1916 Entry::Vacant(entry) => {
1917 let mut child_path = *entry.key();
1918 child_path.extend(&ext.key);
1919 entry.insert(SparseNode::new_ext(ext.key));
1920 if Self::is_child_same_level(&path, &child_path) {
1921 self.reveal_node_or_hash(child_path, &ext.child)?;
1922 }
1923 }
1924 },
1925 TrieNode::Leaf(leaf) => match self.nodes.entry(path) {
1926 Entry::Occupied(mut entry) => match entry.get() {
1927 SparseNode::Hash(hash) => {
1929 let mut full = *entry.key();
1930 full.extend(&leaf.key);
1931 self.inner.values.insert(full, leaf.value.clone());
1932 entry.insert(SparseNode::Leaf {
1933 key: leaf.key,
1934 hash: Some(*hash),
1937 });
1938 }
1939 SparseNode::Leaf { .. } => {}
1941 node @ (SparseNode::Empty |
1943 SparseNode::Extension { .. } |
1944 SparseNode::Branch { .. }) => {
1945 return Err(SparseTrieErrorKind::Reveal {
1946 path: *entry.key(),
1947 node: Box::new(node.clone()),
1948 }
1949 .into())
1950 }
1951 },
1952 Entry::Vacant(entry) => {
1953 let mut full = *entry.key();
1954 full.extend(&leaf.key);
1955 entry.insert(SparseNode::new_leaf(leaf.key));
1956 self.inner.values.insert(full, leaf.value.clone());
1957 }
1958 },
1959 }
1960
1961 Ok(())
1962 }
1963
1964 fn reveal_node_or_hash(&mut self, path: Nibbles, child: &[u8]) -> SparseTrieResult<()> {
1983 if child.len() == B256::len_bytes() + 1 {
1984 let hash = B256::from_slice(&child[1..]);
1985 match self.nodes.entry(path) {
1986 Entry::Occupied(entry) => match entry.get() {
1987 SparseNode::Hash(previous_hash) if previous_hash != &hash => {
1989 return Err(SparseTrieErrorKind::Reveal {
1990 path: *entry.key(),
1991 node: Box::new(SparseNode::Hash(hash)),
1992 }
1993 .into())
1994 }
1995 _ => {}
1996 },
1997 Entry::Vacant(entry) => {
1998 entry.insert(SparseNode::Hash(hash));
1999 }
2000 }
2001 return Ok(())
2002 }
2003
2004 self.reveal_node(path, &TrieNode::decode(&mut &child[..])?, TrieMasks::none())
2005 }
2006
2007 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, fields(root = ?self.path), ret)]
2030 fn update_hashes(
2031 &mut self,
2032 prefix_set: &mut PrefixSet,
2033 update_actions: &mut Option<Vec<SparseTrieUpdatesAction>>,
2034 branch_node_tree_masks: &HashMap<Nibbles, TrieMask>,
2035 branch_node_hash_masks: &HashMap<Nibbles, TrieMask>,
2036 ) -> RlpNode {
2037 trace!(target: "trie::parallel_sparse", "Updating subtrie hashes");
2038
2039 debug_assert!(prefix_set.iter().all(|path| path.starts_with(&self.path)));
2040
2041 debug_assert!(self.inner.buffers.path_stack.is_empty());
2042 self.inner
2043 .buffers
2044 .path_stack
2045 .push(RlpNodePathStackItem { path: self.path, is_in_prefix_set: None });
2046
2047 while let Some(stack_item) = self.inner.buffers.path_stack.pop() {
2048 let path = stack_item.path;
2049 let node = self
2050 .nodes
2051 .get_mut(&path)
2052 .unwrap_or_else(|| panic!("node at path {path:?} does not exist"));
2053
2054 self.inner.rlp_node(
2055 prefix_set,
2056 update_actions,
2057 stack_item,
2058 node,
2059 branch_node_tree_masks,
2060 branch_node_hash_masks,
2061 );
2062 }
2063
2064 debug_assert_eq!(self.inner.buffers.rlp_node_stack.len(), 1);
2065 self.inner.buffers.rlp_node_stack.pop().unwrap().rlp_node
2066 }
2067
2068 fn wipe(&mut self) {
2071 self.nodes = HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]);
2072 self.inner.clear();
2073 }
2074
2075 pub(crate) fn clear(&mut self) {
2077 self.nodes.clear();
2078 self.inner.clear();
2079 }
2080}
2081
2082#[derive(Clone, PartialEq, Eq, Debug, Default)]
2085struct SparseSubtrieInner {
2086 values: HashMap<Nibbles, Vec<u8>>,
2089 buffers: SparseSubtrieBuffers,
2091}
2092
2093impl SparseSubtrieInner {
2094 fn rlp_node(
2125 &mut self,
2126 prefix_set: &mut PrefixSet,
2127 update_actions: &mut Option<Vec<SparseTrieUpdatesAction>>,
2128 mut stack_item: RlpNodePathStackItem,
2129 node: &mut SparseNode,
2130 branch_node_tree_masks: &HashMap<Nibbles, TrieMask>,
2131 branch_node_hash_masks: &HashMap<Nibbles, TrieMask>,
2132 ) {
2133 let path = stack_item.path;
2134 trace!(
2135 target: "trie::parallel_sparse",
2136 ?path,
2137 ?node,
2138 "Calculating node RLP"
2139 );
2140
2141 let mut prefix_set_contains = |path: &Nibbles| {
2145 *stack_item.is_in_prefix_set.get_or_insert_with(|| prefix_set.contains(path))
2146 };
2147
2148 let (rlp_node, node_type) = match node {
2149 SparseNode::Empty => (RlpNode::word_rlp(&EMPTY_ROOT_HASH), SparseNodeType::Empty),
2150 SparseNode::Hash(hash) => {
2151 (RlpNode::word_rlp(hash), SparseNodeType::Hash)
2153 }
2154 SparseNode::Leaf { key, hash } => {
2155 let mut path = path;
2156 path.extend(key);
2157 let value = self.values.get(&path);
2158 if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path) || value.is_none())
2159 {
2160 (RlpNode::word_rlp(&hash), SparseNodeType::Leaf)
2164 } else {
2165 let value = self.values.get(&path).unwrap();
2167 self.buffers.rlp_buf.clear();
2168 let rlp_node = LeafNodeRef { key, value }.rlp(&mut self.buffers.rlp_buf);
2169 *hash = rlp_node.as_hash();
2170 (rlp_node, SparseNodeType::Leaf)
2171 }
2172 }
2173 SparseNode::Extension { key, hash, store_in_db_trie } => {
2174 let mut child_path = path;
2175 child_path.extend(key);
2176 if let Some((hash, store_in_db_trie)) =
2177 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
2178 {
2179 (
2182 RlpNode::word_rlp(&hash),
2183 SparseNodeType::Extension { store_in_db_trie: Some(store_in_db_trie) },
2184 )
2185 } else if self.buffers.rlp_node_stack.last().is_some_and(|e| e.path == child_path) {
2186 let RlpNodeStackItem { path: _, rlp_node: child, node_type: child_node_type } =
2189 self.buffers.rlp_node_stack.pop().unwrap();
2190 self.buffers.rlp_buf.clear();
2191 let rlp_node =
2192 ExtensionNodeRef::new(key, &child).rlp(&mut self.buffers.rlp_buf);
2193 *hash = rlp_node.as_hash();
2194
2195 let store_in_db_trie_value = child_node_type.store_in_db_trie();
2196
2197 trace!(
2198 target: "trie::parallel_sparse",
2199 ?path,
2200 ?child_path,
2201 ?child_node_type,
2202 "Extension node"
2203 );
2204
2205 *store_in_db_trie = store_in_db_trie_value;
2206
2207 (
2208 rlp_node,
2209 SparseNodeType::Extension {
2210 store_in_db_trie: store_in_db_trie_value,
2213 },
2214 )
2215 } else {
2216 self.buffers.path_stack.extend([
2219 RlpNodePathStackItem {
2220 path,
2221 is_in_prefix_set: Some(prefix_set_contains(&path)),
2222 },
2223 RlpNodePathStackItem { path: child_path, is_in_prefix_set: None },
2224 ]);
2225 return
2226 }
2227 }
2228 SparseNode::Branch { state_mask, hash, store_in_db_trie } => {
2229 if let Some((hash, store_in_db_trie)) =
2230 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
2231 {
2232 self.buffers.rlp_node_stack.push(RlpNodeStackItem {
2235 path,
2236 rlp_node: RlpNode::word_rlp(&hash),
2237 node_type: SparseNodeType::Branch {
2238 store_in_db_trie: Some(store_in_db_trie),
2239 },
2240 });
2241 return
2242 }
2243
2244 let retain_updates = update_actions.is_some() && prefix_set_contains(&path);
2245
2246 self.buffers.branch_child_buf.clear();
2247 for bit in CHILD_INDEX_RANGE.rev() {
2250 if state_mask.is_bit_set(bit) {
2251 let mut child = path;
2252 child.push_unchecked(bit);
2253 self.buffers.branch_child_buf.push(child);
2254 }
2255 }
2256
2257 self.buffers
2258 .branch_value_stack_buf
2259 .resize(self.buffers.branch_child_buf.len(), Default::default());
2260 let mut added_children = false;
2261
2262 let mut tree_mask = TrieMask::default();
2263 let mut hash_mask = TrieMask::default();
2264 let mut hashes = Vec::new();
2265 for (i, child_path) in self.buffers.branch_child_buf.iter().enumerate() {
2266 if self.buffers.rlp_node_stack.last().is_some_and(|e| &e.path == child_path) {
2267 let RlpNodeStackItem {
2268 path: _,
2269 rlp_node: child,
2270 node_type: child_node_type,
2271 } = self.buffers.rlp_node_stack.pop().unwrap();
2272
2273 if retain_updates {
2275 let last_child_nibble = child_path.last().unwrap();
2277
2278 let should_set_tree_mask_bit = if let Some(store_in_db_trie) =
2280 child_node_type.store_in_db_trie()
2281 {
2282 store_in_db_trie
2285 } else {
2286 child_node_type.is_hash() &&
2288 branch_node_tree_masks
2289 .get(&path)
2290 .is_some_and(|mask| mask.is_bit_set(last_child_nibble))
2291 };
2292 if should_set_tree_mask_bit {
2293 tree_mask.set_bit(last_child_nibble);
2294 }
2295
2296 let hash = child.as_hash().filter(|_| {
2300 child_node_type.is_branch() ||
2301 (child_node_type.is_hash() &&
2302 branch_node_hash_masks.get(&path).is_some_and(
2303 |mask| mask.is_bit_set(last_child_nibble),
2304 ))
2305 });
2306 if let Some(hash) = hash {
2307 hash_mask.set_bit(last_child_nibble);
2308 hashes.push(hash);
2309 }
2310 }
2311
2312 let original_idx = self.buffers.branch_child_buf.len() - i - 1;
2316 self.buffers.branch_value_stack_buf[original_idx] = child;
2317 added_children = true;
2318 } else {
2319 debug_assert!(!added_children);
2322 self.buffers.path_stack.push(RlpNodePathStackItem {
2323 path,
2324 is_in_prefix_set: Some(prefix_set_contains(&path)),
2325 });
2326 self.buffers.path_stack.extend(
2327 self.buffers
2328 .branch_child_buf
2329 .drain(..)
2330 .map(|path| RlpNodePathStackItem { path, is_in_prefix_set: None }),
2331 );
2332 return
2333 }
2334 }
2335
2336 trace!(
2337 target: "trie::parallel_sparse",
2338 ?path,
2339 ?tree_mask,
2340 ?hash_mask,
2341 "Branch node masks"
2342 );
2343
2344 self.buffers.rlp_buf.clear();
2347 let branch_node_ref =
2348 BranchNodeRef::new(&self.buffers.branch_value_stack_buf, *state_mask);
2349 let rlp_node = branch_node_ref.rlp(&mut self.buffers.rlp_buf);
2350 *hash = rlp_node.as_hash();
2351
2352 let store_in_db_trie_value = if let Some(update_actions) =
2355 update_actions.as_mut().filter(|_| retain_updates && !path.is_empty())
2356 {
2357 let store_in_db_trie = !tree_mask.is_empty() || !hash_mask.is_empty();
2358 if store_in_db_trie {
2359 hashes.reverse();
2362 let branch_node = BranchNodeCompact::new(
2363 *state_mask,
2364 tree_mask,
2365 hash_mask,
2366 hashes,
2367 hash.filter(|_| path.is_empty()),
2368 );
2369 update_actions
2370 .push(SparseTrieUpdatesAction::InsertUpdated(path, branch_node));
2371 } else if branch_node_tree_masks.get(&path).is_some_and(|mask| !mask.is_empty()) ||
2372 branch_node_hash_masks.get(&path).is_some_and(|mask| !mask.is_empty())
2373 {
2374 update_actions.push(SparseTrieUpdatesAction::InsertRemoved(path));
2378 } else if branch_node_tree_masks.get(&path).is_none_or(|mask| mask.is_empty()) &&
2379 branch_node_hash_masks.get(&path).is_none_or(|mask| mask.is_empty())
2380 {
2381 update_actions.push(SparseTrieUpdatesAction::RemoveUpdated(path));
2384 }
2385
2386 store_in_db_trie
2387 } else {
2388 false
2389 };
2390 *store_in_db_trie = Some(store_in_db_trie_value);
2391
2392 (
2393 rlp_node,
2394 SparseNodeType::Branch { store_in_db_trie: Some(store_in_db_trie_value) },
2395 )
2396 }
2397 };
2398
2399 self.buffers.rlp_node_stack.push(RlpNodeStackItem { path, rlp_node, node_type });
2400 trace!(
2401 target: "trie::parallel_sparse",
2402 ?path,
2403 ?node_type,
2404 "Added node to RLP node stack"
2405 );
2406 }
2407
2408 fn clear(&mut self) {
2410 self.values.clear();
2411 self.buffers.clear();
2412 }
2413}
2414
2415#[derive(Clone, Debug, PartialEq, Eq, Default)]
2417pub enum LeafUpdateStep {
2418 Continue {
2420 next_node: Nibbles,
2422 },
2423 Complete {
2425 inserted_nodes: Vec<Nibbles>,
2427 reveal_path: Option<Nibbles>,
2429 },
2430 #[default]
2432 NodeNotFound,
2433}
2434
2435impl LeafUpdateStep {
2436 pub const fn continue_with(next_node: Nibbles) -> Self {
2438 Self::Continue { next_node }
2439 }
2440
2441 pub const fn complete_with_insertions(
2443 inserted_nodes: Vec<Nibbles>,
2444 reveal_path: Option<Nibbles>,
2445 ) -> Self {
2446 Self::Complete { inserted_nodes, reveal_path }
2447 }
2448}
2449
2450#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2459pub enum SparseSubtrieType {
2460 Upper,
2462 Lower(usize),
2465}
2466
2467impl SparseSubtrieType {
2468 pub const fn path_len_is_upper(len: usize) -> bool {
2473 len < UPPER_TRIE_MAX_DEPTH
2474 }
2475
2476 pub fn from_path(path: &Nibbles) -> Self {
2478 if Self::path_len_is_upper(path.len()) {
2479 Self::Upper
2480 } else {
2481 Self::Lower(path_subtrie_index_unchecked(path))
2482 }
2483 }
2484
2485 pub const fn lower_index(&self) -> Option<usize> {
2487 match self {
2488 Self::Upper => None,
2489 Self::Lower(index) => Some(*index),
2490 }
2491 }
2492}
2493
2494impl Ord for SparseSubtrieType {
2495 fn cmp(&self, other: &Self) -> Ordering {
2498 match (self, other) {
2499 (Self::Upper, Self::Upper) => Ordering::Equal,
2500 (Self::Upper, Self::Lower(_)) => Ordering::Less,
2501 (Self::Lower(_), Self::Upper) => Ordering::Greater,
2502 (Self::Lower(idx_a), Self::Lower(idx_b)) if idx_a == idx_b => Ordering::Equal,
2503 (Self::Lower(idx_a), Self::Lower(idx_b)) => idx_a.cmp(idx_b),
2504 }
2505 }
2506}
2507
2508impl PartialOrd for SparseSubtrieType {
2509 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2510 Some(self.cmp(other))
2511 }
2512}
2513
2514#[derive(Clone, PartialEq, Eq, Debug, Default)]
2518pub struct SparseSubtrieBuffers {
2519 path_stack: Vec<RlpNodePathStackItem>,
2521 rlp_node_stack: Vec<RlpNodeStackItem>,
2523 branch_child_buf: SmallVec<[Nibbles; 16]>,
2525 branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
2527 rlp_buf: Vec<u8>,
2529}
2530
2531impl SparseSubtrieBuffers {
2532 fn clear(&mut self) {
2534 self.path_stack.clear();
2535 self.rlp_node_stack.clear();
2536 self.branch_child_buf.clear();
2537 self.branch_value_stack_buf.clear();
2538 self.rlp_buf.clear();
2539 }
2540}
2541
2542#[derive(Clone, PartialEq, Eq, Debug)]
2544pub struct RlpNodePathStackItem {
2545 pub path: Nibbles,
2547 pub is_in_prefix_set: Option<bool>,
2549}
2550
2551#[derive(Debug)]
2553struct ChangedSubtrie {
2554 index: usize,
2556 subtrie: Box<SparseSubtrie>,
2558 prefix_set: PrefixSet,
2560 update_actions_buf: Option<Vec<SparseTrieUpdatesAction>>,
2563}
2564
2565fn path_subtrie_index_unchecked(path: &Nibbles) -> usize {
2572 debug_assert_eq!(UPPER_TRIE_MAX_DEPTH, 2);
2573 path.get_byte_unchecked(0) as usize
2574}
2575
2576#[derive(Clone, Debug, Eq, PartialEq)]
2578enum SparseTrieUpdatesAction {
2579 InsertRemoved(Nibbles),
2581 RemoveUpdated(Nibbles),
2584 InsertUpdated(Nibbles, BranchNodeCompact),
2586}
2587
2588#[cfg(test)]
2589mod tests {
2590 use super::{
2591 path_subtrie_index_unchecked, LowerSparseSubtrie, ParallelSparseTrie, SparseSubtrie,
2592 SparseSubtrieType,
2593 };
2594 use crate::trie::ChangedSubtrie;
2595 use alloy_primitives::{
2596 b256, hex,
2597 map::{B256Set, DefaultHashBuilder, HashMap},
2598 B256, U256,
2599 };
2600 use alloy_rlp::{Decodable, Encodable};
2601 use alloy_trie::{BranchNodeCompact, Nibbles};
2602 use assert_matches::assert_matches;
2603 use itertools::Itertools;
2604 use proptest::{prelude::*, sample::SizeRange};
2605 use proptest_arbitrary_interop::arb;
2606 use reth_execution_errors::{SparseTrieError, SparseTrieErrorKind};
2607 use reth_primitives_traits::Account;
2608 use reth_provider::{test_utils::create_test_provider_factory, TrieWriter};
2609 use reth_trie::{
2610 hashed_cursor::{noop::NoopHashedAccountCursor, HashedPostStateAccountCursor},
2611 node_iter::{TrieElement, TrieNodeIter},
2612 trie_cursor::{noop::NoopAccountTrieCursor, TrieCursor, TrieCursorFactory},
2613 walker::TrieWalker,
2614 HashedPostState,
2615 };
2616 use reth_trie_common::{
2617 prefix_set::PrefixSetMut,
2618 proof::{ProofNodes, ProofRetainer},
2619 updates::TrieUpdates,
2620 BranchNode, ExtensionNode, HashBuilder, LeafNode, RlpNode, TrieMask, TrieNode,
2621 EMPTY_ROOT_HASH,
2622 };
2623 use reth_trie_db::DatabaseTrieCursorFactory;
2624 use reth_trie_sparse::{
2625 provider::{DefaultTrieNodeProvider, RevealedNode, TrieNodeProvider},
2626 LeafLookup, LeafLookupError, RevealedSparseNode, SerialSparseTrie, SparseNode,
2627 SparseTrieInterface, SparseTrieUpdates, TrieMasks,
2628 };
2629 use std::collections::{BTreeMap, BTreeSet};
2630
2631 fn pad_nibbles_right(mut nibbles: Nibbles) -> Nibbles {
2633 nibbles.extend(&Nibbles::from_nibbles_unchecked(vec![
2634 0;
2635 B256::len_bytes() * 2 - nibbles.len()
2636 ]));
2637 nibbles
2638 }
2639
2640 #[derive(Debug, Clone)]
2645 struct MockTrieNodeProvider {
2646 nodes: HashMap<Nibbles, RevealedNode, DefaultHashBuilder>,
2648 }
2649
2650 impl MockTrieNodeProvider {
2651 fn new() -> Self {
2653 Self { nodes: HashMap::default() }
2654 }
2655
2656 fn add_revealed_node(&mut self, path: Nibbles, node: RevealedNode) {
2658 self.nodes.insert(path, node);
2659 }
2660 }
2661
2662 impl TrieNodeProvider for MockTrieNodeProvider {
2663 fn trie_node(&self, path: &Nibbles) -> Result<Option<RevealedNode>, SparseTrieError> {
2664 Ok(self.nodes.get(path).cloned())
2665 }
2666 }
2667
2668 fn create_account(nonce: u64) -> Account {
2669 Account { nonce, ..Default::default() }
2670 }
2671
2672 fn encode_account_value(nonce: u64) -> Vec<u8> {
2673 let account = Account { nonce, ..Default::default() };
2674 let trie_account = account.into_trie_account(EMPTY_ROOT_HASH);
2675 let mut buf = Vec::new();
2676 trie_account.encode(&mut buf);
2677 buf
2678 }
2679
2680 #[derive(Default)]
2682 struct ParallelSparseTrieTestContext;
2683
2684 impl ParallelSparseTrieTestContext {
2685 fn assert_subtrie_exists(&self, trie: &ParallelSparseTrie, path: &Nibbles) {
2687 let idx = path_subtrie_index_unchecked(path);
2688 assert!(
2689 trie.lower_subtries[idx].as_revealed_ref().is_some(),
2690 "Expected lower subtrie at path {path:?} to exist",
2691 );
2692 }
2693
2694 fn get_subtrie<'a>(
2696 &self,
2697 trie: &'a ParallelSparseTrie,
2698 path: &Nibbles,
2699 ) -> &'a SparseSubtrie {
2700 let idx = path_subtrie_index_unchecked(path);
2701 trie.lower_subtries[idx]
2702 .as_revealed_ref()
2703 .unwrap_or_else(|| panic!("Lower subtrie at path {path:?} should exist"))
2704 }
2705
2706 fn assert_subtrie_path(
2708 &self,
2709 trie: &ParallelSparseTrie,
2710 subtrie_prefix: impl AsRef<[u8]>,
2711 expected_path: impl AsRef<[u8]>,
2712 ) {
2713 let subtrie_prefix = Nibbles::from_nibbles(subtrie_prefix);
2714 let expected_path = Nibbles::from_nibbles(expected_path);
2715 let idx = path_subtrie_index_unchecked(&subtrie_prefix);
2716
2717 let subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap_or_else(|| {
2718 panic!("Lower subtrie at prefix {subtrie_prefix:?} should exist")
2719 });
2720
2721 assert_eq!(
2722 subtrie.path, expected_path,
2723 "Subtrie at prefix {subtrie_prefix:?} should have path {expected_path:?}, but has {:?}",
2724 subtrie.path
2725 );
2726 }
2727
2728 fn create_test_leaves(&self, paths: &[&[u8]]) -> Vec<(Nibbles, Vec<u8>)> {
2730 paths
2731 .iter()
2732 .enumerate()
2733 .map(|(i, path)| (Nibbles::from_nibbles(path), encode_account_value(i as u64 + 1)))
2734 .collect()
2735 }
2736
2737 fn create_test_leaf(&self, path: impl AsRef<[u8]>, value_nonce: u64) -> (Nibbles, Vec<u8>) {
2739 (Nibbles::from_nibbles(path), encode_account_value(value_nonce))
2740 }
2741
2742 fn update_leaves(
2744 &self,
2745 trie: &mut ParallelSparseTrie,
2746 leaves: impl IntoIterator<Item = (Nibbles, Vec<u8>)>,
2747 ) {
2748 for (path, value) in leaves {
2749 trie.update_leaf(path, value, DefaultTrieNodeProvider).unwrap();
2750 }
2751 }
2752
2753 fn assert_subtrie<'a>(
2755 &self,
2756 trie: &'a ParallelSparseTrie,
2757 path: Nibbles,
2758 ) -> SubtrieAssertion<'a> {
2759 self.assert_subtrie_exists(trie, &path);
2760 let subtrie = self.get_subtrie(trie, &path);
2761 SubtrieAssertion::new(subtrie)
2762 }
2763
2764 fn assert_upper_subtrie<'a>(&self, trie: &'a ParallelSparseTrie) -> SubtrieAssertion<'a> {
2766 SubtrieAssertion::new(&trie.upper_subtrie)
2767 }
2768
2769 fn assert_with_hash_builder(
2771 &self,
2772 trie: &mut ParallelSparseTrie,
2773 hash_builder_root: B256,
2774 hash_builder_updates: TrieUpdates,
2775 hash_builder_proof_nodes: ProofNodes,
2776 ) {
2777 assert_eq!(trie.root(), hash_builder_root);
2778 pretty_assertions::assert_eq!(
2779 BTreeMap::from_iter(trie.updates_ref().updated_nodes.clone()),
2780 BTreeMap::from_iter(hash_builder_updates.account_nodes)
2781 );
2782 assert_eq_parallel_sparse_trie_proof_nodes(trie, hash_builder_proof_nodes);
2783 }
2784 }
2785
2786 struct SubtrieAssertion<'a> {
2788 subtrie: &'a SparseSubtrie,
2789 }
2790
2791 impl<'a> SubtrieAssertion<'a> {
2792 fn new(subtrie: &'a SparseSubtrie) -> Self {
2793 Self { subtrie }
2794 }
2795
2796 fn has_branch(self, path: &Nibbles, expected_mask_bits: &[u8]) -> Self {
2797 match self.subtrie.nodes.get(path) {
2798 Some(SparseNode::Branch { state_mask, .. }) => {
2799 for bit in expected_mask_bits {
2800 assert!(
2801 state_mask.is_bit_set(*bit),
2802 "Expected branch at {path:?} to have bit {bit} set, instead mask is: {state_mask:?}",
2803 );
2804 }
2805 }
2806 node => panic!("Expected branch node at {path:?}, found {node:?}"),
2807 }
2808 self
2809 }
2810
2811 fn has_leaf(self, path: &Nibbles, expected_key: &Nibbles) -> Self {
2812 match self.subtrie.nodes.get(path) {
2813 Some(SparseNode::Leaf { key, .. }) => {
2814 assert_eq!(
2815 *key, *expected_key,
2816 "Expected leaf at {path:?} to have key {expected_key:?}, found {key:?}",
2817 );
2818 }
2819 node => panic!("Expected leaf node at {path:?}, found {node:?}"),
2820 }
2821 self
2822 }
2823
2824 fn has_extension(self, path: &Nibbles, expected_key: &Nibbles) -> Self {
2825 match self.subtrie.nodes.get(path) {
2826 Some(SparseNode::Extension { key, .. }) => {
2827 assert_eq!(
2828 *key, *expected_key,
2829 "Expected extension at {path:?} to have key {expected_key:?}, found {key:?}",
2830 );
2831 }
2832 node => panic!("Expected extension node at {path:?}, found {node:?}"),
2833 }
2834 self
2835 }
2836
2837 fn has_hash(self, path: &Nibbles, expected_hash: &B256) -> Self {
2838 match self.subtrie.nodes.get(path) {
2839 Some(SparseNode::Hash(hash)) => {
2840 assert_eq!(
2841 *hash, *expected_hash,
2842 "Expected hash at {path:?} to be {expected_hash:?}, found {hash:?}",
2843 );
2844 }
2845 node => panic!("Expected hash node at {path:?}, found {node:?}"),
2846 }
2847 self
2848 }
2849
2850 fn has_value(self, path: &Nibbles, expected_value: &[u8]) -> Self {
2851 let actual = self.subtrie.inner.values.get(path);
2852 assert_eq!(
2853 actual.map(|v| v.as_slice()),
2854 Some(expected_value),
2855 "Expected value at {path:?} to be {expected_value:?}, found {actual:?}",
2856 );
2857 self
2858 }
2859
2860 fn has_no_value(self, path: &Nibbles) -> Self {
2861 let actual = self.subtrie.inner.values.get(path);
2862 assert!(actual.is_none(), "Expected no value at {path:?}, but found {actual:?}");
2863 self
2864 }
2865 }
2866
2867 fn create_leaf_node(key: impl AsRef<[u8]>, value_nonce: u64) -> TrieNode {
2868 TrieNode::Leaf(LeafNode::new(Nibbles::from_nibbles(key), encode_account_value(value_nonce)))
2869 }
2870
2871 fn create_extension_node(key: impl AsRef<[u8]>, child_hash: B256) -> TrieNode {
2872 TrieNode::Extension(ExtensionNode::new(
2873 Nibbles::from_nibbles(key),
2874 RlpNode::word_rlp(&child_hash),
2875 ))
2876 }
2877
2878 fn create_branch_node_with_children(
2879 children_indices: &[u8],
2880 child_hashes: impl IntoIterator<Item = RlpNode>,
2881 ) -> TrieNode {
2882 let mut stack = Vec::new();
2883 let mut state_mask = TrieMask::default();
2884
2885 for (&idx, hash) in children_indices.iter().zip(child_hashes.into_iter()) {
2886 state_mask.set_bit(idx);
2887 stack.push(hash);
2888 }
2889
2890 TrieNode::Branch(BranchNode::new(stack, state_mask))
2891 }
2892
2893 fn run_hash_builder(
2898 state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
2899 trie_cursor: impl TrieCursor,
2900 destroyed_accounts: B256Set,
2901 proof_targets: impl IntoIterator<Item = Nibbles>,
2902 ) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>, HashMap<Nibbles, TrieMask>)
2903 {
2904 let mut account_rlp = Vec::new();
2905
2906 let mut hash_builder = HashBuilder::default()
2907 .with_updates(true)
2908 .with_proof_retainer(ProofRetainer::from_iter(proof_targets));
2909
2910 let mut prefix_set = PrefixSetMut::default();
2911 prefix_set.extend_keys(state.clone().into_iter().map(|(nibbles, _)| nibbles));
2912 prefix_set.extend_keys(destroyed_accounts.iter().map(Nibbles::unpack));
2913 let walker = TrieWalker::<_>::state_trie(trie_cursor, prefix_set.freeze())
2914 .with_deletions_retained(true);
2915 let hashed_post_state = HashedPostState::default()
2916 .with_accounts(state.into_iter().map(|(nibbles, account)| {
2917 (nibbles.pack().into_inner().unwrap().into(), Some(account))
2918 }))
2919 .into_sorted();
2920 let mut node_iter = TrieNodeIter::state_trie(
2921 walker,
2922 HashedPostStateAccountCursor::new(
2923 NoopHashedAccountCursor::default(),
2924 hashed_post_state.accounts(),
2925 ),
2926 );
2927
2928 while let Some(node) = node_iter.try_next().unwrap() {
2929 match node {
2930 TrieElement::Branch(branch) => {
2931 hash_builder.add_branch(branch.key, branch.value, branch.children_are_in_trie);
2932 }
2933 TrieElement::Leaf(key, account) => {
2934 let account = account.into_trie_account(EMPTY_ROOT_HASH);
2935 account.encode(&mut account_rlp);
2936
2937 hash_builder.add_leaf(Nibbles::unpack(key), &account_rlp);
2938 account_rlp.clear();
2939 }
2940 }
2941 }
2942 let root = hash_builder.root();
2943 let proof_nodes = hash_builder.take_proof_nodes();
2944 let branch_node_hash_masks = hash_builder
2945 .updated_branch_nodes
2946 .clone()
2947 .unwrap_or_default()
2948 .iter()
2949 .map(|(path, node)| (*path, node.hash_mask))
2950 .collect();
2951 let branch_node_tree_masks = hash_builder
2952 .updated_branch_nodes
2953 .clone()
2954 .unwrap_or_default()
2955 .iter()
2956 .map(|(path, node)| (*path, node.tree_mask))
2957 .collect();
2958
2959 let mut trie_updates = TrieUpdates::default();
2960 let removed_keys = node_iter.walker.take_removed_keys();
2961 trie_updates.finalize(hash_builder, removed_keys, destroyed_accounts);
2962
2963 (root, trie_updates, proof_nodes, branch_node_hash_masks, branch_node_tree_masks)
2964 }
2965
2966 fn new_test_trie<Nodes>(nodes: Nodes) -> ParallelSparseTrie
2969 where
2970 Nodes: Iterator<Item = (Nibbles, SparseNode)>,
2971 {
2972 let mut trie = ParallelSparseTrie::default().with_updates(true);
2973
2974 for (path, node) in nodes {
2975 let subtrie = trie.subtrie_for_path_mut(&path);
2976 if let SparseNode::Leaf { key, .. } = &node {
2977 let mut full_key = path;
2978 full_key.extend(key);
2979 subtrie.inner.values.insert(full_key, "LEAF VALUE".into());
2980 }
2981 subtrie.nodes.insert(path, node);
2982 }
2983 trie
2984 }
2985
2986 fn parallel_sparse_trie_nodes(
2987 sparse_trie: &ParallelSparseTrie,
2988 ) -> impl IntoIterator<Item = (&Nibbles, &SparseNode)> {
2989 let lower_sparse_nodes = sparse_trie
2990 .lower_subtries
2991 .iter()
2992 .filter_map(|subtrie| subtrie.as_revealed_ref())
2993 .flat_map(|subtrie| subtrie.nodes.iter());
2994
2995 let upper_sparse_nodes = sparse_trie.upper_subtrie.nodes.iter();
2996
2997 lower_sparse_nodes.chain(upper_sparse_nodes).sorted_by_key(|(path, _)| *path)
2998 }
2999
3000 fn assert_eq_parallel_sparse_trie_proof_nodes(
3003 sparse_trie: &ParallelSparseTrie,
3004 proof_nodes: ProofNodes,
3005 ) {
3006 let proof_nodes = proof_nodes
3007 .into_nodes_sorted()
3008 .into_iter()
3009 .map(|(path, node)| (path, TrieNode::decode(&mut node.as_ref()).unwrap()));
3010
3011 let all_sparse_nodes = parallel_sparse_trie_nodes(sparse_trie);
3012
3013 for ((proof_node_path, proof_node), (sparse_node_path, sparse_node)) in
3014 proof_nodes.zip(all_sparse_nodes)
3015 {
3016 assert_eq!(&proof_node_path, sparse_node_path);
3017
3018 let equals = match (&proof_node, &sparse_node) {
3019 (TrieNode::EmptyRoot, SparseNode::Empty) => true,
3021 (
3023 TrieNode::Branch(BranchNode { state_mask: proof_state_mask, .. }),
3024 SparseNode::Branch { state_mask: sparse_state_mask, .. },
3025 ) => proof_state_mask == sparse_state_mask,
3026 (
3028 TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
3029 SparseNode::Extension { key: sparse_key, .. },
3030 ) |
3031 (
3033 TrieNode::Leaf(LeafNode { key: proof_key, .. }),
3034 SparseNode::Leaf { key: sparse_key, .. },
3035 ) => proof_key == sparse_key,
3036 (_, SparseNode::Empty | SparseNode::Hash(_)) => continue,
3038 _ => false,
3039 };
3040 assert!(
3041 equals,
3042 "path: {proof_node_path:?}\nproof node: {proof_node:?}\nsparse node: {sparse_node:?}"
3043 );
3044 }
3045 }
3046
3047 #[test]
3048 fn test_get_changed_subtries_empty() {
3049 let mut trie = ParallelSparseTrie::default();
3050 let mut prefix_set = PrefixSetMut::from([Nibbles::default()]).freeze();
3051
3052 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3053 assert!(subtries.is_empty());
3054 assert_eq!(unchanged_prefix_set, PrefixSetMut::from(prefix_set.iter().copied()));
3055 }
3056
3057 #[test]
3058 fn test_get_changed_subtries() {
3059 let mut trie = ParallelSparseTrie::default();
3061 let subtrie_1 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3062 let subtrie_1_index = path_subtrie_index_unchecked(&subtrie_1.path);
3063 let subtrie_2 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x1, 0x0])));
3064 let subtrie_2_index = path_subtrie_index_unchecked(&subtrie_2.path);
3065 let subtrie_3 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x3, 0x0])));
3066 let subtrie_3_index = path_subtrie_index_unchecked(&subtrie_3.path);
3067
3068 trie.lower_subtries[subtrie_1_index] = LowerSparseSubtrie::Revealed(subtrie_1.clone());
3070 trie.lower_subtries[subtrie_2_index] = LowerSparseSubtrie::Revealed(subtrie_2.clone());
3071 trie.lower_subtries[subtrie_3_index] = LowerSparseSubtrie::Revealed(subtrie_3);
3072
3073 let unchanged_prefix_set = PrefixSetMut::from([
3074 Nibbles::from_nibbles([0x0]),
3075 Nibbles::from_nibbles([0x2, 0x0, 0x0]),
3076 ]);
3077 let mut prefix_set = PrefixSetMut::from([
3079 Nibbles::from_nibbles([0x1, 0x0, 0x0]),
3081 Nibbles::from_nibbles([0x1, 0x0, 0x1, 0x0]),
3082 ]);
3083 prefix_set.extend(unchanged_prefix_set);
3084 let mut prefix_set = prefix_set.freeze();
3085
3086 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3088 assert_eq!(
3089 subtries
3090 .into_iter()
3091 .map(|ChangedSubtrie { index, subtrie, prefix_set, .. }| {
3092 (index, subtrie, prefix_set.iter().copied().collect::<Vec<_>>())
3093 })
3094 .collect::<Vec<_>>(),
3095 vec![(
3096 subtrie_2_index,
3097 subtrie_2,
3098 vec![
3099 Nibbles::from_nibbles([0x1, 0x0, 0x0]),
3100 Nibbles::from_nibbles([0x1, 0x0, 0x1, 0x0])
3101 ]
3102 )]
3103 );
3104 assert_eq!(unchanged_prefix_set, unchanged_prefix_set);
3105 assert!(trie.lower_subtries[subtrie_2_index].as_revealed_ref().is_none());
3106
3107 assert_eq!(trie.lower_subtries[subtrie_1_index], LowerSparseSubtrie::Revealed(subtrie_1));
3109 }
3110
3111 #[test]
3112 fn test_get_changed_subtries_all() {
3113 let mut trie = ParallelSparseTrie::default();
3115 let subtrie_1 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3116 let subtrie_1_index = path_subtrie_index_unchecked(&subtrie_1.path);
3117 let subtrie_2 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x1, 0x0])));
3118 let subtrie_2_index = path_subtrie_index_unchecked(&subtrie_2.path);
3119 let subtrie_3 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x3, 0x0])));
3120 let subtrie_3_index = path_subtrie_index_unchecked(&subtrie_3.path);
3121
3122 trie.lower_subtries[subtrie_1_index] = LowerSparseSubtrie::Revealed(subtrie_1.clone());
3124 trie.lower_subtries[subtrie_2_index] = LowerSparseSubtrie::Revealed(subtrie_2.clone());
3125 trie.lower_subtries[subtrie_3_index] = LowerSparseSubtrie::Revealed(subtrie_3.clone());
3126
3127 let mut prefix_set = PrefixSetMut::all().freeze();
3129
3130 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3132 assert_eq!(
3133 subtries
3134 .into_iter()
3135 .map(|ChangedSubtrie { index, subtrie, prefix_set, .. }| {
3136 (index, subtrie, prefix_set.all())
3137 })
3138 .collect::<Vec<_>>(),
3139 vec![
3140 (subtrie_1_index, subtrie_1, true),
3141 (subtrie_2_index, subtrie_2, true),
3142 (subtrie_3_index, subtrie_3, true)
3143 ]
3144 );
3145 assert_eq!(unchanged_prefix_set, PrefixSetMut::all());
3146
3147 assert!(trie.lower_subtries.iter().all(|subtrie| subtrie.as_revealed_ref().is_none()));
3148 }
3149
3150 #[test]
3151 fn test_sparse_subtrie_type() {
3152 assert_eq!(SparseSubtrieType::from_path(&Nibbles::new()), SparseSubtrieType::Upper);
3153 assert_eq!(
3154 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0])),
3155 SparseSubtrieType::Upper
3156 );
3157 assert_eq!(
3158 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15])),
3159 SparseSubtrieType::Upper
3160 );
3161 assert_eq!(
3162 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 0])),
3163 SparseSubtrieType::Lower(0)
3164 );
3165 assert_eq!(
3166 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 0, 0])),
3167 SparseSubtrieType::Lower(0)
3168 );
3169 assert_eq!(
3170 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 1])),
3171 SparseSubtrieType::Lower(1)
3172 );
3173 assert_eq!(
3174 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 1, 0])),
3175 SparseSubtrieType::Lower(1)
3176 );
3177 assert_eq!(
3178 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 15])),
3179 SparseSubtrieType::Lower(15)
3180 );
3181 assert_eq!(
3182 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 0])),
3183 SparseSubtrieType::Lower(240)
3184 );
3185 assert_eq!(
3186 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 1])),
3187 SparseSubtrieType::Lower(241)
3188 );
3189 assert_eq!(
3190 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 15])),
3191 SparseSubtrieType::Lower(255)
3192 );
3193 assert_eq!(
3194 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 15, 15])),
3195 SparseSubtrieType::Lower(255)
3196 );
3197 }
3198
3199 #[test]
3200 fn test_reveal_node_leaves() {
3201 let mut trie = ParallelSparseTrie::default();
3202
3203 {
3205 let path = Nibbles::from_nibbles([0x1]);
3206 let node = create_leaf_node([0x2, 0x3], 42);
3207 let masks = TrieMasks::none();
3208
3209 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3210
3211 assert_matches!(
3212 trie.upper_subtrie.nodes.get(&path),
3213 Some(SparseNode::Leaf { key, hash: None })
3214 if key == &Nibbles::from_nibbles([0x2, 0x3])
3215 );
3216
3217 let full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3218 assert_eq!(
3219 trie.upper_subtrie.inner.values.get(&full_path),
3220 Some(&encode_account_value(42))
3221 );
3222 }
3223
3224 {
3226 let path = Nibbles::from_nibbles([0x1, 0x2]);
3227 let node = create_leaf_node([0x3, 0x4], 42);
3228 let masks = TrieMasks::none();
3229
3230 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3231
3232 let idx = path_subtrie_index_unchecked(&path);
3234 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3235
3236 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3238 assert_eq!(lower_subtrie.path, path);
3239
3240 assert_matches!(
3241 lower_subtrie.nodes.get(&path),
3242 Some(SparseNode::Leaf { key, hash: None })
3243 if key == &Nibbles::from_nibbles([0x3, 0x4])
3244 );
3245 }
3246
3247 {
3250 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3251 let node = create_leaf_node([0x4, 0x5], 42);
3252 let masks = TrieMasks::none();
3253
3254 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3255
3256 let idx = path_subtrie_index_unchecked(&path);
3258 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3259 assert_eq!(lower_subtrie.path, Nibbles::from_nibbles([0x1, 0x2]));
3260 }
3261 }
3262
3263 #[test]
3264 fn test_reveal_node_extension_all_upper() {
3265 let path = Nibbles::new();
3266 let child_hash = B256::repeat_byte(0xab);
3267 let node = create_extension_node([0x1], child_hash);
3268 let masks = TrieMasks::none();
3269 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3270
3271 assert_matches!(
3272 trie.upper_subtrie.nodes.get(&path),
3273 Some(SparseNode::Extension { key, hash: None, .. })
3274 if key == &Nibbles::from_nibbles([0x1])
3275 );
3276
3277 let child_path = Nibbles::from_nibbles([0x1]);
3279 assert_eq!(trie.upper_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3280 }
3281
3282 #[test]
3283 fn test_reveal_node_extension_cross_level() {
3284 let path = Nibbles::new();
3285 let child_hash = B256::repeat_byte(0xcd);
3286 let node = create_extension_node([0x1, 0x2, 0x3], child_hash);
3287 let masks = TrieMasks::none();
3288 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3289
3290 assert_matches!(
3292 trie.upper_subtrie.nodes.get(&path),
3293 Some(SparseNode::Extension { key, hash: None, .. })
3294 if key == &Nibbles::from_nibbles([0x1, 0x2, 0x3])
3295 );
3296
3297 let child_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3299 let idx = path_subtrie_index_unchecked(&child_path);
3300 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3301
3302 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3303 assert_eq!(lower_subtrie.path, child_path);
3304 assert_eq!(lower_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3305 }
3306
3307 #[test]
3308 fn test_reveal_node_extension_cross_level_boundary() {
3309 let mut trie = ParallelSparseTrie::default();
3310 let path = Nibbles::from_nibbles([0x1]);
3311 let child_hash = B256::repeat_byte(0xcd);
3312 let node = create_extension_node([0x2], child_hash);
3313 let masks = TrieMasks::none();
3314
3315 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3316
3317 assert_matches!(
3319 trie.upper_subtrie.nodes.get(&path),
3320 Some(SparseNode::Extension { key, hash: None, .. })
3321 if key == &Nibbles::from_nibbles([0x2])
3322 );
3323
3324 let child_path = Nibbles::from_nibbles([0x1, 0x2]);
3326 let idx = path_subtrie_index_unchecked(&child_path);
3327 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3328
3329 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3330 assert_eq!(lower_subtrie.path, child_path);
3331 assert_eq!(lower_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3332 }
3333
3334 #[test]
3335 fn test_reveal_node_branch_all_upper() {
3336 let path = Nibbles::new();
3337 let child_hashes = [
3338 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
3339 RlpNode::word_rlp(&B256::repeat_byte(0x22)),
3340 ];
3341 let node = create_branch_node_with_children(&[0x0, 0x5], child_hashes.clone());
3342 let masks = TrieMasks::none();
3343 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3344
3345 assert_matches!(
3347 trie.upper_subtrie.nodes.get(&path),
3348 Some(SparseNode::Branch { state_mask, hash: None, .. })
3349 if *state_mask == 0b0000000000100001.into()
3350 );
3351
3352 let child_path_0 = Nibbles::from_nibbles([0x0]);
3354 let child_path_5 = Nibbles::from_nibbles([0x5]);
3355 assert_eq!(
3356 trie.upper_subtrie.nodes.get(&child_path_0),
3357 Some(&SparseNode::Hash(child_hashes[0].as_hash().unwrap()))
3358 );
3359 assert_eq!(
3360 trie.upper_subtrie.nodes.get(&child_path_5),
3361 Some(&SparseNode::Hash(child_hashes[1].as_hash().unwrap()))
3362 );
3363 }
3364
3365 #[test]
3366 fn test_reveal_node_branch_cross_level() {
3367 let mut trie = ParallelSparseTrie::default();
3368 let path = Nibbles::from_nibbles([0x1]); let child_hashes = [
3370 RlpNode::word_rlp(&B256::repeat_byte(0x33)),
3371 RlpNode::word_rlp(&B256::repeat_byte(0x44)),
3372 RlpNode::word_rlp(&B256::repeat_byte(0x55)),
3373 ];
3374 let node = create_branch_node_with_children(&[0x0, 0x7, 0xf], child_hashes.clone());
3375 let masks = TrieMasks::none();
3376
3377 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3378
3379 assert_matches!(
3381 trie.upper_subtrie.nodes.get(&path),
3382 Some(SparseNode::Branch { state_mask, hash: None, .. })
3383 if *state_mask == 0b1000000010000001.into()
3384 );
3385
3386 let child_paths = [
3388 Nibbles::from_nibbles([0x1, 0x0]),
3389 Nibbles::from_nibbles([0x1, 0x7]),
3390 Nibbles::from_nibbles([0x1, 0xf]),
3391 ];
3392
3393 for (i, child_path) in child_paths.iter().enumerate() {
3394 let idx = path_subtrie_index_unchecked(child_path);
3395 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3396 assert_eq!(&lower_subtrie.path, child_path);
3397 assert_eq!(
3398 lower_subtrie.nodes.get(child_path),
3399 Some(&SparseNode::Hash(child_hashes[i].as_hash().unwrap())),
3400 );
3401 }
3402 }
3403
3404 #[test]
3405 fn test_update_subtrie_hashes_prefix_set_matching() {
3406 let mut trie = ParallelSparseTrie::default();
3408
3409 let leaf_1_full_path = Nibbles::from_nibbles([0; 64]);
3411 let leaf_1_path = leaf_1_full_path.slice(..2);
3412 let leaf_1_key = leaf_1_full_path.slice(2..);
3413 let leaf_2_full_path = Nibbles::from_nibbles([vec![0, 1], vec![0; 62]].concat());
3414 let leaf_2_path = leaf_2_full_path.slice(..2);
3415 let leaf_2_key = leaf_2_full_path.slice(2..);
3416 let leaf_3_full_path = Nibbles::from_nibbles([vec![0, 2], vec![0; 62]].concat());
3417 let leaf_3_path = leaf_3_full_path.slice(..2);
3418 let leaf_3_key = leaf_3_full_path.slice(2..);
3419 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), 1);
3420 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), 2);
3421 let leaf_3 = create_leaf_node(leaf_3_key.to_vec(), 3);
3422
3423 let child_hashes = [
3425 RlpNode::word_rlp(&B256::repeat_byte(0x00)),
3426 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
3427 ];
3429 let branch_path = Nibbles::from_nibbles([0x0]);
3430 let branch_node = create_branch_node_with_children(&[0x0, 0x1, 0x2], child_hashes);
3431
3432 trie.reveal_nodes(vec![
3434 RevealedSparseNode { path: branch_path, node: branch_node, masks: TrieMasks::none() },
3435 RevealedSparseNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
3436 RevealedSparseNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
3437 RevealedSparseNode { path: leaf_3_path, node: leaf_3, masks: TrieMasks::none() },
3438 ])
3439 .unwrap();
3440
3441 let subtrie_1_index = SparseSubtrieType::from_path(&leaf_1_path).lower_index().unwrap();
3443 let subtrie_2_index = SparseSubtrieType::from_path(&leaf_2_path).lower_index().unwrap();
3444 let subtrie_3_index = SparseSubtrieType::from_path(&leaf_3_path).lower_index().unwrap();
3445
3446 let mut unchanged_prefix_set = PrefixSetMut::from([
3447 Nibbles::from_nibbles([0x0]),
3448 leaf_2_full_path,
3449 Nibbles::from_nibbles([0x3, 0x0, 0x0]),
3450 ]);
3451 let mut prefix_set = PrefixSetMut::from([
3453 Nibbles::from_nibbles([0x0, 0x1, 0x0]),
3455 Nibbles::from_nibbles([0x0, 0x1, 0x1, 0x0]),
3456 ]);
3457 prefix_set.extend(unchanged_prefix_set.clone());
3458 trie.prefix_set = prefix_set;
3459
3460 trie.update_subtrie_hashes();
3462
3463 unchanged_prefix_set.insert(leaf_3_full_path);
3467
3468 assert_eq!(
3470 trie.prefix_set.clone().freeze().into_iter().collect::<Vec<_>>(),
3471 unchanged_prefix_set.freeze().into_iter().collect::<Vec<_>>()
3472 );
3473 assert!(trie.lower_subtries[subtrie_1_index].as_revealed_ref().is_some());
3475 assert!(trie.lower_subtries[subtrie_2_index].as_revealed_ref().is_some());
3476 assert!(trie.lower_subtries[subtrie_3_index].as_revealed_ref().is_some());
3477 }
3478
3479 #[test]
3480 fn test_subtrie_update_hashes() {
3481 let mut subtrie = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3482
3483 let leaf_1_full_path = Nibbles::from_nibbles([0; 64]);
3485 let leaf_1_path = leaf_1_full_path.slice(..5);
3486 let leaf_1_key = leaf_1_full_path.slice(5..);
3487 let leaf_2_full_path = Nibbles::from_nibbles([vec![0, 0, 0, 0, 1], vec![0; 59]].concat());
3488 let leaf_2_path = leaf_2_full_path.slice(..5);
3489 let leaf_2_key = leaf_2_full_path.slice(5..);
3490 let leaf_3_full_path = Nibbles::from_nibbles([vec![0, 0, 1], vec![0; 61]].concat());
3491 let leaf_3_path = leaf_3_full_path.slice(..3);
3492 let leaf_3_key = leaf_3_full_path.slice(3..);
3493
3494 let account_1 = create_account(1);
3495 let account_2 = create_account(2);
3496 let account_3 = create_account(3);
3497 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), account_1.nonce);
3498 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), account_2.nonce);
3499 let leaf_3 = create_leaf_node(leaf_3_key.to_vec(), account_3.nonce);
3500
3501 let branch_1_path = Nibbles::from_nibbles([0, 0, 0, 0]);
3503 let branch_1 = create_branch_node_with_children(
3504 &[0, 1],
3505 vec![
3506 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_1)),
3507 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_2)),
3508 ],
3509 );
3510
3511 let extension_path = Nibbles::from_nibbles([0, 0, 0]);
3513 let extension_key = Nibbles::from_nibbles([0]);
3514 let extension = create_extension_node(
3515 extension_key.to_vec(),
3516 RlpNode::from_rlp(&alloy_rlp::encode(&branch_1)).as_hash().unwrap(),
3517 );
3518
3519 let branch_2_path = Nibbles::from_nibbles([0, 0]);
3521 let branch_2 = create_branch_node_with_children(
3522 &[0, 1],
3523 vec![
3524 RlpNode::from_rlp(&alloy_rlp::encode(&extension)),
3525 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_3)),
3526 ],
3527 );
3528
3529 subtrie.reveal_node(branch_2_path, &branch_2, TrieMasks::none()).unwrap();
3531 subtrie.reveal_node(leaf_1_path, &leaf_1, TrieMasks::none()).unwrap();
3532 subtrie.reveal_node(extension_path, &extension, TrieMasks::none()).unwrap();
3533 subtrie.reveal_node(branch_1_path, &branch_1, TrieMasks::none()).unwrap();
3534 subtrie.reveal_node(leaf_2_path, &leaf_2, TrieMasks::none()).unwrap();
3535 subtrie.reveal_node(leaf_3_path, &leaf_3, TrieMasks::none()).unwrap();
3536
3537 let (_, _, proof_nodes, _, _) = run_hash_builder(
3539 [
3540 (leaf_1_full_path, account_1),
3541 (leaf_2_full_path, account_2),
3542 (leaf_3_full_path, account_3),
3543 ],
3544 NoopAccountTrieCursor::default(),
3545 Default::default(),
3546 [
3547 branch_1_path,
3548 extension_path,
3549 branch_2_path,
3550 leaf_1_full_path,
3551 leaf_2_full_path,
3552 leaf_3_full_path,
3553 ],
3554 );
3555
3556 subtrie.update_hashes(
3558 &mut PrefixSetMut::from([leaf_1_full_path, leaf_2_full_path, leaf_3_full_path])
3559 .freeze(),
3560 &mut None,
3561 &HashMap::default(),
3562 &HashMap::default(),
3563 );
3564
3565 let hash_builder_branch_1_hash =
3567 RlpNode::from_rlp(proof_nodes.get(&branch_1_path).unwrap().as_ref()).as_hash().unwrap();
3568 let subtrie_branch_1_hash = subtrie.nodes.get(&branch_1_path).unwrap().hash().unwrap();
3569 assert_eq!(hash_builder_branch_1_hash, subtrie_branch_1_hash);
3570
3571 let hash_builder_extension_hash =
3572 RlpNode::from_rlp(proof_nodes.get(&extension_path).unwrap().as_ref())
3573 .as_hash()
3574 .unwrap();
3575 let subtrie_extension_hash = subtrie.nodes.get(&extension_path).unwrap().hash().unwrap();
3576 assert_eq!(hash_builder_extension_hash, subtrie_extension_hash);
3577
3578 let hash_builder_branch_2_hash =
3579 RlpNode::from_rlp(proof_nodes.get(&branch_2_path).unwrap().as_ref()).as_hash().unwrap();
3580 let subtrie_branch_2_hash = subtrie.nodes.get(&branch_2_path).unwrap().hash().unwrap();
3581 assert_eq!(hash_builder_branch_2_hash, subtrie_branch_2_hash);
3582
3583 let subtrie_leaf_1_hash = subtrie.nodes.get(&leaf_1_path).unwrap().hash().unwrap();
3584 let hash_builder_leaf_1_hash =
3585 RlpNode::from_rlp(proof_nodes.get(&leaf_1_path).unwrap().as_ref()).as_hash().unwrap();
3586 assert_eq!(hash_builder_leaf_1_hash, subtrie_leaf_1_hash);
3587
3588 let hash_builder_leaf_2_hash =
3589 RlpNode::from_rlp(proof_nodes.get(&leaf_2_path).unwrap().as_ref()).as_hash().unwrap();
3590 let subtrie_leaf_2_hash = subtrie.nodes.get(&leaf_2_path).unwrap().hash().unwrap();
3591 assert_eq!(hash_builder_leaf_2_hash, subtrie_leaf_2_hash);
3592
3593 let hash_builder_leaf_3_hash =
3594 RlpNode::from_rlp(proof_nodes.get(&leaf_3_path).unwrap().as_ref()).as_hash().unwrap();
3595 let subtrie_leaf_3_hash = subtrie.nodes.get(&leaf_3_path).unwrap().hash().unwrap();
3596 assert_eq!(hash_builder_leaf_3_hash, subtrie_leaf_3_hash);
3597 }
3598
3599 #[test]
3600 fn test_remove_leaf_branch_becomes_extension() {
3601 let mut trie = new_test_trie(
3613 [
3614 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
3615 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(TrieMask::new(0b1001))),
3616 (
3617 Nibbles::from_nibbles([0x5, 0x0]),
3618 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3])),
3619 ),
3620 (
3621 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
3622 SparseNode::new_branch(TrieMask::new(0b0101)),
3623 ),
3624 (
3625 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
3626 SparseNode::new_leaf(Nibbles::new()),
3627 ),
3628 (
3629 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
3630 SparseNode::new_leaf(Nibbles::new()),
3631 ),
3632 (
3633 Nibbles::from_nibbles([0x5, 0x3]),
3634 SparseNode::new_leaf(Nibbles::from_nibbles([0x7])),
3635 ),
3636 ]
3637 .into_iter(),
3638 );
3639
3640 let provider = MockTrieNodeProvider::new();
3641
3642 let leaf_full_path = Nibbles::from_nibbles([0x5, 0x3, 0x7]);
3644 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3645
3646 let upper_subtrie = &trie.upper_subtrie;
3647 let lower_subtrie_50 = trie.lower_subtries[0x50].as_revealed_ref().unwrap();
3648
3649 assert_matches!(trie.lower_subtries[0x53].as_revealed_ref(), None);
3652
3653 assert_matches!(
3656 upper_subtrie.nodes.get(&Nibbles::from_nibbles([])),
3657 Some(SparseNode::Extension{ key, ..})
3658 if key == &Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3])
3659 );
3660 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x5])), None);
3661 assert_matches!(lower_subtrie_50.nodes.get(&Nibbles::from_nibbles([0x5, 0x0])), None);
3662 assert_matches!(
3663 lower_subtrie_50.nodes.get(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3])),
3664 Some(SparseNode::Branch{ state_mask, .. })
3665 if *state_mask == 0b0101.into()
3666 );
3667 }
3668
3669 #[test]
3670 fn test_remove_leaf_branch_becomes_leaf() {
3671 let mut trie = new_test_trie(
3679 [
3680 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0011))),
3681 (
3682 Nibbles::from_nibbles([0x0]),
3683 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3684 ),
3685 (
3686 Nibbles::from_nibbles([0x1]),
3687 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3688 ),
3689 ]
3690 .into_iter(),
3691 );
3692
3693 if let Some(updates) = trie.updates.as_mut() {
3695 updates
3696 .updated_nodes
3697 .insert(Nibbles::default(), BranchNodeCompact::new(0b11, 0, 0, vec![], None));
3698 }
3699
3700 let provider = MockTrieNodeProvider::new();
3701
3702 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2]);
3704 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3705
3706 let upper_subtrie = &trie.upper_subtrie;
3707
3708 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
3710
3711 assert_matches!(
3713 upper_subtrie.nodes.get(&Nibbles::default()),
3714 Some(SparseNode::Leaf{ key, ..})
3715 if key == &Nibbles::from_nibbles([0x1, 0x3, 0x4])
3716 );
3717
3718 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])), None);
3720 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x0])), None);
3722
3723 let updates = trie.updates.as_ref().unwrap();
3725
3726 assert!(updates.removed_nodes.contains(&Nibbles::default()));
3728
3729 assert!(!updates.updated_nodes.contains_key(&Nibbles::default()));
3731 }
3732
3733 #[test]
3734 fn test_remove_leaf_extension_becomes_leaf() {
3735 let mut trie = new_test_trie(
3744 [
3745 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
3746 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(TrieMask::new(0b0011))),
3747 (
3748 Nibbles::from_nibbles([0x5, 0x0]),
3749 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3750 ),
3751 (
3752 Nibbles::from_nibbles([0x5, 0x1]),
3753 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3754 ),
3755 ]
3756 .into_iter(),
3757 );
3758
3759 let provider = MockTrieNodeProvider::new();
3760
3761 let leaf_full_path = Nibbles::from_nibbles([0x5, 0x0, 0x1, 0x2]);
3763 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3764
3765 let upper_subtrie = &trie.upper_subtrie;
3766
3767 assert_matches!(trie.lower_subtries[0x50].as_revealed_ref(), None);
3771 assert_matches!(trie.lower_subtries[0x51].as_revealed_ref(), None);
3772
3773 let other_leaf_full_value = Nibbles::from_nibbles([0x5, 0x1, 0x3, 0x4]);
3775 assert_matches!(upper_subtrie.inner.values.get(&other_leaf_full_value), Some(_));
3776
3777 assert_matches!(
3779 upper_subtrie.nodes.get(&Nibbles::default()),
3780 Some(SparseNode::Leaf{ key, ..})
3781 if key == &Nibbles::from_nibbles([0x5, 0x1, 0x3, 0x4])
3782 );
3783
3784 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x5])), None);
3786 }
3787
3788 #[test]
3789 fn test_remove_leaf_branch_on_branch() {
3790 let mut trie = new_test_trie(
3800 [
3801 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0101))),
3802 (
3803 Nibbles::from_nibbles([0x0]),
3804 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3805 ),
3806 (Nibbles::from_nibbles([0x2]), SparseNode::new_branch(TrieMask::new(0b0011))),
3807 (
3808 Nibbles::from_nibbles([0x2, 0x0]),
3809 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3810 ),
3811 (
3812 Nibbles::from_nibbles([0x2, 0x1]),
3813 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x6])),
3814 ),
3815 ]
3816 .into_iter(),
3817 );
3818
3819 let provider = MockTrieNodeProvider::new();
3820
3821 let leaf_full_path = Nibbles::from_nibbles([0x2, 0x0, 0x3, 0x4]);
3823 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3824
3825 let upper_subtrie = &trie.upper_subtrie;
3826
3827 assert_matches!(trie.lower_subtries[0x20].as_revealed_ref(), None);
3831 assert_matches!(trie.lower_subtries[0x21].as_revealed_ref(), None);
3832
3833 let other_leaf_full_value = Nibbles::from_nibbles([0x2, 0x1, 0x5, 0x6]);
3835 assert_matches!(upper_subtrie.inner.values.get(&other_leaf_full_value), Some(_));
3836
3837 assert_matches!(
3839 upper_subtrie.nodes.get(&Nibbles::default()),
3840 Some(SparseNode::Branch{ state_mask, .. })
3841 if *state_mask == 0b0101.into()
3842 );
3843
3844 assert_matches!(
3846 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x2])),
3847 Some(SparseNode::Leaf{ key, ..})
3848 if key == &Nibbles::from_nibbles([0x1, 0x5, 0x6])
3849 );
3850 }
3851
3852 #[test]
3853 fn test_remove_leaf_lower_subtrie_root_path_update() {
3854 let mut trie = new_test_trie(
3868 [
3869 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x1, 0x2, 0x3]))),
3870 (
3871 Nibbles::from_nibbles([0x1, 0x2, 0x3]),
3872 SparseNode::new_branch(TrieMask::new(0b0011000)),
3873 ),
3874 (
3875 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x3]),
3876 SparseNode::new_leaf(Nibbles::default()),
3877 ),
3878 (
3879 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]),
3880 SparseNode::new_ext(Nibbles::from_nibbles([0x5])),
3881 ),
3882 (
3883 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]),
3884 SparseNode::new_branch(TrieMask::new(0b0011)),
3885 ),
3886 (
3887 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5, 0x0]),
3888 SparseNode::new_leaf(Nibbles::default()),
3889 ),
3890 (
3891 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5, 0x1]),
3892 SparseNode::new_leaf(Nibbles::default()),
3893 ),
3894 ]
3895 .into_iter(),
3896 );
3897
3898 let provider = MockTrieNodeProvider::new();
3899
3900 let lower_subtrie_root_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3902 assert_matches!(
3903 trie.lower_subtrie_for_path_mut(&lower_subtrie_root_path),
3904 Some(subtrie)
3905 if subtrie.path == lower_subtrie_root_path
3906 );
3907
3908 let leaf_full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x3]);
3910 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3911
3912 let lower_subtrie = trie.lower_subtries[0x12].as_revealed_ref().unwrap();
3917 assert_eq!(lower_subtrie.path, Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]));
3918
3919 assert_matches!(
3921 trie.upper_subtrie.nodes.get(&Nibbles::default()),
3922 Some(SparseNode::Extension { key, .. })
3923 if key == &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5])
3924 );
3925
3926 assert_matches!(
3928 lower_subtrie.nodes.get(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5])),
3929 Some(SparseNode::Branch { state_mask, .. })
3930 if state_mask == &TrieMask::new(0b0011)
3931 );
3932 }
3933
3934 #[test]
3935 fn test_remove_leaf_remaining_child_needs_reveal() {
3936 let mut trie = new_test_trie(
3944 [
3945 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0011))),
3946 (
3947 Nibbles::from_nibbles([0x0]),
3948 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3949 ),
3950 (Nibbles::from_nibbles([0x1]), SparseNode::Hash(B256::repeat_byte(0xab))),
3951 ]
3952 .into_iter(),
3953 );
3954
3955 let mut provider = MockTrieNodeProvider::new();
3957 let revealed_leaf = create_leaf_node([0x3, 0x4], 42);
3958 let mut encoded = Vec::new();
3959 revealed_leaf.encode(&mut encoded);
3960 provider.add_revealed_node(
3961 Nibbles::from_nibbles([0x1]),
3962 RevealedNode { node: encoded.into(), tree_mask: None, hash_mask: None },
3963 );
3964
3965 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2]);
3967 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3968
3969 let upper_subtrie = &trie.upper_subtrie;
3970
3971 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
3973
3974 assert_matches!(
3976 upper_subtrie.nodes.get(&Nibbles::default()),
3977 Some(SparseNode::Leaf{ key, ..})
3978 if key == &Nibbles::from_nibbles([0x1, 0x3, 0x4])
3979 );
3980
3981 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])), None);
3983 }
3984
3985 #[test]
3986 fn test_remove_leaf_root() {
3987 let mut trie = new_test_trie(std::iter::once((
3993 Nibbles::default(),
3994 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2, 0x3])),
3995 )));
3996
3997 let provider = MockTrieNodeProvider::new();
3998
3999 let leaf_full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
4001 trie.remove_leaf(&leaf_full_path, provider).unwrap();
4002
4003 let upper_subtrie = &trie.upper_subtrie;
4004
4005 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
4007
4008 assert_matches!(upper_subtrie.nodes.get(&Nibbles::default()), Some(SparseNode::Empty));
4010 }
4011
4012 #[test]
4013 fn test_remove_leaf_unsets_hash_along_path() {
4014 let mut trie = new_test_trie(
4029 [
4030 (
4031 Nibbles::default(),
4032 SparseNode::Branch {
4033 state_mask: TrieMask::new(0b0011),
4034 hash: Some(B256::repeat_byte(0x10)),
4035 store_in_db_trie: None,
4036 },
4037 ),
4038 (
4039 Nibbles::from_nibbles([0x0]),
4040 SparseNode::Extension {
4041 key: Nibbles::from_nibbles([0x1]),
4042 hash: Some(B256::repeat_byte(0x20)),
4043 store_in_db_trie: None,
4044 },
4045 ),
4046 (
4047 Nibbles::from_nibbles([0x0, 0x1]),
4048 SparseNode::Branch {
4049 state_mask: TrieMask::new(0b11100),
4050 hash: Some(B256::repeat_byte(0x30)),
4051 store_in_db_trie: None,
4052 },
4053 ),
4054 (
4055 Nibbles::from_nibbles([0x0, 0x1, 0x2]),
4056 SparseNode::Leaf {
4057 key: Nibbles::from_nibbles([0x3, 0x4]),
4058 hash: Some(B256::repeat_byte(0x40)),
4059 },
4060 ),
4061 (
4062 Nibbles::from_nibbles([0x0, 0x1, 0x3]),
4063 SparseNode::Leaf {
4064 key: Nibbles::from_nibbles([0x5, 0x6]),
4065 hash: Some(B256::repeat_byte(0x50)),
4066 },
4067 ),
4068 (
4069 Nibbles::from_nibbles([0x0, 0x1, 0x4]),
4070 SparseNode::Leaf {
4071 key: Nibbles::from_nibbles([0x6, 0x7]),
4072 hash: Some(B256::repeat_byte(0x60)),
4073 },
4074 ),
4075 (
4076 Nibbles::from_nibbles([0x1]),
4077 SparseNode::Leaf {
4078 key: Nibbles::from_nibbles([0x7, 0x8]),
4079 hash: Some(B256::repeat_byte(0x70)),
4080 },
4081 ),
4082 ]
4083 .into_iter(),
4084 );
4085
4086 let provider = MockTrieNodeProvider::new();
4087
4088 trie.remove_leaf(&Nibbles::from_nibbles([0x0, 0x1, 0x2, 0x3, 0x4, 0xF]), &provider)
4090 .unwrap();
4091 for (path, node) in trie.all_nodes() {
4092 assert!(node.hash().is_some(), "path {path:?} should still have a hash");
4093 }
4094
4095 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2, 0x3, 0x4]);
4097 trie.remove_leaf(&leaf_full_path, &provider).unwrap();
4098
4099 let upper_subtrie = &trie.upper_subtrie;
4100 let lower_subtrie_10 = trie.lower_subtries[0x01].as_revealed_ref().unwrap();
4101
4102 assert_matches!(
4104 upper_subtrie.nodes.get(&Nibbles::default()),
4105 Some(SparseNode::Branch { hash: None, .. })
4106 );
4107 assert_matches!(
4108 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x0])),
4109 Some(SparseNode::Extension { hash: None, .. })
4110 );
4111 assert_matches!(
4112 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1])),
4113 Some(SparseNode::Branch { hash: None, .. })
4114 );
4115
4116 assert_matches!(
4118 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])),
4119 Some(SparseNode::Leaf { hash: Some(_), .. })
4120 );
4121 assert_matches!(
4122 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1, 0x3])),
4123 Some(SparseNode::Leaf { hash: Some(_), .. })
4124 );
4125 assert_matches!(
4126 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1, 0x4])),
4127 Some(SparseNode::Leaf { hash: Some(_), .. })
4128 );
4129 }
4130
4131 #[test]
4132 fn test_remove_leaf_remaining_extension_node_child_is_revealed() {
4133 let branch_path = Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7]);
4134 let removed_branch_path = Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2]);
4135
4136 let nodes = vec![
4138 RevealedSparseNode {
4140 path: branch_path,
4141 node: {
4142 TrieNode::Branch(BranchNode::new(
4143 vec![
4144 RlpNode::word_rlp(&B256::from(hex!(
4145 "dede882d52f0e0eddfb5b89293a10c87468b4a73acd0d4ae550054a92353f6d5"
4146 ))),
4147 RlpNode::word_rlp(&B256::from(hex!(
4148 "8746f18e465e2eed16117306b6f2eef30bc9d2978aee4a7838255e39c41a3222"
4149 ))),
4150 RlpNode::word_rlp(&B256::from(hex!(
4151 "35a4ea861548af5f0262a9b6d619b4fc88fce6531cbd004eab1530a73f34bbb1"
4152 ))),
4153 RlpNode::word_rlp(&B256::from(hex!(
4154 "47d5c2bf9eea5c1ee027e4740c2b86159074a27d52fd2f6a8a8c86c77e48006f"
4155 ))),
4156 RlpNode::word_rlp(&B256::from(hex!(
4157 "eb76a359b216e1d86b1f2803692a9fe8c3d3f97a9fe6a82b396e30344febc0c1"
4158 ))),
4159 RlpNode::word_rlp(&B256::from(hex!(
4160 "437656f2697f167b23e33cb94acc8550128cfd647fc1579d61e982cb7616b8bc"
4161 ))),
4162 RlpNode::word_rlp(&B256::from(hex!(
4163 "45a1ac2faf15ea8a4da6f921475974e0379f39c3d08166242255a567fa88ce6c"
4164 ))),
4165 RlpNode::word_rlp(&B256::from(hex!(
4166 "7dbb299d714d3dfa593f53bc1b8c66d5c401c30a0b5587b01254a56330361395"
4167 ))),
4168 RlpNode::word_rlp(&B256::from(hex!(
4169 "ae407eb14a74ed951c9949c1867fb9ee9ba5d5b7e03769eaf3f29c687d080429"
4170 ))),
4171 RlpNode::word_rlp(&B256::from(hex!(
4172 "768d0fe1003f0e85d3bc76e4a1fa0827f63b10ca9bca52d56c2b1cceb8eb8b08"
4173 ))),
4174 RlpNode::word_rlp(&B256::from(hex!(
4175 "e5127935143493d5094f4da6e4f7f5a0f62d524fbb61e7bb9fb63d8a166db0f3"
4176 ))),
4177 RlpNode::word_rlp(&B256::from(hex!(
4178 "7f3698297308664fbc1b9e2c41d097fbd57d8f364c394f6ad7c71b10291fbf42"
4179 ))),
4180 RlpNode::word_rlp(&B256::from(hex!(
4181 "4a2bc7e19cec63cb5ef5754add0208959b50bcc79f13a22a370f77b277dbe6db"
4182 ))),
4183 RlpNode::word_rlp(&B256::from(hex!(
4184 "40764b8c48de59258e62a3371909a107e76e1b5e847cfa94dbc857e9fd205103"
4185 ))),
4186 RlpNode::word_rlp(&B256::from(hex!(
4187 "2985dca29a7616920d95c43ab62eb013a40e6a0c88c284471e4c3bd22f3b9b25"
4188 ))),
4189 RlpNode::word_rlp(&B256::from(hex!(
4190 "1b6511f7a385e79477239f7dd4a49f52082ecac05aa5bd0de18b1d55fe69d10c"
4191 ))),
4192 ],
4193 TrieMask::new(0b1111111111111111),
4194 ))
4195 },
4196 masks: TrieMasks {
4197 hash_mask: Some(TrieMask::new(0b1111111111111111)),
4198 tree_mask: Some(TrieMask::new(0b0011110100100101)),
4199 },
4200 },
4201 RevealedSparseNode {
4203 path: removed_branch_path,
4204 node: {
4205 let stack = vec![
4206 RlpNode::word_rlp(&B256::from(hex!(
4207 "15fd4993a41feff1af3b629b32572ab05acddd97c681d82ec2eb89c8a8e3ab9e"
4208 ))),
4209 RlpNode::word_rlp(&B256::from(hex!(
4210 "a272b0b94ced4e6ec7adb41719850cf4a167ad8711d0dda6a810d129258a0d94"
4211 ))),
4212 ];
4213 let branch_node = BranchNode::new(stack, TrieMask::new(0b0001000000000100));
4214 TrieNode::Branch(branch_node)
4215 },
4216 masks: TrieMasks {
4217 hash_mask: Some(TrieMask::new(0b0000000000000000)),
4218 tree_mask: Some(TrieMask::new(0b0000000000000100)),
4219 },
4220 },
4221 RevealedSparseNode {
4223 path: Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0x2]),
4224 node: {
4225 let extension_node = ExtensionNode::new(
4226 Nibbles::from_nibbles([0x6]),
4227 RlpNode::word_rlp(&B256::from(hex!(
4228 "56fab2b106a97eae9c7197f86d03bca292da6e0ac725b783082f7d950cc4e0fc"
4229 ))),
4230 );
4231 TrieNode::Extension(extension_node)
4232 },
4233 masks: TrieMasks { hash_mask: None, tree_mask: None },
4234 },
4235 RevealedSparseNode {
4237 path: Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0xc]),
4238 node: {
4239 let leaf_node = LeafNode::new(
4240 Nibbles::from_nibbles([
4241 0x0, 0x7, 0x7, 0xf, 0x8, 0x6, 0x6, 0x1, 0x3, 0x0, 0x8, 0x8, 0xd, 0xf,
4242 0xc, 0xa, 0xe, 0x6, 0x4, 0x8, 0xa, 0xb, 0xe, 0x8, 0x3, 0x1, 0xf, 0xa,
4243 0xd, 0xc, 0xa, 0x5, 0x5, 0xa, 0xd, 0x4, 0x3, 0xa, 0xb, 0x1, 0x6, 0x5,
4244 0xd, 0x1, 0x6, 0x8, 0x0, 0xd, 0xd, 0x5, 0x6, 0x7, 0xb, 0x5, 0xd, 0x6,
4245 ]),
4246 hex::decode("8468d3971d").unwrap(),
4247 );
4248 TrieNode::Leaf(leaf_node)
4249 },
4250 masks: TrieMasks { hash_mask: None, tree_mask: None },
4251 },
4252 ];
4253
4254 let mut trie = ParallelSparseTrie::from_root(
4256 TrieNode::Extension(ExtensionNode::new(
4257 Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7]),
4258 RlpNode::word_rlp(&B256::from(hex!(
4259 "56fab2b106a97eae9c7197f86d03bca292da6e0ac725b783082f7d950cc4e0fc"
4260 ))),
4261 )),
4262 TrieMasks::none(),
4263 true,
4264 )
4265 .unwrap();
4266
4267 trie.reveal_nodes(nodes).unwrap();
4269
4270 let leaf_key = Nibbles::from_nibbles([
4272 0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0xc, 0x0, 0x7, 0x7, 0xf, 0x8, 0x6, 0x6, 0x1, 0x3,
4273 0x0, 0x8, 0x8, 0xd, 0xf, 0xc, 0xa, 0xe, 0x6, 0x4, 0x8, 0xa, 0xb, 0xe, 0x8, 0x3, 0x1,
4274 0xf, 0xa, 0xd, 0xc, 0xa, 0x5, 0x5, 0xa, 0xd, 0x4, 0x3, 0xa, 0xb, 0x1, 0x6, 0x5, 0xd,
4275 0x1, 0x6, 0x8, 0x0, 0xd, 0xd, 0x5, 0x6, 0x7, 0xb, 0x5, 0xd, 0x6,
4276 ]);
4277
4278 let mut provider = MockTrieNodeProvider::new();
4279 let revealed_branch = create_branch_node_with_children(&[], []);
4280 let mut encoded = Vec::new();
4281 revealed_branch.encode(&mut encoded);
4282 provider.add_revealed_node(
4283 Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0x2, 0x6]),
4284 RevealedNode {
4285 node: encoded.into(),
4286 tree_mask: None,
4287 hash_mask: Some(TrieMask::new(0b1111)),
4289 },
4290 );
4291
4292 trie.remove_leaf(&leaf_key, provider).unwrap();
4293
4294 trie.root();
4296
4297 let updates = trie.take_updates();
4299 assert_eq!(
4300 updates.removed_nodes.into_iter().collect::<Vec<_>>(),
4301 vec![removed_branch_path]
4302 );
4303 assert_eq!(updates.updated_nodes.len(), 1);
4304 let updated_node = updates.updated_nodes.get(&branch_path).unwrap();
4305
4306 assert_eq!(updated_node.tree_mask, TrieMask::new(0b011110100100101),)
4308 }
4309
4310 #[test]
4311 fn test_parallel_sparse_trie_root() {
4312 let extension_path = Nibbles::new();
4315 let extension_key = Nibbles::from_nibbles([0x2]);
4316
4317 let branch_path = Nibbles::from_nibbles([0x2]);
4319
4320 let leaf_1_path = Nibbles::from_nibbles([0x2, 0x0]);
4322 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());
4324
4325 let leaf_2_path = Nibbles::from_nibbles([0x2, 0x1]);
4326 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());
4328
4329 let account_1 = create_account(1);
4331 let account_2 = create_account(2);
4332
4333 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), account_1.nonce);
4335 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), account_2.nonce);
4336
4337 let branch = create_branch_node_with_children(
4339 &[0, 1],
4340 vec![
4341 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_1)),
4342 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_2)),
4343 ],
4344 );
4345
4346 let extension = create_extension_node(
4348 extension_key.to_vec(),
4349 RlpNode::from_rlp(&alloy_rlp::encode(&branch)).as_hash().unwrap(),
4350 );
4351
4352 let mut trie = ParallelSparseTrie::from_root(extension, TrieMasks::none(), true).unwrap();
4354 trie.reveal_nodes(vec![
4355 RevealedSparseNode { path: branch_path, node: branch, masks: TrieMasks::none() },
4356 RevealedSparseNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
4357 RevealedSparseNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
4358 ])
4359 .unwrap();
4360
4361 trie.upper_subtrie.nodes.get_mut(&extension_path).unwrap().set_hash(None);
4364 trie.upper_subtrie.nodes.get_mut(&branch_path).unwrap().set_hash(None);
4365
4366 let leaf_1_subtrie_idx = path_subtrie_index_unchecked(&leaf_1_path);
4368 let leaf_2_subtrie_idx = path_subtrie_index_unchecked(&leaf_2_path);
4369
4370 trie.lower_subtries[leaf_1_subtrie_idx]
4371 .as_revealed_mut()
4372 .unwrap()
4373 .nodes
4374 .get_mut(&leaf_1_path)
4375 .unwrap()
4376 .set_hash(None);
4377 trie.lower_subtries[leaf_2_subtrie_idx]
4378 .as_revealed_mut()
4379 .unwrap()
4380 .nodes
4381 .get_mut(&leaf_2_path)
4382 .unwrap()
4383 .set_hash(None);
4384
4385 trie.prefix_set.insert(leaf_1_full_path);
4387 trie.prefix_set.insert(leaf_2_full_path);
4388
4389 let root = trie.root();
4391
4392 let (hash_builder_root, _, _proof_nodes, _, _) = run_hash_builder(
4394 [(leaf_1_full_path, account_1), (leaf_2_full_path, account_2)],
4395 NoopAccountTrieCursor::default(),
4396 Default::default(),
4397 [extension_path, branch_path, leaf_1_full_path, leaf_2_full_path],
4398 );
4399
4400 assert_eq!(root, hash_builder_root);
4402
4403 let leaf_1_subtrie = trie.lower_subtries[leaf_1_subtrie_idx].as_revealed_ref().unwrap();
4405 let leaf_2_subtrie = trie.lower_subtries[leaf_2_subtrie_idx].as_revealed_ref().unwrap();
4406 assert!(trie.upper_subtrie.nodes.get(&extension_path).unwrap().hash().is_some());
4407 assert!(trie.upper_subtrie.nodes.get(&branch_path).unwrap().hash().is_some());
4408 assert!(leaf_1_subtrie.nodes.get(&leaf_1_path).unwrap().hash().is_some());
4409 assert!(leaf_2_subtrie.nodes.get(&leaf_2_path).unwrap().hash().is_some());
4410 }
4411
4412 #[test]
4413 fn sparse_trie_empty_update_one() {
4414 let ctx = ParallelSparseTrieTestContext;
4415
4416 let key = Nibbles::unpack(B256::with_last_byte(42));
4417 let value = || Account::default();
4418 let value_encoded = || {
4419 let mut account_rlp = Vec::new();
4420 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4421 account_rlp
4422 };
4423
4424 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4425 run_hash_builder(
4426 [(key, value())],
4427 NoopAccountTrieCursor::default(),
4428 Default::default(),
4429 [key],
4430 );
4431
4432 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4433 ctx.update_leaves(&mut sparse, [(key, value_encoded())]);
4434 ctx.assert_with_hash_builder(
4435 &mut sparse,
4436 hash_builder_root,
4437 hash_builder_updates,
4438 hash_builder_proof_nodes,
4439 );
4440 }
4441
4442 #[test]
4443 fn sparse_trie_empty_update_multiple_lower_nibbles() {
4444 let ctx = ParallelSparseTrieTestContext;
4445
4446 let paths = (0..=16).map(|b| Nibbles::unpack(B256::with_last_byte(b))).collect::<Vec<_>>();
4447 let value = || Account::default();
4448 let value_encoded = || {
4449 let mut account_rlp = Vec::new();
4450 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4451 account_rlp
4452 };
4453
4454 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4455 run_hash_builder(
4456 paths.iter().copied().zip(std::iter::repeat_with(value)),
4457 NoopAccountTrieCursor::default(),
4458 Default::default(),
4459 paths.clone(),
4460 );
4461
4462 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4463 ctx.update_leaves(
4464 &mut sparse,
4465 paths.into_iter().zip(std::iter::repeat_with(value_encoded)),
4466 );
4467
4468 ctx.assert_with_hash_builder(
4469 &mut sparse,
4470 hash_builder_root,
4471 hash_builder_updates,
4472 hash_builder_proof_nodes,
4473 );
4474 }
4475
4476 #[test]
4477 fn sparse_trie_empty_update_multiple_upper_nibbles() {
4478 let paths = (239..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
4479 let value = || Account::default();
4480 let value_encoded = || {
4481 let mut account_rlp = Vec::new();
4482 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4483 account_rlp
4484 };
4485
4486 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4487 run_hash_builder(
4488 paths.iter().copied().zip(std::iter::repeat_with(value)),
4489 NoopAccountTrieCursor::default(),
4490 Default::default(),
4491 paths.clone(),
4492 );
4493
4494 let provider = DefaultTrieNodeProvider;
4495 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4496 for path in &paths {
4497 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
4498 }
4499 let sparse_root = sparse.root();
4500 let sparse_updates = sparse.take_updates();
4501
4502 assert_eq!(sparse_root, hash_builder_root);
4503 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
4504 assert_eq_parallel_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
4505 }
4506
4507 #[test]
4508 fn sparse_trie_empty_update_multiple() {
4509 let ctx = ParallelSparseTrieTestContext;
4510
4511 let paths = (0..=255)
4512 .map(|b| {
4513 Nibbles::unpack(if b % 2 == 0 {
4514 B256::repeat_byte(b)
4515 } else {
4516 B256::with_last_byte(b)
4517 })
4518 })
4519 .collect::<Vec<_>>();
4520 let value = || Account::default();
4521 let value_encoded = || {
4522 let mut account_rlp = Vec::new();
4523 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4524 account_rlp
4525 };
4526
4527 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4528 run_hash_builder(
4529 paths.iter().sorted_unstable().copied().zip(std::iter::repeat_with(value)),
4530 NoopAccountTrieCursor::default(),
4531 Default::default(),
4532 paths.clone(),
4533 );
4534
4535 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4536 ctx.update_leaves(
4537 &mut sparse,
4538 paths.iter().copied().zip(std::iter::repeat_with(value_encoded)),
4539 );
4540 ctx.assert_with_hash_builder(
4541 &mut sparse,
4542 hash_builder_root,
4543 hash_builder_updates,
4544 hash_builder_proof_nodes,
4545 );
4546 }
4547
4548 #[test]
4549 fn sparse_trie_empty_update_repeated() {
4550 let ctx = ParallelSparseTrieTestContext;
4551
4552 let paths = (0..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
4553 let old_value = Account { nonce: 1, ..Default::default() };
4554 let old_value_encoded = {
4555 let mut account_rlp = Vec::new();
4556 old_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4557 account_rlp
4558 };
4559 let new_value = Account { nonce: 2, ..Default::default() };
4560 let new_value_encoded = {
4561 let mut account_rlp = Vec::new();
4562 new_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4563 account_rlp
4564 };
4565
4566 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4567 run_hash_builder(
4568 paths.iter().copied().zip(std::iter::repeat_with(|| old_value)),
4569 NoopAccountTrieCursor::default(),
4570 Default::default(),
4571 paths.clone(),
4572 );
4573
4574 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4575 ctx.update_leaves(
4576 &mut sparse,
4577 paths.iter().copied().zip(std::iter::repeat(old_value_encoded)),
4578 );
4579 ctx.assert_with_hash_builder(
4580 &mut sparse,
4581 hash_builder_root,
4582 hash_builder_updates,
4583 hash_builder_proof_nodes,
4584 );
4585
4586 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4587 run_hash_builder(
4588 paths.iter().copied().zip(std::iter::repeat(new_value)),
4589 NoopAccountTrieCursor::default(),
4590 Default::default(),
4591 paths.clone(),
4592 );
4593
4594 ctx.update_leaves(
4595 &mut sparse,
4596 paths.iter().copied().zip(std::iter::repeat(new_value_encoded)),
4597 );
4598 ctx.assert_with_hash_builder(
4599 &mut sparse,
4600 hash_builder_root,
4601 hash_builder_updates,
4602 hash_builder_proof_nodes,
4603 );
4604 }
4605
4606 #[test]
4607 fn sparse_trie_remove_leaf() {
4608 let ctx = ParallelSparseTrieTestContext;
4609 let provider = DefaultTrieNodeProvider;
4610 let mut sparse = ParallelSparseTrie::default();
4611
4612 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
4613
4614 ctx.update_leaves(
4615 &mut sparse,
4616 [
4617 (Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone()),
4618 (Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone()),
4619 (Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone()),
4620 (Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone()),
4621 (Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone()),
4622 (Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value),
4623 ],
4624 );
4625
4626 pretty_assertions::assert_eq!(
4639 parallel_sparse_trie_nodes(&sparse)
4640 .into_iter()
4641 .map(|(k, v)| (*k, v.clone()))
4642 .collect::<BTreeMap<_, _>>(),
4643 BTreeMap::from_iter([
4644 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4645 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1101.into())),
4646 (
4647 Nibbles::from_nibbles([0x5, 0x0]),
4648 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
4649 ),
4650 (
4651 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
4652 SparseNode::new_branch(0b1010.into())
4653 ),
4654 (
4655 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
4656 SparseNode::new_leaf(Nibbles::default())
4657 ),
4658 (
4659 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
4660 SparseNode::new_leaf(Nibbles::default())
4661 ),
4662 (
4663 Nibbles::from_nibbles([0x5, 0x2]),
4664 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x1, 0x3]))
4665 ),
4666 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4667 (
4668 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4669 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4670 ),
4671 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4672 (
4673 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4674 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4675 ),
4676 (
4677 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4678 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4679 )
4680 ])
4681 );
4682
4683 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), &provider).unwrap();
4684
4685 pretty_assertions::assert_eq!(
4697 parallel_sparse_trie_nodes(&sparse)
4698 .into_iter()
4699 .map(|(k, v)| (*k, v.clone()))
4700 .collect::<BTreeMap<_, _>>(),
4701 BTreeMap::from_iter([
4702 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4703 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4704 (
4705 Nibbles::from_nibbles([0x5, 0x0]),
4706 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
4707 ),
4708 (
4709 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
4710 SparseNode::new_branch(0b1010.into())
4711 ),
4712 (
4713 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
4714 SparseNode::new_leaf(Nibbles::default())
4715 ),
4716 (
4717 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
4718 SparseNode::new_leaf(Nibbles::default())
4719 ),
4720 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4721 (
4722 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4723 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4724 ),
4725 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4726 (
4727 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4728 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4729 ),
4730 (
4731 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4732 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4733 )
4734 ])
4735 );
4736
4737 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), &provider).unwrap();
4738
4739 pretty_assertions::assert_eq!(
4748 parallel_sparse_trie_nodes(&sparse)
4749 .into_iter()
4750 .map(|(k, v)| (*k, v.clone()))
4751 .collect::<BTreeMap<_, _>>(),
4752 BTreeMap::from_iter([
4753 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4754 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4755 (
4756 Nibbles::from_nibbles([0x5, 0x0]),
4757 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4758 ),
4759 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4760 (
4761 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4762 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4763 ),
4764 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4765 (
4766 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4767 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4768 ),
4769 (
4770 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4771 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4772 )
4773 ])
4774 );
4775
4776 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), &provider).unwrap();
4777
4778 pretty_assertions::assert_eq!(
4785 parallel_sparse_trie_nodes(&sparse)
4786 .into_iter()
4787 .map(|(k, v)| (*k, v.clone()))
4788 .collect::<BTreeMap<_, _>>(),
4789 BTreeMap::from_iter([
4790 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4791 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4792 (
4793 Nibbles::from_nibbles([0x5, 0x0]),
4794 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4795 ),
4796 (
4797 Nibbles::from_nibbles([0x5, 0x3]),
4798 SparseNode::new_ext(Nibbles::from_nibbles([0x3]))
4799 ),
4800 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4801 (
4802 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4803 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4804 ),
4805 (
4806 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4807 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4808 )
4809 ])
4810 );
4811
4812 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), &provider).unwrap();
4813
4814 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 (
4831 Nibbles::from_nibbles([0x5, 0x3]),
4832 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x0, 0x2]))
4833 ),
4834 ])
4835 );
4836
4837 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), &provider).unwrap();
4838
4839 pretty_assertions::assert_eq!(
4841 parallel_sparse_trie_nodes(&sparse)
4842 .into_iter()
4843 .map(|(k, v)| (*k, v.clone()))
4844 .collect::<BTreeMap<_, _>>(),
4845 BTreeMap::from_iter([(
4846 Nibbles::default(),
4847 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]))
4848 ),])
4849 );
4850
4851 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), &provider).unwrap();
4852
4853 pretty_assertions::assert_eq!(
4855 parallel_sparse_trie_nodes(&sparse)
4856 .into_iter()
4857 .map(|(k, v)| (*k, v.clone()))
4858 .collect::<BTreeMap<_, _>>(),
4859 BTreeMap::from_iter([(Nibbles::default(), SparseNode::Empty)])
4860 );
4861 }
4862
4863 #[test]
4864 fn sparse_trie_remove_leaf_blinded() {
4865 let leaf = LeafNode::new(
4866 Nibbles::default(),
4867 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
4868 );
4869 let branch = TrieNode::Branch(BranchNode::new(
4870 vec![
4871 RlpNode::word_rlp(&B256::repeat_byte(1)),
4872 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
4873 ],
4874 TrieMask::new(0b11),
4875 ));
4876
4877 let provider = DefaultTrieNodeProvider;
4878 let mut sparse = ParallelSparseTrie::from_root(
4879 branch.clone(),
4880 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
4881 false,
4882 )
4883 .unwrap();
4884
4885 sparse
4891 .reveal_nodes(vec![
4892 RevealedSparseNode {
4893 path: Nibbles::default(),
4894 node: branch,
4895 masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
4896 },
4897 RevealedSparseNode {
4898 path: Nibbles::from_nibbles([0x1]),
4899 node: TrieNode::Leaf(leaf),
4900 masks: TrieMasks::none(),
4901 },
4902 ])
4903 .unwrap();
4904
4905 assert_matches!(
4907 sparse.remove_leaf(&Nibbles::from_nibbles([0x0]), &provider).map_err(|e| e.into_kind()),
4908 Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
4909 );
4910 }
4911
4912 #[test]
4913 fn sparse_trie_remove_leaf_non_existent() {
4914 let leaf = LeafNode::new(
4915 Nibbles::default(),
4916 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
4917 );
4918 let branch = TrieNode::Branch(BranchNode::new(
4919 vec![
4920 RlpNode::word_rlp(&B256::repeat_byte(1)),
4921 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
4922 ],
4923 TrieMask::new(0b11),
4924 ));
4925
4926 let provider = DefaultTrieNodeProvider;
4927 let mut sparse = ParallelSparseTrie::from_root(
4928 branch.clone(),
4929 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
4930 false,
4931 )
4932 .unwrap();
4933
4934 sparse
4940 .reveal_nodes(vec![
4941 RevealedSparseNode {
4942 path: Nibbles::default(),
4943 node: branch,
4944 masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
4945 },
4946 RevealedSparseNode {
4947 path: Nibbles::from_nibbles([0x1]),
4948 node: TrieNode::Leaf(leaf),
4949 masks: TrieMasks::none(),
4950 },
4951 ])
4952 .unwrap();
4953
4954 let sparse_old = sparse.clone();
4956 assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2]), &provider), Ok(()));
4957 assert_eq!(sparse, sparse_old);
4958 }
4959
4960 #[test]
4961 fn sparse_trie_fuzz() {
4962 const KEY_NIBBLES_LEN: usize = 3;
4966
4967 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
4968 {
4969 let mut state = BTreeMap::default();
4970 let default_provider = DefaultTrieNodeProvider;
4971 let provider_factory = create_test_provider_factory();
4972 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4973
4974 for (update, keys_to_delete) in updates {
4975 for (key, account) in update.clone() {
4977 let account = account.into_trie_account(EMPTY_ROOT_HASH);
4978 let mut account_rlp = Vec::new();
4979 account.encode(&mut account_rlp);
4980 sparse.update_leaf(key, account_rlp, &default_provider).unwrap();
4981 }
4982 let mut updated_sparse = sparse.clone();
4986 let sparse_root = updated_sparse.root();
4987 let sparse_updates = updated_sparse.take_updates();
4988
4989 state.extend(update);
4991 let provider = provider_factory.provider().unwrap();
4992 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
4993 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4994 run_hash_builder(
4995 state.clone(),
4996 trie_cursor.account_trie_cursor().unwrap(),
4997 Default::default(),
4998 state.keys().copied(),
4999 );
5000
5001 let provider_rw = provider_factory.provider_rw().unwrap();
5003 provider_rw.write_trie_updates(&hash_builder_updates).unwrap();
5004 provider_rw.commit().unwrap();
5005
5006 assert_eq!(sparse_root, hash_builder_root);
5008 pretty_assertions::assert_eq!(
5010 BTreeMap::from_iter(sparse_updates.updated_nodes),
5011 BTreeMap::from_iter(hash_builder_updates.account_nodes)
5012 );
5013 assert_eq_parallel_sparse_trie_proof_nodes(
5015 &updated_sparse,
5016 hash_builder_proof_nodes,
5017 );
5018
5019 for key in &keys_to_delete {
5022 state.remove(key).unwrap();
5023 sparse.remove_leaf(key, &default_provider).unwrap();
5024 }
5025
5026 let mut updated_sparse = sparse.clone();
5030 let sparse_root = updated_sparse.root();
5031 let sparse_updates = updated_sparse.take_updates();
5032
5033 let provider = provider_factory.provider().unwrap();
5034 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
5035 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
5036 run_hash_builder(
5037 state.clone(),
5038 trie_cursor.account_trie_cursor().unwrap(),
5039 keys_to_delete
5040 .iter()
5041 .map(|nibbles| B256::from_slice(&nibbles.pack()))
5042 .collect(),
5043 state.keys().copied(),
5044 );
5045
5046 let provider_rw = provider_factory.provider_rw().unwrap();
5048 provider_rw.write_trie_updates(&hash_builder_updates).unwrap();
5049 provider_rw.commit().unwrap();
5050
5051 assert_eq!(sparse_root, hash_builder_root);
5053 pretty_assertions::assert_eq!(
5055 BTreeMap::from_iter(sparse_updates.updated_nodes),
5056 BTreeMap::from_iter(hash_builder_updates.account_nodes)
5057 );
5058 assert_eq_parallel_sparse_trie_proof_nodes(
5060 &updated_sparse,
5061 hash_builder_proof_nodes,
5062 );
5063 }
5064 }
5065 }
5066
5067 fn transform_updates(
5068 updates: Vec<BTreeMap<Nibbles, Account>>,
5069 mut rng: impl rand::Rng,
5070 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
5071 let mut keys = BTreeSet::new();
5072 updates
5073 .into_iter()
5074 .map(|update| {
5075 keys.extend(update.keys().copied());
5076
5077 let keys_to_delete_len = update.len() / 2;
5078 let keys_to_delete = (0..keys_to_delete_len)
5079 .map(|_| {
5080 let key =
5081 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
5082 keys.take(&key).unwrap()
5083 })
5084 .collect();
5085
5086 (update, keys_to_delete)
5087 })
5088 .collect::<Vec<_>>()
5089 }
5090
5091 proptest!(ProptestConfig::with_cases(10), |(
5092 updates in proptest::collection::vec(
5093 proptest::collection::btree_map(
5094 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
5095 arb::<Account>(),
5096 1..50,
5097 ),
5098 1..50,
5099 ).prop_perturb(transform_updates)
5100 )| {
5101 test(updates)
5102 });
5103 }
5104
5105 #[test]
5106 fn sparse_trie_fuzz_vs_serial() {
5107 const KEY_NIBBLES_LEN: usize = 3;
5111
5112 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
5113 let default_provider = DefaultTrieNodeProvider;
5114 let mut serial = SerialSparseTrie::default().with_updates(true);
5115 let mut parallel = ParallelSparseTrie::default().with_updates(true);
5116
5117 for (update, keys_to_delete) in updates {
5118 for (key, account) in update.clone() {
5120 let account = account.into_trie_account(EMPTY_ROOT_HASH);
5121 let mut account_rlp = Vec::new();
5122 account.encode(&mut account_rlp);
5123 serial.update_leaf(key, account_rlp.clone(), &default_provider).unwrap();
5124 parallel.update_leaf(key, account_rlp, &default_provider).unwrap();
5125 }
5126
5127 let serial_root = serial.root();
5129 let parallel_root = parallel.root();
5130 assert_eq!(parallel_root, serial_root);
5131
5132 let serial_updates = serial.take_updates();
5134 let parallel_updates = parallel.take_updates();
5135 pretty_assertions::assert_eq!(
5136 BTreeMap::from_iter(parallel_updates.updated_nodes),
5137 BTreeMap::from_iter(serial_updates.updated_nodes),
5138 );
5139 pretty_assertions::assert_eq!(
5140 BTreeSet::from_iter(parallel_updates.removed_nodes),
5141 BTreeSet::from_iter(serial_updates.removed_nodes),
5142 );
5143
5144 for key in &keys_to_delete {
5146 parallel.remove_leaf(key, &default_provider).unwrap();
5147 serial.remove_leaf(key, &default_provider).unwrap();
5148 }
5149
5150 let serial_root = serial.root();
5152 let parallel_root = parallel.root();
5153 assert_eq!(parallel_root, serial_root);
5154
5155 let serial_updates = serial.take_updates();
5157 let parallel_updates = parallel.take_updates();
5158 pretty_assertions::assert_eq!(
5159 BTreeMap::from_iter(parallel_updates.updated_nodes),
5160 BTreeMap::from_iter(serial_updates.updated_nodes),
5161 );
5162 pretty_assertions::assert_eq!(
5163 BTreeSet::from_iter(parallel_updates.removed_nodes),
5164 BTreeSet::from_iter(serial_updates.removed_nodes),
5165 );
5166 }
5167 }
5168
5169 fn transform_updates(
5170 updates: Vec<BTreeMap<Nibbles, Account>>,
5171 mut rng: impl rand::Rng,
5172 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
5173 let mut keys = BTreeSet::new();
5174 updates
5175 .into_iter()
5176 .map(|update| {
5177 keys.extend(update.keys().copied());
5178
5179 let keys_to_delete_len = update.len() / 2;
5180 let keys_to_delete = (0..keys_to_delete_len)
5181 .map(|_| {
5182 let key =
5183 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
5184 keys.take(&key).unwrap()
5185 })
5186 .collect();
5187
5188 (update, keys_to_delete)
5189 })
5190 .collect::<Vec<_>>()
5191 }
5192
5193 proptest!(ProptestConfig::with_cases(10), |(
5194 updates in proptest::collection::vec(
5195 proptest::collection::btree_map(
5196 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
5197 arb::<Account>(),
5198 1..50,
5199 ),
5200 1..50,
5201 ).prop_perturb(transform_updates)
5202 )| {
5203 test(updates)
5204 });
5205 }
5206
5207 #[test]
5208 fn sparse_trie_two_leaves_at_lower_roots() {
5209 let provider = DefaultTrieNodeProvider;
5210 let mut trie = ParallelSparseTrie::default().with_updates(true);
5211 let key_50 = Nibbles::unpack(hex!(
5212 "0x5000000000000000000000000000000000000000000000000000000000000000"
5213 ));
5214 let key_51 = Nibbles::unpack(hex!(
5215 "0x5100000000000000000000000000000000000000000000000000000000000000"
5216 ));
5217
5218 let account = Account::default().into_trie_account(EMPTY_ROOT_HASH);
5219 let mut account_rlp = Vec::new();
5220 account.encode(&mut account_rlp);
5221
5222 trie.update_leaf(key_50, account_rlp.clone(), &provider).unwrap();
5224 trie.root();
5225
5226 trie.update_leaf(key_51, account_rlp.clone(), &provider).unwrap();
5228
5229 let expected_root =
5230 hex!("0xdaf0ef9f91a2f179bb74501209effdb5301db1697bcab041eca2234b126e25de");
5231 let root = trie.root();
5232 assert_eq!(root, expected_root);
5233 assert_eq!(SparseTrieUpdates::default(), trie.take_updates());
5234 }
5235
5236 #[test]
5248 fn sparse_trie_reveal_node_1() {
5249 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00]));
5250 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01]));
5251 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x02]));
5252 let value = || Account::default();
5253 let value_encoded = || {
5254 let mut account_rlp = Vec::new();
5255 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
5256 account_rlp
5257 };
5258
5259 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5261 run_hash_builder(
5262 [(key1(), value()), (key3(), value())],
5263 NoopAccountTrieCursor::default(),
5264 Default::default(),
5265 [Nibbles::default()],
5266 );
5267
5268 let provider = DefaultTrieNodeProvider;
5269 let mut sparse = ParallelSparseTrie::from_root(
5270 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5271 TrieMasks {
5272 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5273 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5274 },
5275 false,
5276 )
5277 .unwrap();
5278
5279 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5281 run_hash_builder(
5282 [(key1(), value()), (key3(), value())],
5283 NoopAccountTrieCursor::default(),
5284 Default::default(),
5285 [key1()],
5286 );
5287 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5288 .nodes_sorted()
5289 .into_iter()
5290 .map(|(path, node)| {
5291 let hash_mask = branch_node_hash_masks.get(&path).copied();
5292 let tree_mask = branch_node_tree_masks.get(&path).copied();
5293 RevealedSparseNode {
5294 path,
5295 node: TrieNode::decode(&mut &node[..]).unwrap(),
5296 masks: TrieMasks { hash_mask, tree_mask },
5297 }
5298 })
5299 .collect();
5300 sparse.reveal_nodes(revealed_nodes).unwrap();
5301
5302 assert_eq!(
5304 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5305 Some(&SparseNode::new_branch(0b101.into()))
5306 );
5307
5308 sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
5310
5311 assert_eq!(
5313 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5314 Some(&SparseNode::new_branch(0b111.into()))
5315 );
5316
5317 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5319 run_hash_builder(
5320 [(key1(), value()), (key3(), value())],
5321 NoopAccountTrieCursor::default(),
5322 Default::default(),
5323 [key3()],
5324 );
5325 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5326 .nodes_sorted()
5327 .into_iter()
5328 .map(|(path, node)| {
5329 let hash_mask = branch_node_hash_masks.get(&path).copied();
5330 let tree_mask = branch_node_tree_masks.get(&path).copied();
5331 RevealedSparseNode {
5332 path,
5333 node: TrieNode::decode(&mut &node[..]).unwrap(),
5334 masks: TrieMasks { hash_mask, tree_mask },
5335 }
5336 })
5337 .collect();
5338 sparse.reveal_nodes(revealed_nodes).unwrap();
5339
5340 assert_eq!(
5342 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5343 Some(&SparseNode::new_branch(0b111.into()))
5344 );
5345
5346 let (_, _, hash_builder_proof_nodes, _, _) = run_hash_builder(
5349 [(key1(), value()), (key2(), value()), (key3(), value())],
5350 NoopAccountTrieCursor::default(),
5351 Default::default(),
5352 [key1(), key2(), key3()],
5353 );
5354
5355 assert_eq_parallel_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
5356 }
5357
5358 #[test]
5369 fn sparse_trie_reveal_node_2() {
5370 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x00]));
5371 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x01]));
5372 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x02]));
5373 let value = || Account::default();
5374
5375 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5377 run_hash_builder(
5378 [(key1(), value()), (key2(), value()), (key3(), value())],
5379 NoopAccountTrieCursor::default(),
5380 Default::default(),
5381 [Nibbles::default()],
5382 );
5383
5384 let provider = DefaultTrieNodeProvider;
5385 let mut sparse = ParallelSparseTrie::from_root(
5386 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5387 TrieMasks {
5388 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5389 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5390 },
5391 false,
5392 )
5393 .unwrap();
5394
5395 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5398 run_hash_builder(
5399 [(key1(), value()), (key2(), value()), (key3(), value())],
5400 NoopAccountTrieCursor::default(),
5401 Default::default(),
5402 [key1(), Nibbles::from_nibbles_unchecked([0x01])],
5403 );
5404 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5405 .nodes_sorted()
5406 .into_iter()
5407 .map(|(path, node)| {
5408 let hash_mask = branch_node_hash_masks.get(&path).copied();
5409 let tree_mask = branch_node_tree_masks.get(&path).copied();
5410 RevealedSparseNode {
5411 path,
5412 node: TrieNode::decode(&mut &node[..]).unwrap(),
5413 masks: TrieMasks { hash_mask, tree_mask },
5414 }
5415 })
5416 .collect();
5417 sparse.reveal_nodes(revealed_nodes).unwrap();
5418
5419 assert_eq!(
5421 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5422 Some(&SparseNode::new_branch(0b11.into()))
5423 );
5424
5425 sparse.remove_leaf(&key1(), &provider).unwrap();
5427
5428 assert_eq!(
5430 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5431 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
5432 );
5433
5434 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5436 run_hash_builder(
5437 [(key1(), value()), (key2(), value()), (key3(), value())],
5438 NoopAccountTrieCursor::default(),
5439 Default::default(),
5440 [key2()],
5441 );
5442 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5443 .nodes_sorted()
5444 .into_iter()
5445 .map(|(path, node)| {
5446 let hash_mask = branch_node_hash_masks.get(&path).copied();
5447 let tree_mask = branch_node_tree_masks.get(&path).copied();
5448 RevealedSparseNode {
5449 path,
5450 node: TrieNode::decode(&mut &node[..]).unwrap(),
5451 masks: TrieMasks { hash_mask, tree_mask },
5452 }
5453 })
5454 .collect();
5455 sparse.reveal_nodes(revealed_nodes).unwrap();
5456
5457 assert_eq!(
5459 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5460 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
5461 );
5462 }
5463
5464 #[test]
5473 fn sparse_trie_reveal_node_3() {
5474 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x01]));
5475 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x02]));
5476 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x00]));
5477 let value = || Account::default();
5478 let value_encoded = || {
5479 let mut account_rlp = Vec::new();
5480 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
5481 account_rlp
5482 };
5483
5484 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5486 run_hash_builder(
5487 [(key1(), value()), (key2(), value())],
5488 NoopAccountTrieCursor::default(),
5489 Default::default(),
5490 [Nibbles::default()],
5491 );
5492
5493 let provider = DefaultTrieNodeProvider;
5494 let mut sparse = ParallelSparseTrie::from_root(
5495 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5496 TrieMasks {
5497 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5498 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5499 },
5500 false,
5501 )
5502 .unwrap();
5503
5504 assert_matches!(
5506 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5507 Some(SparseNode::Extension { key, hash: None, store_in_db_trie: None }) if *key == Nibbles::from_nibbles([0x00])
5508 );
5509
5510 sparse.update_leaf(key3(), value_encoded(), &provider).unwrap();
5512
5513 assert_matches!(
5515 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5516 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
5517 );
5518
5519 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5521 run_hash_builder(
5522 [(key1(), value()), (key2(), value())],
5523 NoopAccountTrieCursor::default(),
5524 Default::default(),
5525 [key1()],
5526 );
5527 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5528 .nodes_sorted()
5529 .into_iter()
5530 .map(|(path, node)| {
5531 let hash_mask = branch_node_hash_masks.get(&path).copied();
5532 let tree_mask = branch_node_tree_masks.get(&path).copied();
5533 RevealedSparseNode {
5534 path,
5535 node: TrieNode::decode(&mut &node[..]).unwrap(),
5536 masks: TrieMasks { hash_mask, tree_mask },
5537 }
5538 })
5539 .collect();
5540 sparse.reveal_nodes(revealed_nodes).unwrap();
5541
5542 assert_matches!(
5544 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5545 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
5546 );
5547 }
5548
5549 #[test]
5550 fn test_update_leaf_cross_level() {
5551 let ctx = ParallelSparseTrieTestContext;
5552 let mut trie =
5553 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5554
5555 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x3, 0x4, 0x5], 1);
5577 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
5578
5579 ctx.assert_upper_subtrie(&trie)
5581 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x3, 0x4, 0x5]))
5582 .has_value(&leaf1_path, &value1);
5583
5584 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 2);
5586 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
5587
5588 ctx.assert_upper_subtrie(&trie)
5590 .has_branch(&Nibbles::from_nibbles([0x1]), &[0x2, 0x3])
5591 .has_no_value(&leaf1_path)
5592 .has_no_value(&leaf2_path);
5593
5594 let (leaf3_path, value3) = ctx.create_test_leaf([0x1, 0x2, 0x4, 0x5], 3);
5596 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
5597
5598 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5600 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5601 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5602 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::from_nibbles([0x5]))
5603 .has_value(&leaf2_path, &value2)
5604 .has_value(&leaf3_path, &value3);
5605
5606 let (leaf4_path, value4) = ctx.create_test_leaf([0x1, 0x3, 0x3, 0x4], 4);
5608 trie.update_leaf(leaf4_path, value4.clone(), DefaultTrieNodeProvider).unwrap();
5609
5610 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x3]))
5612 .has_value(&leaf1_path, &value1)
5613 .has_value(&leaf4_path, &value4);
5614
5615 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5617 .has_value(&leaf2_path, &value2)
5618 .has_value(&leaf3_path, &value3);
5619
5620 ctx.assert_upper_subtrie(&trie)
5622 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1]))
5623 .has_branch(&Nibbles::from_nibbles([0x1]), &[0x2, 0x3])
5624 .has_no_value(&leaf1_path)
5625 .has_no_value(&leaf2_path)
5626 .has_no_value(&leaf3_path)
5627 .has_no_value(&leaf4_path);
5628 }
5629
5630 #[test]
5631 fn test_update_leaf_split_at_level_boundary() {
5632 let ctx = ParallelSparseTrieTestContext;
5633 let mut trie =
5634 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5635
5636 let (first_leaf_path, first_value) = ctx.create_test_leaf([0x1, 0x2, 0x2, 0x4], 1);
5651
5652 trie.update_leaf(first_leaf_path, first_value.clone(), DefaultTrieNodeProvider).unwrap();
5653
5654 ctx.assert_upper_subtrie(&trie)
5656 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x2, 0x4]))
5657 .has_value(&first_leaf_path, &first_value);
5658
5659 let (second_leaf_path, second_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 2);
5661
5662 trie.update_leaf(second_leaf_path, second_value.clone(), DefaultTrieNodeProvider).unwrap();
5663
5664 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5666 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x2, 0x3])
5667 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x2]), &Nibbles::from_nibbles([0x4]))
5668 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5669 .has_value(&first_leaf_path, &first_value)
5670 .has_value(&second_leaf_path, &second_value);
5671
5672 ctx.assert_upper_subtrie(&trie)
5674 .has_no_value(&first_leaf_path)
5675 .has_no_value(&second_leaf_path);
5676 }
5677
5678 #[test]
5679 fn test_update_subtrie_with_multiple_leaves() {
5680 let ctx = ParallelSparseTrieTestContext;
5681 let mut trie =
5682 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5683
5684 let leaves = ctx.create_test_leaves(&[
5698 &[0x1, 0x2, 0x3, 0x4],
5699 &[0x1, 0x2, 0x3, 0x5],
5700 &[0x1, 0x2, 0x4, 0x6],
5701 &[0x1, 0x2, 0x4, 0x7],
5702 ]);
5703
5704 ctx.update_leaves(&mut trie, leaves.clone());
5706
5707 ctx.assert_upper_subtrie(&trie)
5709 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
5710
5711 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5713 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5714 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
5715 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &[0x6, 0x7])
5716 .has_value(&leaves[0].0, &leaves[0].1)
5717 .has_value(&leaves[1].0, &leaves[1].1)
5718 .has_value(&leaves[2].0, &leaves[2].1)
5719 .has_value(&leaves[3].0, &leaves[3].1);
5720
5721 let updated_path = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]);
5723 let (_, updated_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 100);
5724
5725 trie.update_leaf(updated_path, updated_value.clone(), DefaultTrieNodeProvider).unwrap();
5726
5727 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5730 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5731 .has_value(&updated_path, &updated_value)
5732 .has_value(&leaves[1].0, &leaves[1].1)
5733 .has_value(&leaves[2].0, &leaves[2].1)
5734 .has_value(&leaves[3].0, &leaves[3].1);
5735
5736 let (new_leaf_path, new_leaf_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x6], 200);
5738
5739 trie.update_leaf(new_leaf_path, new_leaf_value.clone(), DefaultTrieNodeProvider).unwrap();
5740
5741 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5743 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5, 0x6])
5744 .has_value(&new_leaf_path, &new_leaf_value);
5745 }
5746
5747 #[test]
5748 fn test_update_subtrie_extension_node_subtrie() {
5749 let ctx = ParallelSparseTrieTestContext;
5750 let mut trie =
5751 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5752
5753 let leaves = ctx.create_test_leaves(&[&[0x1, 0x2, 0x3, 0x4], &[0x1, 0x2, 0x3, 0x5]]);
5762
5763 ctx.update_leaves(&mut trie, leaves.clone());
5765
5766 ctx.assert_upper_subtrie(&trie)
5768 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
5769
5770 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5772 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
5773 .has_value(&leaves[0].0, &leaves[0].1)
5774 .has_value(&leaves[1].0, &leaves[1].1);
5775 }
5776
5777 #[test]
5778 fn update_subtrie_extension_node_cross_level() {
5779 let ctx = ParallelSparseTrieTestContext;
5780 let mut trie =
5781 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5782
5783 let leaves = ctx.create_test_leaves(&[&[0x1, 0x2, 0x3, 0x4], &[0x1, 0x2, 0x4, 0x5]]);
5793
5794 ctx.update_leaves(&mut trie, leaves.clone());
5796
5797 ctx.assert_upper_subtrie(&trie)
5799 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
5800
5801 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5803 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5804 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5805 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::from_nibbles([0x5]))
5806 .has_value(&leaves[0].0, &leaves[0].1)
5807 .has_value(&leaves[1].0, &leaves[1].1);
5808 }
5809
5810 #[test]
5811 fn test_update_single_nibble_paths() {
5812 let ctx = ParallelSparseTrieTestContext;
5813 let mut trie =
5814 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5815
5816 let (leaf1_path, value1) = ctx.create_test_leaf([0x0], 1);
5828 let (leaf2_path, value2) = ctx.create_test_leaf([0x1], 2);
5829 let (leaf3_path, value3) = ctx.create_test_leaf([0x2], 3);
5830 let (leaf4_path, value4) = ctx.create_test_leaf([0x3], 4);
5831
5832 ctx.update_leaves(
5833 &mut trie,
5834 [
5835 (leaf1_path, value1.clone()),
5836 (leaf2_path, value2.clone()),
5837 (leaf3_path, value3.clone()),
5838 (leaf4_path, value4.clone()),
5839 ],
5840 );
5841
5842 ctx.assert_upper_subtrie(&trie)
5844 .has_branch(&Nibbles::default(), &[0x0, 0x1, 0x2, 0x3])
5845 .has_leaf(&Nibbles::from_nibbles([0x0]), &Nibbles::default())
5846 .has_leaf(&Nibbles::from_nibbles([0x1]), &Nibbles::default())
5847 .has_leaf(&Nibbles::from_nibbles([0x2]), &Nibbles::default())
5848 .has_leaf(&Nibbles::from_nibbles([0x3]), &Nibbles::default())
5849 .has_value(&leaf1_path, &value1)
5850 .has_value(&leaf2_path, &value2)
5851 .has_value(&leaf3_path, &value3)
5852 .has_value(&leaf4_path, &value4);
5853 }
5854
5855 #[test]
5856 fn test_update_deep_extension_chain() {
5857 let ctx = ParallelSparseTrieTestContext;
5858 let mut trie =
5859 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5860
5861 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0], 1);
5875 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1], 2);
5876
5877 ctx.update_leaves(&mut trie, [(leaf1_path, value1.clone()), (leaf2_path, value2.clone())]);
5878
5879 ctx.assert_upper_subtrie(&trie).has_extension(
5881 &Nibbles::default(),
5882 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1]),
5883 );
5884
5885 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x1]))
5887 .has_branch(&Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1]), &[0x0, 0x1])
5888 .has_leaf(
5889 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0]),
5890 &Nibbles::default(),
5891 )
5892 .has_leaf(
5893 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1]),
5894 &Nibbles::default(),
5895 )
5896 .has_value(&leaf1_path, &value1)
5897 .has_value(&leaf2_path, &value2);
5898 }
5899
5900 #[test]
5901 fn test_update_branch_with_all_nibbles() {
5902 let ctx = ParallelSparseTrieTestContext;
5903 let mut trie =
5904 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5905
5906 let mut leaves = Vec::new();
5923 for nibble in 0x0..=0xF {
5924 let (path, value) = ctx.create_test_leaf([0xA, 0x0, nibble], nibble as u64 + 1);
5925 leaves.push((path, value));
5926 }
5927
5928 ctx.update_leaves(&mut trie, leaves.iter().cloned());
5930
5931 ctx.assert_upper_subtrie(&trie)
5933 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA, 0x0]));
5934
5935 let mut subtrie_assert =
5937 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0x0])).has_branch(
5938 &Nibbles::from_nibbles([0xA, 0x0]),
5939 &[0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
5940 );
5941
5942 for (i, (path, value)) in leaves.iter().enumerate() {
5944 subtrie_assert = subtrie_assert
5945 .has_leaf(&Nibbles::from_nibbles([0xA, 0x0, i as u8]), &Nibbles::default())
5946 .has_value(path, value);
5947 }
5948 }
5949
5950 #[test]
5951 fn test_update_creates_multiple_subtries() {
5952 let ctx = ParallelSparseTrieTestContext;
5953 let mut trie =
5954 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5955
5956 let leaves = [
5972 ctx.create_test_leaf([0x0, 0x0, 0x1, 0x2], 1),
5973 ctx.create_test_leaf([0x0, 0x1, 0x3, 0x4], 2),
5974 ctx.create_test_leaf([0x0, 0x2, 0x5, 0x6], 3),
5975 ctx.create_test_leaf([0x0, 0x3, 0x7, 0x8], 4),
5976 ];
5977
5978 ctx.update_leaves(&mut trie, leaves.iter().cloned());
5980
5981 ctx.assert_upper_subtrie(&trie)
5983 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x0]))
5984 .has_branch(&Nibbles::from_nibbles([0x0]), &[0x0, 0x1, 0x2, 0x3]);
5985
5986 for (i, (leaf_path, leaf_value)) in leaves.iter().enumerate() {
5988 let subtrie_path = Nibbles::from_nibbles([0x0, i as u8]);
5989 ctx.assert_subtrie(&trie, subtrie_path)
5990 .has_leaf(
5991 &subtrie_path,
5992 &Nibbles::from_nibbles(match i {
5993 0 => vec![0x1, 0x2],
5994 1 => vec![0x3, 0x4],
5995 2 => vec![0x5, 0x6],
5996 3 => vec![0x7, 0x8],
5997 _ => unreachable!(),
5998 }),
5999 )
6000 .has_value(leaf_path, leaf_value);
6001 }
6002 }
6003
6004 #[test]
6005 fn test_update_extension_to_branch_transformation() {
6006 let ctx = ParallelSparseTrieTestContext;
6007 let mut trie =
6008 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6009
6010 let (leaf1_path, value1) = ctx.create_test_leaf([0xF, 0xF, 0x0, 0x1], 1);
6026 let (leaf2_path, value2) = ctx.create_test_leaf([0xF, 0xF, 0x0, 0x2], 2);
6027 let (leaf3_path, value3) = ctx.create_test_leaf([0xF, 0x0, 0x0, 0x3], 3);
6028
6029 ctx.update_leaves(&mut trie, [(leaf1_path, value1.clone()), (leaf2_path, value2.clone())]);
6030
6031 ctx.assert_upper_subtrie(&trie)
6033 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xF, 0xF, 0x0]));
6034
6035 ctx.update_leaves(&mut trie, [(leaf3_path, value3.clone())]);
6037
6038 ctx.assert_upper_subtrie(&trie)
6040 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xF]))
6041 .has_branch(&Nibbles::from_nibbles([0xF]), &[0x0, 0xF]);
6042
6043 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0xF]))
6045 .has_branch(&Nibbles::from_nibbles([0xF, 0xF, 0x0]), &[0x1, 0x2])
6046 .has_leaf(&Nibbles::from_nibbles([0xF, 0xF, 0x0, 0x1]), &Nibbles::default())
6047 .has_leaf(&Nibbles::from_nibbles([0xF, 0xF, 0x0, 0x2]), &Nibbles::default())
6048 .has_value(&leaf1_path, &value1)
6049 .has_value(&leaf2_path, &value2);
6050
6051 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0x0]))
6052 .has_leaf(&Nibbles::from_nibbles([0xF, 0x0]), &Nibbles::from_nibbles([0x0, 0x3]))
6053 .has_value(&leaf3_path, &value3);
6054 }
6055
6056 #[test]
6057 fn test_update_upper_extension_reveal_lower_hash_node() {
6058 let ctx = ParallelSparseTrieTestContext;
6059
6060 let mut provider = MockTrieNodeProvider::new();
6083
6084 let child_hashes = [
6086 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
6087 RlpNode::word_rlp(&B256::repeat_byte(0x22)),
6088 ];
6089 let revealed_branch = create_branch_node_with_children(&[0x1, 0x2], child_hashes);
6090 let mut encoded = Vec::new();
6091 revealed_branch.encode(&mut encoded);
6092 provider.add_revealed_node(
6093 Nibbles::from_nibbles([0xA, 0xB]),
6094 RevealedNode { node: encoded.into(), tree_mask: None, hash_mask: None },
6095 );
6096
6097 let mut trie = new_test_trie(
6098 [
6099 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0xA, 0xB]))),
6100 (Nibbles::from_nibbles([0xA, 0xB]), SparseNode::Hash(B256::repeat_byte(0x42))),
6101 ]
6102 .into_iter(),
6103 );
6104
6105 let (leaf_path, value) = ctx.create_test_leaf([0xA, 0x0], 1);
6107 trie.update_leaf(leaf_path, value, provider).unwrap();
6108
6109 ctx.assert_upper_subtrie(&trie)
6111 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA]))
6112 .has_branch(&Nibbles::from_nibbles([0xA]), &[0x0, 0xB]);
6113
6114 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0xB]))
6116 .has_branch(&Nibbles::from_nibbles([0xA, 0xB]), &[0x1, 0x2])
6117 .has_hash(&Nibbles::from_nibbles([0xA, 0xB, 0x1]), &B256::repeat_byte(0x11))
6118 .has_hash(&Nibbles::from_nibbles([0xA, 0xB, 0x2]), &B256::repeat_byte(0x22));
6119 }
6120
6121 #[test]
6122 fn test_update_long_shared_prefix_at_boundary() {
6123 let ctx = ParallelSparseTrieTestContext;
6124 let mut trie =
6125 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6126
6127 let (leaf1_path, value1) = ctx.create_test_leaf([0xA, 0xB, 0xC, 0xD, 0xE, 0xF], 1);
6141 let (leaf2_path, value2) = ctx.create_test_leaf([0xA, 0xB, 0xD, 0xE, 0xF, 0x0], 2);
6142
6143 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6144 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6145
6146 ctx.assert_upper_subtrie(&trie)
6148 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA, 0xB]));
6149
6150 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0xB]))
6152 .has_branch(&Nibbles::from_nibbles([0xA, 0xB]), &[0xC, 0xD])
6153 .has_leaf(
6154 &Nibbles::from_nibbles([0xA, 0xB, 0xC]),
6155 &Nibbles::from_nibbles([0xD, 0xE, 0xF]),
6156 )
6157 .has_leaf(
6158 &Nibbles::from_nibbles([0xA, 0xB, 0xD]),
6159 &Nibbles::from_nibbles([0xE, 0xF, 0x0]),
6160 )
6161 .has_value(&leaf1_path, &value1)
6162 .has_value(&leaf2_path, &value2);
6163 }
6164
6165 #[test]
6166 fn test_update_branch_to_extension_collapse() {
6167 let ctx = ParallelSparseTrieTestContext;
6168 let mut trie =
6169 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6170
6171 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 1);
6197 let (leaf2_path, value2) = ctx.create_test_leaf([0x2, 0x3, 0x4, 0x5], 2);
6198 let (leaf3_path, value3) = ctx.create_test_leaf([0x2, 0x3, 0x5, 0x6], 3);
6199
6200 trie.update_leaf(leaf1_path, value1, DefaultTrieNodeProvider).unwrap();
6201 trie.update_leaf(leaf2_path, value2, DefaultTrieNodeProvider).unwrap();
6202 trie.update_leaf(leaf3_path, value3, DefaultTrieNodeProvider).unwrap();
6203
6204 ctx.assert_upper_subtrie(&trie).has_branch(&Nibbles::default(), &[0x1, 0x2]);
6206
6207 let (new_leaf1_path, new_value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 10);
6210 let (new_leaf2_path, new_value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x5], 11);
6211 let (new_leaf3_path, new_value3) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x6], 12);
6212
6213 let mut trie =
6215 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6216 trie.update_leaf(new_leaf1_path, new_value1.clone(), DefaultTrieNodeProvider).unwrap();
6217 trie.update_leaf(new_leaf2_path, new_value2.clone(), DefaultTrieNodeProvider).unwrap();
6218 trie.update_leaf(new_leaf3_path, new_value3.clone(), DefaultTrieNodeProvider).unwrap();
6219
6220 ctx.assert_upper_subtrie(&trie)
6222 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
6223
6224 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3]);
6226
6227 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6229 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5, 0x6]) .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &Nibbles::default())
6231 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x5]), &Nibbles::default())
6232 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x6]), &Nibbles::default())
6233 .has_value(&new_leaf1_path, &new_value1)
6234 .has_value(&new_leaf2_path, &new_value2)
6235 .has_value(&new_leaf3_path, &new_value3);
6236 }
6237
6238 #[test]
6239 fn test_update_shared_prefix_patterns() {
6240 let ctx = ParallelSparseTrieTestContext;
6241 let mut trie =
6242 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6243
6244 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 1);
6260 let (leaf2_path, value2) = ctx.create_test_leaf([0x2, 0x3, 0x4, 0x5], 2);
6261 let (leaf3_path, value3) = ctx.create_test_leaf([0x2, 0x3, 0x5, 0x6], 3);
6262
6263 trie.update_leaf(leaf1_path, value1, DefaultTrieNodeProvider).unwrap();
6264 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6265 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
6266
6267 ctx.assert_upper_subtrie(&trie)
6269 .has_branch(&Nibbles::default(), &[0x1, 0x2])
6270 .has_leaf(&Nibbles::from_nibbles([0x1]), &Nibbles::from_nibbles([0x2, 0x3, 0x4]))
6271 .has_extension(&Nibbles::from_nibbles([0x2]), &Nibbles::from_nibbles([0x3]));
6272
6273 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x2, 0x3]))
6275 .has_branch(&Nibbles::from_nibbles([0x2, 0x3]), &[0x4, 0x5])
6276 .has_leaf(&Nibbles::from_nibbles([0x2, 0x3, 0x4]), &Nibbles::from_nibbles([0x5]))
6277 .has_leaf(&Nibbles::from_nibbles([0x2, 0x3, 0x5]), &Nibbles::from_nibbles([0x6]))
6278 .has_value(&leaf2_path, &value2)
6279 .has_value(&leaf3_path, &value3);
6280 }
6281
6282 #[test]
6283 fn test_progressive_branch_creation() {
6284 let ctx = ParallelSparseTrieTestContext;
6285 let mut trie =
6286 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6287
6288 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4, 0x5], 1);
6324 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6325
6326 ctx.assert_upper_subtrie(&trie)
6328 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]))
6329 .has_value(&leaf1_path, &value1);
6330
6331 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4, 0x6], 2);
6333 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6334
6335 ctx.assert_upper_subtrie(&trie)
6337 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]));
6338
6339 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3, 0x4]);
6341
6342 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6343 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6344 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]), &Nibbles::default())
6345 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x6]), &Nibbles::default())
6346 .has_value(&leaf1_path, &value1)
6347 .has_value(&leaf2_path, &value2);
6348
6349 let (leaf3_path, value3) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x5], 3);
6351 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
6352
6353 ctx.assert_upper_subtrie(&trie)
6355 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
6356
6357 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3]);
6359
6360 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6361 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
6362 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6363 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x5]), &Nibbles::default())
6364 .has_value(&leaf1_path, &value1)
6365 .has_value(&leaf2_path, &value2)
6366 .has_value(&leaf3_path, &value3);
6367
6368 let (leaf4_path, value4) = ctx.create_test_leaf([0x1, 0x2, 0x4], 4);
6370 trie.update_leaf(leaf4_path, value4.clone(), DefaultTrieNodeProvider).unwrap();
6371
6372 ctx.assert_upper_subtrie(&trie)
6374 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
6375
6376 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2]);
6378
6379 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6381 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
6382 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
6383 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6384 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::default())
6385 .has_value(&leaf1_path, &value1)
6386 .has_value(&leaf2_path, &value2)
6387 .has_value(&leaf3_path, &value3)
6388 .has_value(&leaf4_path, &value4);
6389 }
6390
6391 #[test]
6392 fn test_update_max_depth_paths() {
6393 let ctx = ParallelSparseTrieTestContext;
6394 let mut trie =
6395 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6396
6397 let mut path1_nibbles = vec![0xF; 63];
6409 path1_nibbles.push(0x0);
6410 let mut path2_nibbles = vec![0xF; 63];
6411 path2_nibbles.push(0x1);
6412
6413 let (leaf1_path, value1) = ctx.create_test_leaf(&path1_nibbles, 1);
6414 let (leaf2_path, value2) = ctx.create_test_leaf(&path2_nibbles, 2);
6415
6416 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6417 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6418
6419 let extension_key = vec![0xF; 63];
6421 ctx.assert_upper_subtrie(&trie)
6422 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles(&extension_key));
6423
6424 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0xF]))
6426 .has_branch(&Nibbles::from_nibbles(&path1_nibbles[..63]), &[0x0, 0x1])
6427 .has_value(&leaf1_path, &value1)
6428 .has_value(&leaf2_path, &value2);
6429 }
6430
6431 #[test]
6432 fn test_hoodie_block_1_data() {
6433 let root_branch_stack = vec![
6435 hex!("a0550b6aba4dd4582a2434d2cbdad8d3007d09f622d7a6e6eaa7a49385823c2fa2"),
6436 hex!("a04788a4975a9e1efd29b834fd80fdfe8a57cc1b1c5ace6d30ce5a36a15e0092b3"),
6437 hex!("a093aeccf87da304e6f7d09edc5d7bd3a552808866d2149dd0940507a8f9bfa910"),
6438 hex!("a08b5b423ba68d0dec2eca1f408076f9170678505eb4a5db2abbbd83bb37666949"),
6439 hex!("a08592f62216af4218098a78acad7cf472a727fb55e6c27d3cfdf2774d4518eb83"),
6440 hex!("a0ef02aeee845cb64c11f85edc1a3094227c26445952554b8a9248915d80c746c3"),
6441 hex!("a0df2529ee3a1ce4df5a758cf17e6a86d0fb5ea22ab7071cf60af6412e9b0a428a"),
6442 hex!("a0acaa1092db69cd5a63676685827b3484c4b80dc1d3361f6073bbb9240101e144"),
6443 hex!("a09c3f2bb2a729d71f246a833353ade65667716bb330e0127a3299a42d11200f93"),
6444 hex!("a0ce978470f4c0b1f8069570563a14d2b79d709add2db4bf22dd9b6aed3271c566"),
6445 hex!("a095f783cd1d464a60e3c8adcadc28c6eb9fec7306664df39553be41dccc909606"),
6446 hex!("a0a9083f5fb914b255e1feb5d951a4dfddacf3c8003ef1d1ec6a13bb6ba5b2ac62"),
6447 hex!("a0fec113d537d8577cd361e0cabf5e95ef58f1cc34318292fdecce9fae57c3e094"),
6448 hex!("a08b7465f5fe8b3e3c0d087cb7521310d4065ef2a0ee43bf73f68dee8a5742b3dd"),
6449 hex!("a0c589aa1ae3d5fd87d8640957f7d5184a4ac06f393b453a8e8ed7e8fba0d385c8"),
6450 hex!("a0b516d6f3352f87beab4ed6e7322f191fc7a147686500ef4de7dd290ad784ef51"),
6451 ];
6452
6453 let root_branch_rlp_stack: Vec<RlpNode> = root_branch_stack
6454 .iter()
6455 .map(|hex_str| RlpNode::from_raw_rlp(&hex_str[..]).unwrap())
6456 .collect();
6457
6458 let root_branch_node = BranchNode::new(
6459 root_branch_rlp_stack,
6460 TrieMask::new(0b1111111111111111), );
6462
6463 let root_branch_masks = TrieMasks {
6464 hash_mask: Some(TrieMask::new(0b1111111111111111)),
6465 tree_mask: Some(TrieMask::new(0b1111111111111111)),
6466 };
6467
6468 let mut trie = ParallelSparseTrie::from_root(
6469 TrieNode::Branch(root_branch_node),
6470 root_branch_masks,
6471 true,
6472 )
6473 .unwrap();
6474
6475 let branch_0x3_stack = vec![
6477 hex!("a09da7d9755fe0c558b3c3de9fdcdf9f28ae641f38c9787b05b73ab22ae53af3e2"),
6478 hex!("a0d9990bf0b810d1145ecb2b011fd68c63cc85564e6724166fd4a9520180706e5f"),
6479 hex!("a0f60eb4b12132a40df05d9bbdb88bbde0185a3f097f3c76bf4200c23eda26cf86"),
6480 hex!("a0ca976997ddaf06f18992f6207e4f6a05979d07acead96568058789017cc6d06b"),
6481 hex!("a04d78166b48044fdc28ed22d2fd39c8df6f8aaa04cb71d3a17286856f6893ff83"),
6482 hex!("a021d4f90c34d3f1706e78463b6482bca77a3aa1cd059a3f326c42a1cfd30b9b60"),
6483 hex!("a0fc3b71c33e2e6b77c5e494c1db7fdbb447473f003daf378c7a63ba9bf3f0049d"),
6484 hex!("a0e33ed2be194a3d93d343e85642447c93a9d0cfc47a016c2c23d14c083be32a7c"),
6485 hex!("a07b8e7a21c1178d28074f157b50fca85ee25c12568ff8e9706dcbcdacb77bf854"),
6486 hex!("a0973274526811393ea0bf4811ca9077531db00d06b86237a2ecd683f55ba4bcb0"),
6487 hex!("a03a93d726d7487874e51b52d8d534c63aa2a689df18e3b307c0d6cb0a388b00f3"),
6488 hex!("a06aa67101d011d1c22fe739ef83b04b5214a3e2f8e1a2625d8bfdb116b447e86f"),
6489 hex!("a02dd545b33c62d33a183e127a08a4767fba891d9f3b94fc20a2ca02600d6d1fff"),
6490 hex!("a0fe6db87d00f06d53bff8169fa497571ff5af1addfb715b649b4d79dd3e394b04"),
6491 hex!("a0d9240a9d2d5851d05a97ff3305334dfdb0101e1e321fc279d2bb3cad6afa8fc8"),
6492 hex!("a01b69c6ab5173de8a8ec53a6ebba965713a4cc7feb86cb3e230def37c230ca2b2"),
6493 ];
6494
6495 let branch_0x3_rlp_stack: Vec<RlpNode> = branch_0x3_stack
6496 .iter()
6497 .map(|hex_str| RlpNode::from_raw_rlp(&hex_str[..]).unwrap())
6498 .collect();
6499
6500 let branch_0x3_node = BranchNode::new(
6501 branch_0x3_rlp_stack,
6502 TrieMask::new(0b1111111111111111), );
6504
6505 let branch_0x3_masks = TrieMasks {
6506 hash_mask: Some(TrieMask::new(0b0100010000010101)),
6507 tree_mask: Some(TrieMask::new(0b0100000000000000)),
6508 };
6509
6510 let leaf_path = Nibbles::from_nibbles([0x3, 0x7]);
6512 let leaf_key = Nibbles::unpack(
6513 &hex!("d65eaa92c6bc4c13a5ec45527f0c18ea8932588728769ec7aecfe6d9f32e42")[..],
6514 );
6515 let leaf_value = hex!("f8440180a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c").to_vec();
6516
6517 let leaf_node = LeafNode::new(leaf_key, leaf_value);
6518 let leaf_masks = TrieMasks::none();
6519
6520 trie.reveal_nodes(vec![
6521 RevealedSparseNode {
6522 path: Nibbles::from_nibbles([0x3]),
6523 node: TrieNode::Branch(branch_0x3_node),
6524 masks: branch_0x3_masks,
6525 },
6526 RevealedSparseNode {
6527 path: leaf_path,
6528 node: TrieNode::Leaf(leaf_node),
6529 masks: leaf_masks,
6530 },
6531 ])
6532 .unwrap();
6533
6534 let mut leaf_full_path = leaf_path;
6536 leaf_full_path.extend(&leaf_key);
6537
6538 let leaf_new_value = vec![
6539 248, 68, 1, 128, 160, 224, 163, 152, 169, 122, 160, 155, 102, 53, 41, 0, 47, 28, 205,
6540 190, 199, 5, 215, 108, 202, 22, 138, 70, 196, 178, 193, 208, 18, 96, 95, 63, 238, 160,
6541 245, 122, 205, 64, 37, 152, 114, 96, 109, 118, 25, 126, 240, 82, 243, 211, 85, 136,
6542 218, 223, 145, 158, 225, 240, 227, 203, 155, 98, 211, 244, 176, 44,
6543 ];
6544
6545 trie.update_leaf(leaf_full_path, leaf_new_value.clone(), DefaultTrieNodeProvider).unwrap();
6546
6547 assert_eq!(
6549 Some(&leaf_new_value),
6550 trie.lower_subtrie_for_path(&leaf_path).unwrap().inner.values.get(&leaf_full_path)
6551 );
6552 assert!(trie.upper_subtrie.inner.values.is_empty());
6553
6554 let expected_root =
6556 b256!("0x29b07de8376e9ce7b3a69e9b102199869514d3f42590b5abc6f7d48ec9b8665c");
6557 assert_eq!(trie.root(), expected_root);
6558 }
6559
6560 #[test]
6561 fn find_leaf_existing_leaf() {
6562 let provider = DefaultTrieNodeProvider;
6564 let mut sparse = ParallelSparseTrie::default();
6565 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6566 let value = b"test_value".to_vec();
6567
6568 sparse.update_leaf(path, value.clone(), &provider).unwrap();
6569
6570 let result = sparse.find_leaf(&path, None);
6572 assert_matches!(result, Ok(LeafLookup::Exists));
6573
6574 let result = sparse.find_leaf(&path, Some(&value));
6576 assert_matches!(result, Ok(LeafLookup::Exists));
6577 }
6578
6579 #[test]
6580 fn find_leaf_value_mismatch() {
6581 let provider = DefaultTrieNodeProvider;
6583 let mut sparse = ParallelSparseTrie::default();
6584 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6585 let value = b"test_value".to_vec();
6586 let wrong_value = b"wrong_value".to_vec();
6587
6588 sparse.update_leaf(path, value, &provider).unwrap();
6589
6590 let result = sparse.find_leaf(&path, Some(&wrong_value));
6592 assert_matches!(
6593 result,
6594 Err(LeafLookupError::ValueMismatch { path: p, expected: Some(e), actual: _a }) if p == path && e == wrong_value
6595 );
6596 }
6597
6598 #[test]
6599 fn find_leaf_not_found_empty_trie() {
6600 let sparse = ParallelSparseTrie::default();
6602 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6603
6604 let result = sparse.find_leaf(&path, None);
6606 assert_matches!(result, Ok(LeafLookup::NonExistent));
6607 }
6608
6609 #[test]
6610 fn find_leaf_empty_trie() {
6611 let sparse = ParallelSparseTrie::default();
6612 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6613
6614 let result = sparse.find_leaf(&path, None);
6615 assert_matches!(result, Ok(LeafLookup::NonExistent));
6616 }
6617
6618 #[test]
6619 fn find_leaf_exists_no_value_check() {
6620 let provider = DefaultTrieNodeProvider;
6621 let mut sparse = ParallelSparseTrie::default();
6622 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6623 sparse.update_leaf(path, encode_account_value(0), &provider).unwrap();
6624
6625 let result = sparse.find_leaf(&path, None);
6626 assert_matches!(result, Ok(LeafLookup::Exists));
6627 }
6628
6629 #[test]
6630 fn find_leaf_exists_with_value_check_ok() {
6631 let provider = DefaultTrieNodeProvider;
6632 let mut sparse = ParallelSparseTrie::default();
6633 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6634 let value = encode_account_value(0);
6635 sparse.update_leaf(path, value.clone(), &provider).unwrap();
6636
6637 let result = sparse.find_leaf(&path, Some(&value));
6638 assert_matches!(result, Ok(LeafLookup::Exists));
6639 }
6640
6641 #[test]
6642 fn find_leaf_exclusion_branch_divergence() {
6643 let provider = DefaultTrieNodeProvider;
6644 let mut sparse = ParallelSparseTrie::default();
6645 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();
6650 sparse.update_leaf(path2, encode_account_value(1), &provider).unwrap();
6651
6652 let result = sparse.find_leaf(&search_path, None);
6653 assert_matches!(result, Ok(LeafLookup::NonExistent))
6654 }
6655
6656 #[test]
6657 fn find_leaf_exclusion_extension_divergence() {
6658 let provider = DefaultTrieNodeProvider;
6659 let mut sparse = ParallelSparseTrie::default();
6660 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
6662 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]);
6664
6665 sparse.update_leaf(path1, encode_account_value(0), &provider).unwrap();
6666
6667 let result = sparse.find_leaf(&search_path, None);
6668 assert_matches!(result, Ok(LeafLookup::NonExistent))
6669 }
6670
6671 #[test]
6672 fn find_leaf_exclusion_leaf_divergence() {
6673 let provider = DefaultTrieNodeProvider;
6674 let mut sparse = ParallelSparseTrie::default();
6675 let existing_leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6676 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
6677
6678 sparse.update_leaf(existing_leaf_path, encode_account_value(0), &provider).unwrap();
6679
6680 let result = sparse.find_leaf(&search_path, None);
6681 assert_matches!(result, Ok(LeafLookup::NonExistent))
6682 }
6683
6684 #[test]
6685 fn find_leaf_exclusion_path_ends_at_branch() {
6686 let provider = DefaultTrieNodeProvider;
6687 let mut sparse = ParallelSparseTrie::default();
6688 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]);
6690 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2]); sparse.update_leaf(path1, encode_account_value(0), &provider).unwrap();
6693 sparse.update_leaf(path2, encode_account_value(1), &provider).unwrap();
6694
6695 let result = sparse.find_leaf(&search_path, None);
6696 assert_matches!(result, Ok(LeafLookup::NonExistent));
6697 }
6698
6699 #[test]
6700 fn find_leaf_error_blinded_node_at_leaf_path() {
6701 let blinded_hash = B256::repeat_byte(0xBB);
6703 let leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6704
6705 let sparse = new_test_trie(
6706 [
6707 (
6708 Nibbles::default(),
6710 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x1, 0x2])),
6711 ),
6712 (
6713 Nibbles::from_nibbles_unchecked([0x1, 0x2]),
6715 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x3])),
6716 ),
6717 (
6718 Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3]),
6720 SparseNode::new_branch(TrieMask::new(0b10000)),
6721 ),
6722 (
6723 leaf_path,
6725 SparseNode::Hash(blinded_hash),
6726 ),
6727 ]
6728 .into_iter(),
6729 );
6730
6731 let result = sparse.find_leaf(&leaf_path, None);
6732
6733 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
6735 if path == leaf_path && hash == blinded_hash
6736 );
6737 }
6738
6739 #[test]
6740 fn find_leaf_error_blinded_node() {
6741 let blinded_hash = B256::repeat_byte(0xAA);
6742 let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]);
6743 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6744
6745 let sparse = new_test_trie(
6746 [
6747 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b100010))),
6750 (path_to_blind, SparseNode::Hash(blinded_hash)),
6751 (
6752 Nibbles::from_nibbles_unchecked([0x5]),
6753 SparseNode::new_leaf(Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8])),
6754 ),
6755 ]
6756 .into_iter(),
6757 );
6758
6759 let result = sparse.find_leaf(&search_path, None);
6760
6761 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
6763 if path == path_to_blind && hash == blinded_hash
6764 );
6765 }
6766}