1use crate::{
2 provider::{RevealedNode, TrieNodeProvider},
3 LeafLookup, LeafLookupError, SparseTrieInterface, SparseTrieUpdates,
4};
5use alloc::{
6 borrow::Cow,
7 boxed::Box,
8 fmt,
9 string::{String, ToString},
10 vec,
11 vec::Vec,
12};
13use alloy_primitives::{
14 hex, keccak256,
15 map::{Entry, HashMap, HashSet},
16 B256,
17};
18use alloy_rlp::Decodable;
19use reth_execution_errors::{SparseTrieErrorKind, SparseTrieResult};
20use reth_trie_common::{
21 prefix_set::{PrefixSet, PrefixSetMut},
22 BranchNodeCompact, BranchNodeMasks, BranchNodeMasksMap, BranchNodeRef, ExtensionNodeRef,
23 LeafNodeRef, Nibbles, ProofTrieNode, RlpNode, TrieMask, TrieMasks, TrieNode, CHILD_INDEX_RANGE,
24 EMPTY_ROOT_HASH,
25};
26use smallvec::SmallVec;
27use tracing::{debug, instrument, trace};
28
29const SPARSE_TRIE_SUBTRIE_HASHES_LEVEL: usize = 2;
32
33#[derive(PartialEq, Eq, Debug, Clone)]
46pub enum SparseTrie<T = SerialSparseTrie> {
47 Blind(Option<Box<T>>),
55 Revealed(Box<T>),
61}
62
63impl<T: Default> Default for SparseTrie<T> {
64 fn default() -> Self {
65 Self::Blind(None)
66 }
67}
68
69impl<T: SparseTrieInterface + Default> SparseTrie<T> {
70 pub fn revealed_empty() -> Self {
81 Self::Revealed(Box::default())
82 }
83
84 pub fn reveal_root(
96 &mut self,
97 root: TrieNode,
98 masks: TrieMasks,
99 retain_updates: bool,
100 ) -> SparseTrieResult<&mut T> {
101 if self.is_blind() {
104 let mut revealed_trie = if let Self::Blind(Some(cleared_trie)) = core::mem::take(self) {
105 cleared_trie
106 } else {
107 Box::default()
108 };
109
110 *revealed_trie = revealed_trie.with_root(root, masks, retain_updates)?;
111 *self = Self::Revealed(revealed_trie);
112 }
113
114 Ok(self.as_revealed_mut().unwrap())
115 }
116}
117
118impl<T: SparseTrieInterface> SparseTrie<T> {
119 pub const fn blind() -> Self {
132 Self::Blind(None)
133 }
134
135 pub fn blind_from(mut trie: T) -> Self {
138 trie.clear();
139 Self::Blind(Some(Box::new(trie)))
140 }
141
142 pub const fn is_blind(&self) -> bool {
144 matches!(self, Self::Blind(_))
145 }
146
147 pub const fn is_revealed(&self) -> bool {
149 matches!(self, Self::Revealed(_))
150 }
151
152 pub const fn as_revealed_ref(&self) -> Option<&T> {
156 if let Self::Revealed(revealed) = self {
157 Some(revealed)
158 } else {
159 None
160 }
161 }
162
163 pub fn as_revealed_mut(&mut self) -> Option<&mut T> {
167 if let Self::Revealed(revealed) = self {
168 Some(revealed)
169 } else {
170 None
171 }
172 }
173
174 pub fn wipe(&mut self) -> SparseTrieResult<()> {
179 let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
180 revealed.wipe();
181 Ok(())
182 }
183
184 pub fn root(&mut self) -> Option<B256> {
195 Some(self.as_revealed_mut()?.root())
196 }
197
198 pub fn root_with_updates(&mut self) -> Option<(B256, SparseTrieUpdates)> {
211 let revealed = self.as_revealed_mut()?;
212 Some((revealed.root(), revealed.take_updates()))
213 }
214
215 pub fn clear(self) -> Self {
219 match self {
220 Self::Blind(_) => self,
221 Self::Revealed(mut trie) => {
222 trie.clear();
223 Self::Blind(Some(trie))
224 }
225 }
226 }
227
228 #[instrument(level = "trace", target = "trie::sparse", skip_all)]
234 pub fn update_leaf(
235 &mut self,
236 path: Nibbles,
237 value: Vec<u8>,
238 provider: impl TrieNodeProvider,
239 ) -> SparseTrieResult<()> {
240 let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
241 revealed.update_leaf(path, value, provider)?;
242 Ok(())
243 }
244
245 #[instrument(level = "trace", target = "trie::sparse", skip_all)]
251 pub fn remove_leaf(
252 &mut self,
253 path: &Nibbles,
254 provider: impl TrieNodeProvider,
255 ) -> SparseTrieResult<()> {
256 let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
257 revealed.remove_leaf(path, provider)?;
258 Ok(())
259 }
260
261 pub fn shrink_nodes_to(&mut self, size: usize) {
264 match self {
265 Self::Blind(Some(trie)) | Self::Revealed(trie) => {
266 trie.shrink_nodes_to(size);
267 }
268 _ => {}
269 }
270 }
271
272 pub fn shrink_values_to(&mut self, size: usize) {
275 match self {
276 Self::Blind(Some(trie)) | Self::Revealed(trie) => {
277 trie.shrink_values_to(size);
278 }
279 _ => {}
280 }
281 }
282}
283
284#[derive(Clone, PartialEq, Eq)]
298pub struct SerialSparseTrie {
299 nodes: HashMap<Nibbles, SparseNode>,
302 branch_node_masks: BranchNodeMasksMap,
308 values: HashMap<Nibbles, Vec<u8>>,
311 prefix_set: PrefixSetMut,
314 updates: Option<SparseTrieUpdates>,
316 rlp_buf: Vec<u8>,
318}
319
320impl fmt::Debug for SerialSparseTrie {
321 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 f.debug_struct("SerialSparseTrie")
323 .field("nodes", &self.nodes)
324 .field("branch_node_masks", &self.branch_node_masks)
325 .field("values", &self.values)
326 .field("prefix_set", &self.prefix_set)
327 .field("updates", &self.updates)
328 .field("rlp_buf", &hex::encode(&self.rlp_buf))
329 .finish_non_exhaustive()
330 }
331}
332
333fn encode_nibbles(nibbles: &Nibbles) -> String {
335 let encoded = hex::encode(nibbles.pack());
336 encoded[..nibbles.len()].to_string()
337}
338
339impl fmt::Display for SerialSparseTrie {
340 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341 let mut stack = Vec::new();
343 let mut visited = HashSet::new();
344
345 const INDENT: &str = " ";
347
348 stack.push((Nibbles::default(), self.nodes_ref().get(&Nibbles::default()).unwrap(), 0));
350
351 while let Some((path, node, depth)) = stack.pop() {
352 if !visited.insert(path) {
353 continue;
354 }
355
356 if f.alternate() {
358 write!(f, "{}", INDENT.repeat(depth))?;
359 }
360
361 let packed_path = if depth == 0 { String::from("Root") } else { encode_nibbles(&path) };
362
363 match node {
364 SparseNode::Empty | SparseNode::Hash(_) => {
365 writeln!(f, "{packed_path} -> {node:?}")?;
366 }
367 SparseNode::Leaf { key, .. } => {
368 let mut full_path = path;
370 full_path.extend(key);
371 let packed_path = encode_nibbles(&full_path);
372
373 writeln!(f, "{packed_path} -> {node:?}")?;
374 }
375 SparseNode::Extension { key, .. } => {
376 writeln!(f, "{packed_path} -> {node:?}")?;
377
378 let mut child_path = path;
380 child_path.extend(key);
381 if let Some(child_node) = self.nodes_ref().get(&child_path) {
382 stack.push((child_path, child_node, depth + 1));
383 }
384 }
385 SparseNode::Branch { state_mask, .. } => {
386 writeln!(f, "{packed_path} -> {node:?}")?;
387
388 for i in CHILD_INDEX_RANGE.rev() {
389 if state_mask.is_bit_set(i) {
390 let mut child_path = path;
391 child_path.push_unchecked(i);
392 if let Some(child_node) = self.nodes_ref().get(&child_path) {
393 stack.push((child_path, child_node, depth + 1));
394 }
395 }
396 }
397 }
398 }
399 }
400
401 Ok(())
402 }
403}
404
405impl Default for SerialSparseTrie {
406 fn default() -> Self {
407 Self {
408 nodes: HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]),
409 branch_node_masks: BranchNodeMasksMap::default(),
410 values: HashMap::default(),
411 prefix_set: PrefixSetMut::default(),
412 updates: None,
413 rlp_buf: Vec::new(),
414 }
415 }
416}
417
418impl SparseTrieInterface for SerialSparseTrie {
419 fn with_root(
420 mut self,
421 root: TrieNode,
422 masks: TrieMasks,
423 retain_updates: bool,
424 ) -> SparseTrieResult<Self> {
425 self = self.with_updates(retain_updates);
426
427 let path = Nibbles::default();
430 let _removed_root = self.nodes.remove(&path).expect("root node should exist");
431 debug_assert_eq!(_removed_root, SparseNode::Empty);
432
433 self.reveal_node(path, root, masks)?;
434 Ok(self)
435 }
436
437 fn with_updates(mut self, retain_updates: bool) -> Self {
438 if retain_updates {
439 self.updates = Some(SparseTrieUpdates::default());
440 }
441 self
442 }
443
444 fn reserve_nodes(&mut self, additional: usize) {
445 self.nodes.reserve(additional);
446 }
447 fn reveal_node(
448 &mut self,
449 path: Nibbles,
450 node: TrieNode,
451 masks: TrieMasks,
452 ) -> SparseTrieResult<()> {
453 trace!(target: "trie::sparse", ?path, ?node, ?masks, "reveal_node called");
454
455 if self.nodes.get(&path).is_some_and(|node| !node.is_hash()) {
457 return Ok(())
458 }
459
460 if masks.tree_mask.is_some() || masks.hash_mask.is_some() {
461 self.branch_node_masks.insert(
462 path,
463 BranchNodeMasks {
464 tree_mask: masks.tree_mask.unwrap_or_default(),
465 hash_mask: masks.hash_mask.unwrap_or_default(),
466 },
467 );
468 }
469
470 match node {
471 TrieNode::EmptyRoot => {
472 debug_assert!(path.is_empty());
474 self.nodes.insert(path, SparseNode::Empty);
475 }
476 TrieNode::Branch(branch) => {
477 let mut stack_ptr = branch.as_ref().first_child_index();
479 for idx in CHILD_INDEX_RANGE {
480 if branch.state_mask.is_bit_set(idx) {
481 let mut child_path = path;
482 child_path.push_unchecked(idx);
483 self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
485 stack_ptr += 1;
486 }
487 }
488 match self.nodes.entry(path) {
491 Entry::Occupied(mut entry) => match entry.get() {
492 SparseNode::Hash(hash) => {
494 entry.insert(SparseNode::Branch {
495 state_mask: branch.state_mask,
496 hash: Some(*hash),
499 store_in_db_trie: Some(
500 masks.hash_mask.is_some_and(|mask| !mask.is_empty()) ||
501 masks.tree_mask.is_some_and(|mask| !mask.is_empty()),
502 ),
503 });
504 }
505 SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
508 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
510 return Err(SparseTrieErrorKind::Reveal {
511 path: *entry.key(),
512 node: Box::new(node.clone()),
513 }
514 .into())
515 }
516 },
517 Entry::Vacant(entry) => {
518 entry.insert(SparseNode::new_branch(branch.state_mask));
519 }
520 }
521 }
522 TrieNode::Extension(ext) => match self.nodes.entry(path) {
523 Entry::Occupied(mut entry) => match entry.get() {
524 SparseNode::Hash(hash) => {
526 let mut child_path = *entry.key();
527 child_path.extend(&ext.key);
528 entry.insert(SparseNode::Extension {
529 key: ext.key,
530 hash: Some(*hash),
533 store_in_db_trie: None,
534 });
535 self.reveal_node_or_hash(child_path, &ext.child)?;
536 }
537 SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
540 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
542 return Err(SparseTrieErrorKind::Reveal {
543 path: *entry.key(),
544 node: Box::new(node.clone()),
545 }
546 .into())
547 }
548 },
549 Entry::Vacant(entry) => {
550 let mut child_path = *entry.key();
551 child_path.extend(&ext.key);
552 entry.insert(SparseNode::new_ext(ext.key));
553 self.reveal_node_or_hash(child_path, &ext.child)?;
554 }
555 },
556 TrieNode::Leaf(leaf) => match self.nodes.entry(path) {
557 Entry::Occupied(mut entry) => match entry.get() {
558 SparseNode::Hash(hash) => {
560 let mut full = *entry.key();
561 full.extend(&leaf.key);
562 self.values.insert(full, leaf.value.clone());
563 entry.insert(SparseNode::Leaf {
564 key: leaf.key,
565 hash: Some(*hash),
568 });
569 }
570 SparseNode::Leaf { .. } => {}
572 node @ (SparseNode::Empty |
574 SparseNode::Extension { .. } |
575 SparseNode::Branch { .. }) => {
576 return Err(SparseTrieErrorKind::Reveal {
577 path: *entry.key(),
578 node: Box::new(node.clone()),
579 }
580 .into())
581 }
582 },
583 Entry::Vacant(entry) => {
584 let mut full = *entry.key();
585 full.extend(&leaf.key);
586 entry.insert(SparseNode::new_leaf(leaf.key));
587 self.values.insert(full, leaf.value.clone());
588 }
589 },
590 }
591
592 Ok(())
593 }
594
595 fn reveal_nodes(&mut self, mut nodes: Vec<ProofTrieNode>) -> SparseTrieResult<()> {
596 nodes.sort_unstable_by_key(|node| node.path);
597 for node in nodes {
598 self.reveal_node(node.path, node.node, node.masks)?;
599 }
600 Ok(())
601 }
602
603 #[instrument(level = "trace", target = "trie::sparse::serial", skip(self, provider))]
604 fn update_leaf<P: TrieNodeProvider>(
605 &mut self,
606 full_path: Nibbles,
607 value: Vec<u8>,
608 provider: P,
609 ) -> SparseTrieResult<()> {
610 self.prefix_set.insert(full_path);
611 let existing = self.values.insert(full_path, value);
612 if existing.is_some() {
613 return Ok(())
615 }
616
617 let mut current = Nibbles::default();
618 while let Some(node) = self.nodes.get_mut(¤t) {
619 match node {
620 SparseNode::Empty => {
621 *node = SparseNode::new_leaf(full_path);
622 break
623 }
624 &mut SparseNode::Hash(hash) => {
625 return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
626 }
627 SparseNode::Leaf { key: current_key, .. } => {
628 current.extend(current_key);
629
630 if current == full_path {
632 unreachable!("we already checked leaf presence in the beginning");
633 }
634
635 let common = current.common_prefix_length(&full_path);
637
638 let new_ext_key = current.slice(current.len() - current_key.len()..common);
640 *node = SparseNode::new_ext(new_ext_key);
641
642 self.nodes.reserve(3);
644 self.nodes.insert(
645 current.slice(..common),
646 SparseNode::new_split_branch(
647 current.get_unchecked(common),
648 full_path.get_unchecked(common),
649 ),
650 );
651 self.nodes.insert(
652 full_path.slice(..=common),
653 SparseNode::new_leaf(full_path.slice(common + 1..)),
654 );
655 self.nodes.insert(
656 current.slice(..=common),
657 SparseNode::new_leaf(current.slice(common + 1..)),
658 );
659
660 break;
661 }
662 SparseNode::Extension { key, .. } => {
663 current.extend(key);
664
665 if !full_path.starts_with(¤t) {
666 let common = current.common_prefix_length(&full_path);
668 *key = current.slice(current.len() - key.len()..common);
669
670 if self.updates.is_some() {
674 if self.nodes.get(¤t).unwrap().is_hash() {
676 debug!(
677 target: "trie::sparse",
678 leaf_full_path = ?full_path,
679 child_path = ?current,
680 "Extension node child not revealed in update_leaf, falling back to db",
681 );
682 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
683 provider.trie_node(¤t)?
684 {
685 let decoded = TrieNode::decode(&mut &node[..])?;
686 trace!(
687 target: "trie::sparse",
688 ?current,
689 ?decoded,
690 ?tree_mask,
691 ?hash_mask,
692 "Revealing extension node child",
693 );
694 self.reveal_node(
695 current,
696 decoded,
697 TrieMasks { hash_mask, tree_mask },
698 )?;
699 }
700 }
701 }
702
703 self.nodes.reserve(3);
706 let branch = SparseNode::new_split_branch(
707 current.get_unchecked(common),
708 full_path.get_unchecked(common),
709 );
710 self.nodes.insert(current.slice(..common), branch);
711
712 let new_leaf = SparseNode::new_leaf(full_path.slice(common + 1..));
714 self.nodes.insert(full_path.slice(..=common), new_leaf);
715
716 let key = current.slice(common + 1..);
718 if !key.is_empty() {
719 self.nodes.insert(current.slice(..=common), SparseNode::new_ext(key));
720 }
721
722 break;
723 }
724 }
725 SparseNode::Branch { state_mask, .. } => {
726 let nibble = full_path.get_unchecked(current.len());
727 current.push_unchecked(nibble);
728 if !state_mask.is_bit_set(nibble) {
729 state_mask.set_bit(nibble);
730 let new_leaf = SparseNode::new_leaf(full_path.slice(current.len()..));
731 self.nodes.insert(current, new_leaf);
732 break;
733 }
734 }
735 };
736 }
737
738 Ok(())
739 }
740
741 #[instrument(level = "trace", target = "trie::sparse::serial", skip(self, provider))]
742 fn remove_leaf<P: TrieNodeProvider>(
743 &mut self,
744 full_path: &Nibbles,
745 provider: P,
746 ) -> SparseTrieResult<()> {
747 trace!(target: "trie::sparse", ?full_path, "remove_leaf called");
748
749 if self.values.remove(full_path).is_none() {
750 if let Some(&SparseNode::Hash(hash)) = self.nodes.get(full_path) {
751 return Err(SparseTrieErrorKind::BlindedNode { path: *full_path, hash }.into())
753 }
754
755 trace!(target: "trie::sparse", ?full_path, "Leaf node is not present in the trie");
756 return Ok(())
758 }
759 self.prefix_set.insert(*full_path);
760
761 let mut removed_nodes = self.take_nodes_for_path(full_path)?;
766 let mut child = removed_nodes.pop().expect("leaf exists");
768 #[cfg(debug_assertions)]
769 {
770 let mut child_path = child.path;
771 let SparseNode::Leaf { key, .. } = &child.node else { panic!("expected leaf node") };
772 child_path.extend(key);
773 assert_eq!(&child_path, full_path);
774 }
775
776 if removed_nodes.is_empty() {
778 debug_assert!(self.nodes.is_empty());
779 self.nodes.insert(Nibbles::default(), SparseNode::Empty);
780
781 return Ok(())
782 }
783
784 while let Some(removed_node) = removed_nodes.pop() {
787 let removed_path = removed_node.path;
788
789 let new_node = match &removed_node.node {
790 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
791 &SparseNode::Hash(hash) => {
792 return Err(SparseTrieErrorKind::BlindedNode { path: removed_path, hash }.into())
793 }
794 SparseNode::Leaf { .. } => {
795 unreachable!("we already popped the leaf node")
796 }
797 SparseNode::Extension { key, .. } => {
798 match &child.node {
801 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
802 &SparseNode::Hash(hash) => {
803 return Err(
804 SparseTrieErrorKind::BlindedNode { path: child.path, hash }.into()
805 )
806 }
807 SparseNode::Leaf { key: leaf_key, .. } => {
813 self.nodes.remove(&child.path);
814
815 let mut new_key = *key;
816 new_key.extend(leaf_key);
817 SparseNode::new_leaf(new_key)
818 }
819 SparseNode::Extension { key: extension_key, .. } => {
822 self.nodes.remove(&child.path);
823
824 let mut new_key = *key;
825 new_key.extend(extension_key);
826 SparseNode::new_ext(new_key)
827 }
828 SparseNode::Branch { .. } => removed_node.node,
830 }
831 }
832 &SparseNode::Branch { mut state_mask, hash: _, store_in_db_trie: _ } => {
833 if let Some(removed_nibble) = removed_node.unset_branch_nibble {
837 state_mask.unset_bit(removed_nibble);
838 }
839
840 if state_mask.count_bits() == 1 {
842 let child_nibble =
843 state_mask.first_set_bit_index().expect("state mask is not empty");
844
845 let mut child_path = removed_path;
847 child_path.push_unchecked(child_nibble);
848
849 trace!(target: "trie::sparse", ?removed_path, ?child_path, "Branch node has only one child");
850
851 let child = self.reveal_remaining_child_on_leaf_removal(
854 &provider,
855 full_path,
856 &child_path,
857 true, )?;
859
860 let mut delete_child = false;
861 let new_node = match &child {
862 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
863 &SparseNode::Hash(hash) => {
864 return Err(SparseTrieErrorKind::BlindedNode {
865 path: child_path,
866 hash,
867 }
868 .into())
869 }
870 SparseNode::Leaf { key, .. } => {
874 delete_child = true;
875
876 let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
877 new_key.extend(key);
878 SparseNode::new_leaf(new_key)
879 }
880 SparseNode::Extension { key, .. } => {
884 delete_child = true;
885
886 let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
887 new_key.extend(key);
888 SparseNode::new_ext(new_key)
889 }
890 SparseNode::Branch { .. } => {
893 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([child_nibble]))
894 }
895 };
896
897 if delete_child {
898 self.nodes.remove(&child_path);
899 }
900
901 if let Some(updates) = self.updates.as_mut() {
902 updates.updated_nodes.remove(&removed_path);
903 updates.removed_nodes.insert(removed_path);
904 }
905
906 new_node
907 }
908 else {
910 SparseNode::new_branch(state_mask)
911 }
912 }
913 };
914
915 child = RemovedSparseNode {
916 path: removed_path,
917 node: new_node.clone(),
918 unset_branch_nibble: None,
919 };
920 trace!(target: "trie::sparse", ?removed_path, ?new_node, "Re-inserting the node");
921 self.nodes.insert(removed_path, new_node);
922 }
923
924 Ok(())
925 }
926
927 #[instrument(target = "trie::sparse::serial", skip(self))]
928 fn root(&mut self) -> B256 {
929 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
931 let rlp_node = self.rlp_node_allocate(&mut prefix_set);
932 if let Some(root_hash) = rlp_node.as_hash() {
933 root_hash
934 } else {
935 keccak256(rlp_node)
936 }
937 }
938
939 fn update_subtrie_hashes(&mut self) {
940 self.update_rlp_node_level(SPARSE_TRIE_SUBTRIE_HASHES_LEVEL);
941 }
942
943 fn get_leaf_value(&self, full_path: &Nibbles) -> Option<&Vec<u8>> {
944 self.values.get(full_path)
945 }
946
947 fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
948 self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
949 }
950
951 fn take_updates(&mut self) -> SparseTrieUpdates {
952 self.updates.take().unwrap_or_default()
953 }
954
955 fn wipe(&mut self) {
956 self.nodes = HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]);
957 self.values = HashMap::default();
958 self.prefix_set = PrefixSetMut::all();
959 self.updates = self.updates.is_some().then(SparseTrieUpdates::wiped);
960 }
961
962 fn clear(&mut self) {
963 self.nodes.clear();
964 self.nodes.insert(Nibbles::default(), SparseNode::Empty);
965
966 self.branch_node_masks.clear();
967 self.values.clear();
968 self.prefix_set.clear();
969 self.updates = None;
970 self.rlp_buf.clear();
971 }
972
973 fn find_leaf(
974 &self,
975 full_path: &Nibbles,
976 expected_value: Option<&Vec<u8>>,
977 ) -> Result<LeafLookup, LeafLookupError> {
978 #[inline]
980 fn check_value_match(
981 actual_value: &Vec<u8>,
982 expected_value: Option<&Vec<u8>>,
983 path: &Nibbles,
984 ) -> Result<(), LeafLookupError> {
985 if let Some(expected) = expected_value &&
986 actual_value != expected
987 {
988 return Err(LeafLookupError::ValueMismatch {
989 path: *path,
990 expected: Some(expected.clone()),
991 actual: actual_value.clone(),
992 });
993 }
994 Ok(())
995 }
996
997 let mut current = Nibbles::default(); if let Some(actual_value) = self.values.get(full_path) {
1005 check_value_match(actual_value, expected_value, full_path)?;
1007 return Ok(LeafLookup::Exists);
1008 }
1009
1010 while current.len() < full_path.len() {
1017 match self.nodes.get(¤t) {
1018 Some(SparseNode::Empty) | None => {
1019 return Ok(LeafLookup::NonExistent);
1022 }
1023 Some(&SparseNode::Hash(hash)) => {
1024 return Err(LeafLookupError::BlindedNode { path: current, hash });
1026 }
1027 Some(SparseNode::Leaf { key, .. }) => {
1028 current.extend(key);
1030 if ¤t == full_path {
1031 if let Some(value) = self.values.get(full_path) {
1033 check_value_match(value, expected_value, full_path)?;
1034 return Ok(LeafLookup::Exists);
1035 }
1036 }
1037
1038 return Ok(LeafLookup::NonExistent);
1041 }
1042 Some(SparseNode::Extension { key, .. }) => {
1043 let saved_len = current.len();
1045 current.extend(key);
1046
1047 if full_path.len() < current.len() || !full_path.starts_with(¤t) {
1048 current.truncate(saved_len); return Ok(LeafLookup::NonExistent);
1050 }
1051 }
1053 Some(SparseNode::Branch { state_mask, .. }) => {
1054 let nibble = full_path.get_unchecked(current.len());
1056 if !state_mask.is_bit_set(nibble) {
1057 return Ok(LeafLookup::NonExistent);
1059 }
1060
1061 current.push_unchecked(nibble);
1063 }
1064 }
1065 }
1066
1067 match self.nodes.get(full_path) {
1070 Some(SparseNode::Leaf { key, .. }) if key.is_empty() => {
1071 if let Some(value) = self.values.get(full_path) {
1074 check_value_match(value, expected_value, full_path)?;
1075 return Ok(LeafLookup::Exists);
1076 }
1077 }
1078 Some(&SparseNode::Hash(hash)) => {
1079 return Err(LeafLookupError::BlindedNode { path: *full_path, hash });
1080 }
1081 _ => {
1082 return Ok(LeafLookup::NonExistent);
1084 }
1085 }
1086
1087 Ok(LeafLookup::NonExistent)
1089 }
1090
1091 fn shrink_nodes_to(&mut self, size: usize) {
1092 self.nodes.shrink_to(size);
1093 self.branch_node_masks.shrink_to(size);
1094 }
1095
1096 fn shrink_values_to(&mut self, size: usize) {
1097 self.values.shrink_to(size);
1098 }
1099}
1100
1101impl SerialSparseTrie {
1102 pub fn from_root(
1117 root: TrieNode,
1118 masks: TrieMasks,
1119 retain_updates: bool,
1120 ) -> SparseTrieResult<Self> {
1121 Self::default().with_root(root, masks, retain_updates)
1122 }
1123
1124 pub fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
1128 self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
1129 }
1130
1131 pub const fn nodes_ref(&self) -> &HashMap<Nibbles, SparseNode> {
1133 &self.nodes
1134 }
1135
1136 fn reveal_node_or_hash(&mut self, path: Nibbles, child: &[u8]) -> SparseTrieResult<()> {
1155 if child.len() == B256::len_bytes() + 1 {
1156 let hash = B256::from_slice(&child[1..]);
1157 match self.nodes.entry(path) {
1158 Entry::Occupied(entry) => match entry.get() {
1159 SparseNode::Hash(previous_hash) if previous_hash != &hash => {
1161 return Err(SparseTrieErrorKind::Reveal {
1162 path: *entry.key(),
1163 node: Box::new(SparseNode::Hash(hash)),
1164 }
1165 .into())
1166 }
1167 _ => {}
1168 },
1169 Entry::Vacant(entry) => {
1170 entry.insert(SparseNode::Hash(hash));
1171 }
1172 }
1173 return Ok(())
1174 }
1175
1176 self.reveal_node(path, TrieNode::decode(&mut &child[..])?, TrieMasks::none())
1177 }
1178
1179 fn take_nodes_for_path(&mut self, path: &Nibbles) -> SparseTrieResult<Vec<RemovedSparseNode>> {
1196 let mut current = Nibbles::default(); let mut nodes = Vec::new(); while let Some(node) = self.nodes.remove(¤t) {
1200 match &node {
1201 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
1202 &SparseNode::Hash(hash) => {
1203 return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
1204 }
1205 SparseNode::Leaf { key: _key, .. } => {
1206 #[cfg(debug_assertions)]
1210 {
1211 let mut current = current;
1212 current.extend(_key);
1213 assert_eq!(¤t, path);
1214 }
1215
1216 nodes.push(RemovedSparseNode {
1217 path: current,
1218 node,
1219 unset_branch_nibble: None,
1220 });
1221 break
1222 }
1223 SparseNode::Extension { key, .. } => {
1224 #[cfg(debug_assertions)]
1225 {
1226 let mut current = current;
1227 current.extend(key);
1228 assert!(
1229 path.starts_with(¤t),
1230 "path: {path:?}, current: {current:?}, key: {key:?}",
1231 );
1232 }
1233
1234 let path = current;
1235 current.extend(key);
1236 nodes.push(RemovedSparseNode { path, node, unset_branch_nibble: None });
1237 }
1238 SparseNode::Branch { state_mask, .. } => {
1239 let nibble = path.get_unchecked(current.len());
1240 debug_assert!(
1241 state_mask.is_bit_set(nibble),
1242 "current: {current:?}, path: {path:?}, nibble: {nibble:?}, state_mask: {state_mask:?}",
1243 );
1244
1245 let mut child_path = current;
1251 child_path.push_unchecked(nibble);
1252 let unset_branch_nibble = self
1253 .nodes
1254 .get(&child_path)
1255 .is_some_and(move |node| match node {
1256 SparseNode::Leaf { key, .. } => {
1257 child_path.extend(key);
1259 &child_path == path
1260 }
1261 _ => false,
1262 })
1263 .then_some(nibble);
1264
1265 nodes.push(RemovedSparseNode { path: current, node, unset_branch_nibble });
1266
1267 current.push_unchecked(nibble);
1268 }
1269 }
1270 }
1271
1272 Ok(nodes)
1273 }
1274
1275 fn reveal_remaining_child_on_leaf_removal<P: TrieNodeProvider>(
1285 &mut self,
1286 provider: P,
1287 full_path: &Nibbles, remaining_child_path: &Nibbles,
1289 recurse_into_extension: bool,
1290 ) -> SparseTrieResult<SparseNode> {
1291 let remaining_child_node = match self.nodes.get(remaining_child_path).unwrap() {
1292 SparseNode::Hash(_) => {
1293 debug!(
1294 target: "trie::parallel_sparse",
1295 child_path = ?remaining_child_path,
1296 leaf_full_path = ?full_path,
1297 "Node child not revealed in remove_leaf, falling back to db",
1298 );
1299 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1300 provider.trie_node(remaining_child_path)?
1301 {
1302 let decoded = TrieNode::decode(&mut &node[..])?;
1303 trace!(
1304 target: "trie::parallel_sparse",
1305 ?remaining_child_path,
1306 ?decoded,
1307 ?tree_mask,
1308 ?hash_mask,
1309 "Revealing remaining blinded branch child"
1310 );
1311 self.reveal_node(
1312 *remaining_child_path,
1313 decoded,
1314 TrieMasks { hash_mask, tree_mask },
1315 )?;
1316 self.nodes.get(remaining_child_path).unwrap().clone()
1317 } else {
1318 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1319 path: *remaining_child_path,
1320 }
1321 .into())
1322 }
1323 }
1324 node => node.clone(),
1325 };
1326
1327 if let SparseNode::Extension { key, .. } = &remaining_child_node &&
1332 recurse_into_extension
1333 {
1334 let mut remaining_grandchild_path = *remaining_child_path;
1335 remaining_grandchild_path.extend(key);
1336
1337 trace!(
1338 target: "trie::parallel_sparse",
1339 remaining_grandchild_path = ?remaining_grandchild_path,
1340 child_path = ?remaining_child_path,
1341 leaf_full_path = ?full_path,
1342 "Revealing child of extension node, which is the last remaining child of the branch"
1343 );
1344
1345 self.reveal_remaining_child_on_leaf_removal(
1346 provider,
1347 full_path,
1348 &remaining_grandchild_path,
1349 false, )?;
1351 }
1352
1353 Ok(remaining_child_node)
1354 }
1355
1356 #[instrument(level = "trace", target = "trie::sparse::serial", skip(self))]
1365 pub fn update_rlp_node_level(&mut self, depth: usize) {
1366 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
1368 let mut buffers = RlpNodeBuffers::default();
1369
1370 let (targets, new_prefix_set) = self.get_changed_nodes_at_depth(&mut prefix_set, depth);
1372 self.prefix_set = new_prefix_set;
1374
1375 trace!(target: "trie::sparse", ?depth, ?targets, "Updating nodes at depth");
1376
1377 let mut temp_rlp_buf = core::mem::take(&mut self.rlp_buf);
1378 for (level, path) in targets {
1379 buffers.path_stack.push(RlpNodePathStackItem {
1380 level,
1381 path,
1382 is_in_prefix_set: Some(true),
1383 });
1384 self.rlp_node(&mut prefix_set, &mut buffers, &mut temp_rlp_buf);
1385 }
1386 self.rlp_buf = temp_rlp_buf;
1387 }
1388
1389 #[instrument(level = "trace", target = "trie::sparse::serial", skip(self))]
1411 fn get_changed_nodes_at_depth(
1412 &self,
1413 prefix_set: &mut PrefixSet,
1414 depth: usize,
1415 ) -> (Vec<(usize, Nibbles)>, PrefixSetMut) {
1416 let mut unchanged_prefix_set = PrefixSetMut::default();
1417 let mut paths = Vec::from([(Nibbles::default(), 0)]);
1418 let mut targets = Vec::new();
1419
1420 while let Some((mut path, level)) = paths.pop() {
1421 match self.nodes.get(&path).unwrap() {
1422 SparseNode::Empty | SparseNode::Hash(_) => {}
1423 SparseNode::Leaf { key: _, hash } => {
1424 if hash.is_some() && !prefix_set.contains(&path) {
1425 continue
1426 }
1427
1428 targets.push((level, path));
1429 }
1430 SparseNode::Extension { key, hash, store_in_db_trie: _ } => {
1431 if hash.is_some() && !prefix_set.contains(&path) {
1432 continue
1433 }
1434
1435 if level >= depth {
1436 targets.push((level, path));
1437 } else {
1438 unchanged_prefix_set.insert(path);
1439
1440 path.extend(key);
1441 paths.push((path, level + 1));
1442 }
1443 }
1444 SparseNode::Branch { state_mask, hash, store_in_db_trie: _ } => {
1445 if hash.is_some() && !prefix_set.contains(&path) {
1446 continue
1447 }
1448
1449 if level >= depth {
1450 targets.push((level, path));
1451 } else {
1452 unchanged_prefix_set.insert(path);
1453
1454 for bit in CHILD_INDEX_RANGE.rev() {
1455 if state_mask.is_bit_set(bit) {
1456 let mut child_path = path;
1457 child_path.push_unchecked(bit);
1458 paths.push((child_path, level + 1));
1459 }
1460 }
1461 }
1462 }
1463 }
1464 }
1465
1466 (targets, unchanged_prefix_set)
1467 }
1468
1469 pub fn rlp_node_allocate(&mut self, prefix_set: &mut PrefixSet) -> RlpNode {
1475 let mut buffers = RlpNodeBuffers::new_with_root_path();
1476 let mut temp_rlp_buf = core::mem::take(&mut self.rlp_buf);
1477 let result = self.rlp_node(prefix_set, &mut buffers, &mut temp_rlp_buf);
1478 self.rlp_buf = temp_rlp_buf;
1479
1480 result
1481 }
1482
1483 #[instrument(level = "trace", target = "trie::sparse::serial", skip_all, ret(level = "trace"))]
1498 pub fn rlp_node(
1499 &mut self,
1500 prefix_set: &mut PrefixSet,
1501 buffers: &mut RlpNodeBuffers,
1502 rlp_buf: &mut Vec<u8>,
1503 ) -> RlpNode {
1504 let _starting_path = buffers.path_stack.last().map(|item| item.path);
1505
1506 'main: while let Some(RlpNodePathStackItem { level, path, mut is_in_prefix_set }) =
1507 buffers.path_stack.pop()
1508 {
1509 let node = self.nodes.get_mut(&path).unwrap();
1510 trace!(
1511 target: "trie::sparse",
1512 ?_starting_path,
1513 ?level,
1514 ?path,
1515 ?is_in_prefix_set,
1516 ?node,
1517 "Popped node from path stack"
1518 );
1519
1520 let mut prefix_set_contains =
1524 |path: &Nibbles| *is_in_prefix_set.get_or_insert_with(|| prefix_set.contains(path));
1525
1526 let (rlp_node, node_type) = match node {
1527 SparseNode::Empty => (RlpNode::word_rlp(&EMPTY_ROOT_HASH), SparseNodeType::Empty),
1528 SparseNode::Hash(hash) => (RlpNode::word_rlp(hash), SparseNodeType::Hash),
1529 SparseNode::Leaf { key, hash } => {
1530 let mut path = path;
1531 path.extend(key);
1532 if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path)) {
1533 (RlpNode::word_rlp(&hash), SparseNodeType::Leaf)
1534 } else {
1535 let value = self.values.get(&path).unwrap();
1536 rlp_buf.clear();
1537 let rlp_node = LeafNodeRef { key, value }.rlp(rlp_buf);
1538 *hash = rlp_node.as_hash();
1539 (rlp_node, SparseNodeType::Leaf)
1540 }
1541 }
1542 SparseNode::Extension { key, hash, store_in_db_trie } => {
1543 let mut child_path = path;
1544 child_path.extend(key);
1545 if let Some((hash, store_in_db_trie)) =
1546 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
1547 {
1548 (
1549 RlpNode::word_rlp(&hash),
1550 SparseNodeType::Extension { store_in_db_trie: Some(store_in_db_trie) },
1551 )
1552 } else if buffers.rlp_node_stack.last().is_some_and(|e| e.path == child_path) {
1553 let RlpNodeStackItem {
1554 path: _,
1555 rlp_node: child,
1556 node_type: child_node_type,
1557 } = buffers.rlp_node_stack.pop().unwrap();
1558 rlp_buf.clear();
1559 let rlp_node = ExtensionNodeRef::new(key, &child).rlp(rlp_buf);
1560 *hash = rlp_node.as_hash();
1561
1562 let store_in_db_trie_value = child_node_type.store_in_db_trie();
1563
1564 trace!(
1565 target: "trie::sparse",
1566 ?path,
1567 ?child_path,
1568 ?child_node_type,
1569 "Extension node"
1570 );
1571
1572 *store_in_db_trie = store_in_db_trie_value;
1573
1574 (
1575 rlp_node,
1576 SparseNodeType::Extension {
1577 store_in_db_trie: store_in_db_trie_value,
1580 },
1581 )
1582 } else {
1583 buffers.path_stack.extend([
1585 RlpNodePathStackItem { level, path, is_in_prefix_set },
1586 RlpNodePathStackItem {
1587 level: level + 1,
1588 path: child_path,
1589 is_in_prefix_set: None,
1590 },
1591 ]);
1592 continue
1593 }
1594 }
1595 SparseNode::Branch { state_mask, hash, store_in_db_trie } => {
1596 if let Some((hash, store_in_db_trie)) =
1597 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
1598 {
1599 buffers.rlp_node_stack.push(RlpNodeStackItem {
1600 path,
1601 rlp_node: RlpNode::word_rlp(&hash),
1602 node_type: SparseNodeType::Branch {
1603 store_in_db_trie: Some(store_in_db_trie),
1604 },
1605 });
1606 continue
1607 }
1608 let retain_updates = self.updates.is_some() && prefix_set_contains(&path);
1609
1610 buffers.branch_child_buf.clear();
1611 for bit in CHILD_INDEX_RANGE.rev() {
1614 if state_mask.is_bit_set(bit) {
1615 let mut child = path;
1616 child.push_unchecked(bit);
1617 buffers.branch_child_buf.push(child);
1618 }
1619 }
1620
1621 buffers
1622 .branch_value_stack_buf
1623 .resize(buffers.branch_child_buf.len(), Default::default());
1624 let mut added_children = false;
1625
1626 let mut tree_mask = TrieMask::default();
1627 let mut hash_mask = TrieMask::default();
1628 let mut hashes = Vec::new();
1629
1630 let mut path_masks_storage = None;
1632 let mut path_masks = || {
1633 *path_masks_storage.get_or_insert_with(|| self.branch_node_masks.get(&path))
1634 };
1635
1636 for (i, child_path) in buffers.branch_child_buf.iter().enumerate() {
1637 if buffers.rlp_node_stack.last().is_some_and(|e| &e.path == child_path) {
1638 let RlpNodeStackItem {
1639 path: _,
1640 rlp_node: child,
1641 node_type: child_node_type,
1642 } = buffers.rlp_node_stack.pop().unwrap();
1643
1644 if retain_updates {
1646 let last_child_nibble = child_path.last().unwrap();
1648
1649 let should_set_tree_mask_bit = if let Some(store_in_db_trie) =
1651 child_node_type.store_in_db_trie()
1652 {
1653 store_in_db_trie
1656 } else {
1657 child_node_type.is_hash() &&
1659 path_masks().is_some_and(|masks| {
1660 masks.tree_mask.is_bit_set(last_child_nibble)
1661 })
1662 };
1663 if should_set_tree_mask_bit {
1664 tree_mask.set_bit(last_child_nibble);
1665 }
1666
1667 let hash = child.as_hash().filter(|_| {
1671 child_node_type.is_branch() ||
1672 (child_node_type.is_hash() &&
1673 path_masks().is_some_and(|masks| {
1674 masks.hash_mask.is_bit_set(last_child_nibble)
1675 }))
1676 });
1677 if let Some(hash) = hash {
1678 hash_mask.set_bit(last_child_nibble);
1679 hashes.push(hash);
1680 }
1681 }
1682
1683 let original_idx = buffers.branch_child_buf.len() - i - 1;
1687 buffers.branch_value_stack_buf[original_idx] = child;
1688 added_children = true;
1689 } else {
1690 debug_assert!(!added_children);
1691 buffers.path_stack.push(RlpNodePathStackItem {
1692 level,
1693 path,
1694 is_in_prefix_set,
1695 });
1696 buffers.path_stack.extend(buffers.branch_child_buf.drain(..).map(
1697 |path| RlpNodePathStackItem {
1698 level: level + 1,
1699 path,
1700 is_in_prefix_set: None,
1701 },
1702 ));
1703 continue 'main
1704 }
1705 }
1706
1707 trace!(
1708 target: "trie::sparse",
1709 ?path,
1710 ?tree_mask,
1711 ?hash_mask,
1712 "Branch node masks"
1713 );
1714
1715 rlp_buf.clear();
1716 let branch_node_ref =
1717 BranchNodeRef::new(&buffers.branch_value_stack_buf, *state_mask);
1718 let rlp_node = branch_node_ref.rlp(rlp_buf);
1719 *hash = rlp_node.as_hash();
1720
1721 let store_in_db_trie_value = if let Some(updates) =
1724 self.updates.as_mut().filter(|_| retain_updates && !path.is_empty())
1725 {
1726 let store_in_db_trie = !tree_mask.is_empty() || !hash_mask.is_empty();
1727 if store_in_db_trie {
1728 hashes.reverse();
1731 let branch_node = BranchNodeCompact::new(
1732 *state_mask,
1733 tree_mask,
1734 hash_mask,
1735 hashes,
1736 hash.filter(|_| path.is_empty()),
1737 );
1738 updates.updated_nodes.insert(path, branch_node);
1739 } else {
1740 let prev_had_masks = path_masks().is_some_and(|m| {
1742 !m.tree_mask.is_empty() || !m.hash_mask.is_empty()
1743 });
1744 updates.updated_nodes.remove(&path);
1745 if prev_had_masks {
1746 updates.removed_nodes.insert(path);
1748 }
1749 }
1750
1751 store_in_db_trie
1752 } else {
1753 false
1754 };
1755 *store_in_db_trie = Some(store_in_db_trie_value);
1756
1757 (
1758 rlp_node,
1759 SparseNodeType::Branch { store_in_db_trie: Some(store_in_db_trie_value) },
1760 )
1761 }
1762 };
1763
1764 trace!(
1765 target: "trie::sparse",
1766 ?_starting_path,
1767 ?level,
1768 ?path,
1769 ?node,
1770 ?node_type,
1771 ?is_in_prefix_set,
1772 "Added node to rlp node stack"
1773 );
1774
1775 buffers.rlp_node_stack.push(RlpNodeStackItem { path, rlp_node, node_type });
1776 }
1777
1778 debug_assert_eq!(buffers.rlp_node_stack.len(), 1);
1779 buffers.rlp_node_stack.pop().unwrap().rlp_node
1780 }
1781}
1782
1783#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1785pub enum SparseNodeType {
1786 Empty,
1788 Hash,
1790 Leaf,
1792 Extension {
1794 store_in_db_trie: Option<bool>,
1796 },
1797 Branch {
1799 store_in_db_trie: Option<bool>,
1801 },
1802}
1803
1804impl SparseNodeType {
1805 pub const fn is_hash(&self) -> bool {
1807 matches!(self, Self::Hash)
1808 }
1809
1810 pub const fn is_branch(&self) -> bool {
1812 matches!(self, Self::Branch { .. })
1813 }
1814
1815 pub const fn store_in_db_trie(&self) -> Option<bool> {
1817 match *self {
1818 Self::Extension { store_in_db_trie } | Self::Branch { store_in_db_trie } => {
1819 store_in_db_trie
1820 }
1821 _ => None,
1822 }
1823 }
1824}
1825
1826#[derive(Debug, Clone, PartialEq, Eq)]
1828pub enum SparseNode {
1829 Empty,
1831 Hash(B256),
1833 Leaf {
1835 key: Nibbles,
1837 hash: Option<B256>,
1840 },
1841 Extension {
1843 key: Nibbles,
1845 hash: Option<B256>,
1850 store_in_db_trie: Option<bool>,
1855 },
1856 Branch {
1858 state_mask: TrieMask,
1860 hash: Option<B256>,
1865 store_in_db_trie: Option<bool>,
1870 },
1871}
1872
1873impl SparseNode {
1874 pub fn from_node(node: TrieNode) -> Self {
1876 match node {
1877 TrieNode::EmptyRoot => Self::Empty,
1878 TrieNode::Leaf(leaf) => Self::new_leaf(leaf.key),
1879 TrieNode::Extension(ext) => Self::new_ext(ext.key),
1880 TrieNode::Branch(branch) => Self::new_branch(branch.state_mask),
1881 }
1882 }
1883
1884 pub const fn new_branch(state_mask: TrieMask) -> Self {
1886 Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1887 }
1888
1889 pub const fn new_split_branch(bit_a: u8, bit_b: u8) -> Self {
1891 let state_mask = TrieMask::new(
1892 (1u16 << bit_a) | (1u16 << bit_b),
1894 );
1895 Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1896 }
1897
1898 pub const fn new_ext(key: Nibbles) -> Self {
1900 Self::Extension { key, hash: None, store_in_db_trie: None }
1901 }
1902
1903 pub const fn new_leaf(key: Nibbles) -> Self {
1905 Self::Leaf { key, hash: None }
1906 }
1907
1908 pub const fn is_hash(&self) -> bool {
1910 matches!(self, Self::Hash(_))
1911 }
1912
1913 pub const fn hash(&self) -> Option<B256> {
1915 match self {
1916 Self::Empty => None,
1917 Self::Hash(hash) => Some(*hash),
1918 Self::Leaf { hash, .. } | Self::Extension { hash, .. } | Self::Branch { hash, .. } => {
1919 *hash
1920 }
1921 }
1922 }
1923
1924 #[cfg(any(test, feature = "test-utils"))]
1928 pub const fn set_hash(&mut self, new_hash: Option<B256>) {
1929 match self {
1930 Self::Empty | Self::Hash(_) => {
1931 }
1933 Self::Leaf { hash, .. } | Self::Extension { hash, .. } | Self::Branch { hash, .. } => {
1934 *hash = new_hash;
1935 }
1936 }
1937 }
1938}
1939
1940#[derive(Debug)]
1943struct RemovedSparseNode {
1944 path: Nibbles,
1946 node: SparseNode,
1948 unset_branch_nibble: Option<u8>,
1957}
1958
1959#[derive(Debug, Default)]
1963pub struct RlpNodeBuffers {
1964 path_stack: Vec<RlpNodePathStackItem>,
1966 rlp_node_stack: Vec<RlpNodeStackItem>,
1968 branch_child_buf: SmallVec<[Nibbles; 16]>,
1970 branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
1972}
1973
1974impl RlpNodeBuffers {
1975 fn new_with_root_path() -> Self {
1977 Self {
1978 path_stack: vec![RlpNodePathStackItem {
1979 level: 0,
1980 path: Nibbles::default(),
1981 is_in_prefix_set: None,
1982 }],
1983 rlp_node_stack: Vec::new(),
1984 branch_child_buf: SmallVec::<[Nibbles; 16]>::new_const(),
1985 branch_value_stack_buf: SmallVec::<[RlpNode; 16]>::new_const(),
1986 }
1987 }
1988}
1989
1990#[derive(Clone, PartialEq, Eq, Debug)]
1992pub struct RlpNodePathStackItem {
1993 pub level: usize,
1995 pub path: Nibbles,
1997 pub is_in_prefix_set: Option<bool>,
1999}
2000
2001#[derive(Clone, PartialEq, Eq, Debug)]
2003pub struct RlpNodeStackItem {
2004 pub path: Nibbles,
2006 pub rlp_node: RlpNode,
2008 pub node_type: SparseNodeType,
2010}
2011
2012impl SparseTrieUpdates {
2013 pub fn wiped() -> Self {
2015 Self { wiped: true, ..Default::default() }
2016 }
2017
2018 pub fn clear(&mut self) {
2022 self.updated_nodes.clear();
2023 self.removed_nodes.clear();
2024 self.wiped = false;
2025 }
2026
2027 pub fn extend(&mut self, other: Self) {
2029 self.updated_nodes.extend(other.updated_nodes);
2030 self.removed_nodes.extend(other.removed_nodes);
2031 self.wiped |= other.wiped;
2032 }
2033}
2034
2035#[cfg(test)]
2036mod find_leaf_tests {
2037 use super::*;
2038 use crate::provider::DefaultTrieNodeProvider;
2039 use alloy_rlp::Encodable;
2040 use assert_matches::assert_matches;
2041 use reth_primitives_traits::Account;
2042 use reth_trie_common::LeafNode;
2043
2044 fn encode_value(nonce: u64) -> Vec<u8> {
2046 let account = Account { nonce, ..Default::default() };
2047 let trie_account = account.into_trie_account(EMPTY_ROOT_HASH);
2048 let mut buf = Vec::new();
2049 trie_account.encode(&mut buf);
2050 buf
2051 }
2052
2053 const VALUE_A: fn() -> Vec<u8> = || encode_value(1);
2054 const VALUE_B: fn() -> Vec<u8> = || encode_value(2);
2055
2056 #[test]
2057 fn find_leaf_existing_leaf() {
2058 let provider = DefaultTrieNodeProvider;
2060 let mut sparse = SerialSparseTrie::default();
2061 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
2062 let value = b"test_value".to_vec();
2063
2064 sparse.update_leaf(path, value.clone(), &provider).unwrap();
2065
2066 let result = sparse.find_leaf(&path, None);
2068 assert_matches!(result, Ok(LeafLookup::Exists));
2069
2070 let result = sparse.find_leaf(&path, Some(&value));
2072 assert_matches!(result, Ok(LeafLookup::Exists));
2073 }
2074
2075 #[test]
2076 fn find_leaf_value_mismatch() {
2077 let provider = DefaultTrieNodeProvider;
2079 let mut sparse = SerialSparseTrie::default();
2080 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
2081 let value = b"test_value".to_vec();
2082 let wrong_value = b"wrong_value".to_vec();
2083
2084 sparse.update_leaf(path, value, &provider).unwrap();
2085
2086 let result = sparse.find_leaf(&path, Some(&wrong_value));
2088 assert_matches!(
2089 result,
2090 Err(LeafLookupError::ValueMismatch { path: p, expected: Some(e), actual: _a }) if p == path && e == wrong_value
2091 );
2092 }
2093
2094 #[test]
2095 fn find_leaf_not_found_empty_trie() {
2096 let sparse = SerialSparseTrie::default();
2098 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
2099
2100 let result = sparse.find_leaf(&path, None);
2102 assert_matches!(result, Ok(LeafLookup::NonExistent));
2103 }
2104
2105 #[test]
2106 fn find_leaf_empty_trie() {
2107 let sparse = SerialSparseTrie::default();
2108 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2109
2110 let result = sparse.find_leaf(&path, None);
2111 assert_matches!(result, Ok(LeafLookup::NonExistent));
2112 }
2113
2114 #[test]
2115 fn find_leaf_exists_no_value_check() {
2116 let provider = DefaultTrieNodeProvider;
2117 let mut sparse = SerialSparseTrie::default();
2118 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2119 sparse.update_leaf(path, VALUE_A(), &provider).unwrap();
2120
2121 let result = sparse.find_leaf(&path, None);
2122 assert_matches!(result, Ok(LeafLookup::Exists));
2123 }
2124
2125 #[test]
2126 fn find_leaf_exists_with_value_check_ok() {
2127 let provider = DefaultTrieNodeProvider;
2128 let mut sparse = SerialSparseTrie::default();
2129 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2130 let value = VALUE_A();
2131 sparse.update_leaf(path, value.clone(), &provider).unwrap();
2132
2133 let result = sparse.find_leaf(&path, Some(&value));
2134 assert_matches!(result, Ok(LeafLookup::Exists));
2135 }
2136
2137 #[test]
2138 fn find_leaf_exclusion_branch_divergence() {
2139 let provider = DefaultTrieNodeProvider;
2140 let mut sparse = SerialSparseTrie::default();
2141 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, VALUE_A(), &provider).unwrap();
2146 sparse.update_leaf(path2, VALUE_B(), &provider).unwrap();
2147
2148 let result = sparse.find_leaf(&search_path, None);
2149 assert_matches!(result, Ok(LeafLookup::NonExistent));
2150 }
2151
2152 #[test]
2153 fn find_leaf_exclusion_extension_divergence() {
2154 let provider = DefaultTrieNodeProvider;
2155 let mut sparse = SerialSparseTrie::default();
2156 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
2158 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]);
2160
2161 sparse.update_leaf(path1, VALUE_A(), &provider).unwrap();
2162
2163 let result = sparse.find_leaf(&search_path, None);
2164 assert_matches!(result, Ok(LeafLookup::NonExistent));
2165 }
2166
2167 #[test]
2168 fn find_leaf_exclusion_leaf_divergence() {
2169 let provider = DefaultTrieNodeProvider;
2170 let mut sparse = SerialSparseTrie::default();
2171 let existing_leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2172 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
2173
2174 sparse.update_leaf(existing_leaf_path, VALUE_A(), &provider).unwrap();
2175
2176 let result = sparse.find_leaf(&search_path, None);
2177 assert_matches!(result, Ok(LeafLookup::NonExistent));
2178 }
2179
2180 #[test]
2181 fn find_leaf_exclusion_path_ends_at_branch() {
2182 let provider = DefaultTrieNodeProvider;
2183 let mut sparse = SerialSparseTrie::default();
2184 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]);
2186 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2]); sparse.update_leaf(path1, VALUE_A(), &provider).unwrap();
2189 sparse.update_leaf(path2, VALUE_B(), &provider).unwrap();
2190
2191 let result = sparse.find_leaf(&search_path, None);
2192 assert_matches!(result, Ok(LeafLookup::NonExistent));
2193 }
2194
2195 #[test]
2196 fn find_leaf_error_trie_node_at_leaf_path() {
2197 let blinded_hash = B256::repeat_byte(0xBB);
2199 let leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2200
2201 let mut nodes = alloy_primitives::map::HashMap::default();
2202 nodes.insert(
2204 Nibbles::default(),
2205 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x1, 0x2])),
2206 ); nodes.insert(
2208 Nibbles::from_nibbles_unchecked([0x1, 0x2]),
2209 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x3])),
2210 ); nodes.insert(
2212 Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3]),
2213 SparseNode::new_branch(TrieMask::new(0b10000)),
2214 ); nodes.insert(leaf_path, SparseNode::Hash(blinded_hash)); let sparse = SerialSparseTrie {
2218 nodes,
2219 branch_node_masks: Default::default(),
2220 values: Default::default(),
2222 prefix_set: Default::default(),
2223 updates: None,
2224 rlp_buf: Vec::new(),
2225 };
2226
2227 let result = sparse.find_leaf(&leaf_path, None);
2228
2229 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2231 if path == leaf_path && hash == blinded_hash
2232 );
2233 }
2234
2235 #[test]
2236 fn find_leaf_error_trie_node() {
2237 let blinded_hash = B256::repeat_byte(0xAA);
2238 let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]);
2239 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2240
2241 let mut nodes = HashMap::default();
2242
2243 let state_mask = TrieMask::new(0b100010);
2246 nodes.insert(Nibbles::default(), SparseNode::new_branch(state_mask));
2247
2248 nodes.insert(path_to_blind, SparseNode::Hash(blinded_hash));
2249 let path_revealed = Nibbles::from_nibbles_unchecked([0x5]);
2250 let path_revealed_leaf = Nibbles::from_nibbles_unchecked([0x5, 0x6, 0x7, 0x8]);
2251 nodes.insert(
2252 path_revealed,
2253 SparseNode::new_leaf(Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8])),
2254 );
2255
2256 let mut values = HashMap::default();
2257 values.insert(path_revealed_leaf, VALUE_A());
2258
2259 let sparse = SerialSparseTrie {
2260 nodes,
2261 branch_node_masks: Default::default(),
2262 values,
2263 prefix_set: Default::default(),
2264 updates: None,
2265 rlp_buf: Vec::new(),
2266 };
2267
2268 let result = sparse.find_leaf(&search_path, None);
2269
2270 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2272 if path == path_to_blind && hash == blinded_hash
2273 );
2274 }
2275
2276 #[test]
2277 fn find_leaf_error_trie_node_via_reveal() {
2278 let blinded_hash = B256::repeat_byte(0xAA);
2279 let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]); let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); let revealed_leaf_prefix = Nibbles::from_nibbles_unchecked([0x5]);
2283 let revealed_leaf_suffix = Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8]);
2284 let revealed_leaf_full_path = Nibbles::from_nibbles_unchecked([0x5, 0x6, 0x7, 0x8]);
2285 let revealed_value = VALUE_A();
2286
2287 let rlp_node_child1 = RlpNode::word_rlp(&blinded_hash); let leaf_node_child5 = LeafNode::new(revealed_leaf_suffix, revealed_value.clone());
2291 let leaf_node_child5_rlp_buf = alloy_rlp::encode(&leaf_node_child5);
2292 let hash_of_child5 = keccak256(&leaf_node_child5_rlp_buf);
2293 let rlp_node_child5 = RlpNode::word_rlp(&hash_of_child5);
2294
2295 let root_branch_node = reth_trie_common::BranchNode::new(
2298 vec![rlp_node_child1, rlp_node_child5], TrieMask::new(0b100010), );
2301 let root_trie_node = TrieNode::Branch(root_branch_node);
2302
2303 let mut sparse = SerialSparseTrie::from_root(root_trie_node, TrieMasks::none(), false)
2306 .expect("Failed to create trie from root");
2307
2308 assert_matches!(sparse.nodes.get(&Nibbles::default()), Some(SparseNode::Branch { state_mask, .. }) if *state_mask == TrieMask::new(0b100010)); assert_matches!(sparse.nodes.get(&path_to_blind), Some(SparseNode::Hash(h)) if *h == blinded_hash );
2311 assert!(sparse.nodes.get(&revealed_leaf_prefix).unwrap().is_hash()); assert!(sparse.values.is_empty());
2313
2314 sparse
2316 .reveal_node(revealed_leaf_prefix, TrieNode::Leaf(leaf_node_child5), TrieMasks::none())
2317 .expect("Failed to reveal leaf node");
2318
2319 assert_matches!(sparse.nodes.get(&Nibbles::default()), Some(SparseNode::Branch { state_mask, .. }) if *state_mask == TrieMask::new(0b100010));
2321 assert_matches!(sparse.nodes.get(&path_to_blind), Some(SparseNode::Hash(h)) if *h == blinded_hash );
2322 assert_matches!(sparse.nodes.get(&revealed_leaf_prefix), Some(SparseNode::Leaf { key, .. }) if *key == revealed_leaf_suffix);
2323 assert_eq!(sparse.values.get(&revealed_leaf_full_path), Some(&revealed_value));
2324
2325 let result = sparse.find_leaf(&search_path, None);
2326
2327 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2330 if path == path_to_blind && hash == blinded_hash
2331 );
2332 }
2333}
2334
2335#[cfg(test)]
2336mod tests {
2337 use super::*;
2338 use crate::provider::DefaultTrieNodeProvider;
2339 use alloy_primitives::{map::B256Set, U256};
2340 use alloy_rlp::Encodable;
2341 use assert_matches::assert_matches;
2342 use itertools::Itertools;
2343 use prop::sample::SizeRange;
2344 use proptest::prelude::*;
2345 use proptest_arbitrary_interop::arb;
2346 use reth_primitives_traits::Account;
2347 use reth_provider::{test_utils::create_test_provider_factory, TrieWriter};
2348 use reth_trie::{
2349 hashed_cursor::{noop::NoopHashedCursor, HashedPostStateCursor},
2350 node_iter::{TrieElement, TrieNodeIter},
2351 trie_cursor::{noop::NoopAccountTrieCursor, TrieCursor, TrieCursorFactory},
2352 walker::TrieWalker,
2353 BranchNode, ExtensionNode, HashedPostState, LeafNode,
2354 };
2355 use reth_trie_common::{
2356 proof::{ProofNodes, ProofRetainer},
2357 updates::TrieUpdates,
2358 HashBuilder,
2359 };
2360 use reth_trie_db::DatabaseTrieCursorFactory;
2361 use std::collections::{BTreeMap, BTreeSet};
2362
2363 fn pad_nibbles_left(nibbles: Nibbles) -> Nibbles {
2365 let mut base =
2366 Nibbles::from_nibbles_unchecked(vec![0; B256::len_bytes() * 2 - nibbles.len()]);
2367 base.extend(&nibbles);
2368 base
2369 }
2370
2371 fn pad_nibbles_right(mut nibbles: Nibbles) -> Nibbles {
2373 nibbles.extend(&Nibbles::from_nibbles_unchecked(vec![
2374 0;
2375 B256::len_bytes() * 2 - nibbles.len()
2376 ]));
2377 nibbles
2378 }
2379
2380 fn run_hash_builder(
2385 state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
2386 trie_cursor: impl TrieCursor,
2387 destroyed_accounts: B256Set,
2388 proof_targets: impl IntoIterator<Item = Nibbles>,
2389 ) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>, HashMap<Nibbles, TrieMask>)
2390 {
2391 let mut account_rlp = Vec::new();
2392
2393 let mut hash_builder = HashBuilder::default()
2394 .with_updates(true)
2395 .with_proof_retainer(ProofRetainer::from_iter(proof_targets));
2396
2397 let mut prefix_set = PrefixSetMut::default();
2398 prefix_set.extend_keys(state.clone().into_iter().map(|(nibbles, _)| nibbles));
2399 prefix_set.extend_keys(destroyed_accounts.iter().map(Nibbles::unpack));
2400 let walker = TrieWalker::<_>::state_trie(trie_cursor, prefix_set.freeze())
2401 .with_deletions_retained(true);
2402 let hashed_post_state = HashedPostState::default()
2403 .with_accounts(state.into_iter().map(|(nibbles, account)| {
2404 (nibbles.pack().into_inner().unwrap().into(), Some(account))
2405 }))
2406 .into_sorted();
2407 let mut node_iter = TrieNodeIter::state_trie(
2408 walker,
2409 HashedPostStateCursor::new_account(
2410 NoopHashedCursor::<Account>::default(),
2411 &hashed_post_state,
2412 ),
2413 );
2414
2415 while let Some(node) = node_iter.try_next().unwrap() {
2416 match node {
2417 TrieElement::Branch(branch) => {
2418 hash_builder.add_branch(branch.key, branch.value, branch.children_are_in_trie);
2419 }
2420 TrieElement::Leaf(key, account) => {
2421 let account = account.into_trie_account(EMPTY_ROOT_HASH);
2422 account.encode(&mut account_rlp);
2423
2424 hash_builder.add_leaf(Nibbles::unpack(key), &account_rlp);
2425 account_rlp.clear();
2426 }
2427 }
2428 }
2429 let root = hash_builder.root();
2430 let proof_nodes = hash_builder.take_proof_nodes();
2431 let branch_node_hash_masks = hash_builder
2432 .updated_branch_nodes
2433 .clone()
2434 .unwrap_or_default()
2435 .iter()
2436 .map(|(path, node)| (*path, node.hash_mask))
2437 .collect();
2438 let branch_node_tree_masks = hash_builder
2439 .updated_branch_nodes
2440 .clone()
2441 .unwrap_or_default()
2442 .iter()
2443 .map(|(path, node)| (*path, node.tree_mask))
2444 .collect();
2445
2446 let mut trie_updates = TrieUpdates::default();
2447 let removed_keys = node_iter.walker.take_removed_keys();
2448 trie_updates.finalize(hash_builder, removed_keys, destroyed_accounts);
2449
2450 (root, trie_updates, proof_nodes, branch_node_hash_masks, branch_node_tree_masks)
2451 }
2452
2453 fn assert_eq_sparse_trie_proof_nodes(sparse_trie: &SerialSparseTrie, proof_nodes: ProofNodes) {
2455 let proof_nodes = proof_nodes
2456 .into_nodes_sorted()
2457 .into_iter()
2458 .map(|(path, node)| (path, TrieNode::decode(&mut node.as_ref()).unwrap()));
2459
2460 let sparse_nodes = sparse_trie.nodes.iter().sorted_by_key(|(path, _)| *path);
2461
2462 for ((proof_node_path, proof_node), (sparse_node_path, sparse_node)) in
2463 proof_nodes.zip(sparse_nodes)
2464 {
2465 assert_eq!(&proof_node_path, sparse_node_path);
2466
2467 let equals = match (&proof_node, &sparse_node) {
2468 (TrieNode::EmptyRoot, SparseNode::Empty) => true,
2470 (
2472 TrieNode::Branch(BranchNode { state_mask: proof_state_mask, .. }),
2473 SparseNode::Branch { state_mask: sparse_state_mask, .. },
2474 ) => proof_state_mask == sparse_state_mask,
2475 (
2477 TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
2478 SparseNode::Extension { key: sparse_key, .. },
2479 ) |
2480 (
2482 TrieNode::Leaf(LeafNode { key: proof_key, .. }),
2483 SparseNode::Leaf { key: sparse_key, .. },
2484 ) => proof_key == sparse_key,
2485 (_, SparseNode::Empty | SparseNode::Hash(_)) => continue,
2487 _ => false,
2488 };
2489 assert!(
2490 equals,
2491 "path: {proof_node_path:?}\nproof node: {proof_node:?}\nsparse node: {sparse_node:?}"
2492 );
2493 }
2494 }
2495
2496 #[test]
2497 fn sparse_trie_is_blind() {
2498 assert!(SparseTrie::<SerialSparseTrie>::blind().is_blind());
2499 assert!(!SparseTrie::<SerialSparseTrie>::revealed_empty().is_blind());
2500 }
2501
2502 #[test]
2503 fn sparse_trie_empty_update_one() {
2504 let key = Nibbles::unpack(B256::with_last_byte(42));
2505 let value = || Account::default();
2506 let value_encoded = || {
2507 let mut account_rlp = Vec::new();
2508 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2509 account_rlp
2510 };
2511
2512 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2513 run_hash_builder(
2514 [(key, value())],
2515 NoopAccountTrieCursor::default(),
2516 Default::default(),
2517 [key],
2518 );
2519
2520 let provider = DefaultTrieNodeProvider;
2521 let mut sparse = SerialSparseTrie::default().with_updates(true);
2522 sparse.update_leaf(key, value_encoded(), &provider).unwrap();
2523 let sparse_root = sparse.root();
2524 let sparse_updates = sparse.take_updates();
2525
2526 assert_eq!(sparse_root, hash_builder_root);
2527 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2528 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2529 }
2530
2531 #[test]
2532 fn sparse_trie_empty_update_multiple_lower_nibbles() {
2533 reth_tracing::init_test_tracing();
2534
2535 let paths = (0..=16).map(|b| Nibbles::unpack(B256::with_last_byte(b))).collect::<Vec<_>>();
2536 let value = || Account::default();
2537 let value_encoded = || {
2538 let mut account_rlp = Vec::new();
2539 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2540 account_rlp
2541 };
2542
2543 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2544 run_hash_builder(
2545 paths.iter().copied().zip(std::iter::repeat_with(value)),
2546 NoopAccountTrieCursor::default(),
2547 Default::default(),
2548 paths.clone(),
2549 );
2550
2551 let provider = DefaultTrieNodeProvider;
2552 let mut sparse = SerialSparseTrie::default().with_updates(true);
2553 for path in &paths {
2554 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
2555 }
2556 let sparse_root = sparse.root();
2557 let sparse_updates = sparse.take_updates();
2558
2559 assert_eq!(sparse_root, hash_builder_root);
2560 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2561 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2562 }
2563
2564 #[test]
2565 fn sparse_trie_empty_update_multiple_upper_nibbles() {
2566 let paths = (239..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
2567 let value = || Account::default();
2568 let value_encoded = || {
2569 let mut account_rlp = Vec::new();
2570 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2571 account_rlp
2572 };
2573
2574 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2575 run_hash_builder(
2576 paths.iter().copied().zip(std::iter::repeat_with(value)),
2577 NoopAccountTrieCursor::default(),
2578 Default::default(),
2579 paths.clone(),
2580 );
2581
2582 let provider = DefaultTrieNodeProvider;
2583 let mut sparse = SerialSparseTrie::default().with_updates(true);
2584 for path in &paths {
2585 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
2586 }
2587 let sparse_root = sparse.root();
2588 let sparse_updates = sparse.take_updates();
2589
2590 assert_eq!(sparse_root, hash_builder_root);
2591 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2592 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2593 }
2594
2595 #[test]
2596 fn sparse_trie_empty_update_multiple() {
2597 let paths = (0..=255)
2598 .map(|b| {
2599 Nibbles::unpack(if b % 2 == 0 {
2600 B256::repeat_byte(b)
2601 } else {
2602 B256::with_last_byte(b)
2603 })
2604 })
2605 .collect::<Vec<_>>();
2606 let value = || Account::default();
2607 let value_encoded = || {
2608 let mut account_rlp = Vec::new();
2609 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2610 account_rlp
2611 };
2612
2613 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2614 run_hash_builder(
2615 paths.iter().sorted_unstable().copied().zip(std::iter::repeat_with(value)),
2616 NoopAccountTrieCursor::default(),
2617 Default::default(),
2618 paths.clone(),
2619 );
2620
2621 let provider = DefaultTrieNodeProvider;
2622 let mut sparse = SerialSparseTrie::default().with_updates(true);
2623 for path in &paths {
2624 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
2625 }
2626 let sparse_root = sparse.root();
2627 let sparse_updates = sparse.take_updates();
2628
2629 assert_eq!(sparse_root, hash_builder_root);
2630 pretty_assertions::assert_eq!(
2631 BTreeMap::from_iter(sparse_updates.updated_nodes),
2632 BTreeMap::from_iter(hash_builder_updates.account_nodes)
2633 );
2634 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2635 }
2636
2637 #[test]
2638 fn sparse_trie_empty_update_repeated() {
2639 let paths = (0..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
2640 let old_value = Account { nonce: 1, ..Default::default() };
2641 let old_value_encoded = {
2642 let mut account_rlp = Vec::new();
2643 old_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2644 account_rlp
2645 };
2646 let new_value = Account { nonce: 2, ..Default::default() };
2647 let new_value_encoded = {
2648 let mut account_rlp = Vec::new();
2649 new_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2650 account_rlp
2651 };
2652
2653 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2654 run_hash_builder(
2655 paths.iter().copied().zip(std::iter::repeat_with(|| old_value)),
2656 NoopAccountTrieCursor::default(),
2657 Default::default(),
2658 paths.clone(),
2659 );
2660
2661 let provider = DefaultTrieNodeProvider;
2662 let mut sparse = SerialSparseTrie::default().with_updates(true);
2663 for path in &paths {
2664 sparse.update_leaf(*path, old_value_encoded.clone(), &provider).unwrap();
2665 }
2666 let sparse_root = sparse.root();
2667 let sparse_updates = sparse.updates_ref();
2668
2669 assert_eq!(sparse_root, hash_builder_root);
2670 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2671 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2672
2673 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2674 run_hash_builder(
2675 paths.iter().copied().zip(std::iter::repeat_with(|| new_value)),
2676 NoopAccountTrieCursor::default(),
2677 Default::default(),
2678 paths.clone(),
2679 );
2680
2681 for path in &paths {
2682 sparse.update_leaf(*path, new_value_encoded.clone(), &provider).unwrap();
2683 }
2684 let sparse_root = sparse.root();
2685 let sparse_updates = sparse.take_updates();
2686
2687 assert_eq!(sparse_root, hash_builder_root);
2688 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2689 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2690 }
2691
2692 #[test]
2693 fn sparse_trie_remove_leaf() {
2694 reth_tracing::init_test_tracing();
2695
2696 let provider = DefaultTrieNodeProvider;
2697 let mut sparse = SerialSparseTrie::default();
2698
2699 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
2700
2701 sparse
2702 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
2703 .unwrap();
2704 sparse
2705 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
2706 .unwrap();
2707 sparse
2708 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
2709 .unwrap();
2710 sparse
2711 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
2712 .unwrap();
2713 sparse
2714 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
2715 .unwrap();
2716 sparse
2717 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
2718 .unwrap();
2719
2720 pretty_assertions::assert_eq!(
2733 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2734 BTreeMap::from_iter([
2735 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2736 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1101.into())),
2737 (
2738 Nibbles::from_nibbles([0x5, 0x0]),
2739 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
2740 ),
2741 (
2742 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
2743 SparseNode::new_branch(0b1010.into())
2744 ),
2745 (
2746 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
2747 SparseNode::new_leaf(Nibbles::default())
2748 ),
2749 (
2750 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
2751 SparseNode::new_leaf(Nibbles::default())
2752 ),
2753 (
2754 Nibbles::from_nibbles([0x5, 0x2]),
2755 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x1, 0x3]))
2756 ),
2757 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2758 (
2759 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2760 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2761 ),
2762 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2763 (
2764 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2765 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2766 ),
2767 (
2768 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2769 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2770 )
2771 ])
2772 );
2773
2774 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), &provider).unwrap();
2775
2776 pretty_assertions::assert_eq!(
2788 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2789 BTreeMap::from_iter([
2790 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2791 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2792 (
2793 Nibbles::from_nibbles([0x5, 0x0]),
2794 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
2795 ),
2796 (
2797 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
2798 SparseNode::new_branch(0b1010.into())
2799 ),
2800 (
2801 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
2802 SparseNode::new_leaf(Nibbles::default())
2803 ),
2804 (
2805 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
2806 SparseNode::new_leaf(Nibbles::default())
2807 ),
2808 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2809 (
2810 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2811 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2812 ),
2813 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2814 (
2815 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2816 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2817 ),
2818 (
2819 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2820 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2821 )
2822 ])
2823 );
2824
2825 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), &provider).unwrap();
2826
2827 pretty_assertions::assert_eq!(
2836 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2837 BTreeMap::from_iter([
2838 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2839 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2840 (
2841 Nibbles::from_nibbles([0x5, 0x0]),
2842 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2843 ),
2844 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2845 (
2846 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2847 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2848 ),
2849 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2850 (
2851 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2852 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2853 ),
2854 (
2855 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2856 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2857 )
2858 ])
2859 );
2860
2861 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), &provider).unwrap();
2862
2863 pretty_assertions::assert_eq!(
2870 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2871 BTreeMap::from_iter([
2872 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2873 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2874 (
2875 Nibbles::from_nibbles([0x5, 0x0]),
2876 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2877 ),
2878 (
2879 Nibbles::from_nibbles([0x5, 0x3]),
2880 SparseNode::new_ext(Nibbles::from_nibbles([0x3]))
2881 ),
2882 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2883 (
2884 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2885 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2886 ),
2887 (
2888 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2889 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2890 )
2891 ])
2892 );
2893
2894 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), &provider).unwrap();
2895
2896 pretty_assertions::assert_eq!(
2901 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2902 BTreeMap::from_iter([
2903 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2904 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2905 (
2906 Nibbles::from_nibbles([0x5, 0x0]),
2907 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2908 ),
2909 (
2910 Nibbles::from_nibbles([0x5, 0x3]),
2911 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x0, 0x2]))
2912 ),
2913 ])
2914 );
2915
2916 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), &provider).unwrap();
2917
2918 pretty_assertions::assert_eq!(
2920 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2921 BTreeMap::from_iter([(
2922 Nibbles::default(),
2923 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]))
2924 ),])
2925 );
2926
2927 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), &provider).unwrap();
2928
2929 pretty_assertions::assert_eq!(
2931 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2932 BTreeMap::from_iter([(Nibbles::default(), SparseNode::Empty)])
2933 );
2934 }
2935
2936 #[test]
2937 fn sparse_trie_remove_leaf_blinded() {
2938 let leaf = LeafNode::new(
2939 Nibbles::default(),
2940 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
2941 );
2942 let branch = TrieNode::Branch(BranchNode::new(
2943 vec![
2944 RlpNode::word_rlp(&B256::repeat_byte(1)),
2945 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
2946 ],
2947 TrieMask::new(0b11),
2948 ));
2949
2950 let provider = DefaultTrieNodeProvider;
2951 let mut sparse = SerialSparseTrie::from_root(
2952 branch.clone(),
2953 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
2954 false,
2955 )
2956 .unwrap();
2957
2958 sparse
2964 .reveal_node(
2965 Nibbles::default(),
2966 branch,
2967 TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
2968 )
2969 .unwrap();
2970 sparse
2971 .reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), TrieMasks::none())
2972 .unwrap();
2973
2974 assert_matches!(
2976 sparse.remove_leaf(&Nibbles::from_nibbles([0x0]), &provider).map_err(|e| e.into_kind()),
2977 Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
2978 );
2979 }
2980
2981 #[test]
2982 fn sparse_trie_remove_leaf_non_existent() {
2983 let leaf = LeafNode::new(
2984 Nibbles::default(),
2985 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
2986 );
2987 let branch = TrieNode::Branch(BranchNode::new(
2988 vec![
2989 RlpNode::word_rlp(&B256::repeat_byte(1)),
2990 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
2991 ],
2992 TrieMask::new(0b11),
2993 ));
2994
2995 let provider = DefaultTrieNodeProvider;
2996 let mut sparse = SerialSparseTrie::from_root(
2997 branch.clone(),
2998 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
2999 false,
3000 )
3001 .unwrap();
3002
3003 sparse
3009 .reveal_node(
3010 Nibbles::default(),
3011 branch,
3012 TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
3013 )
3014 .unwrap();
3015 sparse
3016 .reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), TrieMasks::none())
3017 .unwrap();
3018
3019 let sparse_old = sparse.clone();
3021 assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2]), &provider), Ok(()));
3022 assert_eq!(sparse, sparse_old);
3023 }
3024
3025 #[test]
3026 fn sparse_trie_fuzz() {
3027 const KEY_NIBBLES_LEN: usize = 3;
3031
3032 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
3033 {
3034 let mut state = BTreeMap::default();
3035 let default_provider = DefaultTrieNodeProvider;
3036 let provider_factory = create_test_provider_factory();
3037 let mut sparse = SerialSparseTrie::default().with_updates(true);
3038
3039 for (update, keys_to_delete) in updates {
3040 for (key, account) in update.clone() {
3042 let account = account.into_trie_account(EMPTY_ROOT_HASH);
3043 let mut account_rlp = Vec::new();
3044 account.encode(&mut account_rlp);
3045 sparse.update_leaf(key, account_rlp, &default_provider).unwrap();
3046 }
3047 let mut updated_sparse = sparse.clone();
3051 let sparse_root = updated_sparse.root();
3052 let sparse_updates = updated_sparse.take_updates();
3053
3054 state.extend(update);
3056 let provider = provider_factory.provider().unwrap();
3057 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
3058 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
3059 run_hash_builder(
3060 state.clone(),
3061 trie_cursor.account_trie_cursor().unwrap(),
3062 Default::default(),
3063 state.keys().copied(),
3064 );
3065
3066 let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
3068
3069 let provider_rw = provider_factory.provider_rw().unwrap();
3071 provider_rw.write_trie_updates(hash_builder_updates).unwrap();
3072 provider_rw.commit().unwrap();
3073
3074 assert_eq!(sparse_root, hash_builder_root);
3076 pretty_assertions::assert_eq!(
3078 BTreeMap::from_iter(sparse_updates.updated_nodes),
3079 BTreeMap::from_iter(hash_builder_account_nodes)
3080 );
3081 assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
3083
3084 for key in &keys_to_delete {
3087 state.remove(key).unwrap();
3088 sparse.remove_leaf(key, &default_provider).unwrap();
3089 }
3090
3091 let mut updated_sparse = sparse.clone();
3095 let sparse_root = updated_sparse.root();
3096 let sparse_updates = updated_sparse.take_updates();
3097
3098 let provider = provider_factory.provider().unwrap();
3099 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
3100 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
3101 run_hash_builder(
3102 state.clone(),
3103 trie_cursor.account_trie_cursor().unwrap(),
3104 keys_to_delete
3105 .iter()
3106 .map(|nibbles| B256::from_slice(&nibbles.pack()))
3107 .collect(),
3108 state.keys().copied(),
3109 );
3110
3111 let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
3113
3114 let provider_rw = provider_factory.provider_rw().unwrap();
3116 provider_rw.write_trie_updates(hash_builder_updates).unwrap();
3117 provider_rw.commit().unwrap();
3118
3119 assert_eq!(sparse_root, hash_builder_root);
3121 pretty_assertions::assert_eq!(
3123 BTreeMap::from_iter(sparse_updates.updated_nodes),
3124 BTreeMap::from_iter(hash_builder_account_nodes)
3125 );
3126 assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
3128 }
3129 }
3130 }
3131
3132 fn transform_updates(
3133 updates: Vec<BTreeMap<Nibbles, Account>>,
3134 mut rng: impl rand::Rng,
3135 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
3136 let mut keys = BTreeSet::new();
3137 updates
3138 .into_iter()
3139 .map(|update| {
3140 keys.extend(update.keys().copied());
3141
3142 let keys_to_delete_len = update.len() / 2;
3143 let keys_to_delete = (0..keys_to_delete_len)
3144 .map(|_| {
3145 let key =
3146 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
3147 keys.take(&key).unwrap()
3148 })
3149 .collect();
3150
3151 (update, keys_to_delete)
3152 })
3153 .collect::<Vec<_>>()
3154 }
3155
3156 proptest!(ProptestConfig::with_cases(10), |(
3157 updates in proptest::collection::vec(
3158 proptest::collection::btree_map(
3159 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
3160 arb::<Account>(),
3161 1..50,
3162 ),
3163 1..50,
3164 ).prop_perturb(transform_updates)
3165 )| {
3166 test(updates)
3167 });
3168 }
3169
3170 #[test]
3182 fn sparse_trie_reveal_node_1() {
3183 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00]));
3184 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01]));
3185 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x02]));
3186 let value = || Account::default();
3187 let value_encoded = || {
3188 let mut account_rlp = Vec::new();
3189 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3190 account_rlp
3191 };
3192
3193 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3195 run_hash_builder(
3196 [(key1(), value()), (key3(), value())],
3197 NoopAccountTrieCursor::default(),
3198 Default::default(),
3199 [Nibbles::default()],
3200 );
3201
3202 let provider = DefaultTrieNodeProvider;
3203 let mut sparse = SerialSparseTrie::from_root(
3204 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3205 TrieMasks {
3206 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3207 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3208 },
3209 false,
3210 )
3211 .unwrap();
3212
3213 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3215 run_hash_builder(
3216 [(key1(), value()), (key3(), value())],
3217 NoopAccountTrieCursor::default(),
3218 Default::default(),
3219 [key1()],
3220 );
3221 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3222 let hash_mask = branch_node_hash_masks.get(&path).copied();
3223 let tree_mask = branch_node_tree_masks.get(&path).copied();
3224 sparse
3225 .reveal_node(
3226 path,
3227 TrieNode::decode(&mut &node[..]).unwrap(),
3228 TrieMasks { hash_mask, tree_mask },
3229 )
3230 .unwrap();
3231 }
3232
3233 assert_eq!(
3235 sparse.nodes.get(&Nibbles::default()),
3236 Some(&SparseNode::new_branch(0b101.into()))
3237 );
3238
3239 sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
3241
3242 assert_eq!(
3244 sparse.nodes.get(&Nibbles::default()),
3245 Some(&SparseNode::new_branch(0b111.into()))
3246 );
3247
3248 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3250 run_hash_builder(
3251 [(key1(), value()), (key3(), value())],
3252 NoopAccountTrieCursor::default(),
3253 Default::default(),
3254 [key3()],
3255 );
3256 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3257 let hash_mask = branch_node_hash_masks.get(&path).copied();
3258 let tree_mask = branch_node_tree_masks.get(&path).copied();
3259 sparse
3260 .reveal_node(
3261 path,
3262 TrieNode::decode(&mut &node[..]).unwrap(),
3263 TrieMasks { hash_mask, tree_mask },
3264 )
3265 .unwrap();
3266 }
3267
3268 assert_eq!(
3270 sparse.nodes.get(&Nibbles::default()),
3271 Some(&SparseNode::new_branch(0b111.into()))
3272 );
3273
3274 let (_, _, hash_builder_proof_nodes, _, _) = run_hash_builder(
3277 [(key1(), value()), (key2(), value()), (key3(), value())],
3278 NoopAccountTrieCursor::default(),
3279 Default::default(),
3280 [key1(), key2(), key3()],
3281 );
3282
3283 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
3284 }
3285
3286 #[test]
3297 fn sparse_trie_reveal_node_2() {
3298 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x00]));
3299 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x01]));
3300 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x02]));
3301 let value = || Account::default();
3302
3303 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3305 run_hash_builder(
3306 [(key1(), value()), (key2(), value()), (key3(), value())],
3307 NoopAccountTrieCursor::default(),
3308 Default::default(),
3309 [Nibbles::default()],
3310 );
3311
3312 let provider = DefaultTrieNodeProvider;
3313 let mut sparse = SerialSparseTrie::from_root(
3314 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3315 TrieMasks {
3316 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3317 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3318 },
3319 false,
3320 )
3321 .unwrap();
3322
3323 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3326 run_hash_builder(
3327 [(key1(), value()), (key2(), value()), (key3(), value())],
3328 NoopAccountTrieCursor::default(),
3329 Default::default(),
3330 [key1(), Nibbles::from_nibbles_unchecked([0x01])],
3331 );
3332 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3333 let hash_mask = branch_node_hash_masks.get(&path).copied();
3334 let tree_mask = branch_node_tree_masks.get(&path).copied();
3335 sparse
3336 .reveal_node(
3337 path,
3338 TrieNode::decode(&mut &node[..]).unwrap(),
3339 TrieMasks { hash_mask, tree_mask },
3340 )
3341 .unwrap();
3342 }
3343
3344 assert_eq!(
3346 sparse.nodes.get(&Nibbles::default()),
3347 Some(&SparseNode::new_branch(0b11.into()))
3348 );
3349
3350 sparse.remove_leaf(&key1(), &provider).unwrap();
3352
3353 assert_eq!(
3355 sparse.nodes.get(&Nibbles::default()),
3356 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3357 );
3358
3359 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3361 run_hash_builder(
3362 [(key1(), value()), (key2(), value()), (key3(), value())],
3363 NoopAccountTrieCursor::default(),
3364 Default::default(),
3365 [key2()],
3366 );
3367 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3368 let hash_mask = branch_node_hash_masks.get(&path).copied();
3369 let tree_mask = branch_node_tree_masks.get(&path).copied();
3370 sparse
3371 .reveal_node(
3372 path,
3373 TrieNode::decode(&mut &node[..]).unwrap(),
3374 TrieMasks { hash_mask, tree_mask },
3375 )
3376 .unwrap();
3377 }
3378
3379 assert_eq!(
3381 sparse.nodes.get(&Nibbles::default()),
3382 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3383 );
3384 }
3385
3386 #[test]
3395 fn sparse_trie_reveal_node_3() {
3396 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x01]));
3397 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x02]));
3398 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x00]));
3399 let value = || Account::default();
3400 let value_encoded = || {
3401 let mut account_rlp = Vec::new();
3402 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3403 account_rlp
3404 };
3405
3406 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3408 run_hash_builder(
3409 [(key1(), value()), (key2(), value())],
3410 NoopAccountTrieCursor::default(),
3411 Default::default(),
3412 [Nibbles::default()],
3413 );
3414
3415 let provider = DefaultTrieNodeProvider;
3416 let mut sparse = SerialSparseTrie::from_root(
3417 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3418 TrieMasks {
3419 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3420 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3421 },
3422 false,
3423 )
3424 .unwrap();
3425
3426 assert_matches!(
3428 sparse.nodes.get(&Nibbles::default()),
3429 Some(SparseNode::Extension { key, hash: None, store_in_db_trie: None }) if *key == Nibbles::from_nibbles([0x00])
3430 );
3431
3432 sparse.update_leaf(key3(), value_encoded(), &provider).unwrap();
3434
3435 assert_matches!(
3437 sparse.nodes.get(&Nibbles::default()),
3438 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
3439 );
3440
3441 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3443 run_hash_builder(
3444 [(key1(), value()), (key2(), value())],
3445 NoopAccountTrieCursor::default(),
3446 Default::default(),
3447 [key1()],
3448 );
3449 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3450 let hash_mask = branch_node_hash_masks.get(&path).copied();
3451 let tree_mask = branch_node_tree_masks.get(&path).copied();
3452 sparse
3453 .reveal_node(
3454 path,
3455 TrieNode::decode(&mut &node[..]).unwrap(),
3456 TrieMasks { hash_mask, tree_mask },
3457 )
3458 .unwrap();
3459 }
3460
3461 assert_matches!(
3463 sparse.nodes.get(&Nibbles::default()),
3464 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
3465 );
3466 }
3467
3468 #[test]
3469 fn sparse_trie_get_changed_nodes_at_depth() {
3470 let provider = DefaultTrieNodeProvider;
3471 let mut sparse = SerialSparseTrie::default();
3472
3473 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3474
3475 sparse
3488 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3489 .unwrap();
3490 sparse
3491 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3492 .unwrap();
3493 sparse
3494 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3495 .unwrap();
3496 sparse
3497 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
3498 .unwrap();
3499 sparse
3500 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
3501 .unwrap();
3502 sparse
3503 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
3504 .unwrap();
3505
3506 assert_eq!(
3507 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 0),
3508 (vec![(0, Nibbles::default())], PrefixSetMut::default())
3509 );
3510 assert_eq!(
3511 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 1),
3512 (vec![(1, Nibbles::from_nibbles_unchecked([0x5]))], [Nibbles::default()].into())
3513 );
3514 assert_eq!(
3515 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 2),
3516 (
3517 vec![
3518 (2, Nibbles::from_nibbles_unchecked([0x5, 0x0])),
3519 (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3520 (2, Nibbles::from_nibbles_unchecked([0x5, 0x3]))
3521 ],
3522 [Nibbles::default(), Nibbles::from_nibbles_unchecked([0x5])].into()
3523 )
3524 );
3525 assert_eq!(
3526 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 3),
3527 (
3528 vec![
3529 (3, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3])),
3530 (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3531 (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1])),
3532 (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3]))
3533 ],
3534 [
3535 Nibbles::default(),
3536 Nibbles::from_nibbles_unchecked([0x5]),
3537 Nibbles::from_nibbles_unchecked([0x5, 0x0]),
3538 Nibbles::from_nibbles_unchecked([0x5, 0x3])
3539 ]
3540 .into()
3541 )
3542 );
3543 assert_eq!(
3544 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 4),
3545 (
3546 vec![
3547 (4, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x1])),
3548 (4, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x3])),
3549 (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3550 (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1])),
3551 (4, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x0])),
3552 (4, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x2]))
3553 ],
3554 [
3555 Nibbles::default(),
3556 Nibbles::from_nibbles_unchecked([0x5]),
3557 Nibbles::from_nibbles_unchecked([0x5, 0x0]),
3558 Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3]),
3559 Nibbles::from_nibbles_unchecked([0x5, 0x3]),
3560 Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3])
3561 ]
3562 .into()
3563 )
3564 );
3565 }
3566
3567 #[test]
3568 fn hash_builder_branch_hash_mask() {
3569 let key1 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x00]));
3570 let key2 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x01]));
3571 let value = || Account { bytecode_hash: Some(B256::repeat_byte(1)), ..Default::default() };
3572 let value_encoded = || {
3573 let mut account_rlp = Vec::new();
3574 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3575 account_rlp
3576 };
3577
3578 let (hash_builder_root, hash_builder_updates, _, _, _) = run_hash_builder(
3579 [(key1(), value()), (key2(), value())],
3580 NoopAccountTrieCursor::default(),
3581 Default::default(),
3582 [Nibbles::default()],
3583 );
3584
3585 let provider = DefaultTrieNodeProvider;
3586 let mut sparse = SerialSparseTrie::default();
3587 sparse.update_leaf(key1(), value_encoded(), &provider).unwrap();
3588 sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
3589 let sparse_root = sparse.root();
3590 let sparse_updates = sparse.take_updates();
3591
3592 assert_eq!(sparse_root, hash_builder_root);
3593 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
3594 }
3595
3596 #[test]
3597 fn sparse_trie_wipe() {
3598 let provider = DefaultTrieNodeProvider;
3599 let mut sparse = SerialSparseTrie::default().with_updates(true);
3600
3601 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3602
3603 sparse
3616 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3617 .unwrap();
3618 sparse
3619 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3620 .unwrap();
3621 sparse
3622 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3623 .unwrap();
3624 sparse
3625 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
3626 .unwrap();
3627 sparse
3628 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
3629 .unwrap();
3630 sparse
3631 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
3632 .unwrap();
3633
3634 sparse.wipe();
3635
3636 assert_matches!(
3637 &sparse.updates,
3638 Some(SparseTrieUpdates{ updated_nodes, removed_nodes, wiped })
3639 if updated_nodes.is_empty() && removed_nodes.is_empty() && *wiped
3640 );
3641 assert_eq!(sparse.root(), EMPTY_ROOT_HASH);
3642 }
3643
3644 #[test]
3645 fn sparse_trie_clear() {
3646 let provider = DefaultTrieNodeProvider;
3649 let mut sparse = SerialSparseTrie::default();
3650 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3651 sparse
3652 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3653 .unwrap();
3654 sparse
3655 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3656 .unwrap();
3657 sparse
3658 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3659 .unwrap();
3660 sparse
3661 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value, &provider)
3662 .unwrap();
3663
3664 sparse.clear();
3665
3666 let empty_trie = SerialSparseTrie::default();
3667 assert_eq!(empty_trie, sparse);
3668 }
3669
3670 #[test]
3671 fn sparse_trie_display() {
3672 let provider = DefaultTrieNodeProvider;
3673 let mut sparse = SerialSparseTrie::default();
3674
3675 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3676
3677 sparse
3690 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3691 .unwrap();
3692 sparse
3693 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3694 .unwrap();
3695 sparse
3696 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3697 .unwrap();
3698 sparse
3699 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
3700 .unwrap();
3701 sparse
3702 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
3703 .unwrap();
3704 sparse
3705 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
3706 .unwrap();
3707
3708 let normal_printed = format!("{sparse}");
3709 let expected = "\
3710Root -> Extension { key: Nibbles(0x5), hash: None, store_in_db_trie: None }
37115 -> Branch { state_mask: TrieMask(0000000000001101), hash: None, store_in_db_trie: None }
371250 -> Extension { key: Nibbles(0x23), hash: None, store_in_db_trie: None }
37135023 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
371450231 -> Leaf { key: Nibbles(0x), hash: None }
371550233 -> Leaf { key: Nibbles(0x), hash: None }
371652013 -> Leaf { key: Nibbles(0x013), hash: None }
371753 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
371853102 -> Leaf { key: Nibbles(0x02), hash: None }
3719533 -> Branch { state_mask: TrieMask(0000000000000101), hash: None, store_in_db_trie: None }
372053302 -> Leaf { key: Nibbles(0x2), hash: None }
372153320 -> Leaf { key: Nibbles(0x0), hash: None }
3722";
3723 assert_eq!(normal_printed, expected);
3724
3725 let alternate_printed = format!("{sparse:#}");
3726 let expected = "\
3727Root -> Extension { key: Nibbles(0x5), hash: None, store_in_db_trie: None }
3728 5 -> Branch { state_mask: TrieMask(0000000000001101), hash: None, store_in_db_trie: None }
3729 50 -> Extension { key: Nibbles(0x23), hash: None, store_in_db_trie: None }
3730 5023 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
3731 50231 -> Leaf { key: Nibbles(0x), hash: None }
3732 50233 -> Leaf { key: Nibbles(0x), hash: None }
3733 52013 -> Leaf { key: Nibbles(0x013), hash: None }
3734 53 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
3735 53102 -> Leaf { key: Nibbles(0x02), hash: None }
3736 533 -> Branch { state_mask: TrieMask(0000000000000101), hash: None, store_in_db_trie: None }
3737 53302 -> Leaf { key: Nibbles(0x2), hash: None }
3738 53320 -> Leaf { key: Nibbles(0x0), hash: None }
3739";
3740
3741 assert_eq!(alternate_printed, expected);
3742 }
3743}