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::{instrument, trace, warn};
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(Clone, PartialEq, Eq, Debug)]
95pub struct ParallelSparseTrie {
96 upper_subtrie: Box<SparseSubtrie>,
98 lower_subtries: [LowerSparseSubtrie; NUM_LOWER_SUBTRIES],
100 prefix_set: PrefixSetMut,
103 updates: Option<SparseTrieUpdates>,
105 branch_node_tree_masks: HashMap<Nibbles, TrieMask>,
107 branch_node_hash_masks: HashMap<Nibbles, TrieMask>,
109 update_actions_buffers: Vec<Vec<SparseTrieUpdatesAction>>,
112 #[cfg(feature = "metrics")]
114 metrics: crate::metrics::ParallelSparseTrieMetrics,
115}
116
117impl Default for ParallelSparseTrie {
118 fn default() -> Self {
119 Self {
120 upper_subtrie: Box::new(SparseSubtrie {
121 nodes: HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]),
122 ..Default::default()
123 }),
124 lower_subtries: [const { LowerSparseSubtrie::Blind(None) }; NUM_LOWER_SUBTRIES],
125 prefix_set: PrefixSetMut::default(),
126 updates: None,
127 branch_node_tree_masks: HashMap::default(),
128 branch_node_hash_masks: HashMap::default(),
129 update_actions_buffers: Vec::default(),
130 #[cfg(feature = "metrics")]
131 metrics: Default::default(),
132 }
133 }
134}
135
136impl SparseTrieInterface for ParallelSparseTrie {
137 fn with_root(
138 mut self,
139 root: TrieNode,
140 masks: TrieMasks,
141 retain_updates: bool,
142 ) -> SparseTrieResult<Self> {
143 let path = Nibbles::default();
146 let _removed_root = self.upper_subtrie.nodes.remove(&path).expect("root node should exist");
147 debug_assert_eq!(_removed_root, SparseNode::Empty);
148
149 self = self.with_updates(retain_updates);
150
151 self.reveal_upper_node(Nibbles::default(), &root, masks)?;
152 Ok(self)
153 }
154
155 fn with_updates(mut self, retain_updates: bool) -> Self {
156 self.updates = retain_updates.then(Default::default);
157 self
158 }
159
160 fn reveal_nodes(&mut self, mut nodes: Vec<RevealedSparseNode>) -> SparseTrieResult<()> {
161 if nodes.is_empty() {
162 return Ok(())
163 }
164
165 nodes.sort_unstable_by(
168 |RevealedSparseNode { path: path_a, .. }, RevealedSparseNode { path: path_b, .. }| {
169 let subtrie_type_a = SparseSubtrieType::from_path(path_a);
170 let subtrie_type_b = SparseSubtrieType::from_path(path_b);
171 subtrie_type_a.cmp(&subtrie_type_b).then(path_a.cmp(path_b))
172 },
173 );
174
175 for RevealedSparseNode { path, masks, .. } in &nodes {
177 if let Some(tree_mask) = masks.tree_mask {
178 self.branch_node_tree_masks.insert(*path, tree_mask);
179 }
180 if let Some(hash_mask) = masks.hash_mask {
181 self.branch_node_hash_masks.insert(*path, hash_mask);
182 }
183 }
184
185 let num_upper_nodes = nodes
189 .iter()
190 .position(|n| !SparseSubtrieType::path_len_is_upper(n.path.len()))
191 .unwrap_or(nodes.len());
192
193 let upper_nodes = &nodes[..num_upper_nodes];
194 let lower_nodes = &nodes[num_upper_nodes..];
195
196 self.upper_subtrie.nodes.reserve(upper_nodes.len());
199 for node in upper_nodes {
200 self.reveal_upper_node(node.path, &node.node, node.masks)?;
201 }
202
203 #[cfg(not(feature = "std"))]
204 {
206 for node in lower_nodes {
207 if let Some(subtrie) = self.lower_subtrie_for_path_mut(&node.path) {
208 subtrie.reveal_node(node.path, &node.node, &node.masks)?;
209 } else {
210 panic!("upper subtrie node {node:?} found amongst lower nodes");
211 }
212 }
213 Ok(())
214 }
215
216 #[cfg(feature = "std")]
217 {
219 use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
220
221 let node_groups: Vec<_> = lower_nodes
224 .chunk_by(|node_a, node_b| {
225 SparseSubtrieType::from_path(&node_a.path) ==
226 SparseSubtrieType::from_path(&node_b.path)
227 })
228 .collect();
229
230 let lower_subtries: Vec<_> = node_groups
234 .iter()
235 .map(|nodes| {
236 let node = &nodes[0];
238 let idx =
239 SparseSubtrieType::from_path(&node.path).lower_index().unwrap_or_else(
240 || panic!("upper subtrie node {node:?} found amongst lower nodes"),
241 );
242 self.lower_subtries[idx].reveal(&node.path);
247 (idx, self.lower_subtries[idx].take_revealed().expect("just revealed"))
248 })
249 .collect();
250
251 let (tx, rx) = mpsc::channel();
252
253 lower_subtries
256 .into_par_iter()
257 .zip(node_groups.into_par_iter())
258 .map(|((subtrie_idx, mut subtrie), nodes)| {
259 subtrie.nodes.reserve(nodes.len());
262
263 for node in nodes {
264 let res = subtrie.reveal_node(node.path, &node.node, node.masks);
266 if res.is_err() {
267 return (subtrie_idx, subtrie, res)
268 }
269 }
270 (subtrie_idx, subtrie, Ok(()))
271 })
272 .for_each_init(|| tx.clone(), |tx, result| tx.send(result).unwrap());
273
274 drop(tx);
275
276 let mut any_err = Ok(());
281 for (subtrie_idx, subtrie, res) in rx {
282 self.lower_subtries[subtrie_idx] = LowerSparseSubtrie::Revealed(subtrie);
283 if res.is_err() {
284 any_err = res;
285 }
286 }
287
288 any_err
289 }
290 }
291
292 fn update_leaf<P: TrieNodeProvider>(
293 &mut self,
294 full_path: Nibbles,
295 value: Vec<u8>,
296 provider: P,
297 ) -> SparseTrieResult<()> {
298 self.prefix_set.insert(full_path);
299 let existing = self.upper_subtrie.inner.values.insert(full_path, value.clone());
300 if existing.is_some() {
301 return Ok(())
303 }
304
305 let retain_updates = self.updates_enabled();
306
307 let mut new_nodes = Vec::new();
316 let mut next = Some(Nibbles::default());
317
318 while let Some(current) =
323 next.filter(|next| SparseSubtrieType::path_len_is_upper(next.len()))
324 {
325 match self.upper_subtrie.update_next_node(current, &full_path, retain_updates)? {
328 LeafUpdateStep::Continue { next_node } => {
329 next = Some(next_node);
330 }
331 LeafUpdateStep::Complete { inserted_nodes, reveal_path } => {
332 new_nodes.extend(inserted_nodes);
333
334 if let Some(reveal_path) = reveal_path {
335 let subtrie = self.subtrie_for_path_mut(&reveal_path);
336 if subtrie.nodes.get(&reveal_path).expect("node must exist").is_hash() {
337 warn!(
338 target: "trie::parallel_sparse",
339 child_path = ?reveal_path,
340 leaf_full_path = ?full_path,
341 "Extension node child not revealed in update_leaf, falling back to db",
342 );
343 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
344 provider.trie_node(&reveal_path)?
345 {
346 let decoded = TrieNode::decode(&mut &node[..])?;
347 trace!(
348 target: "trie::parallel_sparse",
349 ?reveal_path,
350 ?decoded,
351 ?tree_mask,
352 ?hash_mask,
353 "Revealing child (from upper)",
354 );
355 subtrie.reveal_node(
356 reveal_path,
357 &decoded,
358 TrieMasks { hash_mask, tree_mask },
359 )?;
360 } else {
361 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
362 path: reveal_path,
363 }
364 .into())
365 }
366 }
367 }
368
369 next = None;
370 }
371 LeafUpdateStep::NodeNotFound => {
372 next = None;
373 }
374 }
375 }
376
377 for node_path in &new_nodes {
379 if SparseSubtrieType::path_len_is_upper(node_path.len()) {
381 continue
382 }
383
384 let node =
385 self.upper_subtrie.nodes.remove(node_path).expect("node belongs to upper subtrie");
386
387 let leaf_value = if let SparseNode::Leaf { key, .. } = &node {
389 let mut leaf_full_path = *node_path;
390 leaf_full_path.extend(key);
391 Some((
392 leaf_full_path,
393 self.upper_subtrie
394 .inner
395 .values
396 .remove(&leaf_full_path)
397 .expect("leaf nodes have associated values entries"),
398 ))
399 } else {
400 None
401 };
402
403 let subtrie = self.subtrie_for_path_mut(node_path);
405
406 if let Some((leaf_full_path, value)) = leaf_value {
408 subtrie.inner.values.insert(leaf_full_path, value);
409 }
410
411 subtrie.nodes.insert(*node_path, node);
413 }
414
415 if let Some(next_path) = next.filter(|n| !SparseSubtrieType::path_len_is_upper(n.len())) {
417 self.upper_subtrie.inner.values.remove(&full_path);
422
423 let subtrie = self.subtrie_for_path_mut(&next_path);
428
429 if subtrie.nodes.is_empty() {
431 subtrie.nodes.insert(subtrie.path, SparseNode::Empty);
432 }
433
434 subtrie.update_leaf(full_path, value, provider, retain_updates)?;
437 }
438
439 Ok(())
440 }
441
442 fn remove_leaf<P: TrieNodeProvider>(
443 &mut self,
444 full_path: &Nibbles,
445 provider: P,
446 ) -> SparseTrieResult<()> {
447 let leaf_path;
463 let leaf_subtrie;
464
465 let mut branch_parent_path: Option<Nibbles> = None;
466 let mut branch_parent_node: Option<SparseNode> = None;
467
468 let mut ext_grandparent_path: Option<Nibbles> = None;
469 let mut ext_grandparent_node: Option<SparseNode> = None;
470
471 let mut curr_path = Nibbles::new(); let mut curr_subtrie = self.upper_subtrie.as_mut();
473 let mut curr_subtrie_is_upper = true;
474
475 let mut paths_to_reset_hashes = Vec::new();
477
478 loop {
479 let curr_node = curr_subtrie.nodes.get_mut(&curr_path).unwrap();
480
481 match Self::find_next_to_leaf(&curr_path, curr_node, full_path) {
482 FindNextToLeafOutcome::NotFound => return Ok(()), FindNextToLeafOutcome::BlindedNode(hash) => {
484 return Err(SparseTrieErrorKind::BlindedNode { path: curr_path, hash }.into())
485 }
486 FindNextToLeafOutcome::Found => {
487 leaf_path = curr_path;
489 leaf_subtrie = curr_subtrie;
490 break;
491 }
492 FindNextToLeafOutcome::ContinueFrom(next_path) => {
493 match curr_node {
496 SparseNode::Branch { hash, .. } => {
497 if hash.is_some() {
498 paths_to_reset_hashes
499 .push((SparseSubtrieType::from_path(&curr_path), curr_path));
500 }
501
502 match (&branch_parent_path, &ext_grandparent_path) {
505 (Some(branch), Some(ext)) if branch.len() > ext.len() => {
506 ext_grandparent_path = None;
507 ext_grandparent_node = None;
508 }
509 _ => (),
510 };
511 branch_parent_path = Some(curr_path);
512 branch_parent_node = Some(curr_node.clone());
513 }
514 SparseNode::Extension { hash, .. } => {
515 if hash.is_some() {
516 paths_to_reset_hashes
517 .push((SparseSubtrieType::from_path(&curr_path), curr_path));
518 }
519
520 ext_grandparent_path = Some(curr_path);
524 ext_grandparent_node = Some(curr_node.clone());
525 }
526 SparseNode::Empty | SparseNode::Hash(_) | SparseNode::Leaf { .. } => {
527 unreachable!(
528 "find_next_to_leaf only continues to a branch or extension"
529 )
530 }
531 }
532
533 curr_path = next_path;
534
535 if curr_subtrie_is_upper {
538 if let SparseSubtrieType::Lower(idx) =
539 SparseSubtrieType::from_path(&curr_path)
540 {
541 curr_subtrie = self.lower_subtries[idx]
542 .as_revealed_mut()
543 .expect("lower subtrie is revealed");
544 curr_subtrie_is_upper = false;
545 }
546 }
547 }
548 };
549 }
550
551 self.prefix_set.insert(*full_path);
554 leaf_subtrie.inner.values.remove(full_path);
555 for (subtrie_type, path) in paths_to_reset_hashes {
556 let node = match subtrie_type {
557 SparseSubtrieType::Upper => self.upper_subtrie.nodes.get_mut(&path),
558 SparseSubtrieType::Lower(idx) => self.lower_subtries[idx]
559 .as_revealed_mut()
560 .expect("lower subtrie is revealed")
561 .nodes
562 .get_mut(&path),
563 }
564 .expect("node exists");
565
566 match node {
567 SparseNode::Extension { hash, .. } | SparseNode::Branch { hash, .. } => {
568 *hash = None
569 }
570 SparseNode::Empty | SparseNode::Hash(_) | SparseNode::Leaf { .. } => {
571 unreachable!("only branch and extension node hashes can be reset")
572 }
573 }
574 }
575 self.remove_node(&leaf_path);
576
577 if leaf_path.is_empty() {
580 self.upper_subtrie.nodes.insert(leaf_path, SparseNode::Empty);
581 return Ok(())
582 }
583
584 if let (Some(branch_path), Some(SparseNode::Branch { mut state_mask, .. })) =
587 (&branch_parent_path, &branch_parent_node)
588 {
589 let child_nibble = leaf_path.get_unchecked(branch_path.len());
590 state_mask.unset_bit(child_nibble);
591
592 let new_branch_node = if state_mask.count_bits() == 1 {
593 let remaining_child_path = {
596 let mut p = *branch_path;
597 p.push_unchecked(
598 state_mask.first_set_bit_index().expect("state mask is not empty"),
599 );
600 p
601 };
602
603 trace!(
604 target: "trie::parallel_sparse",
605 ?leaf_path,
606 ?branch_path,
607 ?remaining_child_path,
608 "Branch node has only one child",
609 );
610
611 let remaining_child_subtrie = self.subtrie_for_path_mut(&remaining_child_path);
612
613 let remaining_child_node =
616 match remaining_child_subtrie.nodes.get(&remaining_child_path).unwrap() {
617 SparseNode::Hash(_) => {
618 warn!(
619 target: "trie::parallel_sparse",
620 child_path = ?remaining_child_path,
621 leaf_full_path = ?full_path,
622 "Branch node child not revealed in remove_leaf, falling back to db",
623 );
624 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
625 provider.trie_node(&remaining_child_path)?
626 {
627 let decoded = TrieNode::decode(&mut &node[..])?;
628 trace!(
629 target: "trie::parallel_sparse",
630 ?remaining_child_path,
631 ?decoded,
632 ?tree_mask,
633 ?hash_mask,
634 "Revealing remaining blinded branch child"
635 );
636 remaining_child_subtrie.reveal_node(
637 remaining_child_path,
638 &decoded,
639 TrieMasks { hash_mask, tree_mask },
640 )?;
641 remaining_child_subtrie.nodes.get(&remaining_child_path).unwrap()
642 } else {
643 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
644 path: remaining_child_path,
645 }
646 .into())
647 }
648 }
649 node => node,
650 };
651
652 let (new_branch_node, remove_child) = Self::branch_changes_on_leaf_removal(
653 branch_path,
654 &remaining_child_path,
655 remaining_child_node,
656 );
657
658 if remove_child {
659 self.move_value_on_leaf_removal(
660 branch_path,
661 &new_branch_node,
662 &remaining_child_path,
663 );
664 self.remove_node(&remaining_child_path);
665 }
666
667 if let Some(updates) = self.updates.as_mut() {
668 updates.updated_nodes.remove(branch_path);
669 updates.removed_nodes.insert(*branch_path);
670 }
671
672 new_branch_node
673 } else {
674 SparseNode::new_branch(state_mask)
677 };
678
679 let branch_subtrie = self.subtrie_for_path_mut(branch_path);
680 branch_subtrie.nodes.insert(*branch_path, new_branch_node.clone());
681 branch_parent_node = Some(new_branch_node);
682 };
683
684 if let (Some(ext_path), Some(SparseNode::Extension { key: shortkey, .. })) =
688 (ext_grandparent_path, &ext_grandparent_node)
689 {
690 let ext_subtrie = self.subtrie_for_path_mut(&ext_path);
691 let branch_path = branch_parent_path.as_ref().unwrap();
692
693 if let Some(new_ext_node) = Self::extension_changes_on_leaf_removal(
694 &ext_path,
695 shortkey,
696 branch_path,
697 branch_parent_node.as_ref().unwrap(),
698 ) {
699 ext_subtrie.nodes.insert(ext_path, new_ext_node.clone());
700 self.move_value_on_leaf_removal(&ext_path, &new_ext_node, branch_path);
701 self.remove_node(branch_path);
702 }
703 }
704
705 Ok(())
706 }
707
708 fn root(&mut self) -> B256 {
709 trace!(target: "trie::parallel_sparse", "Calculating trie root hash");
710
711 self.update_subtrie_hashes();
713
714 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
717 let root_rlp = self.update_upper_subtrie_hashes(&mut prefix_set);
718
719 root_rlp.as_hash().unwrap_or(EMPTY_ROOT_HASH)
721 }
722
723 fn update_subtrie_hashes(&mut self) {
724 trace!(target: "trie::parallel_sparse", "Updating subtrie hashes");
725
726 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
728 let (subtries, unchanged_prefix_set) = self.take_changed_lower_subtries(&mut prefix_set);
729
730 #[cfg(feature = "metrics")]
732 self.metrics.subtries_updated.record(subtries.len() as f64);
733
734 self.prefix_set = unchanged_prefix_set;
736
737 let (tx, rx) = mpsc::channel();
738
739 #[cfg(not(feature = "std"))]
740 for ChangedSubtrie { index, mut subtrie, mut prefix_set, mut update_actions_buf } in
742 subtries
743 {
744 subtrie.update_hashes(
745 &mut prefix_set,
746 &mut update_actions_buf,
747 &self.branch_node_tree_masks,
748 &self.branch_node_hash_masks,
749 );
750 tx.send((index, subtrie, update_actions_buf)).unwrap();
751 }
752
753 #[cfg(feature = "std")]
754 {
756 use rayon::iter::{IntoParallelIterator, ParallelIterator};
757 let branch_node_tree_masks = &self.branch_node_tree_masks;
758 let branch_node_hash_masks = &self.branch_node_hash_masks;
759 subtries
760 .into_par_iter()
761 .map(
762 |ChangedSubtrie {
763 index,
764 mut subtrie,
765 mut prefix_set,
766 mut update_actions_buf,
767 }| {
768 #[cfg(feature = "metrics")]
769 let start = std::time::Instant::now();
770 subtrie.update_hashes(
771 &mut prefix_set,
772 &mut update_actions_buf,
773 branch_node_tree_masks,
774 branch_node_hash_masks,
775 );
776 #[cfg(feature = "metrics")]
777 self.metrics.subtrie_hash_update_latency.record(start.elapsed());
778 (index, subtrie, update_actions_buf)
779 },
780 )
781 .for_each_init(|| tx.clone(), |tx, result| tx.send(result).unwrap());
782 }
783
784 drop(tx);
785
786 for (index, subtrie, update_actions_buf) in rx {
789 if let Some(mut update_actions_buf) = update_actions_buf {
790 self.apply_subtrie_update_actions(
791 #[allow(clippy::iter_with_drain)]
792 update_actions_buf.drain(..),
793 );
794 self.update_actions_buffers.push(update_actions_buf);
795 }
796
797 self.lower_subtries[index] = LowerSparseSubtrie::Revealed(subtrie);
798 }
799 }
800
801 fn get_leaf_value(&self, full_path: &Nibbles) -> Option<&Vec<u8>> {
802 self.subtrie_for_path(full_path).and_then(|subtrie| subtrie.inner.values.get(full_path))
803 }
804
805 fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
806 self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
807 }
808
809 fn take_updates(&mut self) -> SparseTrieUpdates {
810 self.updates.take().unwrap_or_default()
811 }
812
813 fn wipe(&mut self) {
814 self.upper_subtrie.wipe();
815 self.lower_subtries = [const { LowerSparseSubtrie::Blind(None) }; NUM_LOWER_SUBTRIES];
816 self.prefix_set = PrefixSetMut::all();
817 self.updates = self.updates.is_some().then(SparseTrieUpdates::wiped);
818 }
819
820 fn clear(&mut self) {
821 self.upper_subtrie.clear();
822 self.upper_subtrie.nodes.insert(Nibbles::default(), SparseNode::Empty);
823 for subtrie in &mut self.lower_subtries {
824 subtrie.clear();
825 }
826 self.prefix_set.clear();
827 self.updates = None;
828 self.branch_node_tree_masks.clear();
829 self.branch_node_hash_masks.clear();
830 }
833
834 fn find_leaf(
835 &self,
836 full_path: &Nibbles,
837 expected_value: Option<&Vec<u8>>,
838 ) -> Result<LeafLookup, LeafLookupError> {
839 if let Some(actual_value) = std::iter::once(self.upper_subtrie.as_ref())
845 .chain(self.lower_subtrie_for_path(full_path))
846 .filter_map(|subtrie| subtrie.inner.values.get(full_path))
847 .next()
848 {
849 return expected_value
851 .is_none_or(|v| v == actual_value)
852 .then_some(LeafLookup::Exists)
853 .ok_or_else(|| LeafLookupError::ValueMismatch {
854 path: *full_path,
855 expected: expected_value.cloned(),
856 actual: actual_value.clone(),
857 })
858 }
859
860 let mut curr_path = Nibbles::new(); let mut curr_subtrie = self.upper_subtrie.as_ref();
868 let mut curr_subtrie_is_upper = true;
869
870 loop {
871 let curr_node = curr_subtrie.nodes.get(&curr_path).unwrap();
872
873 match Self::find_next_to_leaf(&curr_path, curr_node, full_path) {
874 FindNextToLeafOutcome::NotFound => return Ok(LeafLookup::NonExistent),
875 FindNextToLeafOutcome::BlindedNode(hash) => {
876 return Err(LeafLookupError::BlindedNode { path: curr_path, hash });
878 }
879 FindNextToLeafOutcome::Found => {
880 panic!("target leaf {full_path:?} found at path {curr_path:?}, even though value wasn't in values hashmap");
881 }
882 FindNextToLeafOutcome::ContinueFrom(next_path) => {
883 curr_path = next_path;
884 if curr_subtrie_is_upper {
887 if let Some(lower_subtrie) = self.lower_subtrie_for_path(&curr_path) {
888 curr_subtrie = lower_subtrie;
889 curr_subtrie_is_upper = false;
890 }
891 }
892 }
893 }
894 }
895 }
896}
897
898impl ParallelSparseTrie {
899 const fn updates_enabled(&self) -> bool {
901 self.updates.is_some()
902 }
903
904 pub fn from_root(
919 root: TrieNode,
920 masks: TrieMasks,
921 retain_updates: bool,
922 ) -> SparseTrieResult<Self> {
923 Self::default().with_root(root, masks, retain_updates)
924 }
925
926 fn lower_subtrie_for_path(&self, path: &Nibbles) -> Option<&SparseSubtrie> {
930 match SparseSubtrieType::from_path(path) {
931 SparseSubtrieType::Upper => None,
932 SparseSubtrieType::Lower(idx) => self.lower_subtries[idx].as_revealed_ref(),
933 }
934 }
935
936 fn lower_subtrie_for_path_mut(&mut self, path: &Nibbles) -> Option<&mut SparseSubtrie> {
943 match SparseSubtrieType::from_path(path) {
944 SparseSubtrieType::Upper => None,
945 SparseSubtrieType::Lower(idx) => {
946 self.lower_subtries[idx].reveal(path);
947 Some(self.lower_subtries[idx].as_revealed_mut().expect("just revealed"))
948 }
949 }
950 }
951
952 fn subtrie_for_path(&self, path: &Nibbles) -> Option<&SparseSubtrie> {
957 if SparseSubtrieType::path_len_is_upper(path.len()) {
960 Some(&self.upper_subtrie)
961 } else {
962 self.lower_subtrie_for_path(path)
963 }
964 }
965
966 fn subtrie_for_path_mut(&mut self, path: &Nibbles) -> &mut SparseSubtrie {
973 if SparseSubtrieType::path_len_is_upper(path.len()) {
976 &mut self.upper_subtrie
977 } else {
978 self.lower_subtrie_for_path_mut(path).unwrap()
979 }
980 }
981
982 fn find_next_to_leaf(
990 from_path: &Nibbles,
991 from_node: &SparseNode,
992 leaf_full_path: &Nibbles,
993 ) -> FindNextToLeafOutcome {
994 debug_assert!(leaf_full_path.len() >= from_path.len());
995 debug_assert!(leaf_full_path.starts_with(from_path));
996
997 match from_node {
998 SparseNode::Empty => FindNextToLeafOutcome::NotFound,
1001 SparseNode::Hash(hash) => FindNextToLeafOutcome::BlindedNode(*hash),
1002 SparseNode::Leaf { key, .. } => {
1003 let mut found_full_path = *from_path;
1004 found_full_path.extend(key);
1005
1006 if &found_full_path == leaf_full_path {
1007 return FindNextToLeafOutcome::Found
1008 }
1009 FindNextToLeafOutcome::NotFound
1010 }
1011 SparseNode::Extension { key, .. } => {
1012 if leaf_full_path.len() == from_path.len() {
1013 return FindNextToLeafOutcome::NotFound
1014 }
1015
1016 let mut child_path = *from_path;
1017 child_path.extend(key);
1018
1019 if !leaf_full_path.starts_with(&child_path) {
1020 return FindNextToLeafOutcome::NotFound
1021 }
1022 FindNextToLeafOutcome::ContinueFrom(child_path)
1023 }
1024 SparseNode::Branch { state_mask, .. } => {
1025 if leaf_full_path.len() == from_path.len() {
1026 return FindNextToLeafOutcome::NotFound
1027 }
1028
1029 let nibble = leaf_full_path.get_unchecked(from_path.len());
1030 if !state_mask.is_bit_set(nibble) {
1031 return FindNextToLeafOutcome::NotFound
1032 }
1033
1034 let mut child_path = *from_path;
1035 child_path.push_unchecked(nibble);
1036
1037 FindNextToLeafOutcome::ContinueFrom(child_path)
1038 }
1039 }
1040 }
1041
1042 fn move_value_on_leaf_removal(
1047 &mut self,
1048 parent_path: &Nibbles,
1049 new_parent_node: &SparseNode,
1050 prev_child_path: &Nibbles,
1051 ) {
1052 if SparseSubtrieType::from_path(parent_path).lower_index().is_some() {
1055 return;
1056 }
1057
1058 if let SparseNode::Leaf { key, .. } = new_parent_node {
1059 let Some(prev_child_subtrie) = self.lower_subtrie_for_path_mut(prev_child_path) else {
1060 return;
1061 };
1062
1063 let mut leaf_full_path = *parent_path;
1064 leaf_full_path.extend(key);
1065
1066 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");
1067 self.upper_subtrie.inner.values.insert(leaf_full_path, val);
1068 }
1069 }
1070
1071 fn remove_node(&mut self, path: &Nibbles) {
1083 let subtrie = self.subtrie_for_path_mut(path);
1084 let node = subtrie.nodes.remove(path);
1085
1086 let Some(idx) = SparseSubtrieType::from_path(path).lower_index() else {
1087 return;
1090 };
1091
1092 match node {
1093 Some(SparseNode::Leaf { .. }) => {
1094 if subtrie.nodes.is_empty() {
1097 self.lower_subtries[idx].clear();
1098 }
1099 }
1100 Some(SparseNode::Extension { key, .. }) => {
1101 if &subtrie.path == path {
1105 subtrie.path.extend(&key);
1106 }
1107 }
1108 _ => panic!("Expected to remove a leaf or extension, but removed {node:?}"),
1109 }
1110 }
1111
1112 fn branch_changes_on_leaf_removal(
1121 parent_path: &Nibbles,
1122 remaining_child_path: &Nibbles,
1123 remaining_child_node: &SparseNode,
1124 ) -> (SparseNode, bool) {
1125 debug_assert!(remaining_child_path.len() > parent_path.len());
1126 debug_assert!(remaining_child_path.starts_with(parent_path));
1127
1128 let remaining_child_nibble = remaining_child_path.get_unchecked(parent_path.len());
1129
1130 match remaining_child_node {
1133 SparseNode::Empty | SparseNode::Hash(_) => {
1134 panic!("remaining child must have been revealed already")
1135 }
1136 SparseNode::Leaf { key, .. } => {
1140 let mut new_key = Nibbles::from_nibbles_unchecked([remaining_child_nibble]);
1141 new_key.extend(key);
1142 (SparseNode::new_leaf(new_key), true)
1143 }
1144 SparseNode::Extension { key, .. } => {
1148 let mut new_key = Nibbles::from_nibbles_unchecked([remaining_child_nibble]);
1149 new_key.extend(key);
1150 (SparseNode::new_ext(new_key), true)
1151 }
1152 SparseNode::Branch { .. } => (
1155 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([remaining_child_nibble])),
1156 false,
1157 ),
1158 }
1159 }
1160
1161 fn extension_changes_on_leaf_removal(
1170 parent_path: &Nibbles,
1171 parent_key: &Nibbles,
1172 child_path: &Nibbles,
1173 child: &SparseNode,
1174 ) -> Option<SparseNode> {
1175 debug_assert!(child_path.len() > parent_path.len());
1176 debug_assert!(child_path.starts_with(parent_path));
1177
1178 match child {
1181 SparseNode::Empty | SparseNode::Hash(_) => {
1182 panic!("child must be revealed")
1183 }
1184 SparseNode::Leaf { key, .. } => {
1190 let mut new_key = *parent_key;
1191 new_key.extend(key);
1192 Some(SparseNode::new_leaf(new_key))
1193 }
1194 SparseNode::Extension { key, .. } => {
1197 let mut new_key = *parent_key;
1198 new_key.extend(key);
1199 Some(SparseNode::new_ext(new_key))
1200 }
1201 SparseNode::Branch { .. } => None,
1203 }
1204 }
1205
1206 fn apply_subtrie_update_actions(
1209 &mut self,
1210 update_actions: impl Iterator<Item = SparseTrieUpdatesAction>,
1211 ) {
1212 if let Some(updates) = self.updates.as_mut() {
1213 for action in update_actions {
1214 match action {
1215 SparseTrieUpdatesAction::InsertRemoved(path) => {
1216 updates.updated_nodes.remove(&path);
1217 updates.removed_nodes.insert(path);
1218 }
1219 SparseTrieUpdatesAction::RemoveUpdated(path) => {
1220 updates.updated_nodes.remove(&path);
1221 }
1222 SparseTrieUpdatesAction::InsertUpdated(path, branch_node) => {
1223 updates.updated_nodes.insert(path, branch_node);
1224 }
1225 }
1226 }
1227 };
1228 }
1229
1230 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, ret)]
1232 fn update_upper_subtrie_hashes(&mut self, prefix_set: &mut PrefixSet) -> RlpNode {
1233 trace!(target: "trie::parallel_sparse", "Updating upper subtrie hashes");
1234
1235 debug_assert!(self.upper_subtrie.inner.buffers.path_stack.is_empty());
1236 self.upper_subtrie.inner.buffers.path_stack.push(RlpNodePathStackItem {
1237 path: Nibbles::default(), is_in_prefix_set: None,
1239 });
1240
1241 #[cfg(feature = "metrics")]
1242 let start = std::time::Instant::now();
1243
1244 let mut update_actions_buf =
1245 self.updates_enabled().then(|| self.update_actions_buffers.pop().unwrap_or_default());
1246
1247 while let Some(stack_item) = self.upper_subtrie.inner.buffers.path_stack.pop() {
1248 let path = stack_item.path;
1249 let node = if path.len() < UPPER_TRIE_MAX_DEPTH {
1250 self.upper_subtrie.nodes.get_mut(&path).expect("upper subtrie node must exist")
1251 } else {
1252 let index = path_subtrie_index_unchecked(&path);
1253 let node = self.lower_subtries[index]
1254 .as_revealed_mut()
1255 .expect("lower subtrie must exist")
1256 .nodes
1257 .get_mut(&path)
1258 .expect("lower subtrie node must exist");
1259 debug_assert!(
1262 node.hash().is_some(),
1263 "Lower subtrie root node at path {path:?} has no hash"
1264 );
1265 node
1266 };
1267
1268 self.upper_subtrie.inner.rlp_node(
1270 prefix_set,
1271 &mut update_actions_buf,
1272 stack_item,
1273 node,
1274 &self.branch_node_tree_masks,
1275 &self.branch_node_hash_masks,
1276 );
1277 }
1278
1279 if let Some(mut update_actions_buf) = update_actions_buf {
1282 self.apply_subtrie_update_actions(
1283 #[allow(clippy::iter_with_drain)]
1284 update_actions_buf.drain(..),
1285 );
1286 self.update_actions_buffers.push(update_actions_buf);
1287 }
1288
1289 #[cfg(feature = "metrics")]
1290 self.metrics.subtrie_upper_hash_latency.record(start.elapsed());
1291
1292 debug_assert_eq!(self.upper_subtrie.inner.buffers.rlp_node_stack.len(), 1);
1293 self.upper_subtrie.inner.buffers.rlp_node_stack.pop().unwrap().rlp_node
1294 }
1295
1296 fn take_changed_lower_subtries(
1310 &mut self,
1311 prefix_set: &mut PrefixSet,
1312 ) -> (Vec<ChangedSubtrie>, PrefixSetMut) {
1313 let prefix_set_clone = prefix_set.clone();
1315 let mut prefix_set_iter = prefix_set_clone.into_iter().copied().peekable();
1316 let mut changed_subtries = Vec::new();
1317 let mut unchanged_prefix_set = PrefixSetMut::default();
1318 let updates_enabled = self.updates_enabled();
1319
1320 for (index, subtrie) in self.lower_subtries.iter_mut().enumerate() {
1321 if let Some(subtrie) = subtrie.take_revealed_if(|subtrie| {
1322 prefix_set.contains(&subtrie.path) ||
1323 subtrie.nodes.get(&subtrie.path).is_some_and(|n| n.hash().is_none())
1324 }) {
1325 let prefix_set = if prefix_set.all() {
1326 unchanged_prefix_set = PrefixSetMut::all();
1327 PrefixSetMut::all()
1328 } else {
1329 let mut new_prefix_set = Vec::new();
1334 while let Some(key) = prefix_set_iter.peek() {
1335 if key.starts_with(&subtrie.path) {
1336 new_prefix_set.push(prefix_set_iter.next().unwrap());
1338 } else if new_prefix_set.is_empty() && key < &subtrie.path {
1339 unchanged_prefix_set.insert(prefix_set_iter.next().unwrap());
1343 } else {
1344 break
1348 }
1349 }
1350 PrefixSetMut::from(new_prefix_set)
1351 }
1352 .freeze();
1353
1354 match subtrie.nodes.get(&subtrie.path) {
1357 Some(SparseNode::Extension { key, .. } | SparseNode::Leaf { key, .. }) => {
1358 unchanged_prefix_set.insert(subtrie.path.join(key));
1359 }
1360 Some(SparseNode::Branch { .. }) => {
1361 unchanged_prefix_set.insert(subtrie.path);
1362 }
1363 _ => {}
1364 }
1365
1366 let update_actions_buf =
1367 updates_enabled.then(|| self.update_actions_buffers.pop().unwrap_or_default());
1368
1369 changed_subtries.push(ChangedSubtrie {
1370 index,
1371 subtrie,
1372 prefix_set,
1373 update_actions_buf,
1374 });
1375 }
1376 }
1377
1378 unchanged_prefix_set.extend_keys(prefix_set_iter);
1380
1381 (changed_subtries, unchanged_prefix_set)
1382 }
1383
1384 #[cfg(test)]
1386 fn all_nodes(&self) -> impl IntoIterator<Item = (&Nibbles, &SparseNode)> {
1387 let mut nodes = vec![];
1388 for subtrie in self.lower_subtries.iter().filter_map(LowerSparseSubtrie::as_revealed_ref) {
1389 nodes.extend(subtrie.nodes.iter())
1390 }
1391 nodes.extend(self.upper_subtrie.nodes.iter());
1392 nodes
1393 }
1394
1395 fn reveal_upper_node(
1412 &mut self,
1413 path: Nibbles,
1414 node: &TrieNode,
1415 masks: TrieMasks,
1416 ) -> SparseTrieResult<()> {
1417 self.upper_subtrie.reveal_node(path, node, masks)?;
1420
1421 match node {
1426 TrieNode::Branch(branch) => {
1427 if !SparseSubtrieType::path_len_is_upper(path.len() + 1) {
1431 let mut stack_ptr = branch.as_ref().first_child_index();
1432 for idx in CHILD_INDEX_RANGE {
1433 if branch.state_mask.is_bit_set(idx) {
1434 let mut child_path = path;
1435 child_path.push_unchecked(idx);
1436 self.lower_subtrie_for_path_mut(&child_path)
1437 .expect("child_path must have a lower subtrie")
1438 .reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
1439 stack_ptr += 1;
1440 }
1441 }
1442 }
1443 }
1444 TrieNode::Extension(ext) => {
1445 let mut child_path = path;
1446 child_path.extend(&ext.key);
1447 if let Some(subtrie) = self.lower_subtrie_for_path_mut(&child_path) {
1448 subtrie.reveal_node_or_hash(child_path, &ext.child)?;
1449 }
1450 }
1451 TrieNode::EmptyRoot | TrieNode::Leaf(_) => (),
1452 }
1453
1454 Ok(())
1455 }
1456}
1457
1458#[derive(Clone, PartialEq, Eq, Debug, Default)]
1461pub struct SparseSubtrie {
1462 pub(crate) path: Nibbles,
1470 nodes: HashMap<Nibbles, SparseNode>,
1472 inner: SparseSubtrieInner,
1474}
1475
1476enum FindNextToLeafOutcome {
1479 Found,
1481 ContinueFrom(Nibbles),
1483 NotFound,
1486 BlindedNode(B256),
1489}
1490
1491impl SparseSubtrie {
1492 pub(crate) fn new(path: Nibbles) -> Self {
1494 Self { path, ..Default::default() }
1495 }
1496
1497 pub(crate) fn is_empty(&self) -> bool {
1499 self.nodes.is_empty()
1500 }
1501
1502 fn is_child_same_level(current_path: &Nibbles, child_path: &Nibbles) -> bool {
1504 let current_level = core::mem::discriminant(&SparseSubtrieType::from_path(current_path));
1505 let child_level = core::mem::discriminant(&SparseSubtrieType::from_path(child_path));
1506 current_level == child_level
1507 }
1508
1509 pub fn update_leaf(
1522 &mut self,
1523 full_path: Nibbles,
1524 value: Vec<u8>,
1525 provider: impl TrieNodeProvider,
1526 retain_updates: bool,
1527 ) -> SparseTrieResult<()> {
1528 debug_assert!(full_path.starts_with(&self.path));
1529 let existing = self.inner.values.insert(full_path, value);
1530 if existing.is_some() {
1531 return Ok(())
1533 }
1534
1535 let mut current = Some(self.path);
1537 while let Some(current_path) = current {
1538 match self.update_next_node(current_path, &full_path, retain_updates)? {
1539 LeafUpdateStep::Continue { next_node } => {
1540 current = Some(next_node);
1541 }
1542 LeafUpdateStep::Complete { reveal_path, .. } => {
1543 if let Some(reveal_path) = reveal_path {
1544 if self.nodes.get(&reveal_path).expect("node must exist").is_hash() {
1545 warn!(
1546 target: "trie::parallel_sparse",
1547 child_path = ?reveal_path,
1548 leaf_full_path = ?full_path,
1549 "Extension node child not revealed in update_leaf, falling back to db",
1550 );
1551 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1552 provider.trie_node(&reveal_path)?
1553 {
1554 let decoded = TrieNode::decode(&mut &node[..])?;
1555 trace!(
1556 target: "trie::parallel_sparse",
1557 ?reveal_path,
1558 ?decoded,
1559 ?tree_mask,
1560 ?hash_mask,
1561 "Revealing child (from lower)",
1562 );
1563 self.reveal_node(
1564 reveal_path,
1565 &decoded,
1566 TrieMasks { hash_mask, tree_mask },
1567 )?;
1568 } else {
1569 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1570 path: reveal_path,
1571 }
1572 .into())
1573 }
1574 }
1575 }
1576
1577 current = None;
1578 }
1579 LeafUpdateStep::NodeNotFound => {
1580 current = None;
1581 }
1582 }
1583 }
1584
1585 Ok(())
1586 }
1587
1588 fn update_next_node(
1595 &mut self,
1596 mut current: Nibbles,
1597 path: &Nibbles,
1598 retain_updates: bool,
1599 ) -> SparseTrieResult<LeafUpdateStep> {
1600 debug_assert!(path.starts_with(&self.path));
1601 debug_assert!(current.starts_with(&self.path));
1602 debug_assert!(path.starts_with(¤t));
1603 let Some(node) = self.nodes.get_mut(¤t) else {
1604 return Ok(LeafUpdateStep::NodeNotFound);
1605 };
1606 match node {
1607 SparseNode::Empty => {
1608 let path = path.slice(self.path.len()..);
1611 *node = SparseNode::new_leaf(path);
1612 Ok(LeafUpdateStep::complete_with_insertions(vec![current], None))
1613 }
1614 SparseNode::Hash(hash) => {
1615 Err(SparseTrieErrorKind::BlindedNode { path: current, hash: *hash }.into())
1616 }
1617 SparseNode::Leaf { key: current_key, .. } => {
1618 current.extend(current_key);
1619
1620 debug_assert!(
1622 ¤t != path,
1623 "we already checked leaf presence in the beginning"
1624 );
1625
1626 let common = current.common_prefix_length(path);
1628
1629 let new_ext_key = current.slice(current.len() - current_key.len()..common);
1631 *node = SparseNode::new_ext(new_ext_key);
1632
1633 self.nodes.reserve(3);
1635 let branch_path = current.slice(..common);
1636 let new_leaf_path = path.slice(..=common);
1637 let existing_leaf_path = current.slice(..=common);
1638
1639 self.nodes.insert(
1640 branch_path,
1641 SparseNode::new_split_branch(
1642 current.get_unchecked(common),
1643 path.get_unchecked(common),
1644 ),
1645 );
1646 self.nodes.insert(new_leaf_path, SparseNode::new_leaf(path.slice(common + 1..)));
1647 self.nodes
1648 .insert(existing_leaf_path, SparseNode::new_leaf(current.slice(common + 1..)));
1649
1650 Ok(LeafUpdateStep::complete_with_insertions(
1651 vec![branch_path, new_leaf_path, existing_leaf_path],
1652 None,
1653 ))
1654 }
1655 SparseNode::Extension { key, .. } => {
1656 current.extend(key);
1657
1658 if !path.starts_with(¤t) {
1659 let common = current.common_prefix_length(path);
1661 *key = current.slice(current.len() - key.len()..common);
1662
1663 let reveal_path = retain_updates.then_some(current);
1667
1668 self.nodes.reserve(3);
1671 let branch_path = current.slice(..common);
1672 let new_leaf_path = path.slice(..=common);
1673 let branch = SparseNode::new_split_branch(
1674 current.get_unchecked(common),
1675 path.get_unchecked(common),
1676 );
1677
1678 self.nodes.insert(branch_path, branch);
1679
1680 let new_leaf = SparseNode::new_leaf(path.slice(common + 1..));
1682 self.nodes.insert(new_leaf_path, new_leaf);
1683
1684 let mut inserted_nodes = vec![branch_path, new_leaf_path];
1685
1686 let key = current.slice(common + 1..);
1688 if !key.is_empty() {
1689 let ext_path = current.slice(..=common);
1690 self.nodes.insert(ext_path, SparseNode::new_ext(key));
1691 inserted_nodes.push(ext_path);
1692 }
1693
1694 return Ok(LeafUpdateStep::complete_with_insertions(inserted_nodes, reveal_path))
1695 }
1696
1697 Ok(LeafUpdateStep::continue_with(current))
1698 }
1699 SparseNode::Branch { state_mask, .. } => {
1700 let nibble = path.get_unchecked(current.len());
1701 current.push_unchecked(nibble);
1702 if !state_mask.is_bit_set(nibble) {
1703 state_mask.set_bit(nibble);
1704 let new_leaf = SparseNode::new_leaf(path.slice(current.len()..));
1705 self.nodes.insert(current, new_leaf);
1706 return Ok(LeafUpdateStep::complete_with_insertions(vec![current], None))
1707 }
1708
1709 Ok(LeafUpdateStep::continue_with(current))
1711 }
1712 }
1713 }
1714
1715 fn reveal_node(
1717 &mut self,
1718 path: Nibbles,
1719 node: &TrieNode,
1720 masks: TrieMasks,
1721 ) -> SparseTrieResult<()> {
1722 debug_assert!(path.starts_with(&self.path));
1723
1724 if self.nodes.get(&path).is_some_and(|node| !node.is_hash()) {
1726 return Ok(())
1727 }
1728
1729 match node {
1730 TrieNode::EmptyRoot => {
1731 debug_assert!(path.is_empty());
1733 debug_assert!(self.path.is_empty());
1734 self.nodes.insert(path, SparseNode::Empty);
1735 }
1736 TrieNode::Branch(branch) => {
1737 let mut stack_ptr = branch.as_ref().first_child_index();
1739 for idx in CHILD_INDEX_RANGE {
1740 if branch.state_mask.is_bit_set(idx) {
1741 let mut child_path = path;
1742 child_path.push_unchecked(idx);
1743 if Self::is_child_same_level(&path, &child_path) {
1744 self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
1747 }
1748 stack_ptr += 1;
1749 }
1750 }
1751 match self.nodes.entry(path) {
1754 Entry::Occupied(mut entry) => match entry.get() {
1755 SparseNode::Hash(hash) => {
1757 entry.insert(SparseNode::Branch {
1758 state_mask: branch.state_mask,
1759 hash: Some(*hash),
1762 store_in_db_trie: Some(
1763 masks.hash_mask.is_some_and(|mask| !mask.is_empty()) ||
1764 masks.tree_mask.is_some_and(|mask| !mask.is_empty()),
1765 ),
1766 });
1767 }
1768 SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
1771 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
1773 return Err(SparseTrieErrorKind::Reveal {
1774 path: *entry.key(),
1775 node: Box::new(node.clone()),
1776 }
1777 .into())
1778 }
1779 },
1780 Entry::Vacant(entry) => {
1781 entry.insert(SparseNode::new_branch(branch.state_mask));
1782 }
1783 }
1784 }
1785 TrieNode::Extension(ext) => match self.nodes.entry(path) {
1786 Entry::Occupied(mut entry) => match entry.get() {
1787 SparseNode::Hash(hash) => {
1789 let mut child_path = *entry.key();
1790 child_path.extend(&ext.key);
1791 entry.insert(SparseNode::Extension {
1792 key: ext.key,
1793 hash: Some(*hash),
1796 store_in_db_trie: None,
1797 });
1798 if Self::is_child_same_level(&path, &child_path) {
1799 self.reveal_node_or_hash(child_path, &ext.child)?;
1800 }
1801 }
1802 SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
1805 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
1807 return Err(SparseTrieErrorKind::Reveal {
1808 path: *entry.key(),
1809 node: Box::new(node.clone()),
1810 }
1811 .into())
1812 }
1813 },
1814 Entry::Vacant(entry) => {
1815 let mut child_path = *entry.key();
1816 child_path.extend(&ext.key);
1817 entry.insert(SparseNode::new_ext(ext.key));
1818 if Self::is_child_same_level(&path, &child_path) {
1819 self.reveal_node_or_hash(child_path, &ext.child)?;
1820 }
1821 }
1822 },
1823 TrieNode::Leaf(leaf) => match self.nodes.entry(path) {
1824 Entry::Occupied(mut entry) => match entry.get() {
1825 SparseNode::Hash(hash) => {
1827 let mut full = *entry.key();
1828 full.extend(&leaf.key);
1829 self.inner.values.insert(full, leaf.value.clone());
1830 entry.insert(SparseNode::Leaf {
1831 key: leaf.key,
1832 hash: Some(*hash),
1835 });
1836 }
1837 SparseNode::Leaf { .. } => {}
1839 node @ (SparseNode::Empty |
1841 SparseNode::Extension { .. } |
1842 SparseNode::Branch { .. }) => {
1843 return Err(SparseTrieErrorKind::Reveal {
1844 path: *entry.key(),
1845 node: Box::new(node.clone()),
1846 }
1847 .into())
1848 }
1849 },
1850 Entry::Vacant(entry) => {
1851 let mut full = *entry.key();
1852 full.extend(&leaf.key);
1853 entry.insert(SparseNode::new_leaf(leaf.key));
1854 self.inner.values.insert(full, leaf.value.clone());
1855 }
1856 },
1857 }
1858
1859 Ok(())
1860 }
1861
1862 fn reveal_node_or_hash(&mut self, path: Nibbles, child: &[u8]) -> SparseTrieResult<()> {
1881 if child.len() == B256::len_bytes() + 1 {
1882 let hash = B256::from_slice(&child[1..]);
1883 match self.nodes.entry(path) {
1884 Entry::Occupied(entry) => match entry.get() {
1885 SparseNode::Hash(previous_hash) if previous_hash != &hash => {
1887 return Err(SparseTrieErrorKind::Reveal {
1888 path: *entry.key(),
1889 node: Box::new(SparseNode::Hash(hash)),
1890 }
1891 .into())
1892 }
1893 _ => {}
1894 },
1895 Entry::Vacant(entry) => {
1896 entry.insert(SparseNode::Hash(hash));
1897 }
1898 }
1899 return Ok(())
1900 }
1901
1902 self.reveal_node(path, &TrieNode::decode(&mut &child[..])?, TrieMasks::none())
1903 }
1904
1905 #[instrument(level = "trace", target = "trie::parallel_sparse", skip_all, fields(root = ?self.path), ret)]
1928 fn update_hashes(
1929 &mut self,
1930 prefix_set: &mut PrefixSet,
1931 update_actions: &mut Option<Vec<SparseTrieUpdatesAction>>,
1932 branch_node_tree_masks: &HashMap<Nibbles, TrieMask>,
1933 branch_node_hash_masks: &HashMap<Nibbles, TrieMask>,
1934 ) -> RlpNode {
1935 trace!(target: "trie::parallel_sparse", "Updating subtrie hashes");
1936
1937 debug_assert!(prefix_set.iter().all(|path| path.starts_with(&self.path)));
1938
1939 debug_assert!(self.inner.buffers.path_stack.is_empty());
1940 self.inner
1941 .buffers
1942 .path_stack
1943 .push(RlpNodePathStackItem { path: self.path, is_in_prefix_set: None });
1944
1945 while let Some(stack_item) = self.inner.buffers.path_stack.pop() {
1946 let path = stack_item.path;
1947 let node = self
1948 .nodes
1949 .get_mut(&path)
1950 .unwrap_or_else(|| panic!("node at path {path:?} does not exist"));
1951
1952 self.inner.rlp_node(
1953 prefix_set,
1954 update_actions,
1955 stack_item,
1956 node,
1957 branch_node_tree_masks,
1958 branch_node_hash_masks,
1959 );
1960 }
1961
1962 debug_assert_eq!(self.inner.buffers.rlp_node_stack.len(), 1);
1963 self.inner.buffers.rlp_node_stack.pop().unwrap().rlp_node
1964 }
1965
1966 fn wipe(&mut self) {
1969 self.nodes = HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]);
1970 self.inner.clear();
1971 }
1972
1973 pub(crate) fn clear(&mut self) {
1975 self.nodes.clear();
1976 self.inner.clear();
1977 }
1978}
1979
1980#[derive(Clone, PartialEq, Eq, Debug, Default)]
1983struct SparseSubtrieInner {
1984 values: HashMap<Nibbles, Vec<u8>>,
1987 buffers: SparseSubtrieBuffers,
1989}
1990
1991impl SparseSubtrieInner {
1992 fn rlp_node(
2023 &mut self,
2024 prefix_set: &mut PrefixSet,
2025 update_actions: &mut Option<Vec<SparseTrieUpdatesAction>>,
2026 mut stack_item: RlpNodePathStackItem,
2027 node: &mut SparseNode,
2028 branch_node_tree_masks: &HashMap<Nibbles, TrieMask>,
2029 branch_node_hash_masks: &HashMap<Nibbles, TrieMask>,
2030 ) {
2031 let path = stack_item.path;
2032 trace!(
2033 target: "trie::parallel_sparse",
2034 ?path,
2035 ?node,
2036 "Calculating node RLP"
2037 );
2038
2039 let mut prefix_set_contains = |path: &Nibbles| {
2043 *stack_item.is_in_prefix_set.get_or_insert_with(|| prefix_set.contains(path))
2044 };
2045
2046 let (rlp_node, node_type) = match node {
2047 SparseNode::Empty => (RlpNode::word_rlp(&EMPTY_ROOT_HASH), SparseNodeType::Empty),
2048 SparseNode::Hash(hash) => {
2049 (RlpNode::word_rlp(hash), SparseNodeType::Hash)
2051 }
2052 SparseNode::Leaf { key, hash } => {
2053 let mut path = path;
2054 path.extend(key);
2055 let value = self.values.get(&path);
2056 if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path) || value.is_none())
2057 {
2058 (RlpNode::word_rlp(&hash), SparseNodeType::Leaf)
2062 } else {
2063 let value = self.values.get(&path).unwrap();
2065 self.buffers.rlp_buf.clear();
2066 let rlp_node = LeafNodeRef { key, value }.rlp(&mut self.buffers.rlp_buf);
2067 *hash = rlp_node.as_hash();
2068 (rlp_node, SparseNodeType::Leaf)
2069 }
2070 }
2071 SparseNode::Extension { key, hash, store_in_db_trie } => {
2072 let mut child_path = path;
2073 child_path.extend(key);
2074 if let Some((hash, store_in_db_trie)) =
2075 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
2076 {
2077 (
2080 RlpNode::word_rlp(&hash),
2081 SparseNodeType::Extension { store_in_db_trie: Some(store_in_db_trie) },
2082 )
2083 } else if self.buffers.rlp_node_stack.last().is_some_and(|e| e.path == child_path) {
2084 let RlpNodeStackItem { path: _, rlp_node: child, node_type: child_node_type } =
2087 self.buffers.rlp_node_stack.pop().unwrap();
2088 self.buffers.rlp_buf.clear();
2089 let rlp_node =
2090 ExtensionNodeRef::new(key, &child).rlp(&mut self.buffers.rlp_buf);
2091 *hash = rlp_node.as_hash();
2092
2093 let store_in_db_trie_value = child_node_type.store_in_db_trie();
2094
2095 trace!(
2096 target: "trie::parallel_sparse",
2097 ?path,
2098 ?child_path,
2099 ?child_node_type,
2100 "Extension node"
2101 );
2102
2103 *store_in_db_trie = store_in_db_trie_value;
2104
2105 (
2106 rlp_node,
2107 SparseNodeType::Extension {
2108 store_in_db_trie: store_in_db_trie_value,
2111 },
2112 )
2113 } else {
2114 self.buffers.path_stack.extend([
2117 RlpNodePathStackItem {
2118 path,
2119 is_in_prefix_set: Some(prefix_set_contains(&path)),
2120 },
2121 RlpNodePathStackItem { path: child_path, is_in_prefix_set: None },
2122 ]);
2123 return
2124 }
2125 }
2126 SparseNode::Branch { state_mask, hash, store_in_db_trie } => {
2127 if let Some((hash, store_in_db_trie)) =
2128 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
2129 {
2130 self.buffers.rlp_node_stack.push(RlpNodeStackItem {
2133 path,
2134 rlp_node: RlpNode::word_rlp(&hash),
2135 node_type: SparseNodeType::Branch {
2136 store_in_db_trie: Some(store_in_db_trie),
2137 },
2138 });
2139 return
2140 }
2141
2142 let retain_updates = update_actions.is_some() && prefix_set_contains(&path);
2143
2144 self.buffers.branch_child_buf.clear();
2145 for bit in CHILD_INDEX_RANGE.rev() {
2148 if state_mask.is_bit_set(bit) {
2149 let mut child = path;
2150 child.push_unchecked(bit);
2151 self.buffers.branch_child_buf.push(child);
2152 }
2153 }
2154
2155 self.buffers
2156 .branch_value_stack_buf
2157 .resize(self.buffers.branch_child_buf.len(), Default::default());
2158 let mut added_children = false;
2159
2160 let mut tree_mask = TrieMask::default();
2161 let mut hash_mask = TrieMask::default();
2162 let mut hashes = Vec::new();
2163 for (i, child_path) in self.buffers.branch_child_buf.iter().enumerate() {
2164 if self.buffers.rlp_node_stack.last().is_some_and(|e| &e.path == child_path) {
2165 let RlpNodeStackItem {
2166 path: _,
2167 rlp_node: child,
2168 node_type: child_node_type,
2169 } = self.buffers.rlp_node_stack.pop().unwrap();
2170
2171 if retain_updates {
2173 let last_child_nibble = child_path.last().unwrap();
2175
2176 let should_set_tree_mask_bit = if let Some(store_in_db_trie) =
2178 child_node_type.store_in_db_trie()
2179 {
2180 store_in_db_trie
2183 } else {
2184 child_node_type.is_hash() &&
2186 branch_node_tree_masks
2187 .get(&path)
2188 .is_some_and(|mask| mask.is_bit_set(last_child_nibble))
2189 };
2190 if should_set_tree_mask_bit {
2191 tree_mask.set_bit(last_child_nibble);
2192 }
2193
2194 let hash = child.as_hash().filter(|_| {
2198 child_node_type.is_branch() ||
2199 (child_node_type.is_hash() &&
2200 branch_node_hash_masks.get(&path).is_some_and(
2201 |mask| mask.is_bit_set(last_child_nibble),
2202 ))
2203 });
2204 if let Some(hash) = hash {
2205 hash_mask.set_bit(last_child_nibble);
2206 hashes.push(hash);
2207 }
2208 }
2209
2210 let original_idx = self.buffers.branch_child_buf.len() - i - 1;
2214 self.buffers.branch_value_stack_buf[original_idx] = child;
2215 added_children = true;
2216 } else {
2217 debug_assert!(!added_children);
2220 self.buffers.path_stack.push(RlpNodePathStackItem {
2221 path,
2222 is_in_prefix_set: Some(prefix_set_contains(&path)),
2223 });
2224 self.buffers.path_stack.extend(
2225 self.buffers
2226 .branch_child_buf
2227 .drain(..)
2228 .map(|path| RlpNodePathStackItem { path, is_in_prefix_set: None }),
2229 );
2230 return
2231 }
2232 }
2233
2234 trace!(
2235 target: "trie::parallel_sparse",
2236 ?path,
2237 ?tree_mask,
2238 ?hash_mask,
2239 "Branch node masks"
2240 );
2241
2242 self.buffers.rlp_buf.clear();
2245 let branch_node_ref =
2246 BranchNodeRef::new(&self.buffers.branch_value_stack_buf, *state_mask);
2247 let rlp_node = branch_node_ref.rlp(&mut self.buffers.rlp_buf);
2248 *hash = rlp_node.as_hash();
2249
2250 let store_in_db_trie_value = if let Some(update_actions) =
2253 update_actions.as_mut().filter(|_| retain_updates && !path.is_empty())
2254 {
2255 let store_in_db_trie = !tree_mask.is_empty() || !hash_mask.is_empty();
2256 if store_in_db_trie {
2257 hashes.reverse();
2260 let branch_node = BranchNodeCompact::new(
2261 *state_mask,
2262 tree_mask,
2263 hash_mask,
2264 hashes,
2265 hash.filter(|_| path.is_empty()),
2266 );
2267 update_actions
2268 .push(SparseTrieUpdatesAction::InsertUpdated(path, branch_node));
2269 } else if branch_node_tree_masks.get(&path).is_some_and(|mask| !mask.is_empty()) ||
2270 branch_node_hash_masks.get(&path).is_some_and(|mask| !mask.is_empty())
2271 {
2272 update_actions.push(SparseTrieUpdatesAction::InsertRemoved(path));
2276 } else if branch_node_tree_masks.get(&path).is_none_or(|mask| mask.is_empty()) &&
2277 branch_node_hash_masks.get(&path).is_none_or(|mask| mask.is_empty())
2278 {
2279 update_actions.push(SparseTrieUpdatesAction::RemoveUpdated(path));
2282 }
2283
2284 store_in_db_trie
2285 } else {
2286 false
2287 };
2288 *store_in_db_trie = Some(store_in_db_trie_value);
2289
2290 (
2291 rlp_node,
2292 SparseNodeType::Branch { store_in_db_trie: Some(store_in_db_trie_value) },
2293 )
2294 }
2295 };
2296
2297 self.buffers.rlp_node_stack.push(RlpNodeStackItem { path, rlp_node, node_type });
2298 trace!(
2299 target: "trie::parallel_sparse",
2300 ?path,
2301 ?node_type,
2302 "Added node to RLP node stack"
2303 );
2304 }
2305
2306 fn clear(&mut self) {
2308 self.values.clear();
2309 self.buffers.clear();
2310 }
2311}
2312
2313#[derive(Clone, Debug, PartialEq, Eq, Default)]
2315pub enum LeafUpdateStep {
2316 Continue {
2318 next_node: Nibbles,
2320 },
2321 Complete {
2323 inserted_nodes: Vec<Nibbles>,
2325 reveal_path: Option<Nibbles>,
2327 },
2328 #[default]
2330 NodeNotFound,
2331}
2332
2333impl LeafUpdateStep {
2334 pub const fn continue_with(next_node: Nibbles) -> Self {
2336 Self::Continue { next_node }
2337 }
2338
2339 pub const fn complete_with_insertions(
2341 inserted_nodes: Vec<Nibbles>,
2342 reveal_path: Option<Nibbles>,
2343 ) -> Self {
2344 Self::Complete { inserted_nodes, reveal_path }
2345 }
2346}
2347
2348#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2357pub enum SparseSubtrieType {
2358 Upper,
2360 Lower(usize),
2363}
2364
2365impl SparseSubtrieType {
2366 pub const fn path_len_is_upper(len: usize) -> bool {
2371 len < UPPER_TRIE_MAX_DEPTH
2372 }
2373
2374 pub fn from_path(path: &Nibbles) -> Self {
2376 if Self::path_len_is_upper(path.len()) {
2377 Self::Upper
2378 } else {
2379 Self::Lower(path_subtrie_index_unchecked(path))
2380 }
2381 }
2382
2383 pub const fn lower_index(&self) -> Option<usize> {
2385 match self {
2386 Self::Upper => None,
2387 Self::Lower(index) => Some(*index),
2388 }
2389 }
2390}
2391
2392impl Ord for SparseSubtrieType {
2393 fn cmp(&self, other: &Self) -> Ordering {
2396 match (self, other) {
2397 (Self::Upper, Self::Upper) => Ordering::Equal,
2398 (Self::Upper, Self::Lower(_)) => Ordering::Less,
2399 (Self::Lower(_), Self::Upper) => Ordering::Greater,
2400 (Self::Lower(idx_a), Self::Lower(idx_b)) if idx_a == idx_b => Ordering::Equal,
2401 (Self::Lower(idx_a), Self::Lower(idx_b)) => idx_a.cmp(idx_b),
2402 }
2403 }
2404}
2405
2406impl PartialOrd for SparseSubtrieType {
2407 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2408 Some(self.cmp(other))
2409 }
2410}
2411
2412#[derive(Clone, PartialEq, Eq, Debug, Default)]
2416pub struct SparseSubtrieBuffers {
2417 path_stack: Vec<RlpNodePathStackItem>,
2419 rlp_node_stack: Vec<RlpNodeStackItem>,
2421 branch_child_buf: SmallVec<[Nibbles; 16]>,
2423 branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
2425 rlp_buf: Vec<u8>,
2427}
2428
2429impl SparseSubtrieBuffers {
2430 fn clear(&mut self) {
2432 self.path_stack.clear();
2433 self.rlp_node_stack.clear();
2434 self.branch_child_buf.clear();
2435 self.branch_value_stack_buf.clear();
2436 self.rlp_buf.clear();
2437 }
2438}
2439
2440#[derive(Clone, PartialEq, Eq, Debug)]
2442pub struct RlpNodePathStackItem {
2443 pub path: Nibbles,
2445 pub is_in_prefix_set: Option<bool>,
2447}
2448
2449#[derive(Debug)]
2451struct ChangedSubtrie {
2452 index: usize,
2454 subtrie: Box<SparseSubtrie>,
2456 prefix_set: PrefixSet,
2458 update_actions_buf: Option<Vec<SparseTrieUpdatesAction>>,
2461}
2462
2463fn path_subtrie_index_unchecked(path: &Nibbles) -> usize {
2470 debug_assert_eq!(UPPER_TRIE_MAX_DEPTH, 2);
2471 path.get_byte_unchecked(0) as usize
2472}
2473
2474#[derive(Clone, Debug, Eq, PartialEq)]
2476enum SparseTrieUpdatesAction {
2477 InsertRemoved(Nibbles),
2479 RemoveUpdated(Nibbles),
2482 InsertUpdated(Nibbles, BranchNodeCompact),
2484}
2485
2486#[cfg(test)]
2487mod tests {
2488 use super::{
2489 path_subtrie_index_unchecked, LowerSparseSubtrie, ParallelSparseTrie, SparseSubtrie,
2490 SparseSubtrieType,
2491 };
2492 use crate::trie::ChangedSubtrie;
2493 use alloy_primitives::{
2494 b256, hex,
2495 map::{B256Set, DefaultHashBuilder, HashMap},
2496 B256, U256,
2497 };
2498 use alloy_rlp::{Decodable, Encodable};
2499 use alloy_trie::{BranchNodeCompact, Nibbles};
2500 use assert_matches::assert_matches;
2501 use itertools::Itertools;
2502 use proptest::{prelude::*, sample::SizeRange};
2503 use proptest_arbitrary_interop::arb;
2504 use reth_execution_errors::{SparseTrieError, SparseTrieErrorKind};
2505 use reth_primitives_traits::Account;
2506 use reth_provider::{test_utils::create_test_provider_factory, TrieWriter};
2507 use reth_trie::{
2508 hashed_cursor::{noop::NoopHashedAccountCursor, HashedPostStateAccountCursor},
2509 node_iter::{TrieElement, TrieNodeIter},
2510 trie_cursor::{noop::NoopAccountTrieCursor, TrieCursor, TrieCursorFactory},
2511 walker::TrieWalker,
2512 HashedPostState,
2513 };
2514 use reth_trie_common::{
2515 prefix_set::PrefixSetMut,
2516 proof::{ProofNodes, ProofRetainer},
2517 updates::TrieUpdates,
2518 BranchNode, ExtensionNode, HashBuilder, LeafNode, RlpNode, TrieMask, TrieNode,
2519 EMPTY_ROOT_HASH,
2520 };
2521 use reth_trie_db::DatabaseTrieCursorFactory;
2522 use reth_trie_sparse::{
2523 provider::{DefaultTrieNodeProvider, RevealedNode, TrieNodeProvider},
2524 LeafLookup, LeafLookupError, RevealedSparseNode, SerialSparseTrie, SparseNode,
2525 SparseTrieInterface, SparseTrieUpdates, TrieMasks,
2526 };
2527 use std::collections::{BTreeMap, BTreeSet};
2528
2529 fn pad_nibbles_right(mut nibbles: Nibbles) -> Nibbles {
2531 nibbles.extend(&Nibbles::from_nibbles_unchecked(vec![
2532 0;
2533 B256::len_bytes() * 2 - nibbles.len()
2534 ]));
2535 nibbles
2536 }
2537
2538 #[derive(Debug, Clone)]
2543 struct MockTrieNodeProvider {
2544 nodes: HashMap<Nibbles, RevealedNode, DefaultHashBuilder>,
2546 }
2547
2548 impl MockTrieNodeProvider {
2549 fn new() -> Self {
2551 Self { nodes: HashMap::default() }
2552 }
2553
2554 fn add_revealed_node(&mut self, path: Nibbles, node: RevealedNode) {
2556 self.nodes.insert(path, node);
2557 }
2558 }
2559
2560 impl TrieNodeProvider for MockTrieNodeProvider {
2561 fn trie_node(&self, path: &Nibbles) -> Result<Option<RevealedNode>, SparseTrieError> {
2562 Ok(self.nodes.get(path).cloned())
2563 }
2564 }
2565
2566 fn create_account(nonce: u64) -> Account {
2567 Account { nonce, ..Default::default() }
2568 }
2569
2570 fn encode_account_value(nonce: u64) -> Vec<u8> {
2571 let account = Account { nonce, ..Default::default() };
2572 let trie_account = account.into_trie_account(EMPTY_ROOT_HASH);
2573 let mut buf = Vec::new();
2574 trie_account.encode(&mut buf);
2575 buf
2576 }
2577
2578 #[derive(Default)]
2580 struct ParallelSparseTrieTestContext;
2581
2582 impl ParallelSparseTrieTestContext {
2583 fn assert_subtrie_exists(&self, trie: &ParallelSparseTrie, path: &Nibbles) {
2585 let idx = path_subtrie_index_unchecked(path);
2586 assert!(
2587 trie.lower_subtries[idx].as_revealed_ref().is_some(),
2588 "Expected lower subtrie at path {path:?} to exist",
2589 );
2590 }
2591
2592 fn get_subtrie<'a>(
2594 &self,
2595 trie: &'a ParallelSparseTrie,
2596 path: &Nibbles,
2597 ) -> &'a SparseSubtrie {
2598 let idx = path_subtrie_index_unchecked(path);
2599 trie.lower_subtries[idx]
2600 .as_revealed_ref()
2601 .unwrap_or_else(|| panic!("Lower subtrie at path {path:?} should exist"))
2602 }
2603
2604 fn assert_subtrie_path(
2606 &self,
2607 trie: &ParallelSparseTrie,
2608 subtrie_prefix: impl AsRef<[u8]>,
2609 expected_path: impl AsRef<[u8]>,
2610 ) {
2611 let subtrie_prefix = Nibbles::from_nibbles(subtrie_prefix);
2612 let expected_path = Nibbles::from_nibbles(expected_path);
2613 let idx = path_subtrie_index_unchecked(&subtrie_prefix);
2614
2615 let subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap_or_else(|| {
2616 panic!("Lower subtrie at prefix {subtrie_prefix:?} should exist")
2617 });
2618
2619 assert_eq!(
2620 subtrie.path, expected_path,
2621 "Subtrie at prefix {subtrie_prefix:?} should have path {expected_path:?}, but has {:?}",
2622 subtrie.path
2623 );
2624 }
2625
2626 fn create_test_leaves(&self, paths: &[&[u8]]) -> Vec<(Nibbles, Vec<u8>)> {
2628 paths
2629 .iter()
2630 .enumerate()
2631 .map(|(i, path)| (Nibbles::from_nibbles(path), encode_account_value(i as u64 + 1)))
2632 .collect()
2633 }
2634
2635 fn create_test_leaf(&self, path: impl AsRef<[u8]>, value_nonce: u64) -> (Nibbles, Vec<u8>) {
2637 (Nibbles::from_nibbles(path), encode_account_value(value_nonce))
2638 }
2639
2640 fn update_leaves(
2642 &self,
2643 trie: &mut ParallelSparseTrie,
2644 leaves: impl IntoIterator<Item = (Nibbles, Vec<u8>)>,
2645 ) {
2646 for (path, value) in leaves {
2647 trie.update_leaf(path, value, DefaultTrieNodeProvider).unwrap();
2648 }
2649 }
2650
2651 fn assert_subtrie<'a>(
2653 &self,
2654 trie: &'a ParallelSparseTrie,
2655 path: Nibbles,
2656 ) -> SubtrieAssertion<'a> {
2657 self.assert_subtrie_exists(trie, &path);
2658 let subtrie = self.get_subtrie(trie, &path);
2659 SubtrieAssertion::new(subtrie)
2660 }
2661
2662 fn assert_upper_subtrie<'a>(&self, trie: &'a ParallelSparseTrie) -> SubtrieAssertion<'a> {
2664 SubtrieAssertion::new(&trie.upper_subtrie)
2665 }
2666
2667 fn assert_with_hash_builder(
2669 &self,
2670 trie: &mut ParallelSparseTrie,
2671 hash_builder_root: B256,
2672 hash_builder_updates: TrieUpdates,
2673 hash_builder_proof_nodes: ProofNodes,
2674 ) {
2675 assert_eq!(trie.root(), hash_builder_root);
2676 pretty_assertions::assert_eq!(
2677 BTreeMap::from_iter(trie.updates_ref().updated_nodes.clone()),
2678 BTreeMap::from_iter(hash_builder_updates.account_nodes)
2679 );
2680 assert_eq_parallel_sparse_trie_proof_nodes(trie, hash_builder_proof_nodes);
2681 }
2682 }
2683
2684 struct SubtrieAssertion<'a> {
2686 subtrie: &'a SparseSubtrie,
2687 }
2688
2689 impl<'a> SubtrieAssertion<'a> {
2690 fn new(subtrie: &'a SparseSubtrie) -> Self {
2691 Self { subtrie }
2692 }
2693
2694 fn has_branch(self, path: &Nibbles, expected_mask_bits: &[u8]) -> Self {
2695 match self.subtrie.nodes.get(path) {
2696 Some(SparseNode::Branch { state_mask, .. }) => {
2697 for bit in expected_mask_bits {
2698 assert!(
2699 state_mask.is_bit_set(*bit),
2700 "Expected branch at {path:?} to have bit {bit} set, instead mask is: {state_mask:?}",
2701 );
2702 }
2703 }
2704 node => panic!("Expected branch node at {path:?}, found {node:?}"),
2705 }
2706 self
2707 }
2708
2709 fn has_leaf(self, path: &Nibbles, expected_key: &Nibbles) -> Self {
2710 match self.subtrie.nodes.get(path) {
2711 Some(SparseNode::Leaf { key, .. }) => {
2712 assert_eq!(
2713 *key, *expected_key,
2714 "Expected leaf at {path:?} to have key {expected_key:?}, found {key:?}",
2715 );
2716 }
2717 node => panic!("Expected leaf node at {path:?}, found {node:?}"),
2718 }
2719 self
2720 }
2721
2722 fn has_extension(self, path: &Nibbles, expected_key: &Nibbles) -> Self {
2723 match self.subtrie.nodes.get(path) {
2724 Some(SparseNode::Extension { key, .. }) => {
2725 assert_eq!(
2726 *key, *expected_key,
2727 "Expected extension at {path:?} to have key {expected_key:?}, found {key:?}",
2728 );
2729 }
2730 node => panic!("Expected extension node at {path:?}, found {node:?}"),
2731 }
2732 self
2733 }
2734
2735 fn has_hash(self, path: &Nibbles, expected_hash: &B256) -> Self {
2736 match self.subtrie.nodes.get(path) {
2737 Some(SparseNode::Hash(hash)) => {
2738 assert_eq!(
2739 *hash, *expected_hash,
2740 "Expected hash at {path:?} to be {expected_hash:?}, found {hash:?}",
2741 );
2742 }
2743 node => panic!("Expected hash node at {path:?}, found {node:?}"),
2744 }
2745 self
2746 }
2747
2748 fn has_value(self, path: &Nibbles, expected_value: &[u8]) -> Self {
2749 let actual = self.subtrie.inner.values.get(path);
2750 assert_eq!(
2751 actual.map(|v| v.as_slice()),
2752 Some(expected_value),
2753 "Expected value at {path:?} to be {expected_value:?}, found {actual:?}",
2754 );
2755 self
2756 }
2757
2758 fn has_no_value(self, path: &Nibbles) -> Self {
2759 let actual = self.subtrie.inner.values.get(path);
2760 assert!(actual.is_none(), "Expected no value at {path:?}, but found {actual:?}");
2761 self
2762 }
2763 }
2764
2765 fn create_leaf_node(key: impl AsRef<[u8]>, value_nonce: u64) -> TrieNode {
2766 TrieNode::Leaf(LeafNode::new(Nibbles::from_nibbles(key), encode_account_value(value_nonce)))
2767 }
2768
2769 fn create_extension_node(key: impl AsRef<[u8]>, child_hash: B256) -> TrieNode {
2770 TrieNode::Extension(ExtensionNode::new(
2771 Nibbles::from_nibbles(key),
2772 RlpNode::word_rlp(&child_hash),
2773 ))
2774 }
2775
2776 fn create_branch_node_with_children(
2777 children_indices: &[u8],
2778 child_hashes: impl IntoIterator<Item = RlpNode>,
2779 ) -> TrieNode {
2780 let mut stack = Vec::new();
2781 let mut state_mask = TrieMask::default();
2782
2783 for (&idx, hash) in children_indices.iter().zip(child_hashes.into_iter()) {
2784 state_mask.set_bit(idx);
2785 stack.push(hash);
2786 }
2787
2788 TrieNode::Branch(BranchNode::new(stack, state_mask))
2789 }
2790
2791 fn run_hash_builder(
2796 state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
2797 trie_cursor: impl TrieCursor,
2798 destroyed_accounts: B256Set,
2799 proof_targets: impl IntoIterator<Item = Nibbles>,
2800 ) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>, HashMap<Nibbles, TrieMask>)
2801 {
2802 let mut account_rlp = Vec::new();
2803
2804 let mut hash_builder = HashBuilder::default()
2805 .with_updates(true)
2806 .with_proof_retainer(ProofRetainer::from_iter(proof_targets));
2807
2808 let mut prefix_set = PrefixSetMut::default();
2809 prefix_set.extend_keys(state.clone().into_iter().map(|(nibbles, _)| nibbles));
2810 prefix_set.extend_keys(destroyed_accounts.iter().map(Nibbles::unpack));
2811 let walker = TrieWalker::<_>::state_trie(trie_cursor, prefix_set.freeze())
2812 .with_deletions_retained(true);
2813 let hashed_post_state = HashedPostState::default()
2814 .with_accounts(state.into_iter().map(|(nibbles, account)| {
2815 (nibbles.pack().into_inner().unwrap().into(), Some(account))
2816 }))
2817 .into_sorted();
2818 let mut node_iter = TrieNodeIter::state_trie(
2819 walker,
2820 HashedPostStateAccountCursor::new(
2821 NoopHashedAccountCursor::default(),
2822 hashed_post_state.accounts(),
2823 ),
2824 );
2825
2826 while let Some(node) = node_iter.try_next().unwrap() {
2827 match node {
2828 TrieElement::Branch(branch) => {
2829 hash_builder.add_branch(branch.key, branch.value, branch.children_are_in_trie);
2830 }
2831 TrieElement::Leaf(key, account) => {
2832 let account = account.into_trie_account(EMPTY_ROOT_HASH);
2833 account.encode(&mut account_rlp);
2834
2835 hash_builder.add_leaf(Nibbles::unpack(key), &account_rlp);
2836 account_rlp.clear();
2837 }
2838 }
2839 }
2840 let root = hash_builder.root();
2841 let proof_nodes = hash_builder.take_proof_nodes();
2842 let branch_node_hash_masks = hash_builder
2843 .updated_branch_nodes
2844 .clone()
2845 .unwrap_or_default()
2846 .iter()
2847 .map(|(path, node)| (*path, node.hash_mask))
2848 .collect();
2849 let branch_node_tree_masks = hash_builder
2850 .updated_branch_nodes
2851 .clone()
2852 .unwrap_or_default()
2853 .iter()
2854 .map(|(path, node)| (*path, node.tree_mask))
2855 .collect();
2856
2857 let mut trie_updates = TrieUpdates::default();
2858 let removed_keys = node_iter.walker.take_removed_keys();
2859 trie_updates.finalize(hash_builder, removed_keys, destroyed_accounts);
2860
2861 (root, trie_updates, proof_nodes, branch_node_hash_masks, branch_node_tree_masks)
2862 }
2863
2864 fn new_test_trie<Nodes>(nodes: Nodes) -> ParallelSparseTrie
2867 where
2868 Nodes: Iterator<Item = (Nibbles, SparseNode)>,
2869 {
2870 let mut trie = ParallelSparseTrie::default().with_updates(true);
2871
2872 for (path, node) in nodes {
2873 let subtrie = trie.subtrie_for_path_mut(&path);
2874 if let SparseNode::Leaf { key, .. } = &node {
2875 let mut full_key = path;
2876 full_key.extend(key);
2877 subtrie.inner.values.insert(full_key, "LEAF VALUE".into());
2878 }
2879 subtrie.nodes.insert(path, node);
2880 }
2881 trie
2882 }
2883
2884 fn parallel_sparse_trie_nodes(
2885 sparse_trie: &ParallelSparseTrie,
2886 ) -> impl IntoIterator<Item = (&Nibbles, &SparseNode)> {
2887 let lower_sparse_nodes = sparse_trie
2888 .lower_subtries
2889 .iter()
2890 .filter_map(|subtrie| subtrie.as_revealed_ref())
2891 .flat_map(|subtrie| subtrie.nodes.iter());
2892
2893 let upper_sparse_nodes = sparse_trie.upper_subtrie.nodes.iter();
2894
2895 lower_sparse_nodes.chain(upper_sparse_nodes).sorted_by_key(|(path, _)| *path)
2896 }
2897
2898 fn assert_eq_parallel_sparse_trie_proof_nodes(
2901 sparse_trie: &ParallelSparseTrie,
2902 proof_nodes: ProofNodes,
2903 ) {
2904 let proof_nodes = proof_nodes
2905 .into_nodes_sorted()
2906 .into_iter()
2907 .map(|(path, node)| (path, TrieNode::decode(&mut node.as_ref()).unwrap()));
2908
2909 let all_sparse_nodes = parallel_sparse_trie_nodes(sparse_trie);
2910
2911 for ((proof_node_path, proof_node), (sparse_node_path, sparse_node)) in
2912 proof_nodes.zip(all_sparse_nodes)
2913 {
2914 assert_eq!(&proof_node_path, sparse_node_path);
2915
2916 let equals = match (&proof_node, &sparse_node) {
2917 (TrieNode::EmptyRoot, SparseNode::Empty) => true,
2919 (
2921 TrieNode::Branch(BranchNode { state_mask: proof_state_mask, .. }),
2922 SparseNode::Branch { state_mask: sparse_state_mask, .. },
2923 ) => proof_state_mask == sparse_state_mask,
2924 (
2926 TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
2927 SparseNode::Extension { key: sparse_key, .. },
2928 ) |
2929 (
2931 TrieNode::Leaf(LeafNode { key: proof_key, .. }),
2932 SparseNode::Leaf { key: sparse_key, .. },
2933 ) => proof_key == sparse_key,
2934 (_, SparseNode::Empty | SparseNode::Hash(_)) => continue,
2936 _ => false,
2937 };
2938 assert!(
2939 equals,
2940 "path: {proof_node_path:?}\nproof node: {proof_node:?}\nsparse node: {sparse_node:?}"
2941 );
2942 }
2943 }
2944
2945 #[test]
2946 fn test_get_changed_subtries_empty() {
2947 let mut trie = ParallelSparseTrie::default();
2948 let mut prefix_set = PrefixSetMut::from([Nibbles::default()]).freeze();
2949
2950 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
2951 assert!(subtries.is_empty());
2952 assert_eq!(unchanged_prefix_set, PrefixSetMut::from(prefix_set.iter().copied()));
2953 }
2954
2955 #[test]
2956 fn test_get_changed_subtries() {
2957 let mut trie = ParallelSparseTrie::default();
2959 let subtrie_1 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
2960 let subtrie_1_index = path_subtrie_index_unchecked(&subtrie_1.path);
2961 let subtrie_2 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x1, 0x0])));
2962 let subtrie_2_index = path_subtrie_index_unchecked(&subtrie_2.path);
2963 let subtrie_3 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x3, 0x0])));
2964 let subtrie_3_index = path_subtrie_index_unchecked(&subtrie_3.path);
2965
2966 trie.lower_subtries[subtrie_1_index] = LowerSparseSubtrie::Revealed(subtrie_1.clone());
2968 trie.lower_subtries[subtrie_2_index] = LowerSparseSubtrie::Revealed(subtrie_2.clone());
2969 trie.lower_subtries[subtrie_3_index] = LowerSparseSubtrie::Revealed(subtrie_3);
2970
2971 let unchanged_prefix_set = PrefixSetMut::from([
2972 Nibbles::from_nibbles([0x0]),
2973 Nibbles::from_nibbles([0x2, 0x0, 0x0]),
2974 ]);
2975 let mut prefix_set = PrefixSetMut::from([
2977 Nibbles::from_nibbles([0x1, 0x0, 0x0]),
2979 Nibbles::from_nibbles([0x1, 0x0, 0x1, 0x0]),
2980 ]);
2981 prefix_set.extend(unchanged_prefix_set);
2982 let mut prefix_set = prefix_set.freeze();
2983
2984 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
2986 assert_eq!(
2987 subtries
2988 .into_iter()
2989 .map(|ChangedSubtrie { index, subtrie, prefix_set, .. }| {
2990 (index, subtrie, prefix_set.iter().copied().collect::<Vec<_>>())
2991 })
2992 .collect::<Vec<_>>(),
2993 vec![(
2994 subtrie_2_index,
2995 subtrie_2,
2996 vec![
2997 Nibbles::from_nibbles([0x1, 0x0, 0x0]),
2998 Nibbles::from_nibbles([0x1, 0x0, 0x1, 0x0])
2999 ]
3000 )]
3001 );
3002 assert_eq!(unchanged_prefix_set, unchanged_prefix_set);
3003 assert!(trie.lower_subtries[subtrie_2_index].as_revealed_ref().is_none());
3004
3005 assert_eq!(trie.lower_subtries[subtrie_1_index], LowerSparseSubtrie::Revealed(subtrie_1));
3007 }
3008
3009 #[test]
3010 fn test_get_changed_subtries_all() {
3011 let mut trie = ParallelSparseTrie::default();
3013 let subtrie_1 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3014 let subtrie_1_index = path_subtrie_index_unchecked(&subtrie_1.path);
3015 let subtrie_2 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x1, 0x0])));
3016 let subtrie_2_index = path_subtrie_index_unchecked(&subtrie_2.path);
3017 let subtrie_3 = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x3, 0x0])));
3018 let subtrie_3_index = path_subtrie_index_unchecked(&subtrie_3.path);
3019
3020 trie.lower_subtries[subtrie_1_index] = LowerSparseSubtrie::Revealed(subtrie_1.clone());
3022 trie.lower_subtries[subtrie_2_index] = LowerSparseSubtrie::Revealed(subtrie_2.clone());
3023 trie.lower_subtries[subtrie_3_index] = LowerSparseSubtrie::Revealed(subtrie_3.clone());
3024
3025 let mut prefix_set = PrefixSetMut::all().freeze();
3027
3028 let (subtries, unchanged_prefix_set) = trie.take_changed_lower_subtries(&mut prefix_set);
3030 assert_eq!(
3031 subtries
3032 .into_iter()
3033 .map(|ChangedSubtrie { index, subtrie, prefix_set, .. }| {
3034 (index, subtrie, prefix_set.all())
3035 })
3036 .collect::<Vec<_>>(),
3037 vec![
3038 (subtrie_1_index, subtrie_1, true),
3039 (subtrie_2_index, subtrie_2, true),
3040 (subtrie_3_index, subtrie_3, true)
3041 ]
3042 );
3043 assert_eq!(unchanged_prefix_set, PrefixSetMut::all());
3044
3045 assert!(trie.lower_subtries.iter().all(|subtrie| subtrie.as_revealed_ref().is_none()));
3046 }
3047
3048 #[test]
3049 fn test_sparse_subtrie_type() {
3050 assert_eq!(SparseSubtrieType::from_path(&Nibbles::new()), SparseSubtrieType::Upper);
3051 assert_eq!(
3052 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0])),
3053 SparseSubtrieType::Upper
3054 );
3055 assert_eq!(
3056 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15])),
3057 SparseSubtrieType::Upper
3058 );
3059 assert_eq!(
3060 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 0])),
3061 SparseSubtrieType::Lower(0)
3062 );
3063 assert_eq!(
3064 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 0, 0])),
3065 SparseSubtrieType::Lower(0)
3066 );
3067 assert_eq!(
3068 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 1])),
3069 SparseSubtrieType::Lower(1)
3070 );
3071 assert_eq!(
3072 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 1, 0])),
3073 SparseSubtrieType::Lower(1)
3074 );
3075 assert_eq!(
3076 SparseSubtrieType::from_path(&Nibbles::from_nibbles([0, 15])),
3077 SparseSubtrieType::Lower(15)
3078 );
3079 assert_eq!(
3080 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 0])),
3081 SparseSubtrieType::Lower(240)
3082 );
3083 assert_eq!(
3084 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 1])),
3085 SparseSubtrieType::Lower(241)
3086 );
3087 assert_eq!(
3088 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 15])),
3089 SparseSubtrieType::Lower(255)
3090 );
3091 assert_eq!(
3092 SparseSubtrieType::from_path(&Nibbles::from_nibbles([15, 15, 15])),
3093 SparseSubtrieType::Lower(255)
3094 );
3095 }
3096
3097 #[test]
3098 fn test_reveal_node_leaves() {
3099 let mut trie = ParallelSparseTrie::default();
3100
3101 {
3103 let path = Nibbles::from_nibbles([0x1]);
3104 let node = create_leaf_node([0x2, 0x3], 42);
3105 let masks = TrieMasks::none();
3106
3107 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3108
3109 assert_matches!(
3110 trie.upper_subtrie.nodes.get(&path),
3111 Some(SparseNode::Leaf { key, hash: None })
3112 if key == &Nibbles::from_nibbles([0x2, 0x3])
3113 );
3114
3115 let full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3116 assert_eq!(
3117 trie.upper_subtrie.inner.values.get(&full_path),
3118 Some(&encode_account_value(42))
3119 );
3120 }
3121
3122 {
3124 let path = Nibbles::from_nibbles([0x1, 0x2]);
3125 let node = create_leaf_node([0x3, 0x4], 42);
3126 let masks = TrieMasks::none();
3127
3128 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3129
3130 let idx = path_subtrie_index_unchecked(&path);
3132 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3133
3134 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3136 assert_eq!(lower_subtrie.path, path);
3137
3138 assert_matches!(
3139 lower_subtrie.nodes.get(&path),
3140 Some(SparseNode::Leaf { key, hash: None })
3141 if key == &Nibbles::from_nibbles([0x3, 0x4])
3142 );
3143 }
3144
3145 {
3148 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3149 let node = create_leaf_node([0x4, 0x5], 42);
3150 let masks = TrieMasks::none();
3151
3152 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3153
3154 let idx = path_subtrie_index_unchecked(&path);
3156 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3157 assert_eq!(lower_subtrie.path, Nibbles::from_nibbles([0x1, 0x2]));
3158 }
3159 }
3160
3161 #[test]
3162 fn test_reveal_node_extension_all_upper() {
3163 let path = Nibbles::new();
3164 let child_hash = B256::repeat_byte(0xab);
3165 let node = create_extension_node([0x1], child_hash);
3166 let masks = TrieMasks::none();
3167 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3168
3169 assert_matches!(
3170 trie.upper_subtrie.nodes.get(&path),
3171 Some(SparseNode::Extension { key, hash: None, .. })
3172 if key == &Nibbles::from_nibbles([0x1])
3173 );
3174
3175 let child_path = Nibbles::from_nibbles([0x1]);
3177 assert_eq!(trie.upper_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3178 }
3179
3180 #[test]
3181 fn test_reveal_node_extension_cross_level() {
3182 let path = Nibbles::new();
3183 let child_hash = B256::repeat_byte(0xcd);
3184 let node = create_extension_node([0x1, 0x2, 0x3], child_hash);
3185 let masks = TrieMasks::none();
3186 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3187
3188 assert_matches!(
3190 trie.upper_subtrie.nodes.get(&path),
3191 Some(SparseNode::Extension { key, hash: None, .. })
3192 if key == &Nibbles::from_nibbles([0x1, 0x2, 0x3])
3193 );
3194
3195 let child_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3197 let idx = path_subtrie_index_unchecked(&child_path);
3198 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3199
3200 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3201 assert_eq!(lower_subtrie.path, child_path);
3202 assert_eq!(lower_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3203 }
3204
3205 #[test]
3206 fn test_reveal_node_extension_cross_level_boundary() {
3207 let mut trie = ParallelSparseTrie::default();
3208 let path = Nibbles::from_nibbles([0x1]);
3209 let child_hash = B256::repeat_byte(0xcd);
3210 let node = create_extension_node([0x2], child_hash);
3211 let masks = TrieMasks::none();
3212
3213 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3214
3215 assert_matches!(
3217 trie.upper_subtrie.nodes.get(&path),
3218 Some(SparseNode::Extension { key, hash: None, .. })
3219 if key == &Nibbles::from_nibbles([0x2])
3220 );
3221
3222 let child_path = Nibbles::from_nibbles([0x1, 0x2]);
3224 let idx = path_subtrie_index_unchecked(&child_path);
3225 assert!(trie.lower_subtries[idx].as_revealed_ref().is_some());
3226
3227 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3228 assert_eq!(lower_subtrie.path, child_path);
3229 assert_eq!(lower_subtrie.nodes.get(&child_path), Some(&SparseNode::Hash(child_hash)));
3230 }
3231
3232 #[test]
3233 fn test_reveal_node_branch_all_upper() {
3234 let path = Nibbles::new();
3235 let child_hashes = [
3236 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
3237 RlpNode::word_rlp(&B256::repeat_byte(0x22)),
3238 ];
3239 let node = create_branch_node_with_children(&[0x0, 0x5], child_hashes.clone());
3240 let masks = TrieMasks::none();
3241 let trie = ParallelSparseTrie::from_root(node, masks, true).unwrap();
3242
3243 assert_matches!(
3245 trie.upper_subtrie.nodes.get(&path),
3246 Some(SparseNode::Branch { state_mask, hash: None, .. })
3247 if *state_mask == 0b0000000000100001.into()
3248 );
3249
3250 let child_path_0 = Nibbles::from_nibbles([0x0]);
3252 let child_path_5 = Nibbles::from_nibbles([0x5]);
3253 assert_eq!(
3254 trie.upper_subtrie.nodes.get(&child_path_0),
3255 Some(&SparseNode::Hash(child_hashes[0].as_hash().unwrap()))
3256 );
3257 assert_eq!(
3258 trie.upper_subtrie.nodes.get(&child_path_5),
3259 Some(&SparseNode::Hash(child_hashes[1].as_hash().unwrap()))
3260 );
3261 }
3262
3263 #[test]
3264 fn test_reveal_node_branch_cross_level() {
3265 let mut trie = ParallelSparseTrie::default();
3266 let path = Nibbles::from_nibbles([0x1]); let child_hashes = [
3268 RlpNode::word_rlp(&B256::repeat_byte(0x33)),
3269 RlpNode::word_rlp(&B256::repeat_byte(0x44)),
3270 RlpNode::word_rlp(&B256::repeat_byte(0x55)),
3271 ];
3272 let node = create_branch_node_with_children(&[0x0, 0x7, 0xf], child_hashes.clone());
3273 let masks = TrieMasks::none();
3274
3275 trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3276
3277 assert_matches!(
3279 trie.upper_subtrie.nodes.get(&path),
3280 Some(SparseNode::Branch { state_mask, hash: None, .. })
3281 if *state_mask == 0b1000000010000001.into()
3282 );
3283
3284 let child_paths = [
3286 Nibbles::from_nibbles([0x1, 0x0]),
3287 Nibbles::from_nibbles([0x1, 0x7]),
3288 Nibbles::from_nibbles([0x1, 0xf]),
3289 ];
3290
3291 for (i, child_path) in child_paths.iter().enumerate() {
3292 let idx = path_subtrie_index_unchecked(child_path);
3293 let lower_subtrie = trie.lower_subtries[idx].as_revealed_ref().unwrap();
3294 assert_eq!(&lower_subtrie.path, child_path);
3295 assert_eq!(
3296 lower_subtrie.nodes.get(child_path),
3297 Some(&SparseNode::Hash(child_hashes[i].as_hash().unwrap())),
3298 );
3299 }
3300 }
3301
3302 #[test]
3303 fn test_update_subtrie_hashes_prefix_set_matching() {
3304 let mut trie = ParallelSparseTrie::default();
3306
3307 let leaf_1_full_path = Nibbles::from_nibbles([0; 64]);
3309 let leaf_1_path = leaf_1_full_path.slice(..2);
3310 let leaf_1_key = leaf_1_full_path.slice(2..);
3311 let leaf_2_full_path = Nibbles::from_nibbles([vec![0, 1], vec![0; 62]].concat());
3312 let leaf_2_path = leaf_2_full_path.slice(..2);
3313 let leaf_2_key = leaf_2_full_path.slice(2..);
3314 let leaf_3_full_path = Nibbles::from_nibbles([vec![0, 2], vec![0; 62]].concat());
3315 let leaf_3_path = leaf_3_full_path.slice(..2);
3316 let leaf_3_key = leaf_3_full_path.slice(2..);
3317 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), 1);
3318 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), 2);
3319 let leaf_3 = create_leaf_node(leaf_3_key.to_vec(), 3);
3320
3321 let child_hashes = [
3323 RlpNode::word_rlp(&B256::repeat_byte(0x00)),
3324 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
3325 ];
3327 let branch_path = Nibbles::from_nibbles([0x0]);
3328 let branch_node = create_branch_node_with_children(&[0x0, 0x1, 0x2], child_hashes);
3329
3330 trie.reveal_nodes(vec![
3332 RevealedSparseNode { path: branch_path, node: branch_node, masks: TrieMasks::none() },
3333 RevealedSparseNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
3334 RevealedSparseNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
3335 RevealedSparseNode { path: leaf_3_path, node: leaf_3, masks: TrieMasks::none() },
3336 ])
3337 .unwrap();
3338
3339 let subtrie_1_index = SparseSubtrieType::from_path(&leaf_1_path).lower_index().unwrap();
3341 let subtrie_2_index = SparseSubtrieType::from_path(&leaf_2_path).lower_index().unwrap();
3342 let subtrie_3_index = SparseSubtrieType::from_path(&leaf_3_path).lower_index().unwrap();
3343
3344 let mut unchanged_prefix_set = PrefixSetMut::from([
3345 Nibbles::from_nibbles([0x0]),
3346 leaf_2_full_path,
3347 Nibbles::from_nibbles([0x3, 0x0, 0x0]),
3348 ]);
3349 let mut prefix_set = PrefixSetMut::from([
3351 Nibbles::from_nibbles([0x0, 0x1, 0x0]),
3353 Nibbles::from_nibbles([0x0, 0x1, 0x1, 0x0]),
3354 ]);
3355 prefix_set.extend(unchanged_prefix_set.clone());
3356 trie.prefix_set = prefix_set;
3357
3358 trie.update_subtrie_hashes();
3360
3361 unchanged_prefix_set.insert(leaf_3_full_path);
3365
3366 assert_eq!(
3368 trie.prefix_set.clone().freeze().into_iter().collect::<Vec<_>>(),
3369 unchanged_prefix_set.freeze().into_iter().collect::<Vec<_>>()
3370 );
3371 assert!(trie.lower_subtries[subtrie_1_index].as_revealed_ref().is_some());
3373 assert!(trie.lower_subtries[subtrie_2_index].as_revealed_ref().is_some());
3374 assert!(trie.lower_subtries[subtrie_3_index].as_revealed_ref().is_some());
3375 }
3376
3377 #[test]
3378 fn test_subtrie_update_hashes() {
3379 let mut subtrie = Box::new(SparseSubtrie::new(Nibbles::from_nibbles([0x0, 0x0])));
3380
3381 let leaf_1_full_path = Nibbles::from_nibbles([0; 64]);
3383 let leaf_1_path = leaf_1_full_path.slice(..5);
3384 let leaf_1_key = leaf_1_full_path.slice(5..);
3385 let leaf_2_full_path = Nibbles::from_nibbles([vec![0, 0, 0, 0, 1], vec![0; 59]].concat());
3386 let leaf_2_path = leaf_2_full_path.slice(..5);
3387 let leaf_2_key = leaf_2_full_path.slice(5..);
3388 let leaf_3_full_path = Nibbles::from_nibbles([vec![0, 0, 1], vec![0; 61]].concat());
3389 let leaf_3_path = leaf_3_full_path.slice(..3);
3390 let leaf_3_key = leaf_3_full_path.slice(3..);
3391
3392 let account_1 = create_account(1);
3393 let account_2 = create_account(2);
3394 let account_3 = create_account(3);
3395 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), account_1.nonce);
3396 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), account_2.nonce);
3397 let leaf_3 = create_leaf_node(leaf_3_key.to_vec(), account_3.nonce);
3398
3399 let branch_1_path = Nibbles::from_nibbles([0, 0, 0, 0]);
3401 let branch_1 = create_branch_node_with_children(
3402 &[0, 1],
3403 vec![
3404 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_1)),
3405 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_2)),
3406 ],
3407 );
3408
3409 let extension_path = Nibbles::from_nibbles([0, 0, 0]);
3411 let extension_key = Nibbles::from_nibbles([0]);
3412 let extension = create_extension_node(
3413 extension_key.to_vec(),
3414 RlpNode::from_rlp(&alloy_rlp::encode(&branch_1)).as_hash().unwrap(),
3415 );
3416
3417 let branch_2_path = Nibbles::from_nibbles([0, 0]);
3419 let branch_2 = create_branch_node_with_children(
3420 &[0, 1],
3421 vec![
3422 RlpNode::from_rlp(&alloy_rlp::encode(&extension)),
3423 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_3)),
3424 ],
3425 );
3426
3427 subtrie.reveal_node(branch_2_path, &branch_2, TrieMasks::none()).unwrap();
3429 subtrie.reveal_node(leaf_1_path, &leaf_1, TrieMasks::none()).unwrap();
3430 subtrie.reveal_node(extension_path, &extension, TrieMasks::none()).unwrap();
3431 subtrie.reveal_node(branch_1_path, &branch_1, TrieMasks::none()).unwrap();
3432 subtrie.reveal_node(leaf_2_path, &leaf_2, TrieMasks::none()).unwrap();
3433 subtrie.reveal_node(leaf_3_path, &leaf_3, TrieMasks::none()).unwrap();
3434
3435 let (_, _, proof_nodes, _, _) = run_hash_builder(
3437 [
3438 (leaf_1_full_path, account_1),
3439 (leaf_2_full_path, account_2),
3440 (leaf_3_full_path, account_3),
3441 ],
3442 NoopAccountTrieCursor::default(),
3443 Default::default(),
3444 [
3445 branch_1_path,
3446 extension_path,
3447 branch_2_path,
3448 leaf_1_full_path,
3449 leaf_2_full_path,
3450 leaf_3_full_path,
3451 ],
3452 );
3453
3454 subtrie.update_hashes(
3456 &mut PrefixSetMut::from([leaf_1_full_path, leaf_2_full_path, leaf_3_full_path])
3457 .freeze(),
3458 &mut None,
3459 &HashMap::default(),
3460 &HashMap::default(),
3461 );
3462
3463 let hash_builder_branch_1_hash =
3465 RlpNode::from_rlp(proof_nodes.get(&branch_1_path).unwrap().as_ref()).as_hash().unwrap();
3466 let subtrie_branch_1_hash = subtrie.nodes.get(&branch_1_path).unwrap().hash().unwrap();
3467 assert_eq!(hash_builder_branch_1_hash, subtrie_branch_1_hash);
3468
3469 let hash_builder_extension_hash =
3470 RlpNode::from_rlp(proof_nodes.get(&extension_path).unwrap().as_ref())
3471 .as_hash()
3472 .unwrap();
3473 let subtrie_extension_hash = subtrie.nodes.get(&extension_path).unwrap().hash().unwrap();
3474 assert_eq!(hash_builder_extension_hash, subtrie_extension_hash);
3475
3476 let hash_builder_branch_2_hash =
3477 RlpNode::from_rlp(proof_nodes.get(&branch_2_path).unwrap().as_ref()).as_hash().unwrap();
3478 let subtrie_branch_2_hash = subtrie.nodes.get(&branch_2_path).unwrap().hash().unwrap();
3479 assert_eq!(hash_builder_branch_2_hash, subtrie_branch_2_hash);
3480
3481 let subtrie_leaf_1_hash = subtrie.nodes.get(&leaf_1_path).unwrap().hash().unwrap();
3482 let hash_builder_leaf_1_hash =
3483 RlpNode::from_rlp(proof_nodes.get(&leaf_1_path).unwrap().as_ref()).as_hash().unwrap();
3484 assert_eq!(hash_builder_leaf_1_hash, subtrie_leaf_1_hash);
3485
3486 let hash_builder_leaf_2_hash =
3487 RlpNode::from_rlp(proof_nodes.get(&leaf_2_path).unwrap().as_ref()).as_hash().unwrap();
3488 let subtrie_leaf_2_hash = subtrie.nodes.get(&leaf_2_path).unwrap().hash().unwrap();
3489 assert_eq!(hash_builder_leaf_2_hash, subtrie_leaf_2_hash);
3490
3491 let hash_builder_leaf_3_hash =
3492 RlpNode::from_rlp(proof_nodes.get(&leaf_3_path).unwrap().as_ref()).as_hash().unwrap();
3493 let subtrie_leaf_3_hash = subtrie.nodes.get(&leaf_3_path).unwrap().hash().unwrap();
3494 assert_eq!(hash_builder_leaf_3_hash, subtrie_leaf_3_hash);
3495 }
3496
3497 #[test]
3498 fn test_remove_leaf_branch_becomes_extension() {
3499 let mut trie = new_test_trie(
3511 [
3512 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
3513 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(TrieMask::new(0b1001))),
3514 (
3515 Nibbles::from_nibbles([0x5, 0x0]),
3516 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3])),
3517 ),
3518 (
3519 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
3520 SparseNode::new_branch(TrieMask::new(0b0101)),
3521 ),
3522 (
3523 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
3524 SparseNode::new_leaf(Nibbles::new()),
3525 ),
3526 (
3527 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
3528 SparseNode::new_leaf(Nibbles::new()),
3529 ),
3530 (
3531 Nibbles::from_nibbles([0x5, 0x3]),
3532 SparseNode::new_leaf(Nibbles::from_nibbles([0x7])),
3533 ),
3534 ]
3535 .into_iter(),
3536 );
3537
3538 let provider = MockTrieNodeProvider::new();
3539
3540 let leaf_full_path = Nibbles::from_nibbles([0x5, 0x3, 0x7]);
3542 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3543
3544 let upper_subtrie = &trie.upper_subtrie;
3545 let lower_subtrie_50 = trie.lower_subtries[0x50].as_revealed_ref().unwrap();
3546
3547 assert_matches!(trie.lower_subtries[0x53].as_revealed_ref(), None);
3550
3551 assert_matches!(
3554 upper_subtrie.nodes.get(&Nibbles::from_nibbles([])),
3555 Some(SparseNode::Extension{ key, ..})
3556 if key == &Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3])
3557 );
3558 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x5])), None);
3559 assert_matches!(lower_subtrie_50.nodes.get(&Nibbles::from_nibbles([0x5, 0x0])), None);
3560 assert_matches!(
3561 lower_subtrie_50.nodes.get(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3])),
3562 Some(SparseNode::Branch{ state_mask, .. })
3563 if *state_mask == 0b0101.into()
3564 );
3565 }
3566
3567 #[test]
3568 fn test_remove_leaf_branch_becomes_leaf() {
3569 let mut trie = new_test_trie(
3577 [
3578 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0011))),
3579 (
3580 Nibbles::from_nibbles([0x0]),
3581 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3582 ),
3583 (
3584 Nibbles::from_nibbles([0x1]),
3585 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3586 ),
3587 ]
3588 .into_iter(),
3589 );
3590
3591 if let Some(updates) = trie.updates.as_mut() {
3593 updates
3594 .updated_nodes
3595 .insert(Nibbles::default(), BranchNodeCompact::new(0b11, 0, 0, vec![], None));
3596 }
3597
3598 let provider = MockTrieNodeProvider::new();
3599
3600 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2]);
3602 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3603
3604 let upper_subtrie = &trie.upper_subtrie;
3605
3606 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
3608
3609 assert_matches!(
3611 upper_subtrie.nodes.get(&Nibbles::default()),
3612 Some(SparseNode::Leaf{ key, ..})
3613 if key == &Nibbles::from_nibbles([0x1, 0x3, 0x4])
3614 );
3615
3616 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])), None);
3618 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x0])), None);
3620
3621 let updates = trie.updates.as_ref().unwrap();
3623
3624 assert!(updates.removed_nodes.contains(&Nibbles::default()));
3626
3627 assert!(!updates.updated_nodes.contains_key(&Nibbles::default()));
3629 }
3630
3631 #[test]
3632 fn test_remove_leaf_extension_becomes_leaf() {
3633 let mut trie = new_test_trie(
3642 [
3643 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
3644 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(TrieMask::new(0b0011))),
3645 (
3646 Nibbles::from_nibbles([0x5, 0x0]),
3647 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3648 ),
3649 (
3650 Nibbles::from_nibbles([0x5, 0x1]),
3651 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3652 ),
3653 ]
3654 .into_iter(),
3655 );
3656
3657 let provider = MockTrieNodeProvider::new();
3658
3659 let leaf_full_path = Nibbles::from_nibbles([0x5, 0x0, 0x1, 0x2]);
3661 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3662
3663 let upper_subtrie = &trie.upper_subtrie;
3664
3665 assert_matches!(trie.lower_subtries[0x50].as_revealed_ref(), None);
3669 assert_matches!(trie.lower_subtries[0x51].as_revealed_ref(), None);
3670
3671 let other_leaf_full_value = Nibbles::from_nibbles([0x5, 0x1, 0x3, 0x4]);
3673 assert_matches!(upper_subtrie.inner.values.get(&other_leaf_full_value), Some(_));
3674
3675 assert_matches!(
3677 upper_subtrie.nodes.get(&Nibbles::default()),
3678 Some(SparseNode::Leaf{ key, ..})
3679 if key == &Nibbles::from_nibbles([0x5, 0x1, 0x3, 0x4])
3680 );
3681
3682 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x5])), None);
3684 }
3685
3686 #[test]
3687 fn test_remove_leaf_branch_on_branch() {
3688 let mut trie = new_test_trie(
3698 [
3699 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0101))),
3700 (
3701 Nibbles::from_nibbles([0x0]),
3702 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3703 ),
3704 (Nibbles::from_nibbles([0x2]), SparseNode::new_branch(TrieMask::new(0b0011))),
3705 (
3706 Nibbles::from_nibbles([0x2, 0x0]),
3707 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x4])),
3708 ),
3709 (
3710 Nibbles::from_nibbles([0x2, 0x1]),
3711 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x6])),
3712 ),
3713 ]
3714 .into_iter(),
3715 );
3716
3717 let provider = MockTrieNodeProvider::new();
3718
3719 let leaf_full_path = Nibbles::from_nibbles([0x2, 0x0, 0x3, 0x4]);
3721 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3722
3723 let upper_subtrie = &trie.upper_subtrie;
3724
3725 assert_matches!(trie.lower_subtries[0x20].as_revealed_ref(), None);
3729 assert_matches!(trie.lower_subtries[0x21].as_revealed_ref(), None);
3730
3731 let other_leaf_full_value = Nibbles::from_nibbles([0x2, 0x1, 0x5, 0x6]);
3733 assert_matches!(upper_subtrie.inner.values.get(&other_leaf_full_value), Some(_));
3734
3735 assert_matches!(
3737 upper_subtrie.nodes.get(&Nibbles::default()),
3738 Some(SparseNode::Branch{ state_mask, .. })
3739 if *state_mask == 0b0101.into()
3740 );
3741
3742 assert_matches!(
3744 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x2])),
3745 Some(SparseNode::Leaf{ key, ..})
3746 if key == &Nibbles::from_nibbles([0x1, 0x5, 0x6])
3747 );
3748 }
3749
3750 #[test]
3751 fn test_remove_leaf_lower_subtrie_root_path_update() {
3752 let mut trie = new_test_trie(
3766 [
3767 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x1, 0x2, 0x3]))),
3768 (
3769 Nibbles::from_nibbles([0x1, 0x2, 0x3]),
3770 SparseNode::new_branch(TrieMask::new(0b0011000)),
3771 ),
3772 (
3773 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x3]),
3774 SparseNode::new_leaf(Nibbles::default()),
3775 ),
3776 (
3777 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]),
3778 SparseNode::new_ext(Nibbles::from_nibbles([0x5])),
3779 ),
3780 (
3781 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]),
3782 SparseNode::new_branch(TrieMask::new(0b0011)),
3783 ),
3784 (
3785 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5, 0x0]),
3786 SparseNode::new_leaf(Nibbles::default()),
3787 ),
3788 (
3789 Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5, 0x1]),
3790 SparseNode::new_leaf(Nibbles::default()),
3791 ),
3792 ]
3793 .into_iter(),
3794 );
3795
3796 let provider = MockTrieNodeProvider::new();
3797
3798 let lower_subtrie_root_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3800 assert_matches!(
3801 trie.lower_subtrie_for_path_mut(&lower_subtrie_root_path),
3802 Some(subtrie)
3803 if subtrie.path == lower_subtrie_root_path
3804 );
3805
3806 let leaf_full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x3]);
3808 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3809
3810 let lower_subtrie = trie.lower_subtries[0x12].as_revealed_ref().unwrap();
3815 assert_eq!(lower_subtrie.path, Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]));
3816
3817 assert_matches!(
3819 trie.upper_subtrie.nodes.get(&Nibbles::default()),
3820 Some(SparseNode::Extension { key, .. })
3821 if key == &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5])
3822 );
3823
3824 assert_matches!(
3826 lower_subtrie.nodes.get(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5])),
3827 Some(SparseNode::Branch { state_mask, .. })
3828 if state_mask == &TrieMask::new(0b0011)
3829 );
3830 }
3831
3832 #[test]
3833 fn test_remove_leaf_remaining_child_needs_reveal() {
3834 let mut trie = new_test_trie(
3842 [
3843 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b0011))),
3844 (
3845 Nibbles::from_nibbles([0x0]),
3846 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2])),
3847 ),
3848 (Nibbles::from_nibbles([0x1]), SparseNode::Hash(B256::repeat_byte(0xab))),
3849 ]
3850 .into_iter(),
3851 );
3852
3853 let mut provider = MockTrieNodeProvider::new();
3855 let revealed_leaf = create_leaf_node([0x3, 0x4], 42);
3856 let mut encoded = Vec::new();
3857 revealed_leaf.encode(&mut encoded);
3858 provider.add_revealed_node(
3859 Nibbles::from_nibbles([0x1]),
3860 RevealedNode { node: encoded.into(), tree_mask: None, hash_mask: None },
3861 );
3862
3863 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2]);
3865 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3866
3867 let upper_subtrie = &trie.upper_subtrie;
3868
3869 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
3871
3872 assert_matches!(
3874 upper_subtrie.nodes.get(&Nibbles::default()),
3875 Some(SparseNode::Leaf{ key, ..})
3876 if key == &Nibbles::from_nibbles([0x1, 0x3, 0x4])
3877 );
3878
3879 assert_matches!(upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])), None);
3881 }
3882
3883 #[test]
3884 fn test_remove_leaf_root() {
3885 let mut trie = new_test_trie(std::iter::once((
3891 Nibbles::default(),
3892 SparseNode::new_leaf(Nibbles::from_nibbles([0x1, 0x2, 0x3])),
3893 )));
3894
3895 let provider = MockTrieNodeProvider::new();
3896
3897 let leaf_full_path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
3899 trie.remove_leaf(&leaf_full_path, provider).unwrap();
3900
3901 let upper_subtrie = &trie.upper_subtrie;
3902
3903 assert_matches!(upper_subtrie.inner.values.get(&leaf_full_path), None);
3905
3906 assert_matches!(upper_subtrie.nodes.get(&Nibbles::default()), Some(SparseNode::Empty));
3908 }
3909
3910 #[test]
3911 fn test_remove_leaf_unsets_hash_along_path() {
3912 let mut trie = new_test_trie(
3927 [
3928 (
3929 Nibbles::default(),
3930 SparseNode::Branch {
3931 state_mask: TrieMask::new(0b0011),
3932 hash: Some(B256::repeat_byte(0x10)),
3933 store_in_db_trie: None,
3934 },
3935 ),
3936 (
3937 Nibbles::from_nibbles([0x0]),
3938 SparseNode::Extension {
3939 key: Nibbles::from_nibbles([0x1]),
3940 hash: Some(B256::repeat_byte(0x20)),
3941 store_in_db_trie: None,
3942 },
3943 ),
3944 (
3945 Nibbles::from_nibbles([0x0, 0x1]),
3946 SparseNode::Branch {
3947 state_mask: TrieMask::new(0b11100),
3948 hash: Some(B256::repeat_byte(0x30)),
3949 store_in_db_trie: None,
3950 },
3951 ),
3952 (
3953 Nibbles::from_nibbles([0x0, 0x1, 0x2]),
3954 SparseNode::Leaf {
3955 key: Nibbles::from_nibbles([0x3, 0x4]),
3956 hash: Some(B256::repeat_byte(0x40)),
3957 },
3958 ),
3959 (
3960 Nibbles::from_nibbles([0x0, 0x1, 0x3]),
3961 SparseNode::Leaf {
3962 key: Nibbles::from_nibbles([0x5, 0x6]),
3963 hash: Some(B256::repeat_byte(0x50)),
3964 },
3965 ),
3966 (
3967 Nibbles::from_nibbles([0x0, 0x1, 0x4]),
3968 SparseNode::Leaf {
3969 key: Nibbles::from_nibbles([0x6, 0x7]),
3970 hash: Some(B256::repeat_byte(0x60)),
3971 },
3972 ),
3973 (
3974 Nibbles::from_nibbles([0x1]),
3975 SparseNode::Leaf {
3976 key: Nibbles::from_nibbles([0x7, 0x8]),
3977 hash: Some(B256::repeat_byte(0x70)),
3978 },
3979 ),
3980 ]
3981 .into_iter(),
3982 );
3983
3984 let provider = MockTrieNodeProvider::new();
3985
3986 trie.remove_leaf(&Nibbles::from_nibbles([0x0, 0x1, 0x2, 0x3, 0x4, 0xF]), &provider)
3988 .unwrap();
3989 for (path, node) in trie.all_nodes() {
3990 assert!(node.hash().is_some(), "path {path:?} should still have a hash");
3991 }
3992
3993 let leaf_full_path = Nibbles::from_nibbles([0x0, 0x1, 0x2, 0x3, 0x4]);
3995 trie.remove_leaf(&leaf_full_path, &provider).unwrap();
3996
3997 let upper_subtrie = &trie.upper_subtrie;
3998 let lower_subtrie_10 = trie.lower_subtries[0x01].as_revealed_ref().unwrap();
3999
4000 assert_matches!(
4002 upper_subtrie.nodes.get(&Nibbles::default()),
4003 Some(SparseNode::Branch { hash: None, .. })
4004 );
4005 assert_matches!(
4006 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x0])),
4007 Some(SparseNode::Extension { hash: None, .. })
4008 );
4009 assert_matches!(
4010 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1])),
4011 Some(SparseNode::Branch { hash: None, .. })
4012 );
4013
4014 assert_matches!(
4016 upper_subtrie.nodes.get(&Nibbles::from_nibbles([0x1])),
4017 Some(SparseNode::Leaf { hash: Some(_), .. })
4018 );
4019 assert_matches!(
4020 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1, 0x3])),
4021 Some(SparseNode::Leaf { hash: Some(_), .. })
4022 );
4023 assert_matches!(
4024 lower_subtrie_10.nodes.get(&Nibbles::from_nibbles([0x0, 0x1, 0x4])),
4025 Some(SparseNode::Leaf { hash: Some(_), .. })
4026 );
4027 }
4028
4029 #[test]
4030 fn test_parallel_sparse_trie_root() {
4031 let extension_path = Nibbles::new();
4034 let extension_key = Nibbles::from_nibbles([0x2]);
4035
4036 let branch_path = Nibbles::from_nibbles([0x2]);
4038
4039 let leaf_1_path = Nibbles::from_nibbles([0x2, 0x0]);
4041 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());
4043
4044 let leaf_2_path = Nibbles::from_nibbles([0x2, 0x1]);
4045 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());
4047
4048 let account_1 = create_account(1);
4050 let account_2 = create_account(2);
4051
4052 let leaf_1 = create_leaf_node(leaf_1_key.to_vec(), account_1.nonce);
4054 let leaf_2 = create_leaf_node(leaf_2_key.to_vec(), account_2.nonce);
4055
4056 let branch = create_branch_node_with_children(
4058 &[0, 1],
4059 vec![
4060 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_1)),
4061 RlpNode::from_rlp(&alloy_rlp::encode(&leaf_2)),
4062 ],
4063 );
4064
4065 let extension = create_extension_node(
4067 extension_key.to_vec(),
4068 RlpNode::from_rlp(&alloy_rlp::encode(&branch)).as_hash().unwrap(),
4069 );
4070
4071 let mut trie = ParallelSparseTrie::from_root(extension, TrieMasks::none(), true).unwrap();
4073 trie.reveal_nodes(vec![
4074 RevealedSparseNode { path: branch_path, node: branch, masks: TrieMasks::none() },
4075 RevealedSparseNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
4076 RevealedSparseNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
4077 ])
4078 .unwrap();
4079
4080 trie.upper_subtrie.nodes.get_mut(&extension_path).unwrap().set_hash(None);
4083 trie.upper_subtrie.nodes.get_mut(&branch_path).unwrap().set_hash(None);
4084
4085 let leaf_1_subtrie_idx = path_subtrie_index_unchecked(&leaf_1_path);
4087 let leaf_2_subtrie_idx = path_subtrie_index_unchecked(&leaf_2_path);
4088
4089 trie.lower_subtries[leaf_1_subtrie_idx]
4090 .as_revealed_mut()
4091 .unwrap()
4092 .nodes
4093 .get_mut(&leaf_1_path)
4094 .unwrap()
4095 .set_hash(None);
4096 trie.lower_subtries[leaf_2_subtrie_idx]
4097 .as_revealed_mut()
4098 .unwrap()
4099 .nodes
4100 .get_mut(&leaf_2_path)
4101 .unwrap()
4102 .set_hash(None);
4103
4104 trie.prefix_set.insert(leaf_1_full_path);
4106 trie.prefix_set.insert(leaf_2_full_path);
4107
4108 let root = trie.root();
4110
4111 let (hash_builder_root, _, _proof_nodes, _, _) = run_hash_builder(
4113 [(leaf_1_full_path, account_1), (leaf_2_full_path, account_2)],
4114 NoopAccountTrieCursor::default(),
4115 Default::default(),
4116 [extension_path, branch_path, leaf_1_full_path, leaf_2_full_path],
4117 );
4118
4119 assert_eq!(root, hash_builder_root);
4121
4122 let leaf_1_subtrie = trie.lower_subtries[leaf_1_subtrie_idx].as_revealed_ref().unwrap();
4124 let leaf_2_subtrie = trie.lower_subtries[leaf_2_subtrie_idx].as_revealed_ref().unwrap();
4125 assert!(trie.upper_subtrie.nodes.get(&extension_path).unwrap().hash().is_some());
4126 assert!(trie.upper_subtrie.nodes.get(&branch_path).unwrap().hash().is_some());
4127 assert!(leaf_1_subtrie.nodes.get(&leaf_1_path).unwrap().hash().is_some());
4128 assert!(leaf_2_subtrie.nodes.get(&leaf_2_path).unwrap().hash().is_some());
4129 }
4130
4131 #[test]
4132 fn sparse_trie_empty_update_one() {
4133 let ctx = ParallelSparseTrieTestContext;
4134
4135 let key = Nibbles::unpack(B256::with_last_byte(42));
4136 let value = || Account::default();
4137 let value_encoded = || {
4138 let mut account_rlp = Vec::new();
4139 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4140 account_rlp
4141 };
4142
4143 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4144 run_hash_builder(
4145 [(key, value())],
4146 NoopAccountTrieCursor::default(),
4147 Default::default(),
4148 [key],
4149 );
4150
4151 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4152 ctx.update_leaves(&mut sparse, [(key, value_encoded())]);
4153 ctx.assert_with_hash_builder(
4154 &mut sparse,
4155 hash_builder_root,
4156 hash_builder_updates,
4157 hash_builder_proof_nodes,
4158 );
4159 }
4160
4161 #[test]
4162 fn sparse_trie_empty_update_multiple_lower_nibbles() {
4163 let ctx = ParallelSparseTrieTestContext;
4164
4165 let paths = (0..=16).map(|b| Nibbles::unpack(B256::with_last_byte(b))).collect::<Vec<_>>();
4166 let value = || Account::default();
4167 let value_encoded = || {
4168 let mut account_rlp = Vec::new();
4169 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4170 account_rlp
4171 };
4172
4173 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4174 run_hash_builder(
4175 paths.iter().copied().zip(std::iter::repeat_with(value)),
4176 NoopAccountTrieCursor::default(),
4177 Default::default(),
4178 paths.clone(),
4179 );
4180
4181 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4182 ctx.update_leaves(
4183 &mut sparse,
4184 paths.into_iter().zip(std::iter::repeat_with(value_encoded)),
4185 );
4186
4187 ctx.assert_with_hash_builder(
4188 &mut sparse,
4189 hash_builder_root,
4190 hash_builder_updates,
4191 hash_builder_proof_nodes,
4192 );
4193 }
4194
4195 #[test]
4196 fn sparse_trie_empty_update_multiple_upper_nibbles() {
4197 let paths = (239..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
4198 let value = || Account::default();
4199 let value_encoded = || {
4200 let mut account_rlp = Vec::new();
4201 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4202 account_rlp
4203 };
4204
4205 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4206 run_hash_builder(
4207 paths.iter().copied().zip(std::iter::repeat_with(value)),
4208 NoopAccountTrieCursor::default(),
4209 Default::default(),
4210 paths.clone(),
4211 );
4212
4213 let provider = DefaultTrieNodeProvider;
4214 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4215 for path in &paths {
4216 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
4217 }
4218 let sparse_root = sparse.root();
4219 let sparse_updates = sparse.take_updates();
4220
4221 assert_eq!(sparse_root, hash_builder_root);
4222 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
4223 assert_eq_parallel_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
4224 }
4225
4226 #[test]
4227 fn sparse_trie_empty_update_multiple() {
4228 let ctx = ParallelSparseTrieTestContext;
4229
4230 let paths = (0..=255)
4231 .map(|b| {
4232 Nibbles::unpack(if b % 2 == 0 {
4233 B256::repeat_byte(b)
4234 } else {
4235 B256::with_last_byte(b)
4236 })
4237 })
4238 .collect::<Vec<_>>();
4239 let value = || Account::default();
4240 let value_encoded = || {
4241 let mut account_rlp = Vec::new();
4242 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4243 account_rlp
4244 };
4245
4246 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4247 run_hash_builder(
4248 paths.iter().sorted_unstable().copied().zip(std::iter::repeat_with(value)),
4249 NoopAccountTrieCursor::default(),
4250 Default::default(),
4251 paths.clone(),
4252 );
4253
4254 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4255 ctx.update_leaves(
4256 &mut sparse,
4257 paths.iter().copied().zip(std::iter::repeat_with(value_encoded)),
4258 );
4259 ctx.assert_with_hash_builder(
4260 &mut sparse,
4261 hash_builder_root,
4262 hash_builder_updates,
4263 hash_builder_proof_nodes,
4264 );
4265 }
4266
4267 #[test]
4268 fn sparse_trie_empty_update_repeated() {
4269 let ctx = ParallelSparseTrieTestContext;
4270
4271 let paths = (0..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
4272 let old_value = Account { nonce: 1, ..Default::default() };
4273 let old_value_encoded = {
4274 let mut account_rlp = Vec::new();
4275 old_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4276 account_rlp
4277 };
4278 let new_value = Account { nonce: 2, ..Default::default() };
4279 let new_value_encoded = {
4280 let mut account_rlp = Vec::new();
4281 new_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4282 account_rlp
4283 };
4284
4285 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4286 run_hash_builder(
4287 paths.iter().copied().zip(std::iter::repeat_with(|| old_value)),
4288 NoopAccountTrieCursor::default(),
4289 Default::default(),
4290 paths.clone(),
4291 );
4292
4293 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4294 ctx.update_leaves(
4295 &mut sparse,
4296 paths.iter().copied().zip(std::iter::repeat(old_value_encoded)),
4297 );
4298 ctx.assert_with_hash_builder(
4299 &mut sparse,
4300 hash_builder_root,
4301 hash_builder_updates,
4302 hash_builder_proof_nodes,
4303 );
4304
4305 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4306 run_hash_builder(
4307 paths.iter().copied().zip(std::iter::repeat(new_value)),
4308 NoopAccountTrieCursor::default(),
4309 Default::default(),
4310 paths.clone(),
4311 );
4312
4313 ctx.update_leaves(
4314 &mut sparse,
4315 paths.iter().copied().zip(std::iter::repeat(new_value_encoded)),
4316 );
4317 ctx.assert_with_hash_builder(
4318 &mut sparse,
4319 hash_builder_root,
4320 hash_builder_updates,
4321 hash_builder_proof_nodes,
4322 );
4323 }
4324
4325 #[test]
4326 fn sparse_trie_remove_leaf() {
4327 let ctx = ParallelSparseTrieTestContext;
4328 let provider = DefaultTrieNodeProvider;
4329 let mut sparse = ParallelSparseTrie::default();
4330
4331 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
4332
4333 ctx.update_leaves(
4334 &mut sparse,
4335 [
4336 (Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone()),
4337 (Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone()),
4338 (Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone()),
4339 (Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone()),
4340 (Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone()),
4341 (Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value),
4342 ],
4343 );
4344
4345 pretty_assertions::assert_eq!(
4358 parallel_sparse_trie_nodes(&sparse)
4359 .into_iter()
4360 .map(|(k, v)| (*k, v.clone()))
4361 .collect::<BTreeMap<_, _>>(),
4362 BTreeMap::from_iter([
4363 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4364 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1101.into())),
4365 (
4366 Nibbles::from_nibbles([0x5, 0x0]),
4367 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
4368 ),
4369 (
4370 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
4371 SparseNode::new_branch(0b1010.into())
4372 ),
4373 (
4374 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
4375 SparseNode::new_leaf(Nibbles::default())
4376 ),
4377 (
4378 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
4379 SparseNode::new_leaf(Nibbles::default())
4380 ),
4381 (
4382 Nibbles::from_nibbles([0x5, 0x2]),
4383 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x1, 0x3]))
4384 ),
4385 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4386 (
4387 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4388 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4389 ),
4390 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4391 (
4392 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4393 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4394 ),
4395 (
4396 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4397 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4398 )
4399 ])
4400 );
4401
4402 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), &provider).unwrap();
4403
4404 pretty_assertions::assert_eq!(
4416 parallel_sparse_trie_nodes(&sparse)
4417 .into_iter()
4418 .map(|(k, v)| (*k, v.clone()))
4419 .collect::<BTreeMap<_, _>>(),
4420 BTreeMap::from_iter([
4421 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4422 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4423 (
4424 Nibbles::from_nibbles([0x5, 0x0]),
4425 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
4426 ),
4427 (
4428 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
4429 SparseNode::new_branch(0b1010.into())
4430 ),
4431 (
4432 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
4433 SparseNode::new_leaf(Nibbles::default())
4434 ),
4435 (
4436 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
4437 SparseNode::new_leaf(Nibbles::default())
4438 ),
4439 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4440 (
4441 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4442 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4443 ),
4444 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4445 (
4446 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4447 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4448 ),
4449 (
4450 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4451 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4452 )
4453 ])
4454 );
4455
4456 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), &provider).unwrap();
4457
4458 pretty_assertions::assert_eq!(
4467 parallel_sparse_trie_nodes(&sparse)
4468 .into_iter()
4469 .map(|(k, v)| (*k, v.clone()))
4470 .collect::<BTreeMap<_, _>>(),
4471 BTreeMap::from_iter([
4472 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4473 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4474 (
4475 Nibbles::from_nibbles([0x5, 0x0]),
4476 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4477 ),
4478 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
4479 (
4480 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
4481 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
4482 ),
4483 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4484 (
4485 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4486 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4487 ),
4488 (
4489 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4490 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4491 )
4492 ])
4493 );
4494
4495 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), &provider).unwrap();
4496
4497 pretty_assertions::assert_eq!(
4504 parallel_sparse_trie_nodes(&sparse)
4505 .into_iter()
4506 .map(|(k, v)| (*k, v.clone()))
4507 .collect::<BTreeMap<_, _>>(),
4508 BTreeMap::from_iter([
4509 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4510 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4511 (
4512 Nibbles::from_nibbles([0x5, 0x0]),
4513 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4514 ),
4515 (
4516 Nibbles::from_nibbles([0x5, 0x3]),
4517 SparseNode::new_ext(Nibbles::from_nibbles([0x3]))
4518 ),
4519 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
4520 (
4521 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
4522 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
4523 ),
4524 (
4525 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
4526 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
4527 )
4528 ])
4529 );
4530
4531 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), &provider).unwrap();
4532
4533 pretty_assertions::assert_eq!(
4538 parallel_sparse_trie_nodes(&sparse)
4539 .into_iter()
4540 .map(|(k, v)| (*k, v.clone()))
4541 .collect::<BTreeMap<_, _>>(),
4542 BTreeMap::from_iter([
4543 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
4544 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
4545 (
4546 Nibbles::from_nibbles([0x5, 0x0]),
4547 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
4548 ),
4549 (
4550 Nibbles::from_nibbles([0x5, 0x3]),
4551 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x0, 0x2]))
4552 ),
4553 ])
4554 );
4555
4556 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), &provider).unwrap();
4557
4558 pretty_assertions::assert_eq!(
4560 parallel_sparse_trie_nodes(&sparse)
4561 .into_iter()
4562 .map(|(k, v)| (*k, v.clone()))
4563 .collect::<BTreeMap<_, _>>(),
4564 BTreeMap::from_iter([(
4565 Nibbles::default(),
4566 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]))
4567 ),])
4568 );
4569
4570 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), &provider).unwrap();
4571
4572 pretty_assertions::assert_eq!(
4574 parallel_sparse_trie_nodes(&sparse)
4575 .into_iter()
4576 .map(|(k, v)| (*k, v.clone()))
4577 .collect::<BTreeMap<_, _>>(),
4578 BTreeMap::from_iter([(Nibbles::default(), SparseNode::Empty)])
4579 );
4580 }
4581
4582 #[test]
4583 fn sparse_trie_remove_leaf_blinded() {
4584 let leaf = LeafNode::new(
4585 Nibbles::default(),
4586 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
4587 );
4588 let branch = TrieNode::Branch(BranchNode::new(
4589 vec![
4590 RlpNode::word_rlp(&B256::repeat_byte(1)),
4591 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
4592 ],
4593 TrieMask::new(0b11),
4594 ));
4595
4596 let provider = DefaultTrieNodeProvider;
4597 let mut sparse = ParallelSparseTrie::from_root(
4598 branch.clone(),
4599 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
4600 false,
4601 )
4602 .unwrap();
4603
4604 sparse
4610 .reveal_nodes(vec![
4611 RevealedSparseNode {
4612 path: Nibbles::default(),
4613 node: branch,
4614 masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
4615 },
4616 RevealedSparseNode {
4617 path: Nibbles::from_nibbles([0x1]),
4618 node: TrieNode::Leaf(leaf),
4619 masks: TrieMasks::none(),
4620 },
4621 ])
4622 .unwrap();
4623
4624 assert_matches!(
4626 sparse.remove_leaf(&Nibbles::from_nibbles([0x0]), &provider).map_err(|e| e.into_kind()),
4627 Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
4628 );
4629 }
4630
4631 #[test]
4632 fn sparse_trie_remove_leaf_non_existent() {
4633 let leaf = LeafNode::new(
4634 Nibbles::default(),
4635 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
4636 );
4637 let branch = TrieNode::Branch(BranchNode::new(
4638 vec![
4639 RlpNode::word_rlp(&B256::repeat_byte(1)),
4640 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
4641 ],
4642 TrieMask::new(0b11),
4643 ));
4644
4645 let provider = DefaultTrieNodeProvider;
4646 let mut sparse = ParallelSparseTrie::from_root(
4647 branch.clone(),
4648 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
4649 false,
4650 )
4651 .unwrap();
4652
4653 sparse
4659 .reveal_nodes(vec![
4660 RevealedSparseNode {
4661 path: Nibbles::default(),
4662 node: branch,
4663 masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
4664 },
4665 RevealedSparseNode {
4666 path: Nibbles::from_nibbles([0x1]),
4667 node: TrieNode::Leaf(leaf),
4668 masks: TrieMasks::none(),
4669 },
4670 ])
4671 .unwrap();
4672
4673 let sparse_old = sparse.clone();
4675 assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2]), &provider), Ok(()));
4676 assert_eq!(sparse, sparse_old);
4677 }
4678
4679 #[test]
4680 fn sparse_trie_fuzz() {
4681 const KEY_NIBBLES_LEN: usize = 3;
4685
4686 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
4687 {
4688 let mut state = BTreeMap::default();
4689 let default_provider = DefaultTrieNodeProvider;
4690 let provider_factory = create_test_provider_factory();
4691 let mut sparse = ParallelSparseTrie::default().with_updates(true);
4692
4693 for (update, keys_to_delete) in updates {
4694 for (key, account) in update.clone() {
4696 let account = account.into_trie_account(EMPTY_ROOT_HASH);
4697 let mut account_rlp = Vec::new();
4698 account.encode(&mut account_rlp);
4699 sparse.update_leaf(key, account_rlp, &default_provider).unwrap();
4700 }
4701 let mut updated_sparse = sparse.clone();
4705 let sparse_root = updated_sparse.root();
4706 let sparse_updates = updated_sparse.take_updates();
4707
4708 state.extend(update);
4710 let provider = provider_factory.provider().unwrap();
4711 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
4712 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4713 run_hash_builder(
4714 state.clone(),
4715 trie_cursor.account_trie_cursor().unwrap(),
4716 Default::default(),
4717 state.keys().copied().collect::<Vec<_>>(),
4718 );
4719
4720 let provider_rw = provider_factory.provider_rw().unwrap();
4722 provider_rw.write_trie_updates(&hash_builder_updates).unwrap();
4723 provider_rw.commit().unwrap();
4724
4725 assert_eq!(sparse_root, hash_builder_root);
4727 pretty_assertions::assert_eq!(
4729 BTreeMap::from_iter(sparse_updates.updated_nodes),
4730 BTreeMap::from_iter(hash_builder_updates.account_nodes)
4731 );
4732 assert_eq_parallel_sparse_trie_proof_nodes(
4734 &updated_sparse,
4735 hash_builder_proof_nodes,
4736 );
4737
4738 for key in &keys_to_delete {
4741 state.remove(key).unwrap();
4742 sparse.remove_leaf(key, &default_provider).unwrap();
4743 }
4744
4745 let mut updated_sparse = sparse.clone();
4749 let sparse_root = updated_sparse.root();
4750 let sparse_updates = updated_sparse.take_updates();
4751
4752 let provider = provider_factory.provider().unwrap();
4753 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
4754 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
4755 run_hash_builder(
4756 state.clone(),
4757 trie_cursor.account_trie_cursor().unwrap(),
4758 keys_to_delete
4759 .iter()
4760 .map(|nibbles| B256::from_slice(&nibbles.pack()))
4761 .collect(),
4762 state.keys().copied().collect::<Vec<_>>(),
4763 );
4764
4765 let provider_rw = provider_factory.provider_rw().unwrap();
4767 provider_rw.write_trie_updates(&hash_builder_updates).unwrap();
4768 provider_rw.commit().unwrap();
4769
4770 assert_eq!(sparse_root, hash_builder_root);
4772 pretty_assertions::assert_eq!(
4774 BTreeMap::from_iter(sparse_updates.updated_nodes),
4775 BTreeMap::from_iter(hash_builder_updates.account_nodes)
4776 );
4777 assert_eq_parallel_sparse_trie_proof_nodes(
4779 &updated_sparse,
4780 hash_builder_proof_nodes,
4781 );
4782 }
4783 }
4784 }
4785
4786 fn transform_updates(
4787 updates: Vec<BTreeMap<Nibbles, Account>>,
4788 mut rng: impl rand::Rng,
4789 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
4790 let mut keys = BTreeSet::new();
4791 updates
4792 .into_iter()
4793 .map(|update| {
4794 keys.extend(update.keys().copied());
4795
4796 let keys_to_delete_len = update.len() / 2;
4797 let keys_to_delete = (0..keys_to_delete_len)
4798 .map(|_| {
4799 let key =
4800 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
4801 keys.take(&key).unwrap()
4802 })
4803 .collect();
4804
4805 (update, keys_to_delete)
4806 })
4807 .collect::<Vec<_>>()
4808 }
4809
4810 proptest!(ProptestConfig::with_cases(10), |(
4811 updates in proptest::collection::vec(
4812 proptest::collection::btree_map(
4813 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
4814 arb::<Account>(),
4815 1..50,
4816 ),
4817 1..50,
4818 ).prop_perturb(transform_updates)
4819 )| {
4820 test(updates)
4821 });
4822 }
4823
4824 #[test]
4825 fn sparse_trie_fuzz_vs_serial() {
4826 const KEY_NIBBLES_LEN: usize = 3;
4830
4831 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
4832 let default_provider = DefaultTrieNodeProvider;
4833 let mut serial = SerialSparseTrie::default().with_updates(true);
4834 let mut parallel = ParallelSparseTrie::default().with_updates(true);
4835
4836 for (update, keys_to_delete) in updates {
4837 for (key, account) in update.clone() {
4839 let account = account.into_trie_account(EMPTY_ROOT_HASH);
4840 let mut account_rlp = Vec::new();
4841 account.encode(&mut account_rlp);
4842 serial.update_leaf(key, account_rlp.clone(), &default_provider).unwrap();
4843 parallel.update_leaf(key, account_rlp, &default_provider).unwrap();
4844 }
4845
4846 let serial_root = serial.root();
4848 let parallel_root = parallel.root();
4849 assert_eq!(parallel_root, serial_root);
4850
4851 let serial_updates = serial.take_updates();
4853 let parallel_updates = parallel.take_updates();
4854 pretty_assertions::assert_eq!(
4855 BTreeMap::from_iter(parallel_updates.updated_nodes),
4856 BTreeMap::from_iter(serial_updates.updated_nodes),
4857 );
4858 pretty_assertions::assert_eq!(
4859 BTreeSet::from_iter(parallel_updates.removed_nodes),
4860 BTreeSet::from_iter(serial_updates.removed_nodes),
4861 );
4862
4863 for key in &keys_to_delete {
4865 parallel.remove_leaf(key, &default_provider).unwrap();
4866 serial.remove_leaf(key, &default_provider).unwrap();
4867 }
4868
4869 let serial_root = serial.root();
4871 let parallel_root = parallel.root();
4872 assert_eq!(parallel_root, serial_root);
4873
4874 let serial_updates = serial.take_updates();
4876 let parallel_updates = parallel.take_updates();
4877 pretty_assertions::assert_eq!(
4878 BTreeMap::from_iter(parallel_updates.updated_nodes),
4879 BTreeMap::from_iter(serial_updates.updated_nodes),
4880 );
4881 pretty_assertions::assert_eq!(
4882 BTreeSet::from_iter(parallel_updates.removed_nodes),
4883 BTreeSet::from_iter(serial_updates.removed_nodes),
4884 );
4885 }
4886 }
4887
4888 fn transform_updates(
4889 updates: Vec<BTreeMap<Nibbles, Account>>,
4890 mut rng: impl rand::Rng,
4891 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
4892 let mut keys = BTreeSet::new();
4893 updates
4894 .into_iter()
4895 .map(|update| {
4896 keys.extend(update.keys().copied());
4897
4898 let keys_to_delete_len = update.len() / 2;
4899 let keys_to_delete = (0..keys_to_delete_len)
4900 .map(|_| {
4901 let key =
4902 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
4903 keys.take(&key).unwrap()
4904 })
4905 .collect();
4906
4907 (update, keys_to_delete)
4908 })
4909 .collect::<Vec<_>>()
4910 }
4911
4912 proptest!(ProptestConfig::with_cases(10), |(
4913 updates in proptest::collection::vec(
4914 proptest::collection::btree_map(
4915 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
4916 arb::<Account>(),
4917 1..50,
4918 ),
4919 1..50,
4920 ).prop_perturb(transform_updates)
4921 )| {
4922 test(updates)
4923 });
4924 }
4925
4926 #[test]
4927 fn sparse_trie_two_leaves_at_lower_roots() {
4928 let provider = DefaultTrieNodeProvider;
4929 let mut trie = ParallelSparseTrie::default().with_updates(true);
4930 let key_50 = Nibbles::unpack(hex!(
4931 "0x5000000000000000000000000000000000000000000000000000000000000000"
4932 ));
4933 let key_51 = Nibbles::unpack(hex!(
4934 "0x5100000000000000000000000000000000000000000000000000000000000000"
4935 ));
4936
4937 let account = Account::default().into_trie_account(EMPTY_ROOT_HASH);
4938 let mut account_rlp = Vec::new();
4939 account.encode(&mut account_rlp);
4940
4941 trie.update_leaf(key_50, account_rlp.clone(), &provider).unwrap();
4943 trie.root();
4944
4945 trie.update_leaf(key_51, account_rlp.clone(), &provider).unwrap();
4947
4948 let expected_root =
4949 hex!("0xdaf0ef9f91a2f179bb74501209effdb5301db1697bcab041eca2234b126e25de");
4950 let root = trie.root();
4951 assert_eq!(root, expected_root);
4952 assert_eq!(SparseTrieUpdates::default(), trie.take_updates());
4953 }
4954
4955 #[test]
4967 fn sparse_trie_reveal_node_1() {
4968 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00]));
4969 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01]));
4970 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x02]));
4971 let value = || Account::default();
4972 let value_encoded = || {
4973 let mut account_rlp = Vec::new();
4974 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
4975 account_rlp
4976 };
4977
4978 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
4980 run_hash_builder(
4981 [(key1(), value()), (key3(), value())],
4982 NoopAccountTrieCursor::default(),
4983 Default::default(),
4984 [Nibbles::default()],
4985 );
4986
4987 let provider = DefaultTrieNodeProvider;
4988 let mut sparse = ParallelSparseTrie::from_root(
4989 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
4990 TrieMasks {
4991 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
4992 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
4993 },
4994 false,
4995 )
4996 .unwrap();
4997
4998 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5000 run_hash_builder(
5001 [(key1(), value()), (key3(), value())],
5002 NoopAccountTrieCursor::default(),
5003 Default::default(),
5004 [key1()],
5005 );
5006 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5007 .nodes_sorted()
5008 .into_iter()
5009 .map(|(path, node)| {
5010 let hash_mask = branch_node_hash_masks.get(&path).copied();
5011 let tree_mask = branch_node_tree_masks.get(&path).copied();
5012 RevealedSparseNode {
5013 path,
5014 node: TrieNode::decode(&mut &node[..]).unwrap(),
5015 masks: TrieMasks { hash_mask, tree_mask },
5016 }
5017 })
5018 .collect();
5019 sparse.reveal_nodes(revealed_nodes).unwrap();
5020
5021 assert_eq!(
5023 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5024 Some(&SparseNode::new_branch(0b101.into()))
5025 );
5026
5027 sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
5029
5030 assert_eq!(
5032 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5033 Some(&SparseNode::new_branch(0b111.into()))
5034 );
5035
5036 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5038 run_hash_builder(
5039 [(key1(), value()), (key3(), value())],
5040 NoopAccountTrieCursor::default(),
5041 Default::default(),
5042 [key3()],
5043 );
5044 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5045 .nodes_sorted()
5046 .into_iter()
5047 .map(|(path, node)| {
5048 let hash_mask = branch_node_hash_masks.get(&path).copied();
5049 let tree_mask = branch_node_tree_masks.get(&path).copied();
5050 RevealedSparseNode {
5051 path,
5052 node: TrieNode::decode(&mut &node[..]).unwrap(),
5053 masks: TrieMasks { hash_mask, tree_mask },
5054 }
5055 })
5056 .collect();
5057 sparse.reveal_nodes(revealed_nodes).unwrap();
5058
5059 assert_eq!(
5061 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5062 Some(&SparseNode::new_branch(0b111.into()))
5063 );
5064
5065 let (_, _, hash_builder_proof_nodes, _, _) = run_hash_builder(
5068 [(key1(), value()), (key2(), value()), (key3(), value())],
5069 NoopAccountTrieCursor::default(),
5070 Default::default(),
5071 [key1(), key2(), key3()],
5072 );
5073
5074 assert_eq_parallel_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
5075 }
5076
5077 #[test]
5088 fn sparse_trie_reveal_node_2() {
5089 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x00]));
5090 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x01]));
5091 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x02]));
5092 let value = || Account::default();
5093
5094 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5096 run_hash_builder(
5097 [(key1(), value()), (key2(), value()), (key3(), value())],
5098 NoopAccountTrieCursor::default(),
5099 Default::default(),
5100 [Nibbles::default()],
5101 );
5102
5103 let provider = DefaultTrieNodeProvider;
5104 let mut sparse = ParallelSparseTrie::from_root(
5105 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5106 TrieMasks {
5107 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5108 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5109 },
5110 false,
5111 )
5112 .unwrap();
5113
5114 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5117 run_hash_builder(
5118 [(key1(), value()), (key2(), value()), (key3(), value())],
5119 NoopAccountTrieCursor::default(),
5120 Default::default(),
5121 [key1(), Nibbles::from_nibbles_unchecked([0x01])],
5122 );
5123 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5124 .nodes_sorted()
5125 .into_iter()
5126 .map(|(path, node)| {
5127 let hash_mask = branch_node_hash_masks.get(&path).copied();
5128 let tree_mask = branch_node_tree_masks.get(&path).copied();
5129 RevealedSparseNode {
5130 path,
5131 node: TrieNode::decode(&mut &node[..]).unwrap(),
5132 masks: TrieMasks { hash_mask, tree_mask },
5133 }
5134 })
5135 .collect();
5136 sparse.reveal_nodes(revealed_nodes).unwrap();
5137
5138 assert_eq!(
5140 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5141 Some(&SparseNode::new_branch(0b11.into()))
5142 );
5143
5144 sparse.remove_leaf(&key1(), &provider).unwrap();
5146
5147 assert_eq!(
5149 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5150 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
5151 );
5152
5153 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5155 run_hash_builder(
5156 [(key1(), value()), (key2(), value()), (key3(), value())],
5157 NoopAccountTrieCursor::default(),
5158 Default::default(),
5159 [key2()],
5160 );
5161 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5162 .nodes_sorted()
5163 .into_iter()
5164 .map(|(path, node)| {
5165 let hash_mask = branch_node_hash_masks.get(&path).copied();
5166 let tree_mask = branch_node_tree_masks.get(&path).copied();
5167 RevealedSparseNode {
5168 path,
5169 node: TrieNode::decode(&mut &node[..]).unwrap(),
5170 masks: TrieMasks { hash_mask, tree_mask },
5171 }
5172 })
5173 .collect();
5174 sparse.reveal_nodes(revealed_nodes).unwrap();
5175
5176 assert_eq!(
5178 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5179 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
5180 );
5181 }
5182
5183 #[test]
5192 fn sparse_trie_reveal_node_3() {
5193 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x01]));
5194 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x02]));
5195 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x00]));
5196 let value = || Account::default();
5197 let value_encoded = || {
5198 let mut account_rlp = Vec::new();
5199 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
5200 account_rlp
5201 };
5202
5203 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5205 run_hash_builder(
5206 [(key1(), value()), (key2(), value())],
5207 NoopAccountTrieCursor::default(),
5208 Default::default(),
5209 [Nibbles::default()],
5210 );
5211
5212 let provider = DefaultTrieNodeProvider;
5213 let mut sparse = ParallelSparseTrie::from_root(
5214 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
5215 TrieMasks {
5216 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
5217 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
5218 },
5219 false,
5220 )
5221 .unwrap();
5222
5223 assert_matches!(
5225 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5226 Some(SparseNode::Extension { key, hash: None, store_in_db_trie: None }) if *key == Nibbles::from_nibbles([0x00])
5227 );
5228
5229 sparse.update_leaf(key3(), value_encoded(), &provider).unwrap();
5231
5232 assert_matches!(
5234 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5235 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
5236 );
5237
5238 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
5240 run_hash_builder(
5241 [(key1(), value()), (key2(), value())],
5242 NoopAccountTrieCursor::default(),
5243 Default::default(),
5244 [key1()],
5245 );
5246 let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5247 .nodes_sorted()
5248 .into_iter()
5249 .map(|(path, node)| {
5250 let hash_mask = branch_node_hash_masks.get(&path).copied();
5251 let tree_mask = branch_node_tree_masks.get(&path).copied();
5252 RevealedSparseNode {
5253 path,
5254 node: TrieNode::decode(&mut &node[..]).unwrap(),
5255 masks: TrieMasks { hash_mask, tree_mask },
5256 }
5257 })
5258 .collect();
5259 sparse.reveal_nodes(revealed_nodes).unwrap();
5260
5261 assert_matches!(
5263 sparse.upper_subtrie.nodes.get(&Nibbles::default()),
5264 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
5265 );
5266 }
5267
5268 #[test]
5269 fn test_update_leaf_cross_level() {
5270 let ctx = ParallelSparseTrieTestContext;
5271 let mut trie =
5272 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5273
5274 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x3, 0x4, 0x5], 1);
5296 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
5297
5298 ctx.assert_upper_subtrie(&trie)
5300 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x3, 0x4, 0x5]))
5301 .has_value(&leaf1_path, &value1);
5302
5303 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 2);
5305 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
5306
5307 ctx.assert_upper_subtrie(&trie)
5309 .has_branch(&Nibbles::from_nibbles([0x1]), &[0x2, 0x3])
5310 .has_no_value(&leaf1_path)
5311 .has_no_value(&leaf2_path);
5312
5313 let (leaf3_path, value3) = ctx.create_test_leaf([0x1, 0x2, 0x4, 0x5], 3);
5315 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
5316
5317 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5319 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5320 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5321 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::from_nibbles([0x5]))
5322 .has_value(&leaf2_path, &value2)
5323 .has_value(&leaf3_path, &value3);
5324
5325 let (leaf4_path, value4) = ctx.create_test_leaf([0x1, 0x3, 0x3, 0x4], 4);
5327 trie.update_leaf(leaf4_path, value4.clone(), DefaultTrieNodeProvider).unwrap();
5328
5329 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x3]))
5331 .has_value(&leaf1_path, &value1)
5332 .has_value(&leaf4_path, &value4);
5333
5334 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5336 .has_value(&leaf2_path, &value2)
5337 .has_value(&leaf3_path, &value3);
5338
5339 ctx.assert_upper_subtrie(&trie)
5341 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1]))
5342 .has_branch(&Nibbles::from_nibbles([0x1]), &[0x2, 0x3])
5343 .has_no_value(&leaf1_path)
5344 .has_no_value(&leaf2_path)
5345 .has_no_value(&leaf3_path)
5346 .has_no_value(&leaf4_path);
5347 }
5348
5349 #[test]
5350 fn test_update_leaf_split_at_level_boundary() {
5351 let ctx = ParallelSparseTrieTestContext;
5352 let mut trie =
5353 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5354
5355 let (first_leaf_path, first_value) = ctx.create_test_leaf([0x1, 0x2, 0x2, 0x4], 1);
5370
5371 trie.update_leaf(first_leaf_path, first_value.clone(), DefaultTrieNodeProvider).unwrap();
5372
5373 ctx.assert_upper_subtrie(&trie)
5375 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x2, 0x4]))
5376 .has_value(&first_leaf_path, &first_value);
5377
5378 let (second_leaf_path, second_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 2);
5380
5381 trie.update_leaf(second_leaf_path, second_value.clone(), DefaultTrieNodeProvider).unwrap();
5382
5383 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5385 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x2, 0x3])
5386 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x2]), &Nibbles::from_nibbles([0x4]))
5387 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5388 .has_value(&first_leaf_path, &first_value)
5389 .has_value(&second_leaf_path, &second_value);
5390
5391 ctx.assert_upper_subtrie(&trie)
5393 .has_no_value(&first_leaf_path)
5394 .has_no_value(&second_leaf_path);
5395 }
5396
5397 #[test]
5398 fn test_update_subtrie_with_multiple_leaves() {
5399 let ctx = ParallelSparseTrieTestContext;
5400 let mut trie =
5401 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5402
5403 let leaves = ctx.create_test_leaves(&[
5417 &[0x1, 0x2, 0x3, 0x4],
5418 &[0x1, 0x2, 0x3, 0x5],
5419 &[0x1, 0x2, 0x4, 0x6],
5420 &[0x1, 0x2, 0x4, 0x7],
5421 ]);
5422
5423 ctx.update_leaves(&mut trie, leaves.clone());
5425
5426 ctx.assert_upper_subtrie(&trie)
5428 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
5429
5430 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5432 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5433 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
5434 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &[0x6, 0x7])
5435 .has_value(&leaves[0].0, &leaves[0].1)
5436 .has_value(&leaves[1].0, &leaves[1].1)
5437 .has_value(&leaves[2].0, &leaves[2].1)
5438 .has_value(&leaves[3].0, &leaves[3].1);
5439
5440 let updated_path = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]);
5442 let (_, updated_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 100);
5443
5444 trie.update_leaf(updated_path, updated_value.clone(), DefaultTrieNodeProvider).unwrap();
5445
5446 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5449 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5450 .has_value(&updated_path, &updated_value)
5451 .has_value(&leaves[1].0, &leaves[1].1)
5452 .has_value(&leaves[2].0, &leaves[2].1)
5453 .has_value(&leaves[3].0, &leaves[3].1);
5454
5455 let (new_leaf_path, new_leaf_value) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x6], 200);
5457
5458 trie.update_leaf(new_leaf_path, new_leaf_value.clone(), DefaultTrieNodeProvider).unwrap();
5459
5460 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5462 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5, 0x6])
5463 .has_value(&new_leaf_path, &new_leaf_value);
5464 }
5465
5466 #[test]
5467 fn test_update_subtrie_extension_node_subtrie() {
5468 let ctx = ParallelSparseTrieTestContext;
5469 let mut trie =
5470 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5471
5472 let leaves = ctx.create_test_leaves(&[&[0x1, 0x2, 0x3, 0x4], &[0x1, 0x2, 0x3, 0x5]]);
5481
5482 ctx.update_leaves(&mut trie, leaves.clone());
5484
5485 ctx.assert_upper_subtrie(&trie)
5487 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
5488
5489 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5491 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
5492 .has_value(&leaves[0].0, &leaves[0].1)
5493 .has_value(&leaves[1].0, &leaves[1].1);
5494 }
5495
5496 #[test]
5497 fn update_subtrie_extension_node_cross_level() {
5498 let ctx = ParallelSparseTrieTestContext;
5499 let mut trie =
5500 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5501
5502 let leaves = ctx.create_test_leaves(&[&[0x1, 0x2, 0x3, 0x4], &[0x1, 0x2, 0x4, 0x5]]);
5512
5513 ctx.update_leaves(&mut trie, leaves.clone());
5515
5516 ctx.assert_upper_subtrie(&trie)
5518 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
5519
5520 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5522 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
5523 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &Nibbles::from_nibbles([0x4]))
5524 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::from_nibbles([0x5]))
5525 .has_value(&leaves[0].0, &leaves[0].1)
5526 .has_value(&leaves[1].0, &leaves[1].1);
5527 }
5528
5529 #[test]
5530 fn test_update_single_nibble_paths() {
5531 let ctx = ParallelSparseTrieTestContext;
5532 let mut trie =
5533 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5534
5535 let (leaf1_path, value1) = ctx.create_test_leaf([0x0], 1);
5547 let (leaf2_path, value2) = ctx.create_test_leaf([0x1], 2);
5548 let (leaf3_path, value3) = ctx.create_test_leaf([0x2], 3);
5549 let (leaf4_path, value4) = ctx.create_test_leaf([0x3], 4);
5550
5551 ctx.update_leaves(
5552 &mut trie,
5553 [
5554 (leaf1_path, value1.clone()),
5555 (leaf2_path, value2.clone()),
5556 (leaf3_path, value3.clone()),
5557 (leaf4_path, value4.clone()),
5558 ],
5559 );
5560
5561 ctx.assert_upper_subtrie(&trie)
5563 .has_branch(&Nibbles::default(), &[0x0, 0x1, 0x2, 0x3])
5564 .has_leaf(&Nibbles::from_nibbles([0x0]), &Nibbles::default())
5565 .has_leaf(&Nibbles::from_nibbles([0x1]), &Nibbles::default())
5566 .has_leaf(&Nibbles::from_nibbles([0x2]), &Nibbles::default())
5567 .has_leaf(&Nibbles::from_nibbles([0x3]), &Nibbles::default())
5568 .has_value(&leaf1_path, &value1)
5569 .has_value(&leaf2_path, &value2)
5570 .has_value(&leaf3_path, &value3)
5571 .has_value(&leaf4_path, &value4);
5572 }
5573
5574 #[test]
5575 fn test_update_deep_extension_chain() {
5576 let ctx = ParallelSparseTrieTestContext;
5577 let mut trie =
5578 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5579
5580 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0], 1);
5594 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1], 2);
5595
5596 ctx.update_leaves(&mut trie, [(leaf1_path, value1.clone()), (leaf2_path, value2.clone())]);
5597
5598 ctx.assert_upper_subtrie(&trie).has_extension(
5600 &Nibbles::default(),
5601 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1]),
5602 );
5603
5604 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x1]))
5606 .has_branch(&Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1]), &[0x0, 0x1])
5607 .has_leaf(
5608 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0]),
5609 &Nibbles::default(),
5610 )
5611 .has_leaf(
5612 &Nibbles::from_nibbles([0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1]),
5613 &Nibbles::default(),
5614 )
5615 .has_value(&leaf1_path, &value1)
5616 .has_value(&leaf2_path, &value2);
5617 }
5618
5619 #[test]
5620 fn test_update_branch_with_all_nibbles() {
5621 let ctx = ParallelSparseTrieTestContext;
5622 let mut trie =
5623 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5624
5625 let mut leaves = Vec::new();
5642 for nibble in 0x0..=0xF {
5643 let (path, value) = ctx.create_test_leaf([0xA, 0x0, nibble], nibble as u64 + 1);
5644 leaves.push((path, value));
5645 }
5646
5647 ctx.update_leaves(&mut trie, leaves.iter().cloned());
5649
5650 ctx.assert_upper_subtrie(&trie)
5652 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA, 0x0]));
5653
5654 let mut subtrie_assert =
5656 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0x0])).has_branch(
5657 &Nibbles::from_nibbles([0xA, 0x0]),
5658 &[0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
5659 );
5660
5661 for (i, (path, value)) in leaves.iter().enumerate() {
5663 subtrie_assert = subtrie_assert
5664 .has_leaf(&Nibbles::from_nibbles([0xA, 0x0, i as u8]), &Nibbles::default())
5665 .has_value(path, value);
5666 }
5667 }
5668
5669 #[test]
5670 fn test_update_creates_multiple_subtries() {
5671 let ctx = ParallelSparseTrieTestContext;
5672 let mut trie =
5673 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5674
5675 let leaves = vec![
5691 ctx.create_test_leaf([0x0, 0x0, 0x1, 0x2], 1),
5692 ctx.create_test_leaf([0x0, 0x1, 0x3, 0x4], 2),
5693 ctx.create_test_leaf([0x0, 0x2, 0x5, 0x6], 3),
5694 ctx.create_test_leaf([0x0, 0x3, 0x7, 0x8], 4),
5695 ];
5696
5697 ctx.update_leaves(&mut trie, leaves.iter().cloned());
5699
5700 ctx.assert_upper_subtrie(&trie)
5702 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x0]))
5703 .has_branch(&Nibbles::from_nibbles([0x0]), &[0x0, 0x1, 0x2, 0x3]);
5704
5705 for (i, (leaf_path, leaf_value)) in leaves.iter().enumerate() {
5707 let subtrie_path = Nibbles::from_nibbles([0x0, i as u8]);
5708 ctx.assert_subtrie(&trie, subtrie_path)
5709 .has_leaf(
5710 &subtrie_path,
5711 &Nibbles::from_nibbles(match i {
5712 0 => vec![0x1, 0x2],
5713 1 => vec![0x3, 0x4],
5714 2 => vec![0x5, 0x6],
5715 3 => vec![0x7, 0x8],
5716 _ => unreachable!(),
5717 }),
5718 )
5719 .has_value(leaf_path, leaf_value);
5720 }
5721 }
5722
5723 #[test]
5724 fn test_update_extension_to_branch_transformation() {
5725 let ctx = ParallelSparseTrieTestContext;
5726 let mut trie =
5727 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5728
5729 let (leaf1_path, value1) = ctx.create_test_leaf([0xF, 0xF, 0x0, 0x1], 1);
5745 let (leaf2_path, value2) = ctx.create_test_leaf([0xF, 0xF, 0x0, 0x2], 2);
5746 let (leaf3_path, value3) = ctx.create_test_leaf([0xF, 0x0, 0x0, 0x3], 3);
5747
5748 ctx.update_leaves(&mut trie, [(leaf1_path, value1.clone()), (leaf2_path, value2.clone())]);
5749
5750 ctx.assert_upper_subtrie(&trie)
5752 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xF, 0xF, 0x0]));
5753
5754 ctx.update_leaves(&mut trie, [(leaf3_path, value3.clone())]);
5756
5757 ctx.assert_upper_subtrie(&trie)
5759 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xF]))
5760 .has_branch(&Nibbles::from_nibbles([0xF]), &[0x0, 0xF]);
5761
5762 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0xF]))
5764 .has_branch(&Nibbles::from_nibbles([0xF, 0xF, 0x0]), &[0x1, 0x2])
5765 .has_leaf(&Nibbles::from_nibbles([0xF, 0xF, 0x0, 0x1]), &Nibbles::default())
5766 .has_leaf(&Nibbles::from_nibbles([0xF, 0xF, 0x0, 0x2]), &Nibbles::default())
5767 .has_value(&leaf1_path, &value1)
5768 .has_value(&leaf2_path, &value2);
5769
5770 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0x0]))
5771 .has_leaf(&Nibbles::from_nibbles([0xF, 0x0]), &Nibbles::from_nibbles([0x0, 0x3]))
5772 .has_value(&leaf3_path, &value3);
5773 }
5774
5775 #[test]
5776 fn test_update_upper_extension_reveal_lower_hash_node() {
5777 let ctx = ParallelSparseTrieTestContext;
5778
5779 let mut provider = MockTrieNodeProvider::new();
5802
5803 let child_hashes = [
5805 RlpNode::word_rlp(&B256::repeat_byte(0x11)),
5806 RlpNode::word_rlp(&B256::repeat_byte(0x22)),
5807 ];
5808 let revealed_branch = create_branch_node_with_children(&[0x1, 0x2], child_hashes);
5809 let mut encoded = Vec::new();
5810 revealed_branch.encode(&mut encoded);
5811 provider.add_revealed_node(
5812 Nibbles::from_nibbles([0xA, 0xB]),
5813 RevealedNode { node: encoded.into(), tree_mask: None, hash_mask: None },
5814 );
5815
5816 let mut trie = new_test_trie(
5817 [
5818 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0xA, 0xB]))),
5819 (Nibbles::from_nibbles([0xA, 0xB]), SparseNode::Hash(B256::repeat_byte(0x42))),
5820 ]
5821 .into_iter(),
5822 );
5823
5824 let (leaf_path, value) = ctx.create_test_leaf([0xA, 0x0], 1);
5826 trie.update_leaf(leaf_path, value, provider).unwrap();
5827
5828 ctx.assert_upper_subtrie(&trie)
5830 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA]))
5831 .has_branch(&Nibbles::from_nibbles([0xA]), &[0x0, 0xB]);
5832
5833 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0xB]))
5835 .has_branch(&Nibbles::from_nibbles([0xA, 0xB]), &[0x1, 0x2])
5836 .has_hash(&Nibbles::from_nibbles([0xA, 0xB, 0x1]), &B256::repeat_byte(0x11))
5837 .has_hash(&Nibbles::from_nibbles([0xA, 0xB, 0x2]), &B256::repeat_byte(0x22));
5838 }
5839
5840 #[test]
5841 fn test_update_long_shared_prefix_at_boundary() {
5842 let ctx = ParallelSparseTrieTestContext;
5843 let mut trie =
5844 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5845
5846 let (leaf1_path, value1) = ctx.create_test_leaf([0xA, 0xB, 0xC, 0xD, 0xE, 0xF], 1);
5860 let (leaf2_path, value2) = ctx.create_test_leaf([0xA, 0xB, 0xD, 0xE, 0xF, 0x0], 2);
5861
5862 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
5863 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
5864
5865 ctx.assert_upper_subtrie(&trie)
5867 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0xA, 0xB]));
5868
5869 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xA, 0xB]))
5871 .has_branch(&Nibbles::from_nibbles([0xA, 0xB]), &[0xC, 0xD])
5872 .has_leaf(
5873 &Nibbles::from_nibbles([0xA, 0xB, 0xC]),
5874 &Nibbles::from_nibbles([0xD, 0xE, 0xF]),
5875 )
5876 .has_leaf(
5877 &Nibbles::from_nibbles([0xA, 0xB, 0xD]),
5878 &Nibbles::from_nibbles([0xE, 0xF, 0x0]),
5879 )
5880 .has_value(&leaf1_path, &value1)
5881 .has_value(&leaf2_path, &value2);
5882 }
5883
5884 #[test]
5885 fn test_update_branch_to_extension_collapse() {
5886 let ctx = ParallelSparseTrieTestContext;
5887 let mut trie =
5888 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5889
5890 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 1);
5916 let (leaf2_path, value2) = ctx.create_test_leaf([0x2, 0x3, 0x4, 0x5], 2);
5917 let (leaf3_path, value3) = ctx.create_test_leaf([0x2, 0x3, 0x5, 0x6], 3);
5918
5919 trie.update_leaf(leaf1_path, value1, DefaultTrieNodeProvider).unwrap();
5920 trie.update_leaf(leaf2_path, value2, DefaultTrieNodeProvider).unwrap();
5921 trie.update_leaf(leaf3_path, value3, DefaultTrieNodeProvider).unwrap();
5922
5923 ctx.assert_upper_subtrie(&trie).has_branch(&Nibbles::default(), &[0x1, 0x2]);
5925
5926 let (new_leaf1_path, new_value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 10);
5929 let (new_leaf2_path, new_value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x5], 11);
5930 let (new_leaf3_path, new_value3) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x6], 12);
5931
5932 let mut trie =
5934 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5935 trie.update_leaf(new_leaf1_path, new_value1.clone(), DefaultTrieNodeProvider).unwrap();
5936 trie.update_leaf(new_leaf2_path, new_value2.clone(), DefaultTrieNodeProvider).unwrap();
5937 trie.update_leaf(new_leaf3_path, new_value3.clone(), DefaultTrieNodeProvider).unwrap();
5938
5939 ctx.assert_upper_subtrie(&trie)
5941 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
5942
5943 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3]);
5945
5946 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
5948 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5, 0x6]) .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &Nibbles::default())
5950 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x5]), &Nibbles::default())
5951 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x6]), &Nibbles::default())
5952 .has_value(&new_leaf1_path, &new_value1)
5953 .has_value(&new_leaf2_path, &new_value2)
5954 .has_value(&new_leaf3_path, &new_value3);
5955 }
5956
5957 #[test]
5958 fn test_update_shared_prefix_patterns() {
5959 let ctx = ParallelSparseTrieTestContext;
5960 let mut trie =
5961 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
5962
5963 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4], 1);
5979 let (leaf2_path, value2) = ctx.create_test_leaf([0x2, 0x3, 0x4, 0x5], 2);
5980 let (leaf3_path, value3) = ctx.create_test_leaf([0x2, 0x3, 0x5, 0x6], 3);
5981
5982 trie.update_leaf(leaf1_path, value1, DefaultTrieNodeProvider).unwrap();
5983 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
5984 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
5985
5986 ctx.assert_upper_subtrie(&trie)
5988 .has_branch(&Nibbles::default(), &[0x1, 0x2])
5989 .has_leaf(&Nibbles::from_nibbles([0x1]), &Nibbles::from_nibbles([0x2, 0x3, 0x4]))
5990 .has_extension(&Nibbles::from_nibbles([0x2]), &Nibbles::from_nibbles([0x3]));
5991
5992 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x2, 0x3]))
5994 .has_branch(&Nibbles::from_nibbles([0x2, 0x3]), &[0x4, 0x5])
5995 .has_leaf(&Nibbles::from_nibbles([0x2, 0x3, 0x4]), &Nibbles::from_nibbles([0x5]))
5996 .has_leaf(&Nibbles::from_nibbles([0x2, 0x3, 0x5]), &Nibbles::from_nibbles([0x6]))
5997 .has_value(&leaf2_path, &value2)
5998 .has_value(&leaf3_path, &value3);
5999 }
6000
6001 #[test]
6002 fn test_progressive_branch_creation() {
6003 let ctx = ParallelSparseTrieTestContext;
6004 let mut trie =
6005 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6006
6007 let (leaf1_path, value1) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4, 0x5], 1);
6043 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6044
6045 ctx.assert_upper_subtrie(&trie)
6047 .has_leaf(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]))
6048 .has_value(&leaf1_path, &value1);
6049
6050 let (leaf2_path, value2) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x4, 0x6], 2);
6052 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6053
6054 ctx.assert_upper_subtrie(&trie)
6056 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]));
6057
6058 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3, 0x4]);
6060
6061 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6062 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6063 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x5]), &Nibbles::default())
6064 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4, 0x6]), &Nibbles::default())
6065 .has_value(&leaf1_path, &value1)
6066 .has_value(&leaf2_path, &value2);
6067
6068 let (leaf3_path, value3) = ctx.create_test_leaf([0x1, 0x2, 0x3, 0x5], 3);
6070 trie.update_leaf(leaf3_path, value3.clone(), DefaultTrieNodeProvider).unwrap();
6071
6072 ctx.assert_upper_subtrie(&trie)
6074 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2, 0x3]));
6075
6076 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2, 0x3]);
6078
6079 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6080 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
6081 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6082 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x5]), &Nibbles::default())
6083 .has_value(&leaf1_path, &value1)
6084 .has_value(&leaf2_path, &value2)
6085 .has_value(&leaf3_path, &value3);
6086
6087 let (leaf4_path, value4) = ctx.create_test_leaf([0x1, 0x2, 0x4], 4);
6089 trie.update_leaf(leaf4_path, value4.clone(), DefaultTrieNodeProvider).unwrap();
6090
6091 ctx.assert_upper_subtrie(&trie)
6093 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles([0x1, 0x2]));
6094
6095 ctx.assert_subtrie_path(&trie, [0x1, 0x2], [0x1, 0x2]);
6097
6098 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0x1, 0x2]))
6100 .has_branch(&Nibbles::from_nibbles([0x1, 0x2]), &[0x3, 0x4])
6101 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3]), &[0x4, 0x5])
6102 .has_branch(&Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]), &[0x5, 0x6])
6103 .has_leaf(&Nibbles::from_nibbles([0x1, 0x2, 0x4]), &Nibbles::default())
6104 .has_value(&leaf1_path, &value1)
6105 .has_value(&leaf2_path, &value2)
6106 .has_value(&leaf3_path, &value3)
6107 .has_value(&leaf4_path, &value4);
6108 }
6109
6110 #[test]
6111 fn test_update_max_depth_paths() {
6112 let ctx = ParallelSparseTrieTestContext;
6113 let mut trie =
6114 ParallelSparseTrie::from_root(TrieNode::EmptyRoot, TrieMasks::none(), true).unwrap();
6115
6116 let mut path1_nibbles = vec![0xF; 63];
6128 path1_nibbles.push(0x0);
6129 let mut path2_nibbles = vec![0xF; 63];
6130 path2_nibbles.push(0x1);
6131
6132 let (leaf1_path, value1) = ctx.create_test_leaf(&path1_nibbles, 1);
6133 let (leaf2_path, value2) = ctx.create_test_leaf(&path2_nibbles, 2);
6134
6135 trie.update_leaf(leaf1_path, value1.clone(), DefaultTrieNodeProvider).unwrap();
6136 trie.update_leaf(leaf2_path, value2.clone(), DefaultTrieNodeProvider).unwrap();
6137
6138 let extension_key = vec![0xF; 63];
6140 ctx.assert_upper_subtrie(&trie)
6141 .has_extension(&Nibbles::default(), &Nibbles::from_nibbles(&extension_key));
6142
6143 ctx.assert_subtrie(&trie, Nibbles::from_nibbles([0xF, 0xF]))
6145 .has_branch(&Nibbles::from_nibbles(&path1_nibbles[..63]), &[0x0, 0x1])
6146 .has_value(&leaf1_path, &value1)
6147 .has_value(&leaf2_path, &value2);
6148 }
6149
6150 #[test]
6151 fn test_hoodie_block_1_data() {
6152 let root_branch_stack = vec![
6154 hex!("a0550b6aba4dd4582a2434d2cbdad8d3007d09f622d7a6e6eaa7a49385823c2fa2"),
6155 hex!("a04788a4975a9e1efd29b834fd80fdfe8a57cc1b1c5ace6d30ce5a36a15e0092b3"),
6156 hex!("a093aeccf87da304e6f7d09edc5d7bd3a552808866d2149dd0940507a8f9bfa910"),
6157 hex!("a08b5b423ba68d0dec2eca1f408076f9170678505eb4a5db2abbbd83bb37666949"),
6158 hex!("a08592f62216af4218098a78acad7cf472a727fb55e6c27d3cfdf2774d4518eb83"),
6159 hex!("a0ef02aeee845cb64c11f85edc1a3094227c26445952554b8a9248915d80c746c3"),
6160 hex!("a0df2529ee3a1ce4df5a758cf17e6a86d0fb5ea22ab7071cf60af6412e9b0a428a"),
6161 hex!("a0acaa1092db69cd5a63676685827b3484c4b80dc1d3361f6073bbb9240101e144"),
6162 hex!("a09c3f2bb2a729d71f246a833353ade65667716bb330e0127a3299a42d11200f93"),
6163 hex!("a0ce978470f4c0b1f8069570563a14d2b79d709add2db4bf22dd9b6aed3271c566"),
6164 hex!("a095f783cd1d464a60e3c8adcadc28c6eb9fec7306664df39553be41dccc909606"),
6165 hex!("a0a9083f5fb914b255e1feb5d951a4dfddacf3c8003ef1d1ec6a13bb6ba5b2ac62"),
6166 hex!("a0fec113d537d8577cd361e0cabf5e95ef58f1cc34318292fdecce9fae57c3e094"),
6167 hex!("a08b7465f5fe8b3e3c0d087cb7521310d4065ef2a0ee43bf73f68dee8a5742b3dd"),
6168 hex!("a0c589aa1ae3d5fd87d8640957f7d5184a4ac06f393b453a8e8ed7e8fba0d385c8"),
6169 hex!("a0b516d6f3352f87beab4ed6e7322f191fc7a147686500ef4de7dd290ad784ef51"),
6170 ];
6171
6172 let root_branch_rlp_stack: Vec<RlpNode> = root_branch_stack
6173 .iter()
6174 .map(|hex_str| RlpNode::from_raw_rlp(&hex_str[..]).unwrap())
6175 .collect();
6176
6177 let root_branch_node = BranchNode::new(
6178 root_branch_rlp_stack,
6179 TrieMask::new(0b1111111111111111), );
6181
6182 let root_branch_masks = TrieMasks {
6183 hash_mask: Some(TrieMask::new(0b1111111111111111)),
6184 tree_mask: Some(TrieMask::new(0b1111111111111111)),
6185 };
6186
6187 let mut trie = ParallelSparseTrie::from_root(
6188 TrieNode::Branch(root_branch_node),
6189 root_branch_masks,
6190 true,
6191 )
6192 .unwrap();
6193
6194 let branch_0x3_stack = vec![
6196 hex!("a09da7d9755fe0c558b3c3de9fdcdf9f28ae641f38c9787b05b73ab22ae53af3e2"),
6197 hex!("a0d9990bf0b810d1145ecb2b011fd68c63cc85564e6724166fd4a9520180706e5f"),
6198 hex!("a0f60eb4b12132a40df05d9bbdb88bbde0185a3f097f3c76bf4200c23eda26cf86"),
6199 hex!("a0ca976997ddaf06f18992f6207e4f6a05979d07acead96568058789017cc6d06b"),
6200 hex!("a04d78166b48044fdc28ed22d2fd39c8df6f8aaa04cb71d3a17286856f6893ff83"),
6201 hex!("a021d4f90c34d3f1706e78463b6482bca77a3aa1cd059a3f326c42a1cfd30b9b60"),
6202 hex!("a0fc3b71c33e2e6b77c5e494c1db7fdbb447473f003daf378c7a63ba9bf3f0049d"),
6203 hex!("a0e33ed2be194a3d93d343e85642447c93a9d0cfc47a016c2c23d14c083be32a7c"),
6204 hex!("a07b8e7a21c1178d28074f157b50fca85ee25c12568ff8e9706dcbcdacb77bf854"),
6205 hex!("a0973274526811393ea0bf4811ca9077531db00d06b86237a2ecd683f55ba4bcb0"),
6206 hex!("a03a93d726d7487874e51b52d8d534c63aa2a689df18e3b307c0d6cb0a388b00f3"),
6207 hex!("a06aa67101d011d1c22fe739ef83b04b5214a3e2f8e1a2625d8bfdb116b447e86f"),
6208 hex!("a02dd545b33c62d33a183e127a08a4767fba891d9f3b94fc20a2ca02600d6d1fff"),
6209 hex!("a0fe6db87d00f06d53bff8169fa497571ff5af1addfb715b649b4d79dd3e394b04"),
6210 hex!("a0d9240a9d2d5851d05a97ff3305334dfdb0101e1e321fc279d2bb3cad6afa8fc8"),
6211 hex!("a01b69c6ab5173de8a8ec53a6ebba965713a4cc7feb86cb3e230def37c230ca2b2"),
6212 ];
6213
6214 let branch_0x3_rlp_stack: Vec<RlpNode> = branch_0x3_stack
6215 .iter()
6216 .map(|hex_str| RlpNode::from_raw_rlp(&hex_str[..]).unwrap())
6217 .collect();
6218
6219 let branch_0x3_node = BranchNode::new(
6220 branch_0x3_rlp_stack,
6221 TrieMask::new(0b1111111111111111), );
6223
6224 let branch_0x3_masks = TrieMasks {
6225 hash_mask: Some(TrieMask::new(0b0100010000010101)),
6226 tree_mask: Some(TrieMask::new(0b0100000000000000)),
6227 };
6228
6229 let leaf_path = Nibbles::from_nibbles([0x3, 0x7]);
6231 let leaf_key = Nibbles::unpack(
6232 &hex!("d65eaa92c6bc4c13a5ec45527f0c18ea8932588728769ec7aecfe6d9f32e42")[..],
6233 );
6234 let leaf_value = hex!("f8440180a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c").to_vec();
6235
6236 let leaf_node = LeafNode::new(leaf_key, leaf_value);
6237 let leaf_masks = TrieMasks::none();
6238
6239 trie.reveal_nodes(vec![
6240 RevealedSparseNode {
6241 path: Nibbles::from_nibbles([0x3]),
6242 node: TrieNode::Branch(branch_0x3_node),
6243 masks: branch_0x3_masks,
6244 },
6245 RevealedSparseNode {
6246 path: leaf_path,
6247 node: TrieNode::Leaf(leaf_node),
6248 masks: leaf_masks,
6249 },
6250 ])
6251 .unwrap();
6252
6253 let mut leaf_full_path = leaf_path;
6255 leaf_full_path.extend(&leaf_key);
6256
6257 let leaf_new_value = vec![
6258 248, 68, 1, 128, 160, 224, 163, 152, 169, 122, 160, 155, 102, 53, 41, 0, 47, 28, 205,
6259 190, 199, 5, 215, 108, 202, 22, 138, 70, 196, 178, 193, 208, 18, 96, 95, 63, 238, 160,
6260 245, 122, 205, 64, 37, 152, 114, 96, 109, 118, 25, 126, 240, 82, 243, 211, 85, 136,
6261 218, 223, 145, 158, 225, 240, 227, 203, 155, 98, 211, 244, 176, 44,
6262 ];
6263
6264 trie.update_leaf(leaf_full_path, leaf_new_value.clone(), DefaultTrieNodeProvider).unwrap();
6265
6266 assert_eq!(
6268 Some(&leaf_new_value),
6269 trie.lower_subtrie_for_path(&leaf_path).unwrap().inner.values.get(&leaf_full_path)
6270 );
6271 assert!(trie.upper_subtrie.inner.values.is_empty());
6272
6273 let expected_root =
6275 b256!("0x29b07de8376e9ce7b3a69e9b102199869514d3f42590b5abc6f7d48ec9b8665c");
6276 assert_eq!(trie.root(), expected_root);
6277 }
6278
6279 #[test]
6280 fn find_leaf_existing_leaf() {
6281 let provider = DefaultTrieNodeProvider;
6283 let mut sparse = ParallelSparseTrie::default();
6284 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6285 let value = b"test_value".to_vec();
6286
6287 sparse.update_leaf(path, value.clone(), &provider).unwrap();
6288
6289 let result = sparse.find_leaf(&path, None);
6291 assert_matches!(result, Ok(LeafLookup::Exists));
6292
6293 let result = sparse.find_leaf(&path, Some(&value));
6295 assert_matches!(result, Ok(LeafLookup::Exists));
6296 }
6297
6298 #[test]
6299 fn find_leaf_value_mismatch() {
6300 let provider = DefaultTrieNodeProvider;
6302 let mut sparse = ParallelSparseTrie::default();
6303 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6304 let value = b"test_value".to_vec();
6305 let wrong_value = b"wrong_value".to_vec();
6306
6307 sparse.update_leaf(path, value, &provider).unwrap();
6308
6309 let result = sparse.find_leaf(&path, Some(&wrong_value));
6311 assert_matches!(
6312 result,
6313 Err(LeafLookupError::ValueMismatch { path: p, expected: Some(e), actual: _a }) if p == path && e == wrong_value
6314 );
6315 }
6316
6317 #[test]
6318 fn find_leaf_not_found_empty_trie() {
6319 let sparse = ParallelSparseTrie::default();
6321 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
6322
6323 let result = sparse.find_leaf(&path, None);
6325 assert_matches!(result, Ok(LeafLookup::NonExistent));
6326 }
6327
6328 #[test]
6329 fn find_leaf_empty_trie() {
6330 let sparse = ParallelSparseTrie::default();
6331 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6332
6333 let result = sparse.find_leaf(&path, None);
6334 assert_matches!(result, Ok(LeafLookup::NonExistent));
6335 }
6336
6337 #[test]
6338 fn find_leaf_exists_no_value_check() {
6339 let provider = DefaultTrieNodeProvider;
6340 let mut sparse = ParallelSparseTrie::default();
6341 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6342 sparse.update_leaf(path, encode_account_value(0), &provider).unwrap();
6343
6344 let result = sparse.find_leaf(&path, None);
6345 assert_matches!(result, Ok(LeafLookup::Exists));
6346 }
6347
6348 #[test]
6349 fn find_leaf_exists_with_value_check_ok() {
6350 let provider = DefaultTrieNodeProvider;
6351 let mut sparse = ParallelSparseTrie::default();
6352 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6353 let value = encode_account_value(0);
6354 sparse.update_leaf(path, value.clone(), &provider).unwrap();
6355
6356 let result = sparse.find_leaf(&path, Some(&value));
6357 assert_matches!(result, Ok(LeafLookup::Exists));
6358 }
6359
6360 #[test]
6361 fn find_leaf_exclusion_branch_divergence() {
6362 let provider = DefaultTrieNodeProvider;
6363 let mut sparse = ParallelSparseTrie::default();
6364 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();
6369 sparse.update_leaf(path2, encode_account_value(1), &provider).unwrap();
6370
6371 let result = sparse.find_leaf(&search_path, None);
6372 assert_matches!(result, Ok(LeafLookup::NonExistent))
6373 }
6374
6375 #[test]
6376 fn find_leaf_exclusion_extension_divergence() {
6377 let provider = DefaultTrieNodeProvider;
6378 let mut sparse = ParallelSparseTrie::default();
6379 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
6381 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]);
6383
6384 sparse.update_leaf(path1, encode_account_value(0), &provider).unwrap();
6385
6386 let result = sparse.find_leaf(&search_path, None);
6387 assert_matches!(result, Ok(LeafLookup::NonExistent))
6388 }
6389
6390 #[test]
6391 fn find_leaf_exclusion_leaf_divergence() {
6392 let provider = DefaultTrieNodeProvider;
6393 let mut sparse = ParallelSparseTrie::default();
6394 let existing_leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6395 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
6396
6397 sparse.update_leaf(existing_leaf_path, encode_account_value(0), &provider).unwrap();
6398
6399 let result = sparse.find_leaf(&search_path, None);
6400 assert_matches!(result, Ok(LeafLookup::NonExistent))
6401 }
6402
6403 #[test]
6404 fn find_leaf_exclusion_path_ends_at_branch() {
6405 let provider = DefaultTrieNodeProvider;
6406 let mut sparse = ParallelSparseTrie::default();
6407 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]);
6409 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2]); sparse.update_leaf(path1, encode_account_value(0), &provider).unwrap();
6412 sparse.update_leaf(path2, encode_account_value(1), &provider).unwrap();
6413
6414 let result = sparse.find_leaf(&search_path, None);
6415 assert_matches!(result, Ok(LeafLookup::NonExistent));
6416 }
6417
6418 #[test]
6419 fn find_leaf_error_blinded_node_at_leaf_path() {
6420 let blinded_hash = B256::repeat_byte(0xBB);
6422 let leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6423
6424 let sparse = new_test_trie(
6425 [
6426 (
6427 Nibbles::default(),
6429 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x1, 0x2])),
6430 ),
6431 (
6432 Nibbles::from_nibbles_unchecked([0x1, 0x2]),
6434 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x3])),
6435 ),
6436 (
6437 Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3]),
6439 SparseNode::new_branch(TrieMask::new(0b10000)),
6440 ),
6441 (
6442 leaf_path,
6444 SparseNode::Hash(blinded_hash),
6445 ),
6446 ]
6447 .into_iter(),
6448 );
6449
6450 let result = sparse.find_leaf(&leaf_path, None);
6451
6452 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
6454 if path == leaf_path && hash == blinded_hash
6455 );
6456 }
6457
6458 #[test]
6459 fn find_leaf_error_blinded_node() {
6460 let blinded_hash = B256::repeat_byte(0xAA);
6461 let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]);
6462 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
6463
6464 let sparse = new_test_trie(
6465 [
6466 (Nibbles::default(), SparseNode::new_branch(TrieMask::new(0b100010))),
6469 (path_to_blind, SparseNode::Hash(blinded_hash)),
6470 (
6471 Nibbles::from_nibbles_unchecked([0x5]),
6472 SparseNode::new_leaf(Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8])),
6473 ),
6474 ]
6475 .into_iter(),
6476 );
6477
6478 let result = sparse.find_leaf(&search_path, None);
6479
6480 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
6482 if path == path_to_blind && hash == blinded_hash
6483 );
6484 }
6485}