1use crate::{
2 provider::{RevealedNode, TrieNodeProvider},
3 LeafLookup, LeafLookupError, RevealedSparseNode, SparseTrieInterface, SparseTrieUpdates,
4 TrieMasks,
5};
6use alloc::{
7 borrow::Cow,
8 boxed::Box,
9 fmt,
10 string::{String, ToString},
11 vec,
12 vec::Vec,
13};
14use alloy_primitives::{
15 hex, keccak256,
16 map::{Entry, HashMap, HashSet},
17 B256,
18};
19use alloy_rlp::Decodable;
20use reth_execution_errors::{SparseTrieErrorKind, SparseTrieResult};
21use reth_trie_common::{
22 prefix_set::{PrefixSet, PrefixSetMut},
23 BranchNodeCompact, BranchNodeRef, ExtensionNodeRef, LeafNodeRef, Nibbles, RlpNode, TrieMask,
24 TrieNode, CHILD_INDEX_RANGE, 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_tree_masks: HashMap<Nibbles, TrieMask>,
304 branch_node_hash_masks: HashMap<Nibbles, TrieMask>,
306 values: HashMap<Nibbles, Vec<u8>>,
309 prefix_set: PrefixSetMut,
312 updates: Option<SparseTrieUpdates>,
314 rlp_buf: Vec<u8>,
316}
317
318impl fmt::Debug for SerialSparseTrie {
319 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
320 f.debug_struct("SerialSparseTrie")
321 .field("nodes", &self.nodes)
322 .field("branch_tree_masks", &self.branch_node_tree_masks)
323 .field("branch_hash_masks", &self.branch_node_hash_masks)
324 .field("values", &self.values)
325 .field("prefix_set", &self.prefix_set)
326 .field("updates", &self.updates)
327 .field("rlp_buf", &hex::encode(&self.rlp_buf))
328 .finish_non_exhaustive()
329 }
330}
331
332fn encode_nibbles(nibbles: &Nibbles) -> String {
334 let encoded = hex::encode(nibbles.pack());
335 encoded[..nibbles.len()].to_string()
336}
337
338impl fmt::Display for SerialSparseTrie {
339 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340 let mut stack = Vec::new();
342 let mut visited = HashSet::new();
343
344 const INDENT: &str = " ";
346
347 stack.push((Nibbles::default(), self.nodes_ref().get(&Nibbles::default()).unwrap(), 0));
349
350 while let Some((path, node, depth)) = stack.pop() {
351 if !visited.insert(path) {
352 continue;
353 }
354
355 if f.alternate() {
357 write!(f, "{}", INDENT.repeat(depth))?;
358 }
359
360 let packed_path = if depth == 0 { String::from("Root") } else { encode_nibbles(&path) };
361
362 match node {
363 SparseNode::Empty | SparseNode::Hash(_) => {
364 writeln!(f, "{packed_path} -> {node:?}")?;
365 }
366 SparseNode::Leaf { key, .. } => {
367 let mut full_path = path;
369 full_path.extend(key);
370 let packed_path = encode_nibbles(&full_path);
371
372 writeln!(f, "{packed_path} -> {node:?}")?;
373 }
374 SparseNode::Extension { key, .. } => {
375 writeln!(f, "{packed_path} -> {node:?}")?;
376
377 let mut child_path = path;
379 child_path.extend(key);
380 if let Some(child_node) = self.nodes_ref().get(&child_path) {
381 stack.push((child_path, child_node, depth + 1));
382 }
383 }
384 SparseNode::Branch { state_mask, .. } => {
385 writeln!(f, "{packed_path} -> {node:?}")?;
386
387 for i in CHILD_INDEX_RANGE.rev() {
388 if state_mask.is_bit_set(i) {
389 let mut child_path = path;
390 child_path.push_unchecked(i);
391 if let Some(child_node) = self.nodes_ref().get(&child_path) {
392 stack.push((child_path, child_node, depth + 1));
393 }
394 }
395 }
396 }
397 }
398 }
399
400 Ok(())
401 }
402}
403
404impl Default for SerialSparseTrie {
405 fn default() -> Self {
406 Self {
407 nodes: HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]),
408 branch_node_tree_masks: HashMap::default(),
409 branch_node_hash_masks: HashMap::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 let Some(tree_mask) = masks.tree_mask {
461 self.branch_node_tree_masks.insert(path, tree_mask);
462 }
463 if let Some(hash_mask) = masks.hash_mask {
464 self.branch_node_hash_masks.insert(path, hash_mask);
465 }
466
467 match node {
468 TrieNode::EmptyRoot => {
469 debug_assert!(path.is_empty());
471 self.nodes.insert(path, SparseNode::Empty);
472 }
473 TrieNode::Branch(branch) => {
474 let mut stack_ptr = branch.as_ref().first_child_index();
476 for idx in CHILD_INDEX_RANGE {
477 if branch.state_mask.is_bit_set(idx) {
478 let mut child_path = path;
479 child_path.push_unchecked(idx);
480 self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
482 stack_ptr += 1;
483 }
484 }
485 match self.nodes.entry(path) {
488 Entry::Occupied(mut entry) => match entry.get() {
489 SparseNode::Hash(hash) => {
491 entry.insert(SparseNode::Branch {
492 state_mask: branch.state_mask,
493 hash: Some(*hash),
496 store_in_db_trie: Some(
497 masks.hash_mask.is_some_and(|mask| !mask.is_empty()) ||
498 masks.tree_mask.is_some_and(|mask| !mask.is_empty()),
499 ),
500 });
501 }
502 SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
505 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
507 return Err(SparseTrieErrorKind::Reveal {
508 path: *entry.key(),
509 node: Box::new(node.clone()),
510 }
511 .into())
512 }
513 },
514 Entry::Vacant(entry) => {
515 entry.insert(SparseNode::new_branch(branch.state_mask));
516 }
517 }
518 }
519 TrieNode::Extension(ext) => match self.nodes.entry(path) {
520 Entry::Occupied(mut entry) => match entry.get() {
521 SparseNode::Hash(hash) => {
523 let mut child_path = *entry.key();
524 child_path.extend(&ext.key);
525 entry.insert(SparseNode::Extension {
526 key: ext.key,
527 hash: Some(*hash),
530 store_in_db_trie: None,
531 });
532 self.reveal_node_or_hash(child_path, &ext.child)?;
533 }
534 SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
537 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
539 return Err(SparseTrieErrorKind::Reveal {
540 path: *entry.key(),
541 node: Box::new(node.clone()),
542 }
543 .into())
544 }
545 },
546 Entry::Vacant(entry) => {
547 let mut child_path = *entry.key();
548 child_path.extend(&ext.key);
549 entry.insert(SparseNode::new_ext(ext.key));
550 self.reveal_node_or_hash(child_path, &ext.child)?;
551 }
552 },
553 TrieNode::Leaf(leaf) => match self.nodes.entry(path) {
554 Entry::Occupied(mut entry) => match entry.get() {
555 SparseNode::Hash(hash) => {
557 let mut full = *entry.key();
558 full.extend(&leaf.key);
559 self.values.insert(full, leaf.value.clone());
560 entry.insert(SparseNode::Leaf {
561 key: leaf.key,
562 hash: Some(*hash),
565 });
566 }
567 SparseNode::Leaf { .. } => {}
569 node @ (SparseNode::Empty |
571 SparseNode::Extension { .. } |
572 SparseNode::Branch { .. }) => {
573 return Err(SparseTrieErrorKind::Reveal {
574 path: *entry.key(),
575 node: Box::new(node.clone()),
576 }
577 .into())
578 }
579 },
580 Entry::Vacant(entry) => {
581 let mut full = *entry.key();
582 full.extend(&leaf.key);
583 entry.insert(SparseNode::new_leaf(leaf.key));
584 self.values.insert(full, leaf.value.clone());
585 }
586 },
587 }
588
589 Ok(())
590 }
591
592 fn reveal_nodes(&mut self, mut nodes: Vec<RevealedSparseNode>) -> SparseTrieResult<()> {
593 nodes.sort_unstable_by_key(|node| node.path);
594 for node in nodes {
595 self.reveal_node(node.path, node.node, node.masks)?;
596 }
597 Ok(())
598 }
599
600 #[instrument(level = "trace", target = "trie::sparse::serial", skip(self, provider))]
601 fn update_leaf<P: TrieNodeProvider>(
602 &mut self,
603 full_path: Nibbles,
604 value: Vec<u8>,
605 provider: P,
606 ) -> SparseTrieResult<()> {
607 self.prefix_set.insert(full_path);
608 let existing = self.values.insert(full_path, value);
609 if existing.is_some() {
610 return Ok(())
612 }
613
614 let mut current = Nibbles::default();
615 while let Some(node) = self.nodes.get_mut(¤t) {
616 match node {
617 SparseNode::Empty => {
618 *node = SparseNode::new_leaf(full_path);
619 break
620 }
621 &mut SparseNode::Hash(hash) => {
622 return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
623 }
624 SparseNode::Leaf { key: current_key, .. } => {
625 current.extend(current_key);
626
627 if current == full_path {
629 unreachable!("we already checked leaf presence in the beginning");
630 }
631
632 let common = current.common_prefix_length(&full_path);
634
635 let new_ext_key = current.slice(current.len() - current_key.len()..common);
637 *node = SparseNode::new_ext(new_ext_key);
638
639 self.nodes.reserve(3);
641 self.nodes.insert(
642 current.slice(..common),
643 SparseNode::new_split_branch(
644 current.get_unchecked(common),
645 full_path.get_unchecked(common),
646 ),
647 );
648 self.nodes.insert(
649 full_path.slice(..=common),
650 SparseNode::new_leaf(full_path.slice(common + 1..)),
651 );
652 self.nodes.insert(
653 current.slice(..=common),
654 SparseNode::new_leaf(current.slice(common + 1..)),
655 );
656
657 break;
658 }
659 SparseNode::Extension { key, .. } => {
660 current.extend(key);
661
662 if !full_path.starts_with(¤t) {
663 let common = current.common_prefix_length(&full_path);
665 *key = current.slice(current.len() - key.len()..common);
666
667 if self.updates.is_some() {
671 if self.nodes.get(¤t).unwrap().is_hash() {
673 debug!(
674 target: "trie::sparse",
675 leaf_full_path = ?full_path,
676 child_path = ?current,
677 "Extension node child not revealed in update_leaf, falling back to db",
678 );
679 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
680 provider.trie_node(¤t)?
681 {
682 let decoded = TrieNode::decode(&mut &node[..])?;
683 trace!(
684 target: "trie::sparse",
685 ?current,
686 ?decoded,
687 ?tree_mask,
688 ?hash_mask,
689 "Revealing extension node child",
690 );
691 self.reveal_node(
692 current,
693 decoded,
694 TrieMasks { hash_mask, tree_mask },
695 )?;
696 }
697 }
698 }
699
700 self.nodes.reserve(3);
703 let branch = SparseNode::new_split_branch(
704 current.get_unchecked(common),
705 full_path.get_unchecked(common),
706 );
707 self.nodes.insert(current.slice(..common), branch);
708
709 let new_leaf = SparseNode::new_leaf(full_path.slice(common + 1..));
711 self.nodes.insert(full_path.slice(..=common), new_leaf);
712
713 let key = current.slice(common + 1..);
715 if !key.is_empty() {
716 self.nodes.insert(current.slice(..=common), SparseNode::new_ext(key));
717 }
718
719 break;
720 }
721 }
722 SparseNode::Branch { state_mask, .. } => {
723 let nibble = full_path.get_unchecked(current.len());
724 current.push_unchecked(nibble);
725 if !state_mask.is_bit_set(nibble) {
726 state_mask.set_bit(nibble);
727 let new_leaf = SparseNode::new_leaf(full_path.slice(current.len()..));
728 self.nodes.insert(current, new_leaf);
729 break;
730 }
731 }
732 };
733 }
734
735 Ok(())
736 }
737
738 #[instrument(level = "trace", target = "trie::sparse::serial", skip(self, provider))]
739 fn remove_leaf<P: TrieNodeProvider>(
740 &mut self,
741 full_path: &Nibbles,
742 provider: P,
743 ) -> SparseTrieResult<()> {
744 trace!(target: "trie::sparse", ?full_path, "remove_leaf called");
745
746 if self.values.remove(full_path).is_none() {
747 if let Some(&SparseNode::Hash(hash)) = self.nodes.get(full_path) {
748 return Err(SparseTrieErrorKind::BlindedNode { path: *full_path, hash }.into())
750 }
751
752 trace!(target: "trie::sparse", ?full_path, "Leaf node is not present in the trie");
753 return Ok(())
755 }
756 self.prefix_set.insert(*full_path);
757
758 let mut removed_nodes = self.take_nodes_for_path(full_path)?;
763 let mut child = removed_nodes.pop().expect("leaf exists");
765 #[cfg(debug_assertions)]
766 {
767 let mut child_path = child.path;
768 let SparseNode::Leaf { key, .. } = &child.node else { panic!("expected leaf node") };
769 child_path.extend(key);
770 assert_eq!(&child_path, full_path);
771 }
772
773 if removed_nodes.is_empty() {
775 debug_assert!(self.nodes.is_empty());
776 self.nodes.insert(Nibbles::default(), SparseNode::Empty);
777
778 return Ok(())
779 }
780
781 while let Some(removed_node) = removed_nodes.pop() {
784 let removed_path = removed_node.path;
785
786 let new_node = match &removed_node.node {
787 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
788 &SparseNode::Hash(hash) => {
789 return Err(SparseTrieErrorKind::BlindedNode { path: removed_path, hash }.into())
790 }
791 SparseNode::Leaf { .. } => {
792 unreachable!("we already popped the leaf node")
793 }
794 SparseNode::Extension { key, .. } => {
795 match &child.node {
798 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
799 &SparseNode::Hash(hash) => {
800 return Err(
801 SparseTrieErrorKind::BlindedNode { path: child.path, hash }.into()
802 )
803 }
804 SparseNode::Leaf { key: leaf_key, .. } => {
810 self.nodes.remove(&child.path);
811
812 let mut new_key = *key;
813 new_key.extend(leaf_key);
814 SparseNode::new_leaf(new_key)
815 }
816 SparseNode::Extension { key: extension_key, .. } => {
819 self.nodes.remove(&child.path);
820
821 let mut new_key = *key;
822 new_key.extend(extension_key);
823 SparseNode::new_ext(new_key)
824 }
825 SparseNode::Branch { .. } => removed_node.node,
827 }
828 }
829 &SparseNode::Branch { mut state_mask, hash: _, store_in_db_trie: _ } => {
830 if let Some(removed_nibble) = removed_node.unset_branch_nibble {
834 state_mask.unset_bit(removed_nibble);
835 }
836
837 if state_mask.count_bits() == 1 {
839 let child_nibble =
840 state_mask.first_set_bit_index().expect("state mask is not empty");
841
842 let mut child_path = removed_path;
844 child_path.push_unchecked(child_nibble);
845
846 trace!(target: "trie::sparse", ?removed_path, ?child_path, "Branch node has only one child");
847
848 let child = self.reveal_remaining_child_on_leaf_removal(
851 &provider,
852 full_path,
853 &child_path,
854 true, )?;
856
857 let mut delete_child = false;
858 let new_node = match &child {
859 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
860 &SparseNode::Hash(hash) => {
861 return Err(SparseTrieErrorKind::BlindedNode {
862 path: child_path,
863 hash,
864 }
865 .into())
866 }
867 SparseNode::Leaf { key, .. } => {
871 delete_child = true;
872
873 let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
874 new_key.extend(key);
875 SparseNode::new_leaf(new_key)
876 }
877 SparseNode::Extension { key, .. } => {
881 delete_child = true;
882
883 let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
884 new_key.extend(key);
885 SparseNode::new_ext(new_key)
886 }
887 SparseNode::Branch { .. } => {
890 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([child_nibble]))
891 }
892 };
893
894 if delete_child {
895 self.nodes.remove(&child_path);
896 }
897
898 if let Some(updates) = self.updates.as_mut() {
899 updates.updated_nodes.remove(&removed_path);
900 updates.removed_nodes.insert(removed_path);
901 }
902
903 new_node
904 }
905 else {
907 SparseNode::new_branch(state_mask)
908 }
909 }
910 };
911
912 child = RemovedSparseNode {
913 path: removed_path,
914 node: new_node.clone(),
915 unset_branch_nibble: None,
916 };
917 trace!(target: "trie::sparse", ?removed_path, ?new_node, "Re-inserting the node");
918 self.nodes.insert(removed_path, new_node);
919 }
920
921 Ok(())
922 }
923
924 #[instrument(target = "trie::sparse::serial", skip(self))]
925 fn root(&mut self) -> B256 {
926 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
928 let rlp_node = self.rlp_node_allocate(&mut prefix_set);
929 if let Some(root_hash) = rlp_node.as_hash() {
930 root_hash
931 } else {
932 keccak256(rlp_node)
933 }
934 }
935
936 fn update_subtrie_hashes(&mut self) {
937 self.update_rlp_node_level(SPARSE_TRIE_SUBTRIE_HASHES_LEVEL);
938 }
939
940 fn get_leaf_value(&self, full_path: &Nibbles) -> Option<&Vec<u8>> {
941 self.values.get(full_path)
942 }
943
944 fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
945 self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
946 }
947
948 fn take_updates(&mut self) -> SparseTrieUpdates {
949 self.updates.take().unwrap_or_default()
950 }
951
952 fn wipe(&mut self) {
953 self.nodes = HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]);
954 self.values = HashMap::default();
955 self.prefix_set = PrefixSetMut::all();
956 self.updates = self.updates.is_some().then(SparseTrieUpdates::wiped);
957 }
958
959 fn clear(&mut self) {
960 self.nodes.clear();
961 self.nodes.insert(Nibbles::default(), SparseNode::Empty);
962
963 self.branch_node_tree_masks.clear();
964 self.branch_node_hash_masks.clear();
965 self.values.clear();
966 self.prefix_set.clear();
967 self.updates = None;
968 self.rlp_buf.clear();
969 }
970
971 fn find_leaf(
972 &self,
973 full_path: &Nibbles,
974 expected_value: Option<&Vec<u8>>,
975 ) -> Result<LeafLookup, LeafLookupError> {
976 #[inline]
978 fn check_value_match(
979 actual_value: &Vec<u8>,
980 expected_value: Option<&Vec<u8>>,
981 path: &Nibbles,
982 ) -> Result<(), LeafLookupError> {
983 if let Some(expected) = expected_value &&
984 actual_value != expected
985 {
986 return Err(LeafLookupError::ValueMismatch {
987 path: *path,
988 expected: Some(expected.clone()),
989 actual: actual_value.clone(),
990 });
991 }
992 Ok(())
993 }
994
995 let mut current = Nibbles::default(); if let Some(actual_value) = self.values.get(full_path) {
1003 check_value_match(actual_value, expected_value, full_path)?;
1005 return Ok(LeafLookup::Exists);
1006 }
1007
1008 while current.len() < full_path.len() {
1015 match self.nodes.get(¤t) {
1016 Some(SparseNode::Empty) | None => {
1017 return Ok(LeafLookup::NonExistent);
1020 }
1021 Some(&SparseNode::Hash(hash)) => {
1022 return Err(LeafLookupError::BlindedNode { path: current, hash });
1024 }
1025 Some(SparseNode::Leaf { key, .. }) => {
1026 current.extend(key);
1028 if ¤t == full_path {
1029 if let Some(value) = self.values.get(full_path) {
1031 check_value_match(value, expected_value, full_path)?;
1032 return Ok(LeafLookup::Exists);
1033 }
1034 }
1035
1036 return Ok(LeafLookup::NonExistent);
1039 }
1040 Some(SparseNode::Extension { key, .. }) => {
1041 let saved_len = current.len();
1043 current.extend(key);
1044
1045 if full_path.len() < current.len() || !full_path.starts_with(¤t) {
1046 current.truncate(saved_len); return Ok(LeafLookup::NonExistent);
1048 }
1049 }
1051 Some(SparseNode::Branch { state_mask, .. }) => {
1052 let nibble = full_path.get_unchecked(current.len());
1054 if !state_mask.is_bit_set(nibble) {
1055 return Ok(LeafLookup::NonExistent);
1057 }
1058
1059 current.push_unchecked(nibble);
1061 }
1062 }
1063 }
1064
1065 match self.nodes.get(full_path) {
1068 Some(SparseNode::Leaf { key, .. }) if key.is_empty() => {
1069 if let Some(value) = self.values.get(full_path) {
1072 check_value_match(value, expected_value, full_path)?;
1073 return Ok(LeafLookup::Exists);
1074 }
1075 }
1076 Some(&SparseNode::Hash(hash)) => {
1077 return Err(LeafLookupError::BlindedNode { path: *full_path, hash });
1078 }
1079 _ => {
1080 return Ok(LeafLookup::NonExistent);
1082 }
1083 }
1084
1085 Ok(LeafLookup::NonExistent)
1087 }
1088
1089 fn shrink_nodes_to(&mut self, size: usize) {
1090 self.nodes.shrink_to(size);
1091 self.branch_node_tree_masks.shrink_to(size);
1092 self.branch_node_hash_masks.shrink_to(size);
1093 }
1094
1095 fn shrink_values_to(&mut self, size: usize) {
1096 self.values.shrink_to(size);
1097 }
1098}
1099
1100impl SerialSparseTrie {
1101 pub fn from_root(
1116 root: TrieNode,
1117 masks: TrieMasks,
1118 retain_updates: bool,
1119 ) -> SparseTrieResult<Self> {
1120 Self::default().with_root(root, masks, retain_updates)
1121 }
1122
1123 pub fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
1127 self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
1128 }
1129
1130 pub const fn nodes_ref(&self) -> &HashMap<Nibbles, SparseNode> {
1132 &self.nodes
1133 }
1134
1135 fn reveal_node_or_hash(&mut self, path: Nibbles, child: &[u8]) -> SparseTrieResult<()> {
1154 if child.len() == B256::len_bytes() + 1 {
1155 let hash = B256::from_slice(&child[1..]);
1156 match self.nodes.entry(path) {
1157 Entry::Occupied(entry) => match entry.get() {
1158 SparseNode::Hash(previous_hash) if previous_hash != &hash => {
1160 return Err(SparseTrieErrorKind::Reveal {
1161 path: *entry.key(),
1162 node: Box::new(SparseNode::Hash(hash)),
1163 }
1164 .into())
1165 }
1166 _ => {}
1167 },
1168 Entry::Vacant(entry) => {
1169 entry.insert(SparseNode::Hash(hash));
1170 }
1171 }
1172 return Ok(())
1173 }
1174
1175 self.reveal_node(path, TrieNode::decode(&mut &child[..])?, TrieMasks::none())
1176 }
1177
1178 fn take_nodes_for_path(&mut self, path: &Nibbles) -> SparseTrieResult<Vec<RemovedSparseNode>> {
1195 let mut current = Nibbles::default(); let mut nodes = Vec::new(); while let Some(node) = self.nodes.remove(¤t) {
1199 match &node {
1200 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
1201 &SparseNode::Hash(hash) => {
1202 return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
1203 }
1204 SparseNode::Leaf { key: _key, .. } => {
1205 #[cfg(debug_assertions)]
1209 {
1210 let mut current = current;
1211 current.extend(_key);
1212 assert_eq!(¤t, path);
1213 }
1214
1215 nodes.push(RemovedSparseNode {
1216 path: current,
1217 node,
1218 unset_branch_nibble: None,
1219 });
1220 break
1221 }
1222 SparseNode::Extension { key, .. } => {
1223 #[cfg(debug_assertions)]
1224 {
1225 let mut current = current;
1226 current.extend(key);
1227 assert!(
1228 path.starts_with(¤t),
1229 "path: {path:?}, current: {current:?}, key: {key:?}",
1230 );
1231 }
1232
1233 let path = current;
1234 current.extend(key);
1235 nodes.push(RemovedSparseNode { path, node, unset_branch_nibble: None });
1236 }
1237 SparseNode::Branch { state_mask, .. } => {
1238 let nibble = path.get_unchecked(current.len());
1239 debug_assert!(
1240 state_mask.is_bit_set(nibble),
1241 "current: {current:?}, path: {path:?}, nibble: {nibble:?}, state_mask: {state_mask:?}",
1242 );
1243
1244 let mut child_path = current;
1250 child_path.push_unchecked(nibble);
1251 let unset_branch_nibble = self
1252 .nodes
1253 .get(&child_path)
1254 .is_some_and(move |node| match node {
1255 SparseNode::Leaf { key, .. } => {
1256 child_path.extend(key);
1258 &child_path == path
1259 }
1260 _ => false,
1261 })
1262 .then_some(nibble);
1263
1264 nodes.push(RemovedSparseNode { path: current, node, unset_branch_nibble });
1265
1266 current.push_unchecked(nibble);
1267 }
1268 }
1269 }
1270
1271 Ok(nodes)
1272 }
1273
1274 fn reveal_remaining_child_on_leaf_removal<P: TrieNodeProvider>(
1284 &mut self,
1285 provider: P,
1286 full_path: &Nibbles, remaining_child_path: &Nibbles,
1288 recurse_into_extension: bool,
1289 ) -> SparseTrieResult<SparseNode> {
1290 let remaining_child_node = match self.nodes.get(remaining_child_path).unwrap() {
1291 SparseNode::Hash(_) => {
1292 debug!(
1293 target: "trie::parallel_sparse",
1294 child_path = ?remaining_child_path,
1295 leaf_full_path = ?full_path,
1296 "Node child not revealed in remove_leaf, falling back to db",
1297 );
1298 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1299 provider.trie_node(remaining_child_path)?
1300 {
1301 let decoded = TrieNode::decode(&mut &node[..])?;
1302 trace!(
1303 target: "trie::parallel_sparse",
1304 ?remaining_child_path,
1305 ?decoded,
1306 ?tree_mask,
1307 ?hash_mask,
1308 "Revealing remaining blinded branch child"
1309 );
1310 self.reveal_node(
1311 *remaining_child_path,
1312 decoded,
1313 TrieMasks { hash_mask, tree_mask },
1314 )?;
1315 self.nodes.get(remaining_child_path).unwrap().clone()
1316 } else {
1317 return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1318 path: *remaining_child_path,
1319 }
1320 .into())
1321 }
1322 }
1323 node => node.clone(),
1324 };
1325
1326 if let SparseNode::Extension { key, .. } = &remaining_child_node &&
1331 recurse_into_extension
1332 {
1333 let mut remaining_grandchild_path = *remaining_child_path;
1334 remaining_grandchild_path.extend(key);
1335
1336 trace!(
1337 target: "trie::parallel_sparse",
1338 remaining_grandchild_path = ?remaining_grandchild_path,
1339 child_path = ?remaining_child_path,
1340 leaf_full_path = ?full_path,
1341 "Revealing child of extension node, which is the last remaining child of the branch"
1342 );
1343
1344 self.reveal_remaining_child_on_leaf_removal(
1345 provider,
1346 full_path,
1347 &remaining_grandchild_path,
1348 false, )?;
1350 }
1351
1352 Ok(remaining_child_node)
1353 }
1354
1355 #[instrument(level = "trace", target = "trie::sparse::serial", skip(self))]
1364 pub fn update_rlp_node_level(&mut self, depth: usize) {
1365 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
1367 let mut buffers = RlpNodeBuffers::default();
1368
1369 let (targets, new_prefix_set) = self.get_changed_nodes_at_depth(&mut prefix_set, depth);
1371 self.prefix_set = new_prefix_set;
1373
1374 trace!(target: "trie::sparse", ?depth, ?targets, "Updating nodes at depth");
1375
1376 let mut temp_rlp_buf = core::mem::take(&mut self.rlp_buf);
1377 for (level, path) in targets {
1378 buffers.path_stack.push(RlpNodePathStackItem {
1379 level,
1380 path,
1381 is_in_prefix_set: Some(true),
1382 });
1383 self.rlp_node(&mut prefix_set, &mut buffers, &mut temp_rlp_buf);
1384 }
1385 self.rlp_buf = temp_rlp_buf;
1386 }
1387
1388 #[instrument(level = "trace", target = "trie::sparse::serial", skip(self))]
1410 fn get_changed_nodes_at_depth(
1411 &self,
1412 prefix_set: &mut PrefixSet,
1413 depth: usize,
1414 ) -> (Vec<(usize, Nibbles)>, PrefixSetMut) {
1415 let mut unchanged_prefix_set = PrefixSetMut::default();
1416 let mut paths = Vec::from([(Nibbles::default(), 0)]);
1417 let mut targets = Vec::new();
1418
1419 while let Some((mut path, level)) = paths.pop() {
1420 match self.nodes.get(&path).unwrap() {
1421 SparseNode::Empty | SparseNode::Hash(_) => {}
1422 SparseNode::Leaf { key: _, hash } => {
1423 if hash.is_some() && !prefix_set.contains(&path) {
1424 continue
1425 }
1426
1427 targets.push((level, path));
1428 }
1429 SparseNode::Extension { key, hash, store_in_db_trie: _ } => {
1430 if hash.is_some() && !prefix_set.contains(&path) {
1431 continue
1432 }
1433
1434 if level >= depth {
1435 targets.push((level, path));
1436 } else {
1437 unchanged_prefix_set.insert(path);
1438
1439 path.extend(key);
1440 paths.push((path, level + 1));
1441 }
1442 }
1443 SparseNode::Branch { state_mask, hash, store_in_db_trie: _ } => {
1444 if hash.is_some() && !prefix_set.contains(&path) {
1445 continue
1446 }
1447
1448 if level >= depth {
1449 targets.push((level, path));
1450 } else {
1451 unchanged_prefix_set.insert(path);
1452
1453 for bit in CHILD_INDEX_RANGE.rev() {
1454 if state_mask.is_bit_set(bit) {
1455 let mut child_path = path;
1456 child_path.push_unchecked(bit);
1457 paths.push((child_path, level + 1));
1458 }
1459 }
1460 }
1461 }
1462 }
1463 }
1464
1465 (targets, unchanged_prefix_set)
1466 }
1467
1468 pub fn rlp_node_allocate(&mut self, prefix_set: &mut PrefixSet) -> RlpNode {
1474 let mut buffers = RlpNodeBuffers::new_with_root_path();
1475 let mut temp_rlp_buf = core::mem::take(&mut self.rlp_buf);
1476 let result = self.rlp_node(prefix_set, &mut buffers, &mut temp_rlp_buf);
1477 self.rlp_buf = temp_rlp_buf;
1478
1479 result
1480 }
1481
1482 #[instrument(level = "trace", target = "trie::sparse::serial", skip_all, ret(level = "trace"))]
1497 pub fn rlp_node(
1498 &mut self,
1499 prefix_set: &mut PrefixSet,
1500 buffers: &mut RlpNodeBuffers,
1501 rlp_buf: &mut Vec<u8>,
1502 ) -> RlpNode {
1503 let _starting_path = buffers.path_stack.last().map(|item| item.path);
1504
1505 'main: while let Some(RlpNodePathStackItem { level, path, mut is_in_prefix_set }) =
1506 buffers.path_stack.pop()
1507 {
1508 let node = self.nodes.get_mut(&path).unwrap();
1509 trace!(
1510 target: "trie::sparse",
1511 ?_starting_path,
1512 ?level,
1513 ?path,
1514 ?is_in_prefix_set,
1515 ?node,
1516 "Popped node from path stack"
1517 );
1518
1519 let mut prefix_set_contains =
1523 |path: &Nibbles| *is_in_prefix_set.get_or_insert_with(|| prefix_set.contains(path));
1524
1525 let (rlp_node, node_type) = match node {
1526 SparseNode::Empty => (RlpNode::word_rlp(&EMPTY_ROOT_HASH), SparseNodeType::Empty),
1527 SparseNode::Hash(hash) => (RlpNode::word_rlp(hash), SparseNodeType::Hash),
1528 SparseNode::Leaf { key, hash } => {
1529 let mut path = path;
1530 path.extend(key);
1531 if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path)) {
1532 (RlpNode::word_rlp(&hash), SparseNodeType::Leaf)
1533 } else {
1534 let value = self.values.get(&path).unwrap();
1535 rlp_buf.clear();
1536 let rlp_node = LeafNodeRef { key, value }.rlp(rlp_buf);
1537 *hash = rlp_node.as_hash();
1538 (rlp_node, SparseNodeType::Leaf)
1539 }
1540 }
1541 SparseNode::Extension { key, hash, store_in_db_trie } => {
1542 let mut child_path = path;
1543 child_path.extend(key);
1544 if let Some((hash, store_in_db_trie)) =
1545 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
1546 {
1547 (
1548 RlpNode::word_rlp(&hash),
1549 SparseNodeType::Extension { store_in_db_trie: Some(store_in_db_trie) },
1550 )
1551 } else if buffers.rlp_node_stack.last().is_some_and(|e| e.path == child_path) {
1552 let RlpNodeStackItem {
1553 path: _,
1554 rlp_node: child,
1555 node_type: child_node_type,
1556 } = buffers.rlp_node_stack.pop().unwrap();
1557 rlp_buf.clear();
1558 let rlp_node = ExtensionNodeRef::new(key, &child).rlp(rlp_buf);
1559 *hash = rlp_node.as_hash();
1560
1561 let store_in_db_trie_value = child_node_type.store_in_db_trie();
1562
1563 trace!(
1564 target: "trie::sparse",
1565 ?path,
1566 ?child_path,
1567 ?child_node_type,
1568 "Extension node"
1569 );
1570
1571 *store_in_db_trie = store_in_db_trie_value;
1572
1573 (
1574 rlp_node,
1575 SparseNodeType::Extension {
1576 store_in_db_trie: store_in_db_trie_value,
1579 },
1580 )
1581 } else {
1582 buffers.path_stack.extend([
1584 RlpNodePathStackItem { level, path, is_in_prefix_set },
1585 RlpNodePathStackItem {
1586 level: level + 1,
1587 path: child_path,
1588 is_in_prefix_set: None,
1589 },
1590 ]);
1591 continue
1592 }
1593 }
1594 SparseNode::Branch { state_mask, hash, store_in_db_trie } => {
1595 if let Some((hash, store_in_db_trie)) =
1596 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
1597 {
1598 buffers.rlp_node_stack.push(RlpNodeStackItem {
1599 path,
1600 rlp_node: RlpNode::word_rlp(&hash),
1601 node_type: SparseNodeType::Branch {
1602 store_in_db_trie: Some(store_in_db_trie),
1603 },
1604 });
1605 continue
1606 }
1607 let retain_updates = self.updates.is_some() && prefix_set_contains(&path);
1608
1609 buffers.branch_child_buf.clear();
1610 for bit in CHILD_INDEX_RANGE.rev() {
1613 if state_mask.is_bit_set(bit) {
1614 let mut child = path;
1615 child.push_unchecked(bit);
1616 buffers.branch_child_buf.push(child);
1617 }
1618 }
1619
1620 buffers
1621 .branch_value_stack_buf
1622 .resize(buffers.branch_child_buf.len(), Default::default());
1623 let mut added_children = false;
1624
1625 let mut tree_mask = TrieMask::default();
1626 let mut hash_mask = TrieMask::default();
1627 let mut hashes = Vec::new();
1628 for (i, child_path) in buffers.branch_child_buf.iter().enumerate() {
1629 if buffers.rlp_node_stack.last().is_some_and(|e| &e.path == child_path) {
1630 let RlpNodeStackItem {
1631 path: _,
1632 rlp_node: child,
1633 node_type: child_node_type,
1634 } = buffers.rlp_node_stack.pop().unwrap();
1635
1636 if retain_updates {
1638 let last_child_nibble = child_path.last().unwrap();
1640
1641 let should_set_tree_mask_bit = if let Some(store_in_db_trie) =
1643 child_node_type.store_in_db_trie()
1644 {
1645 store_in_db_trie
1648 } else {
1649 child_node_type.is_hash() &&
1651 self.branch_node_tree_masks.get(&path).is_some_and(
1652 |mask| mask.is_bit_set(last_child_nibble),
1653 )
1654 };
1655 if should_set_tree_mask_bit {
1656 tree_mask.set_bit(last_child_nibble);
1657 }
1658
1659 let hash = child.as_hash().filter(|_| {
1663 child_node_type.is_branch() ||
1664 (child_node_type.is_hash() &&
1665 self.branch_node_hash_masks
1666 .get(&path)
1667 .is_some_and(|mask| {
1668 mask.is_bit_set(last_child_nibble)
1669 }))
1670 });
1671 if let Some(hash) = hash {
1672 hash_mask.set_bit(last_child_nibble);
1673 hashes.push(hash);
1674 }
1675 }
1676
1677 let original_idx = buffers.branch_child_buf.len() - i - 1;
1681 buffers.branch_value_stack_buf[original_idx] = child;
1682 added_children = true;
1683 } else {
1684 debug_assert!(!added_children);
1685 buffers.path_stack.push(RlpNodePathStackItem {
1686 level,
1687 path,
1688 is_in_prefix_set,
1689 });
1690 buffers.path_stack.extend(buffers.branch_child_buf.drain(..).map(
1691 |path| RlpNodePathStackItem {
1692 level: level + 1,
1693 path,
1694 is_in_prefix_set: None,
1695 },
1696 ));
1697 continue 'main
1698 }
1699 }
1700
1701 trace!(
1702 target: "trie::sparse",
1703 ?path,
1704 ?tree_mask,
1705 ?hash_mask,
1706 "Branch node masks"
1707 );
1708
1709 rlp_buf.clear();
1710 let branch_node_ref =
1711 BranchNodeRef::new(&buffers.branch_value_stack_buf, *state_mask);
1712 let rlp_node = branch_node_ref.rlp(rlp_buf);
1713 *hash = rlp_node.as_hash();
1714
1715 let store_in_db_trie_value = if let Some(updates) =
1718 self.updates.as_mut().filter(|_| retain_updates && !path.is_empty())
1719 {
1720 let store_in_db_trie = !tree_mask.is_empty() || !hash_mask.is_empty();
1721 if store_in_db_trie {
1722 hashes.reverse();
1725 let branch_node = BranchNodeCompact::new(
1726 *state_mask,
1727 tree_mask,
1728 hash_mask,
1729 hashes,
1730 hash.filter(|_| path.is_empty()),
1731 );
1732 updates.updated_nodes.insert(path, branch_node);
1733 } else if self
1734 .branch_node_tree_masks
1735 .get(&path)
1736 .is_some_and(|mask| !mask.is_empty()) ||
1737 self.branch_node_hash_masks
1738 .get(&path)
1739 .is_some_and(|mask| !mask.is_empty())
1740 {
1741 updates.updated_nodes.remove(&path);
1745 updates.removed_nodes.insert(path);
1746 } else if self
1747 .branch_node_tree_masks
1748 .get(&path)
1749 .is_none_or(|mask| mask.is_empty()) &&
1750 self.branch_node_hash_masks
1751 .get(&path)
1752 .is_none_or(|mask| mask.is_empty())
1753 {
1754 updates.updated_nodes.remove(&path);
1757 }
1758
1759 store_in_db_trie
1760 } else {
1761 false
1762 };
1763 *store_in_db_trie = Some(store_in_db_trie_value);
1764
1765 (
1766 rlp_node,
1767 SparseNodeType::Branch { store_in_db_trie: Some(store_in_db_trie_value) },
1768 )
1769 }
1770 };
1771
1772 trace!(
1773 target: "trie::sparse",
1774 ?_starting_path,
1775 ?level,
1776 ?path,
1777 ?node,
1778 ?node_type,
1779 ?is_in_prefix_set,
1780 "Added node to rlp node stack"
1781 );
1782
1783 buffers.rlp_node_stack.push(RlpNodeStackItem { path, rlp_node, node_type });
1784 }
1785
1786 debug_assert_eq!(buffers.rlp_node_stack.len(), 1);
1787 buffers.rlp_node_stack.pop().unwrap().rlp_node
1788 }
1789}
1790
1791#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1793pub enum SparseNodeType {
1794 Empty,
1796 Hash,
1798 Leaf,
1800 Extension {
1802 store_in_db_trie: Option<bool>,
1804 },
1805 Branch {
1807 store_in_db_trie: Option<bool>,
1809 },
1810}
1811
1812impl SparseNodeType {
1813 pub const fn is_hash(&self) -> bool {
1815 matches!(self, Self::Hash)
1816 }
1817
1818 pub const fn is_branch(&self) -> bool {
1820 matches!(self, Self::Branch { .. })
1821 }
1822
1823 pub const fn store_in_db_trie(&self) -> Option<bool> {
1825 match *self {
1826 Self::Extension { store_in_db_trie } | Self::Branch { store_in_db_trie } => {
1827 store_in_db_trie
1828 }
1829 _ => None,
1830 }
1831 }
1832}
1833
1834#[derive(Debug, Clone, PartialEq, Eq)]
1836pub enum SparseNode {
1837 Empty,
1839 Hash(B256),
1841 Leaf {
1843 key: Nibbles,
1845 hash: Option<B256>,
1848 },
1849 Extension {
1851 key: Nibbles,
1853 hash: Option<B256>,
1858 store_in_db_trie: Option<bool>,
1863 },
1864 Branch {
1866 state_mask: TrieMask,
1868 hash: Option<B256>,
1873 store_in_db_trie: Option<bool>,
1878 },
1879}
1880
1881impl SparseNode {
1882 pub fn from_node(node: TrieNode) -> Self {
1884 match node {
1885 TrieNode::EmptyRoot => Self::Empty,
1886 TrieNode::Leaf(leaf) => Self::new_leaf(leaf.key),
1887 TrieNode::Extension(ext) => Self::new_ext(ext.key),
1888 TrieNode::Branch(branch) => Self::new_branch(branch.state_mask),
1889 }
1890 }
1891
1892 pub const fn new_branch(state_mask: TrieMask) -> Self {
1894 Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1895 }
1896
1897 pub const fn new_split_branch(bit_a: u8, bit_b: u8) -> Self {
1899 let state_mask = TrieMask::new(
1900 (1u16 << bit_a) | (1u16 << bit_b),
1902 );
1903 Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1904 }
1905
1906 pub const fn new_ext(key: Nibbles) -> Self {
1908 Self::Extension { key, hash: None, store_in_db_trie: None }
1909 }
1910
1911 pub const fn new_leaf(key: Nibbles) -> Self {
1913 Self::Leaf { key, hash: None }
1914 }
1915
1916 pub const fn is_hash(&self) -> bool {
1918 matches!(self, Self::Hash(_))
1919 }
1920
1921 pub const fn hash(&self) -> Option<B256> {
1923 match self {
1924 Self::Empty => None,
1925 Self::Hash(hash) => Some(*hash),
1926 Self::Leaf { hash, .. } | Self::Extension { hash, .. } | Self::Branch { hash, .. } => {
1927 *hash
1928 }
1929 }
1930 }
1931
1932 #[cfg(any(test, feature = "test-utils"))]
1936 pub const fn set_hash(&mut self, new_hash: Option<B256>) {
1937 match self {
1938 Self::Empty | Self::Hash(_) => {
1939 }
1941 Self::Leaf { hash, .. } | Self::Extension { hash, .. } | Self::Branch { hash, .. } => {
1942 *hash = new_hash;
1943 }
1944 }
1945 }
1946}
1947
1948#[derive(Debug)]
1951struct RemovedSparseNode {
1952 path: Nibbles,
1954 node: SparseNode,
1956 unset_branch_nibble: Option<u8>,
1965}
1966
1967#[derive(Debug, Default)]
1971pub struct RlpNodeBuffers {
1972 path_stack: Vec<RlpNodePathStackItem>,
1974 rlp_node_stack: Vec<RlpNodeStackItem>,
1976 branch_child_buf: SmallVec<[Nibbles; 16]>,
1978 branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
1980}
1981
1982impl RlpNodeBuffers {
1983 fn new_with_root_path() -> Self {
1985 Self {
1986 path_stack: vec![RlpNodePathStackItem {
1987 level: 0,
1988 path: Nibbles::default(),
1989 is_in_prefix_set: None,
1990 }],
1991 rlp_node_stack: Vec::new(),
1992 branch_child_buf: SmallVec::<[Nibbles; 16]>::new_const(),
1993 branch_value_stack_buf: SmallVec::<[RlpNode; 16]>::new_const(),
1994 }
1995 }
1996}
1997
1998#[derive(Clone, PartialEq, Eq, Debug)]
2000pub struct RlpNodePathStackItem {
2001 pub level: usize,
2003 pub path: Nibbles,
2005 pub is_in_prefix_set: Option<bool>,
2007}
2008
2009#[derive(Clone, PartialEq, Eq, Debug)]
2011pub struct RlpNodeStackItem {
2012 pub path: Nibbles,
2014 pub rlp_node: RlpNode,
2016 pub node_type: SparseNodeType,
2018}
2019
2020impl SparseTrieUpdates {
2021 pub fn wiped() -> Self {
2023 Self { wiped: true, ..Default::default() }
2024 }
2025
2026 pub fn clear(&mut self) {
2030 self.updated_nodes.clear();
2031 self.removed_nodes.clear();
2032 self.wiped = false;
2033 }
2034
2035 pub fn extend(&mut self, other: Self) {
2037 self.updated_nodes.extend(other.updated_nodes);
2038 self.removed_nodes.extend(other.removed_nodes);
2039 self.wiped |= other.wiped;
2040 }
2041}
2042
2043#[cfg(test)]
2044mod find_leaf_tests {
2045 use super::*;
2046 use crate::provider::DefaultTrieNodeProvider;
2047 use alloy_rlp::Encodable;
2048 use assert_matches::assert_matches;
2049 use reth_primitives_traits::Account;
2050 use reth_trie_common::LeafNode;
2051
2052 fn encode_value(nonce: u64) -> Vec<u8> {
2054 let account = Account { nonce, ..Default::default() };
2055 let trie_account = account.into_trie_account(EMPTY_ROOT_HASH);
2056 let mut buf = Vec::new();
2057 trie_account.encode(&mut buf);
2058 buf
2059 }
2060
2061 const VALUE_A: fn() -> Vec<u8> = || encode_value(1);
2062 const VALUE_B: fn() -> Vec<u8> = || encode_value(2);
2063
2064 #[test]
2065 fn find_leaf_existing_leaf() {
2066 let provider = DefaultTrieNodeProvider;
2068 let mut sparse = SerialSparseTrie::default();
2069 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
2070 let value = b"test_value".to_vec();
2071
2072 sparse.update_leaf(path, value.clone(), &provider).unwrap();
2073
2074 let result = sparse.find_leaf(&path, None);
2076 assert_matches!(result, Ok(LeafLookup::Exists));
2077
2078 let result = sparse.find_leaf(&path, Some(&value));
2080 assert_matches!(result, Ok(LeafLookup::Exists));
2081 }
2082
2083 #[test]
2084 fn find_leaf_value_mismatch() {
2085 let provider = DefaultTrieNodeProvider;
2087 let mut sparse = SerialSparseTrie::default();
2088 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
2089 let value = b"test_value".to_vec();
2090 let wrong_value = b"wrong_value".to_vec();
2091
2092 sparse.update_leaf(path, value, &provider).unwrap();
2093
2094 let result = sparse.find_leaf(&path, Some(&wrong_value));
2096 assert_matches!(
2097 result,
2098 Err(LeafLookupError::ValueMismatch { path: p, expected: Some(e), actual: _a }) if p == path && e == wrong_value
2099 );
2100 }
2101
2102 #[test]
2103 fn find_leaf_not_found_empty_trie() {
2104 let sparse = SerialSparseTrie::default();
2106 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
2107
2108 let result = sparse.find_leaf(&path, None);
2110 assert_matches!(result, Ok(LeafLookup::NonExistent));
2111 }
2112
2113 #[test]
2114 fn find_leaf_empty_trie() {
2115 let sparse = SerialSparseTrie::default();
2116 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2117
2118 let result = sparse.find_leaf(&path, None);
2119 assert_matches!(result, Ok(LeafLookup::NonExistent));
2120 }
2121
2122 #[test]
2123 fn find_leaf_exists_no_value_check() {
2124 let provider = DefaultTrieNodeProvider;
2125 let mut sparse = SerialSparseTrie::default();
2126 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2127 sparse.update_leaf(path, VALUE_A(), &provider).unwrap();
2128
2129 let result = sparse.find_leaf(&path, None);
2130 assert_matches!(result, Ok(LeafLookup::Exists));
2131 }
2132
2133 #[test]
2134 fn find_leaf_exists_with_value_check_ok() {
2135 let provider = DefaultTrieNodeProvider;
2136 let mut sparse = SerialSparseTrie::default();
2137 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2138 let value = VALUE_A();
2139 sparse.update_leaf(path, value.clone(), &provider).unwrap();
2140
2141 let result = sparse.find_leaf(&path, Some(&value));
2142 assert_matches!(result, Ok(LeafLookup::Exists));
2143 }
2144
2145 #[test]
2146 fn find_leaf_exclusion_branch_divergence() {
2147 let provider = DefaultTrieNodeProvider;
2148 let mut sparse = SerialSparseTrie::default();
2149 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();
2154 sparse.update_leaf(path2, VALUE_B(), &provider).unwrap();
2155
2156 let result = sparse.find_leaf(&search_path, None);
2157 assert_matches!(result, Ok(LeafLookup::NonExistent));
2158 }
2159
2160 #[test]
2161 fn find_leaf_exclusion_extension_divergence() {
2162 let provider = DefaultTrieNodeProvider;
2163 let mut sparse = SerialSparseTrie::default();
2164 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
2166 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]);
2168
2169 sparse.update_leaf(path1, VALUE_A(), &provider).unwrap();
2170
2171 let result = sparse.find_leaf(&search_path, None);
2172 assert_matches!(result, Ok(LeafLookup::NonExistent));
2173 }
2174
2175 #[test]
2176 fn find_leaf_exclusion_leaf_divergence() {
2177 let provider = DefaultTrieNodeProvider;
2178 let mut sparse = SerialSparseTrie::default();
2179 let existing_leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2180 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
2181
2182 sparse.update_leaf(existing_leaf_path, VALUE_A(), &provider).unwrap();
2183
2184 let result = sparse.find_leaf(&search_path, None);
2185 assert_matches!(result, Ok(LeafLookup::NonExistent));
2186 }
2187
2188 #[test]
2189 fn find_leaf_exclusion_path_ends_at_branch() {
2190 let provider = DefaultTrieNodeProvider;
2191 let mut sparse = SerialSparseTrie::default();
2192 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]);
2194 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2]); sparse.update_leaf(path1, VALUE_A(), &provider).unwrap();
2197 sparse.update_leaf(path2, VALUE_B(), &provider).unwrap();
2198
2199 let result = sparse.find_leaf(&search_path, None);
2200 assert_matches!(result, Ok(LeafLookup::NonExistent));
2201 }
2202
2203 #[test]
2204 fn find_leaf_error_trie_node_at_leaf_path() {
2205 let blinded_hash = B256::repeat_byte(0xBB);
2207 let leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2208
2209 let mut nodes = alloy_primitives::map::HashMap::default();
2210 nodes.insert(
2212 Nibbles::default(),
2213 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x1, 0x2])),
2214 ); nodes.insert(
2216 Nibbles::from_nibbles_unchecked([0x1, 0x2]),
2217 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x3])),
2218 ); nodes.insert(
2220 Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3]),
2221 SparseNode::new_branch(TrieMask::new(0b10000)),
2222 ); nodes.insert(leaf_path, SparseNode::Hash(blinded_hash)); let sparse = SerialSparseTrie {
2226 nodes,
2227 branch_node_tree_masks: Default::default(),
2228 branch_node_hash_masks: Default::default(),
2229 values: Default::default(),
2231 prefix_set: Default::default(),
2232 updates: None,
2233 rlp_buf: Vec::new(),
2234 };
2235
2236 let result = sparse.find_leaf(&leaf_path, None);
2237
2238 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2240 if path == leaf_path && hash == blinded_hash
2241 );
2242 }
2243
2244 #[test]
2245 fn find_leaf_error_trie_node() {
2246 let blinded_hash = B256::repeat_byte(0xAA);
2247 let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]);
2248 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2249
2250 let mut nodes = HashMap::default();
2251
2252 let state_mask = TrieMask::new(0b100010);
2255 nodes.insert(Nibbles::default(), SparseNode::new_branch(state_mask));
2256
2257 nodes.insert(path_to_blind, SparseNode::Hash(blinded_hash));
2258 let path_revealed = Nibbles::from_nibbles_unchecked([0x5]);
2259 let path_revealed_leaf = Nibbles::from_nibbles_unchecked([0x5, 0x6, 0x7, 0x8]);
2260 nodes.insert(
2261 path_revealed,
2262 SparseNode::new_leaf(Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8])),
2263 );
2264
2265 let mut values = HashMap::default();
2266 values.insert(path_revealed_leaf, VALUE_A());
2267
2268 let sparse = SerialSparseTrie {
2269 nodes,
2270 branch_node_tree_masks: Default::default(),
2271 branch_node_hash_masks: Default::default(),
2272 values,
2273 prefix_set: Default::default(),
2274 updates: None,
2275 rlp_buf: Vec::new(),
2276 };
2277
2278 let result = sparse.find_leaf(&search_path, None);
2279
2280 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2282 if path == path_to_blind && hash == blinded_hash
2283 );
2284 }
2285
2286 #[test]
2287 fn find_leaf_error_trie_node_via_reveal() {
2288 let blinded_hash = B256::repeat_byte(0xAA);
2289 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]);
2293 let revealed_leaf_suffix = Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8]);
2294 let revealed_leaf_full_path = Nibbles::from_nibbles_unchecked([0x5, 0x6, 0x7, 0x8]);
2295 let revealed_value = VALUE_A();
2296
2297 let rlp_node_child1 = RlpNode::word_rlp(&blinded_hash); let leaf_node_child5 = LeafNode::new(revealed_leaf_suffix, revealed_value.clone());
2301 let leaf_node_child5_rlp_buf = alloy_rlp::encode(&leaf_node_child5);
2302 let hash_of_child5 = keccak256(&leaf_node_child5_rlp_buf);
2303 let rlp_node_child5 = RlpNode::word_rlp(&hash_of_child5);
2304
2305 let root_branch_node = reth_trie_common::BranchNode::new(
2308 vec![rlp_node_child1, rlp_node_child5], TrieMask::new(0b100010), );
2311 let root_trie_node = TrieNode::Branch(root_branch_node);
2312
2313 let mut sparse = SerialSparseTrie::from_root(root_trie_node, TrieMasks::none(), false)
2316 .expect("Failed to create trie from root");
2317
2318 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 );
2321 assert!(sparse.nodes.get(&revealed_leaf_prefix).unwrap().is_hash()); assert!(sparse.values.is_empty());
2323
2324 sparse
2326 .reveal_node(revealed_leaf_prefix, TrieNode::Leaf(leaf_node_child5), TrieMasks::none())
2327 .expect("Failed to reveal leaf node");
2328
2329 assert_matches!(sparse.nodes.get(&Nibbles::default()), Some(SparseNode::Branch { state_mask, .. }) if *state_mask == TrieMask::new(0b100010));
2331 assert_matches!(sparse.nodes.get(&path_to_blind), Some(SparseNode::Hash(h)) if *h == blinded_hash );
2332 assert_matches!(sparse.nodes.get(&revealed_leaf_prefix), Some(SparseNode::Leaf { key, .. }) if *key == revealed_leaf_suffix);
2333 assert_eq!(sparse.values.get(&revealed_leaf_full_path), Some(&revealed_value));
2334
2335 let result = sparse.find_leaf(&search_path, None);
2336
2337 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2340 if path == path_to_blind && hash == blinded_hash
2341 );
2342 }
2343}
2344
2345#[cfg(test)]
2346mod tests {
2347 use super::*;
2348 use crate::provider::DefaultTrieNodeProvider;
2349 use alloy_primitives::{map::B256Set, U256};
2350 use alloy_rlp::Encodable;
2351 use assert_matches::assert_matches;
2352 use itertools::Itertools;
2353 use prop::sample::SizeRange;
2354 use proptest::prelude::*;
2355 use proptest_arbitrary_interop::arb;
2356 use reth_primitives_traits::Account;
2357 use reth_provider::{test_utils::create_test_provider_factory, TrieWriter};
2358 use reth_trie::{
2359 hashed_cursor::{noop::NoopHashedAccountCursor, HashedPostStateAccountCursor},
2360 node_iter::{TrieElement, TrieNodeIter},
2361 trie_cursor::{noop::NoopAccountTrieCursor, TrieCursor, TrieCursorFactory},
2362 walker::TrieWalker,
2363 BranchNode, ExtensionNode, HashedPostState, LeafNode,
2364 };
2365 use reth_trie_common::{
2366 proof::{ProofNodes, ProofRetainer},
2367 updates::TrieUpdates,
2368 HashBuilder,
2369 };
2370 use reth_trie_db::DatabaseTrieCursorFactory;
2371 use std::collections::{BTreeMap, BTreeSet};
2372
2373 fn pad_nibbles_left(nibbles: Nibbles) -> Nibbles {
2375 let mut base =
2376 Nibbles::from_nibbles_unchecked(vec![0; B256::len_bytes() * 2 - nibbles.len()]);
2377 base.extend(&nibbles);
2378 base
2379 }
2380
2381 fn pad_nibbles_right(mut nibbles: Nibbles) -> Nibbles {
2383 nibbles.extend(&Nibbles::from_nibbles_unchecked(vec![
2384 0;
2385 B256::len_bytes() * 2 - nibbles.len()
2386 ]));
2387 nibbles
2388 }
2389
2390 fn run_hash_builder(
2395 state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
2396 trie_cursor: impl TrieCursor,
2397 destroyed_accounts: B256Set,
2398 proof_targets: impl IntoIterator<Item = Nibbles>,
2399 ) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>, HashMap<Nibbles, TrieMask>)
2400 {
2401 let mut account_rlp = Vec::new();
2402
2403 let mut hash_builder = HashBuilder::default()
2404 .with_updates(true)
2405 .with_proof_retainer(ProofRetainer::from_iter(proof_targets));
2406
2407 let mut prefix_set = PrefixSetMut::default();
2408 prefix_set.extend_keys(state.clone().into_iter().map(|(nibbles, _)| nibbles));
2409 prefix_set.extend_keys(destroyed_accounts.iter().map(Nibbles::unpack));
2410 let walker = TrieWalker::<_>::state_trie(trie_cursor, prefix_set.freeze())
2411 .with_deletions_retained(true);
2412 let hashed_post_state = HashedPostState::default()
2413 .with_accounts(state.into_iter().map(|(nibbles, account)| {
2414 (nibbles.pack().into_inner().unwrap().into(), Some(account))
2415 }))
2416 .into_sorted();
2417 let mut node_iter = TrieNodeIter::state_trie(
2418 walker,
2419 HashedPostStateAccountCursor::new(
2420 NoopHashedAccountCursor::default(),
2421 hashed_post_state.accounts(),
2422 ),
2423 );
2424
2425 while let Some(node) = node_iter.try_next().unwrap() {
2426 match node {
2427 TrieElement::Branch(branch) => {
2428 hash_builder.add_branch(branch.key, branch.value, branch.children_are_in_trie);
2429 }
2430 TrieElement::Leaf(key, account) => {
2431 let account = account.into_trie_account(EMPTY_ROOT_HASH);
2432 account.encode(&mut account_rlp);
2433
2434 hash_builder.add_leaf(Nibbles::unpack(key), &account_rlp);
2435 account_rlp.clear();
2436 }
2437 }
2438 }
2439 let root = hash_builder.root();
2440 let proof_nodes = hash_builder.take_proof_nodes();
2441 let branch_node_hash_masks = hash_builder
2442 .updated_branch_nodes
2443 .clone()
2444 .unwrap_or_default()
2445 .iter()
2446 .map(|(path, node)| (*path, node.hash_mask))
2447 .collect();
2448 let branch_node_tree_masks = hash_builder
2449 .updated_branch_nodes
2450 .clone()
2451 .unwrap_or_default()
2452 .iter()
2453 .map(|(path, node)| (*path, node.tree_mask))
2454 .collect();
2455
2456 let mut trie_updates = TrieUpdates::default();
2457 let removed_keys = node_iter.walker.take_removed_keys();
2458 trie_updates.finalize(hash_builder, removed_keys, destroyed_accounts);
2459
2460 (root, trie_updates, proof_nodes, branch_node_hash_masks, branch_node_tree_masks)
2461 }
2462
2463 fn assert_eq_sparse_trie_proof_nodes(sparse_trie: &SerialSparseTrie, proof_nodes: ProofNodes) {
2465 let proof_nodes = proof_nodes
2466 .into_nodes_sorted()
2467 .into_iter()
2468 .map(|(path, node)| (path, TrieNode::decode(&mut node.as_ref()).unwrap()));
2469
2470 let sparse_nodes = sparse_trie.nodes.iter().sorted_by_key(|(path, _)| *path);
2471
2472 for ((proof_node_path, proof_node), (sparse_node_path, sparse_node)) in
2473 proof_nodes.zip(sparse_nodes)
2474 {
2475 assert_eq!(&proof_node_path, sparse_node_path);
2476
2477 let equals = match (&proof_node, &sparse_node) {
2478 (TrieNode::EmptyRoot, SparseNode::Empty) => true,
2480 (
2482 TrieNode::Branch(BranchNode { state_mask: proof_state_mask, .. }),
2483 SparseNode::Branch { state_mask: sparse_state_mask, .. },
2484 ) => proof_state_mask == sparse_state_mask,
2485 (
2487 TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
2488 SparseNode::Extension { key: sparse_key, .. },
2489 ) |
2490 (
2492 TrieNode::Leaf(LeafNode { key: proof_key, .. }),
2493 SparseNode::Leaf { key: sparse_key, .. },
2494 ) => proof_key == sparse_key,
2495 (_, SparseNode::Empty | SparseNode::Hash(_)) => continue,
2497 _ => false,
2498 };
2499 assert!(
2500 equals,
2501 "path: {proof_node_path:?}\nproof node: {proof_node:?}\nsparse node: {sparse_node:?}"
2502 );
2503 }
2504 }
2505
2506 #[test]
2507 fn sparse_trie_is_blind() {
2508 assert!(SparseTrie::<SerialSparseTrie>::blind().is_blind());
2509 assert!(!SparseTrie::<SerialSparseTrie>::revealed_empty().is_blind());
2510 }
2511
2512 #[test]
2513 fn sparse_trie_empty_update_one() {
2514 let key = Nibbles::unpack(B256::with_last_byte(42));
2515 let value = || Account::default();
2516 let value_encoded = || {
2517 let mut account_rlp = Vec::new();
2518 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2519 account_rlp
2520 };
2521
2522 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2523 run_hash_builder(
2524 [(key, value())],
2525 NoopAccountTrieCursor::default(),
2526 Default::default(),
2527 [key],
2528 );
2529
2530 let provider = DefaultTrieNodeProvider;
2531 let mut sparse = SerialSparseTrie::default().with_updates(true);
2532 sparse.update_leaf(key, value_encoded(), &provider).unwrap();
2533 let sparse_root = sparse.root();
2534 let sparse_updates = sparse.take_updates();
2535
2536 assert_eq!(sparse_root, hash_builder_root);
2537 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2538 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2539 }
2540
2541 #[test]
2542 fn sparse_trie_empty_update_multiple_lower_nibbles() {
2543 reth_tracing::init_test_tracing();
2544
2545 let paths = (0..=16).map(|b| Nibbles::unpack(B256::with_last_byte(b))).collect::<Vec<_>>();
2546 let value = || Account::default();
2547 let value_encoded = || {
2548 let mut account_rlp = Vec::new();
2549 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2550 account_rlp
2551 };
2552
2553 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2554 run_hash_builder(
2555 paths.iter().copied().zip(std::iter::repeat_with(value)),
2556 NoopAccountTrieCursor::default(),
2557 Default::default(),
2558 paths.clone(),
2559 );
2560
2561 let provider = DefaultTrieNodeProvider;
2562 let mut sparse = SerialSparseTrie::default().with_updates(true);
2563 for path in &paths {
2564 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
2565 }
2566 let sparse_root = sparse.root();
2567 let sparse_updates = sparse.take_updates();
2568
2569 assert_eq!(sparse_root, hash_builder_root);
2570 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2571 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2572 }
2573
2574 #[test]
2575 fn sparse_trie_empty_update_multiple_upper_nibbles() {
2576 let paths = (239..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
2577 let value = || Account::default();
2578 let value_encoded = || {
2579 let mut account_rlp = Vec::new();
2580 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2581 account_rlp
2582 };
2583
2584 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2585 run_hash_builder(
2586 paths.iter().copied().zip(std::iter::repeat_with(value)),
2587 NoopAccountTrieCursor::default(),
2588 Default::default(),
2589 paths.clone(),
2590 );
2591
2592 let provider = DefaultTrieNodeProvider;
2593 let mut sparse = SerialSparseTrie::default().with_updates(true);
2594 for path in &paths {
2595 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
2596 }
2597 let sparse_root = sparse.root();
2598 let sparse_updates = sparse.take_updates();
2599
2600 assert_eq!(sparse_root, hash_builder_root);
2601 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2602 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2603 }
2604
2605 #[test]
2606 fn sparse_trie_empty_update_multiple() {
2607 let paths = (0..=255)
2608 .map(|b| {
2609 Nibbles::unpack(if b % 2 == 0 {
2610 B256::repeat_byte(b)
2611 } else {
2612 B256::with_last_byte(b)
2613 })
2614 })
2615 .collect::<Vec<_>>();
2616 let value = || Account::default();
2617 let value_encoded = || {
2618 let mut account_rlp = Vec::new();
2619 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2620 account_rlp
2621 };
2622
2623 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2624 run_hash_builder(
2625 paths.iter().sorted_unstable().copied().zip(std::iter::repeat_with(value)),
2626 NoopAccountTrieCursor::default(),
2627 Default::default(),
2628 paths.clone(),
2629 );
2630
2631 let provider = DefaultTrieNodeProvider;
2632 let mut sparse = SerialSparseTrie::default().with_updates(true);
2633 for path in &paths {
2634 sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
2635 }
2636 let sparse_root = sparse.root();
2637 let sparse_updates = sparse.take_updates();
2638
2639 assert_eq!(sparse_root, hash_builder_root);
2640 pretty_assertions::assert_eq!(
2641 BTreeMap::from_iter(sparse_updates.updated_nodes),
2642 BTreeMap::from_iter(hash_builder_updates.account_nodes)
2643 );
2644 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2645 }
2646
2647 #[test]
2648 fn sparse_trie_empty_update_repeated() {
2649 let paths = (0..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
2650 let old_value = Account { nonce: 1, ..Default::default() };
2651 let old_value_encoded = {
2652 let mut account_rlp = Vec::new();
2653 old_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2654 account_rlp
2655 };
2656 let new_value = Account { nonce: 2, ..Default::default() };
2657 let new_value_encoded = {
2658 let mut account_rlp = Vec::new();
2659 new_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2660 account_rlp
2661 };
2662
2663 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2664 run_hash_builder(
2665 paths.iter().copied().zip(std::iter::repeat_with(|| old_value)),
2666 NoopAccountTrieCursor::default(),
2667 Default::default(),
2668 paths.clone(),
2669 );
2670
2671 let provider = DefaultTrieNodeProvider;
2672 let mut sparse = SerialSparseTrie::default().with_updates(true);
2673 for path in &paths {
2674 sparse.update_leaf(*path, old_value_encoded.clone(), &provider).unwrap();
2675 }
2676 let sparse_root = sparse.root();
2677 let sparse_updates = sparse.updates_ref();
2678
2679 assert_eq!(sparse_root, hash_builder_root);
2680 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2681 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2682
2683 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2684 run_hash_builder(
2685 paths.iter().copied().zip(std::iter::repeat_with(|| new_value)),
2686 NoopAccountTrieCursor::default(),
2687 Default::default(),
2688 paths.clone(),
2689 );
2690
2691 for path in &paths {
2692 sparse.update_leaf(*path, new_value_encoded.clone(), &provider).unwrap();
2693 }
2694 let sparse_root = sparse.root();
2695 let sparse_updates = sparse.take_updates();
2696
2697 assert_eq!(sparse_root, hash_builder_root);
2698 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2699 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2700 }
2701
2702 #[test]
2703 fn sparse_trie_remove_leaf() {
2704 reth_tracing::init_test_tracing();
2705
2706 let provider = DefaultTrieNodeProvider;
2707 let mut sparse = SerialSparseTrie::default();
2708
2709 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
2710
2711 sparse
2712 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
2713 .unwrap();
2714 sparse
2715 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
2716 .unwrap();
2717 sparse
2718 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
2719 .unwrap();
2720 sparse
2721 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
2722 .unwrap();
2723 sparse
2724 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
2725 .unwrap();
2726 sparse
2727 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
2728 .unwrap();
2729
2730 pretty_assertions::assert_eq!(
2743 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2744 BTreeMap::from_iter([
2745 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2746 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1101.into())),
2747 (
2748 Nibbles::from_nibbles([0x5, 0x0]),
2749 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
2750 ),
2751 (
2752 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
2753 SparseNode::new_branch(0b1010.into())
2754 ),
2755 (
2756 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
2757 SparseNode::new_leaf(Nibbles::default())
2758 ),
2759 (
2760 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
2761 SparseNode::new_leaf(Nibbles::default())
2762 ),
2763 (
2764 Nibbles::from_nibbles([0x5, 0x2]),
2765 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x1, 0x3]))
2766 ),
2767 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2768 (
2769 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2770 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2771 ),
2772 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2773 (
2774 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2775 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2776 ),
2777 (
2778 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2779 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2780 )
2781 ])
2782 );
2783
2784 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), &provider).unwrap();
2785
2786 pretty_assertions::assert_eq!(
2798 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2799 BTreeMap::from_iter([
2800 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2801 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2802 (
2803 Nibbles::from_nibbles([0x5, 0x0]),
2804 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
2805 ),
2806 (
2807 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
2808 SparseNode::new_branch(0b1010.into())
2809 ),
2810 (
2811 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
2812 SparseNode::new_leaf(Nibbles::default())
2813 ),
2814 (
2815 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
2816 SparseNode::new_leaf(Nibbles::default())
2817 ),
2818 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2819 (
2820 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2821 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2822 ),
2823 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2824 (
2825 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2826 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2827 ),
2828 (
2829 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2830 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2831 )
2832 ])
2833 );
2834
2835 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), &provider).unwrap();
2836
2837 pretty_assertions::assert_eq!(
2846 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2847 BTreeMap::from_iter([
2848 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2849 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2850 (
2851 Nibbles::from_nibbles([0x5, 0x0]),
2852 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2853 ),
2854 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2855 (
2856 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2857 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2858 ),
2859 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2860 (
2861 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2862 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2863 ),
2864 (
2865 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2866 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2867 )
2868 ])
2869 );
2870
2871 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), &provider).unwrap();
2872
2873 pretty_assertions::assert_eq!(
2880 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2881 BTreeMap::from_iter([
2882 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2883 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2884 (
2885 Nibbles::from_nibbles([0x5, 0x0]),
2886 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2887 ),
2888 (
2889 Nibbles::from_nibbles([0x5, 0x3]),
2890 SparseNode::new_ext(Nibbles::from_nibbles([0x3]))
2891 ),
2892 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2893 (
2894 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2895 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2896 ),
2897 (
2898 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2899 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2900 )
2901 ])
2902 );
2903
2904 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), &provider).unwrap();
2905
2906 pretty_assertions::assert_eq!(
2911 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2912 BTreeMap::from_iter([
2913 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2914 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2915 (
2916 Nibbles::from_nibbles([0x5, 0x0]),
2917 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2918 ),
2919 (
2920 Nibbles::from_nibbles([0x5, 0x3]),
2921 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x0, 0x2]))
2922 ),
2923 ])
2924 );
2925
2926 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), &provider).unwrap();
2927
2928 pretty_assertions::assert_eq!(
2930 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2931 BTreeMap::from_iter([(
2932 Nibbles::default(),
2933 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]))
2934 ),])
2935 );
2936
2937 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), &provider).unwrap();
2938
2939 pretty_assertions::assert_eq!(
2941 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2942 BTreeMap::from_iter([(Nibbles::default(), SparseNode::Empty)])
2943 );
2944 }
2945
2946 #[test]
2947 fn sparse_trie_remove_leaf_blinded() {
2948 let leaf = LeafNode::new(
2949 Nibbles::default(),
2950 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
2951 );
2952 let branch = TrieNode::Branch(BranchNode::new(
2953 vec![
2954 RlpNode::word_rlp(&B256::repeat_byte(1)),
2955 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
2956 ],
2957 TrieMask::new(0b11),
2958 ));
2959
2960 let provider = DefaultTrieNodeProvider;
2961 let mut sparse = SerialSparseTrie::from_root(
2962 branch.clone(),
2963 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
2964 false,
2965 )
2966 .unwrap();
2967
2968 sparse
2974 .reveal_node(
2975 Nibbles::default(),
2976 branch,
2977 TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
2978 )
2979 .unwrap();
2980 sparse
2981 .reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), TrieMasks::none())
2982 .unwrap();
2983
2984 assert_matches!(
2986 sparse.remove_leaf(&Nibbles::from_nibbles([0x0]), &provider).map_err(|e| e.into_kind()),
2987 Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
2988 );
2989 }
2990
2991 #[test]
2992 fn sparse_trie_remove_leaf_non_existent() {
2993 let leaf = LeafNode::new(
2994 Nibbles::default(),
2995 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
2996 );
2997 let branch = TrieNode::Branch(BranchNode::new(
2998 vec![
2999 RlpNode::word_rlp(&B256::repeat_byte(1)),
3000 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
3001 ],
3002 TrieMask::new(0b11),
3003 ));
3004
3005 let provider = DefaultTrieNodeProvider;
3006 let mut sparse = SerialSparseTrie::from_root(
3007 branch.clone(),
3008 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
3009 false,
3010 )
3011 .unwrap();
3012
3013 sparse
3019 .reveal_node(
3020 Nibbles::default(),
3021 branch,
3022 TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
3023 )
3024 .unwrap();
3025 sparse
3026 .reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), TrieMasks::none())
3027 .unwrap();
3028
3029 let sparse_old = sparse.clone();
3031 assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2]), &provider), Ok(()));
3032 assert_eq!(sparse, sparse_old);
3033 }
3034
3035 #[test]
3036 fn sparse_trie_fuzz() {
3037 const KEY_NIBBLES_LEN: usize = 3;
3041
3042 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
3043 {
3044 let mut state = BTreeMap::default();
3045 let default_provider = DefaultTrieNodeProvider;
3046 let provider_factory = create_test_provider_factory();
3047 let mut sparse = SerialSparseTrie::default().with_updates(true);
3048
3049 for (update, keys_to_delete) in updates {
3050 for (key, account) in update.clone() {
3052 let account = account.into_trie_account(EMPTY_ROOT_HASH);
3053 let mut account_rlp = Vec::new();
3054 account.encode(&mut account_rlp);
3055 sparse.update_leaf(key, account_rlp, &default_provider).unwrap();
3056 }
3057 let mut updated_sparse = sparse.clone();
3061 let sparse_root = updated_sparse.root();
3062 let sparse_updates = updated_sparse.take_updates();
3063
3064 state.extend(update);
3066 let provider = provider_factory.provider().unwrap();
3067 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
3068 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
3069 run_hash_builder(
3070 state.clone(),
3071 trie_cursor.account_trie_cursor().unwrap(),
3072 Default::default(),
3073 state.keys().copied(),
3074 );
3075
3076 let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
3078
3079 let provider_rw = provider_factory.provider_rw().unwrap();
3081 provider_rw.write_trie_updates(hash_builder_updates).unwrap();
3082 provider_rw.commit().unwrap();
3083
3084 assert_eq!(sparse_root, hash_builder_root);
3086 pretty_assertions::assert_eq!(
3088 BTreeMap::from_iter(sparse_updates.updated_nodes),
3089 BTreeMap::from_iter(hash_builder_account_nodes)
3090 );
3091 assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
3093
3094 for key in &keys_to_delete {
3097 state.remove(key).unwrap();
3098 sparse.remove_leaf(key, &default_provider).unwrap();
3099 }
3100
3101 let mut updated_sparse = sparse.clone();
3105 let sparse_root = updated_sparse.root();
3106 let sparse_updates = updated_sparse.take_updates();
3107
3108 let provider = provider_factory.provider().unwrap();
3109 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
3110 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
3111 run_hash_builder(
3112 state.clone(),
3113 trie_cursor.account_trie_cursor().unwrap(),
3114 keys_to_delete
3115 .iter()
3116 .map(|nibbles| B256::from_slice(&nibbles.pack()))
3117 .collect(),
3118 state.keys().copied(),
3119 );
3120
3121 let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
3123
3124 let provider_rw = provider_factory.provider_rw().unwrap();
3126 provider_rw.write_trie_updates(hash_builder_updates).unwrap();
3127 provider_rw.commit().unwrap();
3128
3129 assert_eq!(sparse_root, hash_builder_root);
3131 pretty_assertions::assert_eq!(
3133 BTreeMap::from_iter(sparse_updates.updated_nodes),
3134 BTreeMap::from_iter(hash_builder_account_nodes)
3135 );
3136 assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
3138 }
3139 }
3140 }
3141
3142 fn transform_updates(
3143 updates: Vec<BTreeMap<Nibbles, Account>>,
3144 mut rng: impl rand::Rng,
3145 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
3146 let mut keys = BTreeSet::new();
3147 updates
3148 .into_iter()
3149 .map(|update| {
3150 keys.extend(update.keys().copied());
3151
3152 let keys_to_delete_len = update.len() / 2;
3153 let keys_to_delete = (0..keys_to_delete_len)
3154 .map(|_| {
3155 let key =
3156 *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
3157 keys.take(&key).unwrap()
3158 })
3159 .collect();
3160
3161 (update, keys_to_delete)
3162 })
3163 .collect::<Vec<_>>()
3164 }
3165
3166 proptest!(ProptestConfig::with_cases(10), |(
3167 updates in proptest::collection::vec(
3168 proptest::collection::btree_map(
3169 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
3170 arb::<Account>(),
3171 1..50,
3172 ),
3173 1..50,
3174 ).prop_perturb(transform_updates)
3175 )| {
3176 test(updates)
3177 });
3178 }
3179
3180 #[test]
3192 fn sparse_trie_reveal_node_1() {
3193 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00]));
3194 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01]));
3195 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x02]));
3196 let value = || Account::default();
3197 let value_encoded = || {
3198 let mut account_rlp = Vec::new();
3199 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3200 account_rlp
3201 };
3202
3203 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3205 run_hash_builder(
3206 [(key1(), value()), (key3(), value())],
3207 NoopAccountTrieCursor::default(),
3208 Default::default(),
3209 [Nibbles::default()],
3210 );
3211
3212 let provider = DefaultTrieNodeProvider;
3213 let mut sparse = SerialSparseTrie::from_root(
3214 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3215 TrieMasks {
3216 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3217 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3218 },
3219 false,
3220 )
3221 .unwrap();
3222
3223 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3225 run_hash_builder(
3226 [(key1(), value()), (key3(), value())],
3227 NoopAccountTrieCursor::default(),
3228 Default::default(),
3229 [key1()],
3230 );
3231 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3232 let hash_mask = branch_node_hash_masks.get(&path).copied();
3233 let tree_mask = branch_node_tree_masks.get(&path).copied();
3234 sparse
3235 .reveal_node(
3236 path,
3237 TrieNode::decode(&mut &node[..]).unwrap(),
3238 TrieMasks { hash_mask, tree_mask },
3239 )
3240 .unwrap();
3241 }
3242
3243 assert_eq!(
3245 sparse.nodes.get(&Nibbles::default()),
3246 Some(&SparseNode::new_branch(0b101.into()))
3247 );
3248
3249 sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
3251
3252 assert_eq!(
3254 sparse.nodes.get(&Nibbles::default()),
3255 Some(&SparseNode::new_branch(0b111.into()))
3256 );
3257
3258 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3260 run_hash_builder(
3261 [(key1(), value()), (key3(), value())],
3262 NoopAccountTrieCursor::default(),
3263 Default::default(),
3264 [key3()],
3265 );
3266 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3267 let hash_mask = branch_node_hash_masks.get(&path).copied();
3268 let tree_mask = branch_node_tree_masks.get(&path).copied();
3269 sparse
3270 .reveal_node(
3271 path,
3272 TrieNode::decode(&mut &node[..]).unwrap(),
3273 TrieMasks { hash_mask, tree_mask },
3274 )
3275 .unwrap();
3276 }
3277
3278 assert_eq!(
3280 sparse.nodes.get(&Nibbles::default()),
3281 Some(&SparseNode::new_branch(0b111.into()))
3282 );
3283
3284 let (_, _, hash_builder_proof_nodes, _, _) = run_hash_builder(
3287 [(key1(), value()), (key2(), value()), (key3(), value())],
3288 NoopAccountTrieCursor::default(),
3289 Default::default(),
3290 [key1(), key2(), key3()],
3291 );
3292
3293 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
3294 }
3295
3296 #[test]
3307 fn sparse_trie_reveal_node_2() {
3308 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x00]));
3309 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x01]));
3310 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x02]));
3311 let value = || Account::default();
3312
3313 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3315 run_hash_builder(
3316 [(key1(), value()), (key2(), value()), (key3(), value())],
3317 NoopAccountTrieCursor::default(),
3318 Default::default(),
3319 [Nibbles::default()],
3320 );
3321
3322 let provider = DefaultTrieNodeProvider;
3323 let mut sparse = SerialSparseTrie::from_root(
3324 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3325 TrieMasks {
3326 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3327 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3328 },
3329 false,
3330 )
3331 .unwrap();
3332
3333 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3336 run_hash_builder(
3337 [(key1(), value()), (key2(), value()), (key3(), value())],
3338 NoopAccountTrieCursor::default(),
3339 Default::default(),
3340 [key1(), Nibbles::from_nibbles_unchecked([0x01])],
3341 );
3342 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3343 let hash_mask = branch_node_hash_masks.get(&path).copied();
3344 let tree_mask = branch_node_tree_masks.get(&path).copied();
3345 sparse
3346 .reveal_node(
3347 path,
3348 TrieNode::decode(&mut &node[..]).unwrap(),
3349 TrieMasks { hash_mask, tree_mask },
3350 )
3351 .unwrap();
3352 }
3353
3354 assert_eq!(
3356 sparse.nodes.get(&Nibbles::default()),
3357 Some(&SparseNode::new_branch(0b11.into()))
3358 );
3359
3360 sparse.remove_leaf(&key1(), &provider).unwrap();
3362
3363 assert_eq!(
3365 sparse.nodes.get(&Nibbles::default()),
3366 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3367 );
3368
3369 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3371 run_hash_builder(
3372 [(key1(), value()), (key2(), value()), (key3(), value())],
3373 NoopAccountTrieCursor::default(),
3374 Default::default(),
3375 [key2()],
3376 );
3377 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3378 let hash_mask = branch_node_hash_masks.get(&path).copied();
3379 let tree_mask = branch_node_tree_masks.get(&path).copied();
3380 sparse
3381 .reveal_node(
3382 path,
3383 TrieNode::decode(&mut &node[..]).unwrap(),
3384 TrieMasks { hash_mask, tree_mask },
3385 )
3386 .unwrap();
3387 }
3388
3389 assert_eq!(
3391 sparse.nodes.get(&Nibbles::default()),
3392 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3393 );
3394 }
3395
3396 #[test]
3405 fn sparse_trie_reveal_node_3() {
3406 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x01]));
3407 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x02]));
3408 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x00]));
3409 let value = || Account::default();
3410 let value_encoded = || {
3411 let mut account_rlp = Vec::new();
3412 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3413 account_rlp
3414 };
3415
3416 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3418 run_hash_builder(
3419 [(key1(), value()), (key2(), value())],
3420 NoopAccountTrieCursor::default(),
3421 Default::default(),
3422 [Nibbles::default()],
3423 );
3424
3425 let provider = DefaultTrieNodeProvider;
3426 let mut sparse = SerialSparseTrie::from_root(
3427 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3428 TrieMasks {
3429 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3430 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3431 },
3432 false,
3433 )
3434 .unwrap();
3435
3436 assert_matches!(
3438 sparse.nodes.get(&Nibbles::default()),
3439 Some(SparseNode::Extension { key, hash: None, store_in_db_trie: None }) if *key == Nibbles::from_nibbles([0x00])
3440 );
3441
3442 sparse.update_leaf(key3(), value_encoded(), &provider).unwrap();
3444
3445 assert_matches!(
3447 sparse.nodes.get(&Nibbles::default()),
3448 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
3449 );
3450
3451 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3453 run_hash_builder(
3454 [(key1(), value()), (key2(), value())],
3455 NoopAccountTrieCursor::default(),
3456 Default::default(),
3457 [key1()],
3458 );
3459 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3460 let hash_mask = branch_node_hash_masks.get(&path).copied();
3461 let tree_mask = branch_node_tree_masks.get(&path).copied();
3462 sparse
3463 .reveal_node(
3464 path,
3465 TrieNode::decode(&mut &node[..]).unwrap(),
3466 TrieMasks { hash_mask, tree_mask },
3467 )
3468 .unwrap();
3469 }
3470
3471 assert_matches!(
3473 sparse.nodes.get(&Nibbles::default()),
3474 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
3475 );
3476 }
3477
3478 #[test]
3479 fn sparse_trie_get_changed_nodes_at_depth() {
3480 let provider = DefaultTrieNodeProvider;
3481 let mut sparse = SerialSparseTrie::default();
3482
3483 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3484
3485 sparse
3498 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3499 .unwrap();
3500 sparse
3501 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3502 .unwrap();
3503 sparse
3504 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3505 .unwrap();
3506 sparse
3507 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
3508 .unwrap();
3509 sparse
3510 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
3511 .unwrap();
3512 sparse
3513 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
3514 .unwrap();
3515
3516 assert_eq!(
3517 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 0),
3518 (vec![(0, Nibbles::default())], PrefixSetMut::default())
3519 );
3520 assert_eq!(
3521 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 1),
3522 (vec![(1, Nibbles::from_nibbles_unchecked([0x5]))], [Nibbles::default()].into())
3523 );
3524 assert_eq!(
3525 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 2),
3526 (
3527 vec![
3528 (2, Nibbles::from_nibbles_unchecked([0x5, 0x0])),
3529 (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3530 (2, Nibbles::from_nibbles_unchecked([0x5, 0x3]))
3531 ],
3532 [Nibbles::default(), Nibbles::from_nibbles_unchecked([0x5])].into()
3533 )
3534 );
3535 assert_eq!(
3536 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 3),
3537 (
3538 vec![
3539 (3, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3])),
3540 (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3541 (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1])),
3542 (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3]))
3543 ],
3544 [
3545 Nibbles::default(),
3546 Nibbles::from_nibbles_unchecked([0x5]),
3547 Nibbles::from_nibbles_unchecked([0x5, 0x0]),
3548 Nibbles::from_nibbles_unchecked([0x5, 0x3])
3549 ]
3550 .into()
3551 )
3552 );
3553 assert_eq!(
3554 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 4),
3555 (
3556 vec![
3557 (4, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x1])),
3558 (4, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x3])),
3559 (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3560 (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1])),
3561 (4, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x0])),
3562 (4, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x2]))
3563 ],
3564 [
3565 Nibbles::default(),
3566 Nibbles::from_nibbles_unchecked([0x5]),
3567 Nibbles::from_nibbles_unchecked([0x5, 0x0]),
3568 Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3]),
3569 Nibbles::from_nibbles_unchecked([0x5, 0x3]),
3570 Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3])
3571 ]
3572 .into()
3573 )
3574 );
3575 }
3576
3577 #[test]
3578 fn hash_builder_branch_hash_mask() {
3579 let key1 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x00]));
3580 let key2 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x01]));
3581 let value = || Account { bytecode_hash: Some(B256::repeat_byte(1)), ..Default::default() };
3582 let value_encoded = || {
3583 let mut account_rlp = Vec::new();
3584 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3585 account_rlp
3586 };
3587
3588 let (hash_builder_root, hash_builder_updates, _, _, _) = run_hash_builder(
3589 [(key1(), value()), (key2(), value())],
3590 NoopAccountTrieCursor::default(),
3591 Default::default(),
3592 [Nibbles::default()],
3593 );
3594
3595 let provider = DefaultTrieNodeProvider;
3596 let mut sparse = SerialSparseTrie::default();
3597 sparse.update_leaf(key1(), value_encoded(), &provider).unwrap();
3598 sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
3599 let sparse_root = sparse.root();
3600 let sparse_updates = sparse.take_updates();
3601
3602 assert_eq!(sparse_root, hash_builder_root);
3603 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
3604 }
3605
3606 #[test]
3607 fn sparse_trie_wipe() {
3608 let provider = DefaultTrieNodeProvider;
3609 let mut sparse = SerialSparseTrie::default().with_updates(true);
3610
3611 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3612
3613 sparse
3626 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3627 .unwrap();
3628 sparse
3629 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3630 .unwrap();
3631 sparse
3632 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3633 .unwrap();
3634 sparse
3635 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
3636 .unwrap();
3637 sparse
3638 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
3639 .unwrap();
3640 sparse
3641 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
3642 .unwrap();
3643
3644 sparse.wipe();
3645
3646 assert_matches!(
3647 &sparse.updates,
3648 Some(SparseTrieUpdates{ updated_nodes, removed_nodes, wiped })
3649 if updated_nodes.is_empty() && removed_nodes.is_empty() && *wiped
3650 );
3651 assert_eq!(sparse.root(), EMPTY_ROOT_HASH);
3652 }
3653
3654 #[test]
3655 fn sparse_trie_clear() {
3656 let provider = DefaultTrieNodeProvider;
3659 let mut sparse = SerialSparseTrie::default();
3660 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3661 sparse
3662 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3663 .unwrap();
3664 sparse
3665 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3666 .unwrap();
3667 sparse
3668 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3669 .unwrap();
3670 sparse
3671 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value, &provider)
3672 .unwrap();
3673
3674 sparse.clear();
3675
3676 let empty_trie = SerialSparseTrie::default();
3677 assert_eq!(empty_trie, sparse);
3678 }
3679
3680 #[test]
3681 fn sparse_trie_display() {
3682 let provider = DefaultTrieNodeProvider;
3683 let mut sparse = SerialSparseTrie::default();
3684
3685 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3686
3687 sparse
3700 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3701 .unwrap();
3702 sparse
3703 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3704 .unwrap();
3705 sparse
3706 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3707 .unwrap();
3708 sparse
3709 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
3710 .unwrap();
3711 sparse
3712 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
3713 .unwrap();
3714 sparse
3715 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
3716 .unwrap();
3717
3718 let normal_printed = format!("{sparse}");
3719 let expected = "\
3720Root -> Extension { key: Nibbles(0x5), hash: None, store_in_db_trie: None }
37215 -> Branch { state_mask: TrieMask(0000000000001101), hash: None, store_in_db_trie: None }
372250 -> Extension { key: Nibbles(0x23), hash: None, store_in_db_trie: None }
37235023 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
372450231 -> Leaf { key: Nibbles(0x), hash: None }
372550233 -> Leaf { key: Nibbles(0x), hash: None }
372652013 -> Leaf { key: Nibbles(0x013), hash: None }
372753 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
372853102 -> Leaf { key: Nibbles(0x02), hash: None }
3729533 -> Branch { state_mask: TrieMask(0000000000000101), hash: None, store_in_db_trie: None }
373053302 -> Leaf { key: Nibbles(0x2), hash: None }
373153320 -> Leaf { key: Nibbles(0x0), hash: None }
3732";
3733 assert_eq!(normal_printed, expected);
3734
3735 let alternate_printed = format!("{sparse:#}");
3736 let expected = "\
3737Root -> Extension { key: Nibbles(0x5), hash: None, store_in_db_trie: None }
3738 5 -> Branch { state_mask: TrieMask(0000000000001101), hash: None, store_in_db_trie: None }
3739 50 -> Extension { key: Nibbles(0x23), hash: None, store_in_db_trie: None }
3740 5023 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
3741 50231 -> Leaf { key: Nibbles(0x), hash: None }
3742 50233 -> Leaf { key: Nibbles(0x), hash: None }
3743 52013 -> Leaf { key: Nibbles(0x013), hash: None }
3744 53 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
3745 53102 -> Leaf { key: Nibbles(0x02), hash: None }
3746 533 -> Branch { state_mask: TrieMask(0000000000000101), hash: None, store_in_db_trie: None }
3747 53302 -> Leaf { key: Nibbles(0x2), hash: None }
3748 53320 -> Leaf { key: Nibbles(0x0), hash: None }
3749";
3750
3751 assert_eq!(alternate_printed, expected);
3752 }
3753}