1use crate::blinded::{BlindedProvider, DefaultBlindedProvider, RevealedNode};
2use alloc::{
3 borrow::Cow,
4 boxed::Box,
5 fmt,
6 string::{String, ToString},
7 vec,
8 vec::Vec,
9};
10use alloy_primitives::{
11 hex, keccak256,
12 map::{Entry, HashMap, HashSet},
13 B256,
14};
15use alloy_rlp::Decodable;
16use reth_execution_errors::{SparseTrieErrorKind, SparseTrieResult};
17use reth_trie_common::{
18 prefix_set::{PrefixSet, PrefixSetMut},
19 BranchNodeCompact, BranchNodeRef, ExtensionNodeRef, LeafNodeRef, Nibbles, RlpNode, TrieMask,
20 TrieNode, CHILD_INDEX_RANGE, EMPTY_ROOT_HASH,
21};
22use smallvec::SmallVec;
23use tracing::trace;
24
25#[derive(Debug)]
27pub struct TrieMasks {
28 pub hash_mask: Option<TrieMask>,
30 pub tree_mask: Option<TrieMask>,
32}
33
34impl TrieMasks {
35 pub const fn none() -> Self {
37 Self { hash_mask: None, tree_mask: None }
38 }
39}
40
41#[derive(PartialEq, Eq)]
44pub enum SparseTrie<P = DefaultBlindedProvider> {
45 Blind,
47 Revealed(Box<RevealedSparseTrie<P>>),
49}
50
51impl<P> fmt::Debug for SparseTrie<P> {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 match self {
54 Self::Blind => write!(f, "Blind"),
55 Self::Revealed(revealed) => write!(f, "Revealed({revealed:?})"),
56 }
57 }
58}
59
60impl<P> Default for SparseTrie<P> {
61 fn default() -> Self {
62 Self::Blind
63 }
64}
65
66impl SparseTrie {
67 pub const fn blind() -> Self {
69 Self::Blind
70 }
71
72 pub fn revealed_empty() -> Self {
74 Self::Revealed(Box::default())
75 }
76
77 pub fn reveal_root(
83 &mut self,
84 root: TrieNode,
85 masks: TrieMasks,
86 retain_updates: bool,
87 ) -> SparseTrieResult<&mut RevealedSparseTrie> {
88 self.reveal_root_with_provider(Default::default(), root, masks, retain_updates)
89 }
90}
91
92impl<P> SparseTrie<P> {
93 pub const fn is_blind(&self) -> bool {
95 matches!(self, Self::Blind)
96 }
97
98 pub const fn as_revealed_ref(&self) -> Option<&RevealedSparseTrie<P>> {
100 if let Self::Revealed(revealed) = self {
101 Some(revealed)
102 } else {
103 None
104 }
105 }
106
107 pub fn as_revealed_mut(&mut self) -> Option<&mut RevealedSparseTrie<P>> {
109 if let Self::Revealed(revealed) = self {
110 Some(revealed)
111 } else {
112 None
113 }
114 }
115
116 pub fn reveal_root_with_provider(
122 &mut self,
123 provider: P,
124 root: TrieNode,
125 masks: TrieMasks,
126 retain_updates: bool,
127 ) -> SparseTrieResult<&mut RevealedSparseTrie<P>> {
128 if self.is_blind() {
129 *self = Self::Revealed(Box::new(RevealedSparseTrie::from_provider_and_root(
130 provider,
131 root,
132 masks,
133 retain_updates,
134 )?))
135 }
136 Ok(self.as_revealed_mut().unwrap())
137 }
138
139 pub fn wipe(&mut self) -> SparseTrieResult<()> {
141 let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
142 revealed.wipe();
143 Ok(())
144 }
145
146 pub fn root(&mut self) -> Option<B256> {
148 Some(self.as_revealed_mut()?.root())
149 }
150
151 pub fn root_with_updates(&mut self) -> Option<(B256, SparseTrieUpdates)> {
153 let revealed = self.as_revealed_mut()?;
154 Some((revealed.root(), revealed.take_updates()))
155 }
156}
157
158impl<P: BlindedProvider> SparseTrie<P> {
159 pub fn update_leaf(&mut self, path: Nibbles, value: Vec<u8>) -> SparseTrieResult<()> {
161 let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
162 revealed.update_leaf(path, value)?;
163 Ok(())
164 }
165
166 pub fn remove_leaf(&mut self, path: &Nibbles) -> SparseTrieResult<()> {
168 let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
169 revealed.remove_leaf(path)?;
170 Ok(())
171 }
172}
173
174#[derive(Clone, PartialEq, Eq)]
183pub struct RevealedSparseTrie<P = DefaultBlindedProvider> {
184 provider: P,
186 nodes: HashMap<Nibbles, SparseNode>,
188 branch_node_tree_masks: HashMap<Nibbles, TrieMask>,
190 branch_node_hash_masks: HashMap<Nibbles, TrieMask>,
192 values: HashMap<Nibbles, Vec<u8>>,
194 prefix_set: PrefixSetMut,
196 updates: Option<SparseTrieUpdates>,
198 rlp_buf: Vec<u8>,
200}
201
202impl<P> fmt::Debug for RevealedSparseTrie<P> {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 f.debug_struct("RevealedSparseTrie")
205 .field("nodes", &self.nodes)
206 .field("branch_tree_masks", &self.branch_node_tree_masks)
207 .field("branch_hash_masks", &self.branch_node_hash_masks)
208 .field("values", &self.values)
209 .field("prefix_set", &self.prefix_set)
210 .field("updates", &self.updates)
211 .field("rlp_buf", &hex::encode(&self.rlp_buf))
212 .finish_non_exhaustive()
213 }
214}
215
216fn encode_nibbles(nibbles: &Nibbles) -> String {
218 let encoded = hex::encode(nibbles.pack());
219 encoded[..nibbles.len()].to_string()
220}
221
222impl<P: BlindedProvider> fmt::Display for RevealedSparseTrie<P> {
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 let mut stack = Vec::new();
226 let mut visited = HashSet::new();
227
228 const INDENT: &str = " ";
230
231 stack.push((Nibbles::default(), self.nodes_ref().get(&Nibbles::default()).unwrap(), 0));
233
234 while let Some((path, node, depth)) = stack.pop() {
235 if !visited.insert(path.clone()) {
236 continue;
237 }
238
239 if f.alternate() {
241 write!(f, "{}", INDENT.repeat(depth))?;
242 }
243
244 let packed_path = if depth == 0 { String::from("Root") } else { encode_nibbles(&path) };
245
246 match node {
247 SparseNode::Empty | SparseNode::Hash(_) => {
248 writeln!(f, "{packed_path} -> {node:?}")?;
249 }
250 SparseNode::Leaf { key, .. } => {
251 let mut full_path = path.clone();
253 full_path.extend_from_slice_unchecked(key);
254 let packed_path = encode_nibbles(&full_path);
255
256 writeln!(f, "{packed_path} -> {node:?}")?;
257 }
258 SparseNode::Extension { key, .. } => {
259 writeln!(f, "{packed_path} -> {node:?}")?;
260
261 let mut child_path = path.clone();
263 child_path.extend_from_slice_unchecked(key);
264 if let Some(child_node) = self.nodes_ref().get(&child_path) {
265 stack.push((child_path, child_node, depth + 1));
266 }
267 }
268 SparseNode::Branch { state_mask, .. } => {
269 writeln!(f, "{packed_path} -> {node:?}")?;
270
271 for i in CHILD_INDEX_RANGE.rev() {
272 if state_mask.is_bit_set(i) {
273 let mut child_path = path.clone();
274 child_path.push_unchecked(i);
275 if let Some(child_node) = self.nodes_ref().get(&child_path) {
276 stack.push((child_path, child_node, depth + 1));
277 }
278 }
279 }
280 }
281 }
282 }
283
284 Ok(())
285 }
286}
287
288impl Default for RevealedSparseTrie {
289 fn default() -> Self {
290 Self {
291 provider: Default::default(),
292 nodes: HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]),
293 branch_node_tree_masks: HashMap::default(),
294 branch_node_hash_masks: HashMap::default(),
295 values: HashMap::default(),
296 prefix_set: PrefixSetMut::default(),
297 updates: None,
298 rlp_buf: Vec::new(),
299 }
300 }
301}
302
303impl RevealedSparseTrie {
304 pub fn from_root(
306 node: TrieNode,
307 masks: TrieMasks,
308 retain_updates: bool,
309 ) -> SparseTrieResult<Self> {
310 let mut this = Self {
311 provider: Default::default(),
312 nodes: HashMap::default(),
313 branch_node_tree_masks: HashMap::default(),
314 branch_node_hash_masks: HashMap::default(),
315 values: HashMap::default(),
316 prefix_set: PrefixSetMut::default(),
317 rlp_buf: Vec::new(),
318 updates: None,
319 }
320 .with_updates(retain_updates);
321 this.reveal_node(Nibbles::default(), node, masks)?;
322 Ok(this)
323 }
324}
325
326impl<P> RevealedSparseTrie<P> {
327 pub fn from_provider_and_root(
329 provider: P,
330 node: TrieNode,
331 masks: TrieMasks,
332 retain_updates: bool,
333 ) -> SparseTrieResult<Self> {
334 let mut this = Self {
335 provider,
336 nodes: HashMap::default(),
337 branch_node_tree_masks: HashMap::default(),
338 branch_node_hash_masks: HashMap::default(),
339 values: HashMap::default(),
340 prefix_set: PrefixSetMut::default(),
341 rlp_buf: Vec::new(),
342 updates: None,
343 }
344 .with_updates(retain_updates);
345 this.reveal_node(Nibbles::default(), node, masks)?;
346 Ok(this)
347 }
348
349 pub fn with_provider<BP>(self, provider: BP) -> RevealedSparseTrie<BP> {
351 RevealedSparseTrie {
352 provider,
353 nodes: self.nodes,
354 branch_node_tree_masks: self.branch_node_tree_masks,
355 branch_node_hash_masks: self.branch_node_hash_masks,
356 values: self.values,
357 prefix_set: self.prefix_set,
358 updates: self.updates,
359 rlp_buf: self.rlp_buf,
360 }
361 }
362
363 pub fn with_updates(mut self, retain_updates: bool) -> Self {
365 if retain_updates {
366 self.updates = Some(SparseTrieUpdates::default());
367 }
368 self
369 }
370
371 pub fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
373 self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
374 }
375
376 pub const fn nodes_ref(&self) -> &HashMap<Nibbles, SparseNode> {
378 &self.nodes
379 }
380
381 pub fn get_leaf_value(&self, path: &Nibbles) -> Option<&Vec<u8>> {
383 self.values.get(path)
384 }
385
386 pub fn take_updates(&mut self) -> SparseTrieUpdates {
388 self.updates.take().unwrap_or_default()
389 }
390
391 pub fn reserve_nodes(&mut self, additional: usize) {
393 self.nodes.reserve(additional);
394 }
395
396 pub fn reveal_node(
398 &mut self,
399 path: Nibbles,
400 node: TrieNode,
401 masks: TrieMasks,
402 ) -> SparseTrieResult<()> {
403 if self.nodes.get(&path).is_some_and(|node| !node.is_hash()) {
405 return Ok(())
406 }
407
408 if let Some(tree_mask) = masks.tree_mask {
409 self.branch_node_tree_masks.insert(path.clone(), tree_mask);
410 }
411 if let Some(hash_mask) = masks.hash_mask {
412 self.branch_node_hash_masks.insert(path.clone(), hash_mask);
413 }
414
415 match node {
416 TrieNode::EmptyRoot => {
417 debug_assert!(path.is_empty());
418 self.nodes.insert(path, SparseNode::Empty);
419 }
420 TrieNode::Branch(branch) => {
421 let mut stack_ptr = branch.as_ref().first_child_index();
422 for idx in CHILD_INDEX_RANGE {
423 if branch.state_mask.is_bit_set(idx) {
424 let mut child_path = path.clone();
425 child_path.push_unchecked(idx);
426 self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
427 stack_ptr += 1;
428 }
429 }
430
431 match self.nodes.entry(path) {
432 Entry::Occupied(mut entry) => match entry.get() {
433 SparseNode::Hash(hash) => {
435 entry.insert(SparseNode::Branch {
436 state_mask: branch.state_mask,
437 hash: Some(*hash),
440 store_in_db_trie: Some(
441 masks.hash_mask.is_some_and(|mask| !mask.is_empty()) ||
442 masks.tree_mask.is_some_and(|mask| !mask.is_empty()),
443 ),
444 });
445 }
446 SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
449 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
451 return Err(SparseTrieErrorKind::Reveal {
452 path: entry.key().clone(),
453 node: Box::new(node.clone()),
454 }
455 .into())
456 }
457 },
458 Entry::Vacant(entry) => {
459 entry.insert(SparseNode::new_branch(branch.state_mask));
460 }
461 }
462 }
463 TrieNode::Extension(ext) => match self.nodes.entry(path) {
464 Entry::Occupied(mut entry) => match entry.get() {
465 SparseNode::Hash(hash) => {
466 let mut child_path = entry.key().clone();
467 child_path.extend_from_slice_unchecked(&ext.key);
468 entry.insert(SparseNode::Extension {
469 key: ext.key,
470 hash: Some(*hash),
473 store_in_db_trie: None,
474 });
475 self.reveal_node_or_hash(child_path, &ext.child)?;
476 }
477 SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
480 node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
482 return Err(SparseTrieErrorKind::Reveal {
483 path: entry.key().clone(),
484 node: Box::new(node.clone()),
485 }
486 .into())
487 }
488 },
489 Entry::Vacant(entry) => {
490 let mut child_path = entry.key().clone();
491 child_path.extend_from_slice_unchecked(&ext.key);
492 entry.insert(SparseNode::new_ext(ext.key));
493 self.reveal_node_or_hash(child_path, &ext.child)?;
494 }
495 },
496 TrieNode::Leaf(leaf) => match self.nodes.entry(path) {
497 Entry::Occupied(mut entry) => match entry.get() {
498 SparseNode::Hash(hash) => {
499 let mut full = entry.key().clone();
500 full.extend_from_slice_unchecked(&leaf.key);
501 self.values.insert(full, leaf.value);
502 entry.insert(SparseNode::Leaf {
503 key: leaf.key,
504 hash: Some(*hash),
507 });
508 }
509 SparseNode::Leaf { .. } => {}
511 node @ (SparseNode::Empty |
513 SparseNode::Extension { .. } |
514 SparseNode::Branch { .. }) => {
515 return Err(SparseTrieErrorKind::Reveal {
516 path: entry.key().clone(),
517 node: Box::new(node.clone()),
518 }
519 .into())
520 }
521 },
522 Entry::Vacant(entry) => {
523 let mut full = entry.key().clone();
524 full.extend_from_slice_unchecked(&leaf.key);
525 entry.insert(SparseNode::new_leaf(leaf.key));
526 self.values.insert(full, leaf.value);
527 }
528 },
529 }
530
531 Ok(())
532 }
533
534 fn reveal_node_or_hash(&mut self, path: Nibbles, child: &[u8]) -> SparseTrieResult<()> {
535 if child.len() == B256::len_bytes() + 1 {
536 let hash = B256::from_slice(&child[1..]);
537 match self.nodes.entry(path) {
538 Entry::Occupied(entry) => match entry.get() {
539 SparseNode::Hash(previous_hash) if previous_hash != &hash => {
541 return Err(SparseTrieErrorKind::Reveal {
542 path: entry.key().clone(),
543 node: Box::new(SparseNode::Hash(hash)),
544 }
545 .into())
546 }
547 _ => {}
548 },
549 Entry::Vacant(entry) => {
550 entry.insert(SparseNode::Hash(hash));
551 }
552 }
553 return Ok(())
554 }
555
556 self.reveal_node(path, TrieNode::decode(&mut &child[..])?, TrieMasks::none())
557 }
558
559 fn take_nodes_for_path(&mut self, path: &Nibbles) -> SparseTrieResult<Vec<RemovedSparseNode>> {
561 let mut current = Nibbles::default(); let mut nodes = Vec::new(); while let Some(node) = self.nodes.remove(¤t) {
565 match &node {
566 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
567 &SparseNode::Hash(hash) => {
568 return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
569 }
570 SparseNode::Leaf { key: _key, .. } => {
571 #[cfg(debug_assertions)]
575 {
576 let mut current = current.clone();
577 current.extend_from_slice_unchecked(_key);
578 assert_eq!(¤t, path);
579 }
580
581 nodes.push(RemovedSparseNode {
582 path: current.clone(),
583 node,
584 unset_branch_nibble: None,
585 });
586 break
587 }
588 SparseNode::Extension { key, .. } => {
589 #[cfg(debug_assertions)]
590 {
591 let mut current = current.clone();
592 current.extend_from_slice_unchecked(key);
593 assert!(
594 path.starts_with(¤t),
595 "path: {path:?}, current: {current:?}, key: {key:?}",
596 );
597 }
598
599 let path = current.clone();
600 current.extend_from_slice_unchecked(key);
601 nodes.push(RemovedSparseNode { path, node, unset_branch_nibble: None });
602 }
603 SparseNode::Branch { state_mask, .. } => {
604 let nibble = path[current.len()];
605 debug_assert!(
606 state_mask.is_bit_set(nibble),
607 "current: {current:?}, path: {path:?}, nibble: {nibble:?}, state_mask: {state_mask:?}",
608 );
609
610 let mut child_path =
616 Nibbles::from_nibbles([current.as_slice(), &[nibble]].concat());
617 let unset_branch_nibble = self
618 .nodes
619 .get(&child_path)
620 .is_some_and(move |node| match node {
621 SparseNode::Leaf { key, .. } => {
622 child_path.extend_from_slice_unchecked(key);
624 &child_path == path
625 }
626 _ => false,
627 })
628 .then_some(nibble);
629
630 nodes.push(RemovedSparseNode {
631 path: current.clone(),
632 node,
633 unset_branch_nibble,
634 });
635
636 current.push_unchecked(nibble);
637 }
638 }
639 }
640
641 Ok(nodes)
642 }
643
644 pub fn wipe(&mut self) {
646 self.nodes = HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]);
647 self.values = HashMap::default();
648 self.prefix_set = PrefixSetMut::all();
649 self.updates = self.updates.is_some().then(SparseTrieUpdates::wiped);
650 }
651
652 pub fn root(&mut self) -> B256 {
655 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
657 let rlp_node = self.rlp_node_allocate(&mut prefix_set);
658 if let Some(root_hash) = rlp_node.as_hash() {
659 root_hash
660 } else {
661 keccak256(rlp_node)
662 }
663 }
664
665 pub fn update_rlp_node_level(&mut self, depth: usize) {
668 let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
670 let mut buffers = RlpNodeBuffers::default();
671
672 let (targets, new_prefix_set) = self.get_changed_nodes_at_depth(&mut prefix_set, depth);
674 self.prefix_set = new_prefix_set;
676
677 trace!(target: "trie::sparse", ?depth, ?targets, "Updating nodes at depth");
678 for (level, path) in targets {
679 buffers.path_stack.push(RlpNodePathStackItem {
680 level,
681 path,
682 is_in_prefix_set: Some(true),
683 });
684 self.rlp_node(&mut prefix_set, &mut buffers);
685 }
686 }
687
688 fn get_changed_nodes_at_depth(
695 &self,
696 prefix_set: &mut PrefixSet,
697 depth: usize,
698 ) -> (Vec<(usize, Nibbles)>, PrefixSetMut) {
699 let mut unchanged_prefix_set = PrefixSetMut::default();
700 let mut paths = Vec::from([(Nibbles::default(), 0)]);
701 let mut targets = Vec::new();
702
703 while let Some((mut path, level)) = paths.pop() {
704 match self.nodes.get(&path).unwrap() {
705 SparseNode::Empty | SparseNode::Hash(_) => {}
706 SparseNode::Leaf { key: _, hash } => {
707 if hash.is_some() && !prefix_set.contains(&path) {
708 continue
709 }
710
711 targets.push((level, path));
712 }
713 SparseNode::Extension { key, hash, store_in_db_trie: _ } => {
714 if hash.is_some() && !prefix_set.contains(&path) {
715 continue
716 }
717
718 if level >= depth {
719 targets.push((level, path));
720 } else {
721 unchanged_prefix_set.insert(path.clone());
722
723 path.extend_from_slice_unchecked(key);
724 paths.push((path, level + 1));
725 }
726 }
727 SparseNode::Branch { state_mask, hash, store_in_db_trie: _ } => {
728 if hash.is_some() && !prefix_set.contains(&path) {
729 continue
730 }
731
732 if level >= depth {
733 targets.push((level, path));
734 } else {
735 unchanged_prefix_set.insert(path.clone());
736
737 for bit in CHILD_INDEX_RANGE.rev() {
738 if state_mask.is_bit_set(bit) {
739 let mut child_path = path.clone();
740 child_path.push_unchecked(bit);
741 paths.push((child_path, level + 1));
742 }
743 }
744 }
745 }
746 }
747 }
748
749 (targets, unchanged_prefix_set)
750 }
751
752 pub fn rlp_node_allocate(&mut self, prefix_set: &mut PrefixSet) -> RlpNode {
758 let mut buffers = RlpNodeBuffers::new_with_root_path();
759 self.rlp_node(prefix_set, &mut buffers)
760 }
761
762 pub fn rlp_node(
768 &mut self,
769 prefix_set: &mut PrefixSet,
770 buffers: &mut RlpNodeBuffers,
771 ) -> RlpNode {
772 let _starting_path = buffers.path_stack.last().map(|item| item.path.clone());
773
774 'main: while let Some(RlpNodePathStackItem { level, path, mut is_in_prefix_set }) =
775 buffers.path_stack.pop()
776 {
777 let node = self.nodes.get_mut(&path).unwrap();
778 trace!(
779 target: "trie::sparse",
780 ?_starting_path,
781 ?level,
782 ?path,
783 ?is_in_prefix_set,
784 ?node,
785 "Popped node from path stack"
786 );
787
788 let mut prefix_set_contains =
792 |path: &Nibbles| *is_in_prefix_set.get_or_insert_with(|| prefix_set.contains(path));
793
794 let (rlp_node, node_type) = match node {
795 SparseNode::Empty => (RlpNode::word_rlp(&EMPTY_ROOT_HASH), SparseNodeType::Empty),
796 SparseNode::Hash(hash) => (RlpNode::word_rlp(hash), SparseNodeType::Hash),
797 SparseNode::Leaf { key, hash } => {
798 let mut path = path.clone();
799 path.extend_from_slice_unchecked(key);
800 if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path)) {
801 (RlpNode::word_rlp(&hash), SparseNodeType::Leaf)
802 } else {
803 let value = self.values.get(&path).unwrap();
804 self.rlp_buf.clear();
805 let rlp_node = LeafNodeRef { key, value }.rlp(&mut self.rlp_buf);
806 *hash = rlp_node.as_hash();
807 (rlp_node, SparseNodeType::Leaf)
808 }
809 }
810 SparseNode::Extension { key, hash, store_in_db_trie } => {
811 let mut child_path = path.clone();
812 child_path.extend_from_slice_unchecked(key);
813 if let Some((hash, store_in_db_trie)) =
814 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
815 {
816 (
817 RlpNode::word_rlp(&hash),
818 SparseNodeType::Extension { store_in_db_trie: Some(store_in_db_trie) },
819 )
820 } else if buffers.rlp_node_stack.last().is_some_and(|e| e.path == child_path) {
821 let RlpNodeStackItem {
822 path: _,
823 rlp_node: child,
824 node_type: child_node_type,
825 } = buffers.rlp_node_stack.pop().unwrap();
826 self.rlp_buf.clear();
827 let rlp_node = ExtensionNodeRef::new(key, &child).rlp(&mut self.rlp_buf);
828 *hash = rlp_node.as_hash();
829
830 let store_in_db_trie_value = child_node_type.store_in_db_trie();
831
832 trace!(
833 target: "trie::sparse",
834 ?path,
835 ?child_path,
836 ?child_node_type,
837 "Extension node"
838 );
839
840 *store_in_db_trie = store_in_db_trie_value;
841
842 (
843 rlp_node,
844 SparseNodeType::Extension {
845 store_in_db_trie: store_in_db_trie_value,
848 },
849 )
850 } else {
851 buffers.path_stack.extend([
853 RlpNodePathStackItem { level, path, is_in_prefix_set },
854 RlpNodePathStackItem {
855 level: level + 1,
856 path: child_path,
857 is_in_prefix_set: None,
858 },
859 ]);
860 continue
861 }
862 }
863 SparseNode::Branch { state_mask, hash, store_in_db_trie } => {
864 if let Some((hash, store_in_db_trie)) =
865 hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
866 {
867 buffers.rlp_node_stack.push(RlpNodeStackItem {
868 path,
869 rlp_node: RlpNode::word_rlp(&hash),
870 node_type: SparseNodeType::Branch {
871 store_in_db_trie: Some(store_in_db_trie),
872 },
873 });
874 continue
875 }
876 let retain_updates = self.updates.is_some() && prefix_set_contains(&path);
877
878 buffers.branch_child_buf.clear();
879 for bit in CHILD_INDEX_RANGE.rev() {
882 if state_mask.is_bit_set(bit) {
883 let mut child = path.clone();
884 child.push_unchecked(bit);
885 buffers.branch_child_buf.push(child);
886 }
887 }
888
889 buffers
890 .branch_value_stack_buf
891 .resize(buffers.branch_child_buf.len(), Default::default());
892 let mut added_children = false;
893
894 let mut tree_mask = TrieMask::default();
895 let mut hash_mask = TrieMask::default();
896 let mut hashes = Vec::new();
897 for (i, child_path) in buffers.branch_child_buf.iter().enumerate() {
898 if buffers.rlp_node_stack.last().is_some_and(|e| &e.path == child_path) {
899 let RlpNodeStackItem {
900 path: _,
901 rlp_node: child,
902 node_type: child_node_type,
903 } = buffers.rlp_node_stack.pop().unwrap();
904
905 if retain_updates {
907 let last_child_nibble = child_path.last().unwrap();
909
910 let should_set_tree_mask_bit = if let Some(store_in_db_trie) =
912 child_node_type.store_in_db_trie()
913 {
914 store_in_db_trie
917 } else {
918 child_node_type.is_hash() &&
920 self.branch_node_tree_masks.get(&path).is_some_and(
921 |mask| mask.is_bit_set(last_child_nibble),
922 )
923 };
924 if should_set_tree_mask_bit {
925 tree_mask.set_bit(last_child_nibble);
926 }
927
928 let hash = child.as_hash().filter(|_| {
932 child_node_type.is_branch() ||
933 (child_node_type.is_hash() &&
934 self.branch_node_hash_masks
935 .get(&path)
936 .is_some_and(|mask| {
937 mask.is_bit_set(last_child_nibble)
938 }))
939 });
940 if let Some(hash) = hash {
941 hash_mask.set_bit(last_child_nibble);
942 hashes.push(hash);
943 }
944 }
945
946 let original_idx = buffers.branch_child_buf.len() - i - 1;
950 buffers.branch_value_stack_buf[original_idx] = child;
951 added_children = true;
952 } else {
953 debug_assert!(!added_children);
954 buffers.path_stack.push(RlpNodePathStackItem {
955 level,
956 path,
957 is_in_prefix_set,
958 });
959 buffers.path_stack.extend(buffers.branch_child_buf.drain(..).map(
960 |path| RlpNodePathStackItem {
961 level: level + 1,
962 path,
963 is_in_prefix_set: None,
964 },
965 ));
966 continue 'main
967 }
968 }
969
970 trace!(
971 target: "trie::sparse",
972 ?path,
973 ?tree_mask,
974 ?hash_mask,
975 "Branch node masks"
976 );
977
978 self.rlp_buf.clear();
979 let branch_node_ref =
980 BranchNodeRef::new(&buffers.branch_value_stack_buf, *state_mask);
981 let rlp_node = branch_node_ref.rlp(&mut self.rlp_buf);
982 *hash = rlp_node.as_hash();
983
984 let store_in_db_trie_value = if let Some(updates) =
987 self.updates.as_mut().filter(|_| retain_updates && !path.is_empty())
988 {
989 let store_in_db_trie = !tree_mask.is_empty() || !hash_mask.is_empty();
990 if store_in_db_trie {
991 hashes.reverse();
994 let branch_node = BranchNodeCompact::new(
995 *state_mask,
996 tree_mask,
997 hash_mask,
998 hashes,
999 hash.filter(|_| path.is_empty()),
1000 );
1001 updates.updated_nodes.insert(path.clone(), branch_node);
1002 } else if self
1003 .branch_node_tree_masks
1004 .get(&path)
1005 .is_some_and(|mask| !mask.is_empty()) ||
1006 self.branch_node_hash_masks
1007 .get(&path)
1008 .is_some_and(|mask| !mask.is_empty())
1009 {
1010 updates.updated_nodes.remove(&path);
1014 updates.removed_nodes.insert(path.clone());
1015 } else if self
1016 .branch_node_hash_masks
1017 .get(&path)
1018 .is_none_or(|mask| mask.is_empty()) &&
1019 self.branch_node_hash_masks
1020 .get(&path)
1021 .is_none_or(|mask| mask.is_empty())
1022 {
1023 updates.updated_nodes.remove(&path);
1026 }
1027
1028 store_in_db_trie
1029 } else {
1030 false
1031 };
1032 *store_in_db_trie = Some(store_in_db_trie_value);
1033
1034 (
1035 rlp_node,
1036 SparseNodeType::Branch { store_in_db_trie: Some(store_in_db_trie_value) },
1037 )
1038 }
1039 };
1040
1041 trace!(
1042 target: "trie::sparse",
1043 ?_starting_path,
1044 ?level,
1045 ?path,
1046 ?node,
1047 ?node_type,
1048 ?is_in_prefix_set,
1049 "Added node to rlp node stack"
1050 );
1051
1052 buffers.rlp_node_stack.push(RlpNodeStackItem { path, rlp_node, node_type });
1053 }
1054
1055 debug_assert_eq!(buffers.rlp_node_stack.len(), 1);
1056 buffers.rlp_node_stack.pop().unwrap().rlp_node
1057 }
1058}
1059
1060#[derive(Debug, Clone, PartialEq, Eq)]
1062pub enum LeafLookupError {
1063 BlindedNode {
1066 path: Nibbles,
1068 hash: B256,
1070 },
1071 ValueMismatch {
1074 path: Nibbles,
1076 expected: Option<Vec<u8>>,
1078 actual: Vec<u8>,
1080 },
1081}
1082
1083#[derive(Debug, Clone, PartialEq, Eq)]
1085pub enum LeafLookup {
1086 Exists,
1088 NonExistent {
1090 diverged_at: Nibbles,
1092 },
1093}
1094
1095impl<P: BlindedProvider> RevealedSparseTrie<P> {
1096 pub fn find_leaf(
1115 &self,
1116 path: &Nibbles,
1117 expected_value: Option<&Vec<u8>>,
1118 ) -> Result<LeafLookup, LeafLookupError> {
1119 fn check_value_match(
1121 actual_value: &Vec<u8>,
1122 expected_value: Option<&Vec<u8>>,
1123 path: &Nibbles,
1124 ) -> Result<(), LeafLookupError> {
1125 if let Some(expected) = expected_value {
1126 if actual_value != expected {
1127 return Err(LeafLookupError::ValueMismatch {
1128 path: path.clone(),
1129 expected: Some(expected.clone()),
1130 actual: actual_value.clone(),
1131 });
1132 }
1133 }
1134 Ok(())
1135 }
1136
1137 let mut current = Nibbles::default(); if let Some(actual_value) = self.values.get(path) {
1145 check_value_match(actual_value, expected_value, path)?;
1147 return Ok(LeafLookup::Exists);
1148 }
1149
1150 while current.len() < path.len() {
1157 match self.nodes.get(¤t) {
1158 Some(SparseNode::Empty) | None => {
1159 return Ok(LeafLookup::NonExistent { diverged_at: current });
1162 }
1163 Some(&SparseNode::Hash(hash)) => {
1164 return Err(LeafLookupError::BlindedNode { path: current.clone(), hash });
1166 }
1167 Some(SparseNode::Leaf { key, .. }) => {
1168 let saved_len = current.len();
1172 current.extend_from_slice_unchecked(key);
1173
1174 if ¤t == path {
1175 if let Some(value) = self.values.get(path) {
1177 check_value_match(value, expected_value, path)?;
1178 return Ok(LeafLookup::Exists);
1179 }
1180 }
1181
1182 let diverged_at = current.slice(..saved_len);
1183
1184 return Ok(LeafLookup::NonExistent { diverged_at });
1187 }
1188 Some(SparseNode::Extension { key, .. }) => {
1189 let saved_len = current.len();
1191 current.extend_from_slice_unchecked(key);
1192
1193 if path.len() < current.len() || !path.starts_with(¤t) {
1194 let diverged_at = current.slice(..saved_len);
1195 current.truncate(saved_len); return Ok(LeafLookup::NonExistent { diverged_at });
1197 }
1198 }
1200 Some(SparseNode::Branch { state_mask, .. }) => {
1201 let nibble = path[current.len()];
1203 if !state_mask.is_bit_set(nibble) {
1204 return Ok(LeafLookup::NonExistent { diverged_at: current });
1206 }
1207
1208 current.push_unchecked(nibble);
1210 }
1211 }
1212 }
1213
1214 match self.nodes.get(path) {
1217 Some(SparseNode::Leaf { key, .. }) if key.is_empty() => {
1218 if let Some(value) = self.values.get(path) {
1221 check_value_match(value, expected_value, path)?;
1222 return Ok(LeafLookup::Exists);
1223 }
1224 }
1225 Some(&SparseNode::Hash(hash)) => {
1226 return Err(LeafLookupError::BlindedNode { path: path.clone(), hash });
1227 }
1228 _ => {
1229 let parent_path = if path.is_empty() {
1231 Nibbles::default()
1232 } else {
1233 path.slice(0..path.len() - 1)
1234 };
1235 return Ok(LeafLookup::NonExistent { diverged_at: parent_path });
1236 }
1237 }
1238
1239 Ok(LeafLookup::NonExistent { diverged_at: current })
1241 }
1242
1243 pub fn update_leaf(&mut self, path: Nibbles, value: Vec<u8>) -> SparseTrieResult<()> {
1245 self.prefix_set.insert(path.clone());
1246 let existing = self.values.insert(path.clone(), value);
1247 if existing.is_some() {
1248 return Ok(())
1250 }
1251
1252 let mut current = Nibbles::default();
1253 while let Some(node) = self.nodes.get_mut(¤t) {
1254 match node {
1255 SparseNode::Empty => {
1256 *node = SparseNode::new_leaf(path);
1257 break
1258 }
1259 &mut SparseNode::Hash(hash) => {
1260 return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
1261 }
1262 SparseNode::Leaf { key: current_key, .. } => {
1263 current.extend_from_slice_unchecked(current_key);
1264
1265 if current == path {
1267 unreachable!("we already checked leaf presence in the beginning");
1268 }
1269
1270 let common = current.common_prefix_length(&path);
1272
1273 let new_ext_key = current.slice(current.len() - current_key.len()..common);
1275 *node = SparseNode::new_ext(new_ext_key);
1276
1277 self.nodes.reserve(3);
1279 self.nodes.insert(
1280 current.slice(..common),
1281 SparseNode::new_split_branch(current[common], path[common]),
1282 );
1283 self.nodes.insert(
1284 path.slice(..=common),
1285 SparseNode::new_leaf(path.slice(common + 1..)),
1286 );
1287 self.nodes.insert(
1288 current.slice(..=common),
1289 SparseNode::new_leaf(current.slice(common + 1..)),
1290 );
1291
1292 break;
1293 }
1294 SparseNode::Extension { key, .. } => {
1295 current.extend_from_slice(key);
1296
1297 if !path.starts_with(¤t) {
1298 let common = current.common_prefix_length(&path);
1300 *key = current.slice(current.len() - key.len()..common);
1301
1302 if self.updates.is_some() {
1306 if self.nodes.get(¤t).unwrap().is_hash() {
1308 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1309 self.provider.blinded_node(¤t)?
1310 {
1311 let decoded = TrieNode::decode(&mut &node[..])?;
1312 trace!(
1313 target: "trie::sparse",
1314 ?current,
1315 ?decoded,
1316 ?tree_mask,
1317 ?hash_mask,
1318 "Revealing extension node child",
1319 );
1320 self.reveal_node(
1321 current.clone(),
1322 decoded,
1323 TrieMasks { hash_mask, tree_mask },
1324 )?;
1325 }
1326 }
1327 }
1328
1329 self.nodes.reserve(3);
1332 let branch = SparseNode::new_split_branch(current[common], path[common]);
1333 self.nodes.insert(current.slice(..common), branch);
1334
1335 let new_leaf = SparseNode::new_leaf(path.slice(common + 1..));
1337 self.nodes.insert(path.slice(..=common), new_leaf);
1338
1339 let key = current.slice(common + 1..);
1341 if !key.is_empty() {
1342 self.nodes.insert(current.slice(..=common), SparseNode::new_ext(key));
1343 }
1344
1345 break;
1346 }
1347 }
1348 SparseNode::Branch { state_mask, .. } => {
1349 let nibble = path[current.len()];
1350 current.push_unchecked(nibble);
1351 if !state_mask.is_bit_set(nibble) {
1352 state_mask.set_bit(nibble);
1353 let new_leaf = SparseNode::new_leaf(path.slice(current.len()..));
1354 self.nodes.insert(current, new_leaf);
1355 break;
1356 }
1357 }
1358 };
1359 }
1360
1361 Ok(())
1362 }
1363
1364 pub fn remove_leaf(&mut self, path: &Nibbles) -> SparseTrieResult<()> {
1366 if self.values.remove(path).is_none() {
1367 if let Some(&SparseNode::Hash(hash)) = self.nodes.get(path) {
1368 return Err(SparseTrieErrorKind::BlindedNode { path: path.clone(), hash }.into())
1370 }
1371
1372 trace!(target: "trie::sparse", ?path, "Leaf node is not present in the trie");
1373 return Ok(())
1375 }
1376 self.prefix_set.insert(path.clone());
1377
1378 let mut removed_nodes = self.take_nodes_for_path(path)?;
1383 trace!(target: "trie::sparse", ?path, ?removed_nodes, "Removed nodes for path");
1384 let mut child = removed_nodes.pop().expect("leaf exists");
1386 #[cfg(debug_assertions)]
1387 {
1388 let mut child_path = child.path.clone();
1389 let SparseNode::Leaf { key, .. } = &child.node else { panic!("expected leaf node") };
1390 child_path.extend_from_slice_unchecked(key);
1391 assert_eq!(&child_path, path);
1392 }
1393
1394 if removed_nodes.is_empty() {
1396 debug_assert!(self.nodes.is_empty());
1397 self.nodes.insert(Nibbles::default(), SparseNode::Empty);
1398
1399 return Ok(())
1400 }
1401
1402 while let Some(removed_node) = removed_nodes.pop() {
1405 let removed_path = removed_node.path;
1406
1407 let new_node = match &removed_node.node {
1408 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
1409 &SparseNode::Hash(hash) => {
1410 return Err(SparseTrieErrorKind::BlindedNode { path: removed_path, hash }.into())
1411 }
1412 SparseNode::Leaf { .. } => {
1413 unreachable!("we already popped the leaf node")
1414 }
1415 SparseNode::Extension { key, .. } => {
1416 match &child.node {
1419 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
1420 &SparseNode::Hash(hash) => {
1421 return Err(
1422 SparseTrieErrorKind::BlindedNode { path: child.path, hash }.into()
1423 )
1424 }
1425 SparseNode::Leaf { key: leaf_key, .. } => {
1431 self.nodes.remove(&child.path);
1432
1433 let mut new_key = key.clone();
1434 new_key.extend_from_slice_unchecked(leaf_key);
1435 SparseNode::new_leaf(new_key)
1436 }
1437 SparseNode::Extension { key: extension_key, .. } => {
1440 self.nodes.remove(&child.path);
1441
1442 let mut new_key = key.clone();
1443 new_key.extend_from_slice_unchecked(extension_key);
1444 SparseNode::new_ext(new_key)
1445 }
1446 SparseNode::Branch { .. } => removed_node.node,
1448 }
1449 }
1450 &SparseNode::Branch { mut state_mask, hash: _, store_in_db_trie: _ } => {
1451 if let Some(removed_nibble) = removed_node.unset_branch_nibble {
1455 state_mask.unset_bit(removed_nibble);
1456 }
1457
1458 if state_mask.count_bits() == 1 {
1460 let child_nibble =
1461 state_mask.first_set_bit_index().expect("state mask is not empty");
1462
1463 let mut child_path = removed_path.clone();
1465 child_path.push_unchecked(child_nibble);
1466
1467 trace!(target: "trie::sparse", ?removed_path, ?child_path, "Branch node has only one child");
1468
1469 if self.nodes.get(&child_path).unwrap().is_hash() {
1470 trace!(target: "trie::sparse", ?child_path, "Retrieving remaining blinded branch child");
1471 if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1472 self.provider.blinded_node(&child_path)?
1473 {
1474 let decoded = TrieNode::decode(&mut &node[..])?;
1475 trace!(
1476 target: "trie::sparse",
1477 ?child_path,
1478 ?decoded,
1479 ?tree_mask,
1480 ?hash_mask,
1481 "Revealing remaining blinded branch child"
1482 );
1483 self.reveal_node(
1484 child_path.clone(),
1485 decoded,
1486 TrieMasks { hash_mask, tree_mask },
1487 )?;
1488 }
1489 }
1490
1491 let child = self.nodes.get(&child_path).unwrap();
1493
1494 let mut delete_child = false;
1495 let new_node = match child {
1496 SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
1497 &SparseNode::Hash(hash) => {
1498 return Err(SparseTrieErrorKind::BlindedNode {
1499 path: child_path,
1500 hash,
1501 }
1502 .into())
1503 }
1504 SparseNode::Leaf { key, .. } => {
1508 delete_child = true;
1509
1510 let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
1511 new_key.extend_from_slice_unchecked(key);
1512 SparseNode::new_leaf(new_key)
1513 }
1514 SparseNode::Extension { key, .. } => {
1518 delete_child = true;
1519
1520 let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
1521 new_key.extend_from_slice_unchecked(key);
1522 SparseNode::new_ext(new_key)
1523 }
1524 SparseNode::Branch { .. } => {
1527 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([child_nibble]))
1528 }
1529 };
1530
1531 if delete_child {
1532 self.nodes.remove(&child_path);
1533 }
1534
1535 if let Some(updates) = self.updates.as_mut() {
1536 updates.updated_nodes.remove(&removed_path);
1537 updates.removed_nodes.insert(removed_path.clone());
1538 }
1539
1540 new_node
1541 }
1542 else {
1544 SparseNode::new_branch(state_mask)
1545 }
1546 }
1547 };
1548
1549 child = RemovedSparseNode {
1550 path: removed_path.clone(),
1551 node: new_node.clone(),
1552 unset_branch_nibble: None,
1553 };
1554 trace!(target: "trie::sparse", ?removed_path, ?new_node, "Re-inserting the node");
1555 self.nodes.insert(removed_path, new_node);
1556 }
1557
1558 Ok(())
1559 }
1560}
1561
1562#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1564enum SparseNodeType {
1565 Empty,
1567 Hash,
1569 Leaf,
1571 Extension {
1573 store_in_db_trie: Option<bool>,
1575 },
1576 Branch {
1578 store_in_db_trie: Option<bool>,
1580 },
1581}
1582
1583impl SparseNodeType {
1584 const fn is_hash(&self) -> bool {
1585 matches!(self, Self::Hash)
1586 }
1587
1588 const fn is_branch(&self) -> bool {
1589 matches!(self, Self::Branch { .. })
1590 }
1591
1592 const fn store_in_db_trie(&self) -> Option<bool> {
1593 match *self {
1594 Self::Extension { store_in_db_trie } | Self::Branch { store_in_db_trie } => {
1595 store_in_db_trie
1596 }
1597 _ => None,
1598 }
1599 }
1600}
1601
1602#[derive(Debug, Clone, PartialEq, Eq)]
1604pub enum SparseNode {
1605 Empty,
1607 Hash(B256),
1609 Leaf {
1611 key: Nibbles,
1613 hash: Option<B256>,
1616 },
1617 Extension {
1619 key: Nibbles,
1621 hash: Option<B256>,
1626 store_in_db_trie: Option<bool>,
1631 },
1632 Branch {
1634 state_mask: TrieMask,
1636 hash: Option<B256>,
1641 store_in_db_trie: Option<bool>,
1646 },
1647}
1648
1649impl SparseNode {
1650 pub fn from_node(node: TrieNode) -> Self {
1652 match node {
1653 TrieNode::EmptyRoot => Self::Empty,
1654 TrieNode::Leaf(leaf) => Self::new_leaf(leaf.key),
1655 TrieNode::Extension(ext) => Self::new_ext(ext.key),
1656 TrieNode::Branch(branch) => Self::new_branch(branch.state_mask),
1657 }
1658 }
1659
1660 pub const fn new_branch(state_mask: TrieMask) -> Self {
1662 Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1663 }
1664
1665 pub const fn new_split_branch(bit_a: u8, bit_b: u8) -> Self {
1667 let state_mask = TrieMask::new(
1668 (1u16 << bit_a) | (1u16 << bit_b),
1670 );
1671 Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1672 }
1673
1674 pub const fn new_ext(key: Nibbles) -> Self {
1676 Self::Extension { key, hash: None, store_in_db_trie: None }
1677 }
1678
1679 pub const fn new_leaf(key: Nibbles) -> Self {
1681 Self::Leaf { key, hash: None }
1682 }
1683
1684 pub const fn is_hash(&self) -> bool {
1686 matches!(self, Self::Hash(_))
1687 }
1688}
1689
1690#[derive(Debug)]
1691struct RemovedSparseNode {
1692 path: Nibbles,
1693 node: SparseNode,
1694 unset_branch_nibble: Option<u8>,
1695}
1696
1697#[derive(Debug, Default)]
1699pub struct RlpNodeBuffers {
1700 path_stack: Vec<RlpNodePathStackItem>,
1702 rlp_node_stack: Vec<RlpNodeStackItem>,
1704 branch_child_buf: SmallVec<[Nibbles; 16]>,
1706 branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
1708}
1709
1710impl RlpNodeBuffers {
1711 fn new_with_root_path() -> Self {
1713 Self {
1714 path_stack: vec![RlpNodePathStackItem {
1715 level: 0,
1716 path: Nibbles::default(),
1717 is_in_prefix_set: None,
1718 }],
1719 rlp_node_stack: Vec::new(),
1720 branch_child_buf: SmallVec::<[Nibbles; 16]>::new_const(),
1721 branch_value_stack_buf: SmallVec::<[RlpNode; 16]>::new_const(),
1722 }
1723 }
1724}
1725
1726#[derive(Debug)]
1728struct RlpNodePathStackItem {
1729 level: usize,
1731 path: Nibbles,
1733 is_in_prefix_set: Option<bool>,
1735}
1736
1737#[derive(Debug)]
1739struct RlpNodeStackItem {
1740 path: Nibbles,
1742 rlp_node: RlpNode,
1744 node_type: SparseNodeType,
1746}
1747
1748#[derive(Debug, Clone, Default, PartialEq, Eq)]
1750pub struct SparseTrieUpdates {
1751 pub(crate) updated_nodes: HashMap<Nibbles, BranchNodeCompact>,
1752 pub(crate) removed_nodes: HashSet<Nibbles>,
1753 pub(crate) wiped: bool,
1754}
1755
1756impl SparseTrieUpdates {
1757 pub fn wiped() -> Self {
1759 Self { wiped: true, ..Default::default() }
1760 }
1761}
1762
1763#[cfg(test)]
1764mod find_leaf_tests {
1765 use super::*;
1766 use crate::blinded::DefaultBlindedProvider;
1767 use alloy_primitives::map::foldhash::fast::RandomState;
1768 use alloy_rlp::Encodable;
1770 use assert_matches::assert_matches;
1771 use reth_primitives_traits::Account;
1772 use reth_trie_common::LeafNode;
1773
1774 fn encode_value(nonce: u64) -> Vec<u8> {
1776 let account = Account { nonce, ..Default::default() };
1777 let trie_account = account.into_trie_account(EMPTY_ROOT_HASH);
1778 let mut buf = Vec::new();
1779 trie_account.encode(&mut buf);
1780 buf
1781 }
1782
1783 const VALUE_A: fn() -> Vec<u8> = || encode_value(1);
1784 const VALUE_B: fn() -> Vec<u8> = || encode_value(2);
1785
1786 #[test]
1787 fn find_leaf_existing_leaf() {
1788 let mut sparse = RevealedSparseTrie::default();
1790 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
1791 let value = b"test_value".to_vec();
1792
1793 sparse.update_leaf(path.clone(), value.clone()).unwrap();
1794
1795 let result = sparse.find_leaf(&path, None);
1797 assert_matches!(result, Ok(LeafLookup::Exists));
1798
1799 let result = sparse.find_leaf(&path, Some(&value));
1801 assert_matches!(result, Ok(LeafLookup::Exists));
1802 }
1803
1804 #[test]
1805 fn find_leaf_value_mismatch() {
1806 let mut sparse = RevealedSparseTrie::default();
1808 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
1809 let value = b"test_value".to_vec();
1810 let wrong_value = b"wrong_value".to_vec();
1811
1812 sparse.update_leaf(path.clone(), value).unwrap();
1813
1814 let result = sparse.find_leaf(&path, Some(&wrong_value));
1816 assert_matches!(
1817 result,
1818 Err(LeafLookupError::ValueMismatch { path: p, expected: Some(e), actual: _a }) if p == path && e == wrong_value
1819 );
1820 }
1821
1822 #[test]
1823 fn find_leaf_not_found_empty_trie() {
1824 let sparse = RevealedSparseTrie::default();
1826 let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
1827
1828 let result = sparse.find_leaf(&path, None);
1830 assert_matches!(
1831 result,
1832 Ok(LeafLookup::NonExistent { diverged_at }) if diverged_at == Nibbles::default()
1833 );
1834 }
1835
1836 #[test]
1837 fn find_leaf_empty_trie() {
1838 let sparse = RevealedSparseTrie::<DefaultBlindedProvider>::default();
1839 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
1840
1841 let result = sparse.find_leaf(&path, None);
1842
1843 assert_matches!(result, Ok(LeafLookup::NonExistent { diverged_at }) if diverged_at == Nibbles::default());
1845 }
1846
1847 #[test]
1848 fn find_leaf_exists_no_value_check() {
1849 let mut sparse = RevealedSparseTrie::<DefaultBlindedProvider>::default();
1850 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
1851 sparse.update_leaf(path.clone(), VALUE_A()).unwrap();
1852
1853 let result = sparse.find_leaf(&path, None);
1854 assert_matches!(result, Ok(LeafLookup::Exists));
1855 }
1856
1857 #[test]
1858 fn find_leaf_exists_with_value_check_ok() {
1859 let mut sparse = RevealedSparseTrie::<DefaultBlindedProvider>::default();
1860 let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
1861 let value = VALUE_A();
1862 sparse.update_leaf(path.clone(), value.clone()).unwrap();
1863
1864 let result = sparse.find_leaf(&path, Some(&value));
1865 assert_matches!(result, Ok(LeafLookup::Exists));
1866 }
1867
1868 #[test]
1869 fn find_leaf_exclusion_branch_divergence() {
1870 let mut sparse = RevealedSparseTrie::<DefaultBlindedProvider>::default();
1871 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()).unwrap();
1876 sparse.update_leaf(path2, VALUE_B()).unwrap();
1877
1878 let result = sparse.find_leaf(&search_path, None);
1879
1880 let expected_divergence = Nibbles::from_nibbles_unchecked([0x1, 0x2]);
1882 assert_matches!(result, Ok(LeafLookup::NonExistent { diverged_at }) if diverged_at == expected_divergence);
1883 }
1884
1885 #[test]
1886 fn find_leaf_exclusion_extension_divergence() {
1887 let mut sparse = RevealedSparseTrie::<DefaultBlindedProvider>::default();
1888 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
1890 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]);
1892
1893 sparse.update_leaf(path1, VALUE_A()).unwrap();
1894
1895 let result = sparse.find_leaf(&search_path, None);
1896
1897 let expected_divergence = Nibbles::default();
1899 assert_matches!(result, Ok(LeafLookup::NonExistent { diverged_at }) if diverged_at == expected_divergence);
1900 }
1901
1902 #[test]
1903 fn find_leaf_exclusion_leaf_divergence() {
1904 let mut sparse = RevealedSparseTrie::<DefaultBlindedProvider>::default();
1905 let existing_leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
1906 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
1907
1908 sparse.update_leaf(existing_leaf_path, VALUE_A()).unwrap();
1909
1910 let result = sparse.find_leaf(&search_path, None);
1911
1912 let expected_divergence = Nibbles::default();
1916 assert_matches!(result, Ok(LeafLookup::NonExistent { diverged_at }) if diverged_at == expected_divergence);
1917 }
1918
1919 #[test]
1920 fn find_leaf_exclusion_path_ends_at_branch() {
1921 let mut sparse = RevealedSparseTrie::<DefaultBlindedProvider>::default();
1922 let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]);
1924 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2]); sparse.update_leaf(path1, VALUE_A()).unwrap();
1927 sparse.update_leaf(path2, VALUE_B()).unwrap();
1928
1929 let result = sparse.find_leaf(&search_path, None);
1930
1931 let expected_divergence = Nibbles::from_nibbles_unchecked([0x1]);
1934 assert_matches!(result, Ok(LeafLookup::NonExistent { diverged_at }) if diverged_at == expected_divergence);
1935 }
1936
1937 #[test]
1938 fn find_leaf_error_blinded_node_at_leaf_path() {
1939 let blinded_hash = B256::repeat_byte(0xBB);
1941 let leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
1942
1943 let mut nodes = alloy_primitives::map::HashMap::with_hasher(RandomState::default());
1944 nodes.insert(
1946 Nibbles::default(),
1947 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x1, 0x2])),
1948 ); nodes.insert(
1950 Nibbles::from_nibbles_unchecked([0x1, 0x2]),
1951 SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x3])),
1952 ); nodes.insert(
1954 Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3]),
1955 SparseNode::new_branch(TrieMask::new(0b10000)),
1956 ); nodes.insert(leaf_path.clone(), SparseNode::Hash(blinded_hash)); let sparse = RevealedSparseTrie {
1960 provider: DefaultBlindedProvider,
1961 nodes,
1962 branch_node_tree_masks: Default::default(),
1963 branch_node_hash_masks: Default::default(),
1964 values: Default::default(),
1966 prefix_set: Default::default(),
1967 updates: None,
1968 rlp_buf: Vec::new(),
1969 };
1970
1971 let result = sparse.find_leaf(&leaf_path, None);
1972
1973 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
1975 if path == leaf_path && hash == blinded_hash
1976 );
1977 }
1978
1979 #[test]
1980 fn find_leaf_error_blinded_node() {
1981 let blinded_hash = B256::repeat_byte(0xAA);
1982 let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]);
1983 let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
1984
1985 let mut nodes = HashMap::with_hasher(RandomState::default());
1986
1987 let state_mask = TrieMask::new(0b100010);
1990 nodes.insert(Nibbles::default(), SparseNode::new_branch(state_mask));
1991
1992 nodes.insert(path_to_blind.clone(), SparseNode::Hash(blinded_hash));
1993 let path_revealed = Nibbles::from_nibbles_unchecked([0x5]);
1994 let path_revealed_leaf = Nibbles::from_nibbles_unchecked([0x5, 0x6, 0x7, 0x8]);
1995 nodes.insert(
1996 path_revealed,
1997 SparseNode::new_leaf(Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8])),
1998 );
1999
2000 let mut values = HashMap::with_hasher(RandomState::default());
2001 values.insert(path_revealed_leaf, VALUE_A());
2002
2003 let sparse = RevealedSparseTrie {
2004 provider: DefaultBlindedProvider,
2005 nodes,
2006 branch_node_tree_masks: Default::default(),
2007 branch_node_hash_masks: Default::default(),
2008 values,
2009 prefix_set: Default::default(),
2010 updates: None,
2011 rlp_buf: Vec::new(),
2012 };
2013
2014 let result = sparse.find_leaf(&search_path, None);
2015
2016 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2018 if path == path_to_blind && hash == blinded_hash
2019 );
2020 }
2021
2022 #[test]
2023 fn find_leaf_error_blinded_node_via_reveal() {
2024 let blinded_hash = B256::repeat_byte(0xAA);
2025 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]);
2029 let revealed_leaf_suffix = Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8]);
2030 let revealed_leaf_full_path = Nibbles::from_nibbles_unchecked([0x5, 0x6, 0x7, 0x8]);
2031 let revealed_value = VALUE_A();
2032
2033 let rlp_node_child1 = RlpNode::word_rlp(&blinded_hash); let leaf_node_child5 = LeafNode::new(revealed_leaf_suffix.clone(), revealed_value.clone());
2037 let leaf_node_child5_rlp_buf = alloy_rlp::encode(&leaf_node_child5);
2038 let hash_of_child5 = keccak256(&leaf_node_child5_rlp_buf);
2039 let rlp_node_child5 = RlpNode::word_rlp(&hash_of_child5);
2040
2041 let root_branch_node = reth_trie_common::BranchNode::new(
2044 vec![rlp_node_child1, rlp_node_child5], TrieMask::new(0b100010), );
2047 let root_trie_node = TrieNode::Branch(root_branch_node);
2048
2049 let mut sparse = RevealedSparseTrie::from_root(root_trie_node, TrieMasks::none(), false)
2052 .expect("Failed to create trie from root");
2053
2054 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 );
2057 assert!(sparse.nodes.get(&revealed_leaf_prefix).unwrap().is_hash()); assert!(sparse.values.is_empty());
2059
2060 sparse
2062 .reveal_node(
2063 revealed_leaf_prefix.clone(),
2064 TrieNode::Leaf(leaf_node_child5),
2065 TrieMasks::none(),
2066 )
2067 .expect("Failed to reveal leaf node");
2068
2069 assert_matches!(sparse.nodes.get(&Nibbles::default()), Some(SparseNode::Branch { state_mask, .. }) if *state_mask == TrieMask::new(0b100010));
2071 assert_matches!(sparse.nodes.get(&path_to_blind), Some(SparseNode::Hash(h)) if *h == blinded_hash );
2072 assert_matches!(sparse.nodes.get(&revealed_leaf_prefix), Some(SparseNode::Leaf { key, .. }) if *key == revealed_leaf_suffix);
2073 assert_eq!(sparse.values.get(&revealed_leaf_full_path), Some(&revealed_value));
2074
2075 let result = sparse.find_leaf(&search_path, None);
2076
2077 assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2080 if path == path_to_blind && hash == blinded_hash
2081 );
2082 }
2083}
2084
2085#[cfg(test)]
2086mod tests {
2087 use super::*;
2088 use alloy_primitives::{map::B256Set, U256};
2089 use alloy_rlp::Encodable;
2090 use assert_matches::assert_matches;
2091 use itertools::Itertools;
2092 use prop::sample::SizeRange;
2093 use proptest::prelude::*;
2094 use proptest_arbitrary_interop::arb;
2095 use reth_primitives_traits::Account;
2096 use reth_provider::{test_utils::create_test_provider_factory, TrieWriter};
2097 use reth_trie::{
2098 hashed_cursor::{noop::NoopHashedAccountCursor, HashedPostStateAccountCursor},
2099 node_iter::{TrieElement, TrieNodeIter},
2100 trie_cursor::{noop::NoopAccountTrieCursor, TrieCursor, TrieCursorFactory},
2101 walker::TrieWalker,
2102 BranchNode, ExtensionNode, HashedPostState, LeafNode,
2103 };
2104 use reth_trie_common::{
2105 proof::{ProofNodes, ProofRetainer},
2106 updates::TrieUpdates,
2107 HashBuilder,
2108 };
2109 use reth_trie_db::DatabaseTrieCursorFactory;
2110 use std::collections::{BTreeMap, BTreeSet};
2111
2112 fn pad_nibbles_left(nibbles: Nibbles) -> Nibbles {
2114 let mut base =
2115 Nibbles::from_nibbles_unchecked(vec![0; B256::len_bytes() * 2 - nibbles.len()]);
2116 base.extend_from_slice_unchecked(&nibbles);
2117 base
2118 }
2119
2120 fn pad_nibbles_right(mut nibbles: Nibbles) -> Nibbles {
2122 nibbles.extend_from_slice_unchecked(&vec![0; B256::len_bytes() * 2 - nibbles.len()]);
2123 nibbles
2124 }
2125
2126 fn run_hash_builder(
2131 state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
2132 trie_cursor: impl TrieCursor,
2133 destroyed_accounts: B256Set,
2134 proof_targets: impl IntoIterator<Item = Nibbles>,
2135 ) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>, HashMap<Nibbles, TrieMask>)
2136 {
2137 let mut account_rlp = Vec::new();
2138
2139 let mut hash_builder = HashBuilder::default()
2140 .with_updates(true)
2141 .with_proof_retainer(ProofRetainer::from_iter(proof_targets));
2142
2143 let mut prefix_set = PrefixSetMut::default();
2144 prefix_set.extend_keys(state.clone().into_iter().map(|(nibbles, _)| nibbles));
2145 prefix_set.extend_keys(destroyed_accounts.iter().map(Nibbles::unpack));
2146 let walker =
2147 TrieWalker::new(trie_cursor, prefix_set.freeze()).with_deletions_retained(true);
2148 let hashed_post_state = HashedPostState::default()
2149 .with_accounts(state.into_iter().map(|(nibbles, account)| {
2150 (nibbles.pack().into_inner().unwrap().into(), Some(account))
2151 }))
2152 .into_sorted();
2153 let mut node_iter = TrieNodeIter::state_trie(
2154 walker,
2155 HashedPostStateAccountCursor::new(
2156 NoopHashedAccountCursor::default(),
2157 hashed_post_state.accounts(),
2158 ),
2159 );
2160
2161 while let Some(node) = node_iter.try_next().unwrap() {
2162 match node {
2163 TrieElement::Branch(branch) => {
2164 hash_builder.add_branch(branch.key, branch.value, branch.children_are_in_trie);
2165 }
2166 TrieElement::Leaf(key, account) => {
2167 let account = account.into_trie_account(EMPTY_ROOT_HASH);
2168 account.encode(&mut account_rlp);
2169
2170 hash_builder.add_leaf(Nibbles::unpack(key), &account_rlp);
2171 account_rlp.clear();
2172 }
2173 }
2174 }
2175 let root = hash_builder.root();
2176 let proof_nodes = hash_builder.take_proof_nodes();
2177 let branch_node_hash_masks = hash_builder
2178 .updated_branch_nodes
2179 .clone()
2180 .unwrap_or_default()
2181 .iter()
2182 .map(|(path, node)| (path.clone(), node.hash_mask))
2183 .collect();
2184 let branch_node_tree_masks = hash_builder
2185 .updated_branch_nodes
2186 .clone()
2187 .unwrap_or_default()
2188 .iter()
2189 .map(|(path, node)| (path.clone(), node.tree_mask))
2190 .collect();
2191
2192 let mut trie_updates = TrieUpdates::default();
2193 let removed_keys = node_iter.walker.take_removed_keys();
2194 trie_updates.finalize(hash_builder, removed_keys, destroyed_accounts);
2195
2196 (root, trie_updates, proof_nodes, branch_node_hash_masks, branch_node_tree_masks)
2197 }
2198
2199 fn assert_eq_sparse_trie_proof_nodes(
2201 sparse_trie: &RevealedSparseTrie,
2202 proof_nodes: ProofNodes,
2203 ) {
2204 let proof_nodes = proof_nodes
2205 .into_nodes_sorted()
2206 .into_iter()
2207 .map(|(path, node)| (path, TrieNode::decode(&mut node.as_ref()).unwrap()));
2208
2209 let sparse_nodes = sparse_trie.nodes.iter().sorted_by_key(|(path, _)| *path);
2210
2211 for ((proof_node_path, proof_node), (sparse_node_path, sparse_node)) in
2212 proof_nodes.zip(sparse_nodes)
2213 {
2214 assert_eq!(&proof_node_path, sparse_node_path);
2215
2216 let equals = match (&proof_node, &sparse_node) {
2217 (TrieNode::EmptyRoot, SparseNode::Empty) => true,
2219 (
2221 TrieNode::Branch(BranchNode { state_mask: proof_state_mask, .. }),
2222 SparseNode::Branch { state_mask: sparse_state_mask, .. },
2223 ) => proof_state_mask == sparse_state_mask,
2224 (
2226 TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
2227 SparseNode::Extension { key: sparse_key, .. },
2228 ) |
2229 (
2231 TrieNode::Leaf(LeafNode { key: proof_key, .. }),
2232 SparseNode::Leaf { key: sparse_key, .. },
2233 ) => proof_key == sparse_key,
2234 (_, SparseNode::Empty | SparseNode::Hash(_)) => continue,
2236 _ => false,
2237 };
2238 assert!(
2239 equals,
2240 "path: {proof_node_path:?}\nproof node: {proof_node:?}\nsparse node: {sparse_node:?}"
2241 );
2242 }
2243 }
2244
2245 #[test]
2246 fn sparse_trie_is_blind() {
2247 assert!(SparseTrie::blind().is_blind());
2248 assert!(!SparseTrie::revealed_empty().is_blind());
2249 }
2250
2251 #[test]
2252 fn sparse_trie_empty_update_one() {
2253 let key = Nibbles::unpack(B256::with_last_byte(42));
2254 let value = || Account::default();
2255 let value_encoded = || {
2256 let mut account_rlp = Vec::new();
2257 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2258 account_rlp
2259 };
2260
2261 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2262 run_hash_builder(
2263 [(key.clone(), value())],
2264 NoopAccountTrieCursor::default(),
2265 Default::default(),
2266 [key.clone()],
2267 );
2268
2269 let mut sparse = RevealedSparseTrie::default().with_updates(true);
2270 sparse.update_leaf(key, value_encoded()).unwrap();
2271 let sparse_root = sparse.root();
2272 let sparse_updates = sparse.take_updates();
2273
2274 assert_eq!(sparse_root, hash_builder_root);
2275 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2276 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2277 }
2278
2279 #[test]
2280 fn sparse_trie_empty_update_multiple_lower_nibbles() {
2281 reth_tracing::init_test_tracing();
2282
2283 let paths = (0..=16).map(|b| Nibbles::unpack(B256::with_last_byte(b))).collect::<Vec<_>>();
2284 let value = || Account::default();
2285 let value_encoded = || {
2286 let mut account_rlp = Vec::new();
2287 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2288 account_rlp
2289 };
2290
2291 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2292 run_hash_builder(
2293 paths.iter().cloned().zip(std::iter::repeat_with(value)),
2294 NoopAccountTrieCursor::default(),
2295 Default::default(),
2296 paths.clone(),
2297 );
2298
2299 let mut sparse = RevealedSparseTrie::default().with_updates(true);
2300 for path in &paths {
2301 sparse.update_leaf(path.clone(), value_encoded()).unwrap();
2302 }
2303 let sparse_root = sparse.root();
2304 let sparse_updates = sparse.take_updates();
2305
2306 assert_eq!(sparse_root, hash_builder_root);
2307 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2308 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2309 }
2310
2311 #[test]
2312 fn sparse_trie_empty_update_multiple_upper_nibbles() {
2313 let paths = (239..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
2314 let value = || Account::default();
2315 let value_encoded = || {
2316 let mut account_rlp = Vec::new();
2317 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2318 account_rlp
2319 };
2320
2321 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2322 run_hash_builder(
2323 paths.iter().cloned().zip(std::iter::repeat_with(value)),
2324 NoopAccountTrieCursor::default(),
2325 Default::default(),
2326 paths.clone(),
2327 );
2328
2329 let mut sparse = RevealedSparseTrie::default().with_updates(true);
2330 for path in &paths {
2331 sparse.update_leaf(path.clone(), value_encoded()).unwrap();
2332 }
2333 let sparse_root = sparse.root();
2334 let sparse_updates = sparse.take_updates();
2335
2336 assert_eq!(sparse_root, hash_builder_root);
2337 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2338 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2339 }
2340
2341 #[test]
2342 fn sparse_trie_empty_update_multiple() {
2343 let paths = (0..=255)
2344 .map(|b| {
2345 Nibbles::unpack(if b % 2 == 0 {
2346 B256::repeat_byte(b)
2347 } else {
2348 B256::with_last_byte(b)
2349 })
2350 })
2351 .collect::<Vec<_>>();
2352 let value = || Account::default();
2353 let value_encoded = || {
2354 let mut account_rlp = Vec::new();
2355 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2356 account_rlp
2357 };
2358
2359 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2360 run_hash_builder(
2361 paths.iter().sorted_unstable().cloned().zip(std::iter::repeat_with(value)),
2362 NoopAccountTrieCursor::default(),
2363 Default::default(),
2364 paths.clone(),
2365 );
2366
2367 let mut sparse = RevealedSparseTrie::default().with_updates(true);
2368 for path in &paths {
2369 sparse.update_leaf(path.clone(), value_encoded()).unwrap();
2370 }
2371 let sparse_root = sparse.root();
2372 let sparse_updates = sparse.take_updates();
2373
2374 assert_eq!(sparse_root, hash_builder_root);
2375 pretty_assertions::assert_eq!(
2376 BTreeMap::from_iter(sparse_updates.updated_nodes),
2377 BTreeMap::from_iter(hash_builder_updates.account_nodes)
2378 );
2379 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2380 }
2381
2382 #[test]
2383 fn sparse_trie_empty_update_repeated() {
2384 let paths = (0..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
2385 let old_value = Account { nonce: 1, ..Default::default() };
2386 let old_value_encoded = {
2387 let mut account_rlp = Vec::new();
2388 old_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2389 account_rlp
2390 };
2391 let new_value = Account { nonce: 2, ..Default::default() };
2392 let new_value_encoded = {
2393 let mut account_rlp = Vec::new();
2394 new_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2395 account_rlp
2396 };
2397
2398 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2399 run_hash_builder(
2400 paths.iter().cloned().zip(std::iter::repeat_with(|| old_value)),
2401 NoopAccountTrieCursor::default(),
2402 Default::default(),
2403 paths.clone(),
2404 );
2405
2406 let mut sparse = RevealedSparseTrie::default().with_updates(true);
2407 for path in &paths {
2408 sparse.update_leaf(path.clone(), old_value_encoded.clone()).unwrap();
2409 }
2410 let sparse_root = sparse.root();
2411 let sparse_updates = sparse.updates_ref();
2412
2413 assert_eq!(sparse_root, hash_builder_root);
2414 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2415 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2416
2417 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2418 run_hash_builder(
2419 paths.iter().cloned().zip(std::iter::repeat_with(|| new_value)),
2420 NoopAccountTrieCursor::default(),
2421 Default::default(),
2422 paths.clone(),
2423 );
2424
2425 for path in &paths {
2426 sparse.update_leaf(path.clone(), new_value_encoded.clone()).unwrap();
2427 }
2428 let sparse_root = sparse.root();
2429 let sparse_updates = sparse.take_updates();
2430
2431 assert_eq!(sparse_root, hash_builder_root);
2432 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2433 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2434 }
2435
2436 #[test]
2437 fn sparse_trie_remove_leaf() {
2438 reth_tracing::init_test_tracing();
2439
2440 let mut sparse = RevealedSparseTrie::default();
2441
2442 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
2443
2444 sparse
2445 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone())
2446 .unwrap();
2447 sparse
2448 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone())
2449 .unwrap();
2450 sparse
2451 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone())
2452 .unwrap();
2453 sparse
2454 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone())
2455 .unwrap();
2456 sparse
2457 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone())
2458 .unwrap();
2459 sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap();
2460
2461 pretty_assertions::assert_eq!(
2474 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2475 BTreeMap::from_iter([
2476 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2477 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1101.into())),
2478 (
2479 Nibbles::from_nibbles([0x5, 0x0]),
2480 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
2481 ),
2482 (
2483 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
2484 SparseNode::new_branch(0b1010.into())
2485 ),
2486 (
2487 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
2488 SparseNode::new_leaf(Nibbles::default())
2489 ),
2490 (
2491 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
2492 SparseNode::new_leaf(Nibbles::default())
2493 ),
2494 (
2495 Nibbles::from_nibbles([0x5, 0x2]),
2496 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x1, 0x3]))
2497 ),
2498 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2499 (
2500 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2501 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2502 ),
2503 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2504 (
2505 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2506 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2507 ),
2508 (
2509 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2510 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2511 )
2512 ])
2513 );
2514
2515 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3])).unwrap();
2516
2517 pretty_assertions::assert_eq!(
2529 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2530 BTreeMap::from_iter([
2531 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2532 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2533 (
2534 Nibbles::from_nibbles([0x5, 0x0]),
2535 SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
2536 ),
2537 (
2538 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
2539 SparseNode::new_branch(0b1010.into())
2540 ),
2541 (
2542 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
2543 SparseNode::new_leaf(Nibbles::default())
2544 ),
2545 (
2546 Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
2547 SparseNode::new_leaf(Nibbles::default())
2548 ),
2549 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2550 (
2551 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2552 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2553 ),
2554 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2555 (
2556 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2557 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2558 ),
2559 (
2560 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2561 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2562 )
2563 ])
2564 );
2565
2566 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1])).unwrap();
2567
2568 pretty_assertions::assert_eq!(
2577 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2578 BTreeMap::from_iter([
2579 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2580 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2581 (
2582 Nibbles::from_nibbles([0x5, 0x0]),
2583 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2584 ),
2585 (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2586 (
2587 Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2588 SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2589 ),
2590 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2591 (
2592 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2593 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2594 ),
2595 (
2596 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2597 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2598 )
2599 ])
2600 );
2601
2602 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2])).unwrap();
2603
2604 pretty_assertions::assert_eq!(
2611 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2612 BTreeMap::from_iter([
2613 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2614 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2615 (
2616 Nibbles::from_nibbles([0x5, 0x0]),
2617 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2618 ),
2619 (
2620 Nibbles::from_nibbles([0x5, 0x3]),
2621 SparseNode::new_ext(Nibbles::from_nibbles([0x3]))
2622 ),
2623 (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2624 (
2625 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2626 SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2627 ),
2628 (
2629 Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2630 SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2631 )
2632 ])
2633 );
2634
2635 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0])).unwrap();
2636
2637 pretty_assertions::assert_eq!(
2642 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2643 BTreeMap::from_iter([
2644 (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2645 (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2646 (
2647 Nibbles::from_nibbles([0x5, 0x0]),
2648 SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2649 ),
2650 (
2651 Nibbles::from_nibbles([0x5, 0x3]),
2652 SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x0, 0x2]))
2653 ),
2654 ])
2655 );
2656
2657 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3])).unwrap();
2658
2659 pretty_assertions::assert_eq!(
2661 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2662 BTreeMap::from_iter([(
2663 Nibbles::default(),
2664 SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]))
2665 ),])
2666 );
2667
2668 sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2])).unwrap();
2669
2670 pretty_assertions::assert_eq!(
2672 sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2673 BTreeMap::from_iter([(Nibbles::default(), SparseNode::Empty)])
2674 );
2675 }
2676
2677 #[test]
2678 fn sparse_trie_remove_leaf_blinded() {
2679 let leaf = LeafNode::new(
2680 Nibbles::default(),
2681 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
2682 );
2683 let branch = TrieNode::Branch(BranchNode::new(
2684 vec![
2685 RlpNode::word_rlp(&B256::repeat_byte(1)),
2686 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
2687 ],
2688 TrieMask::new(0b11),
2689 ));
2690
2691 let mut sparse = RevealedSparseTrie::from_root(
2692 branch.clone(),
2693 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
2694 false,
2695 )
2696 .unwrap();
2697
2698 sparse
2704 .reveal_node(
2705 Nibbles::default(),
2706 branch,
2707 TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
2708 )
2709 .unwrap();
2710 sparse
2711 .reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), TrieMasks::none())
2712 .unwrap();
2713
2714 assert_matches!(
2716 sparse.remove_leaf(&Nibbles::from_nibbles([0x0])).map_err(|e| e.into_kind()),
2717 Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
2718 );
2719 }
2720
2721 #[test]
2722 fn sparse_trie_remove_leaf_non_existent() {
2723 let leaf = LeafNode::new(
2724 Nibbles::default(),
2725 alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
2726 );
2727 let branch = TrieNode::Branch(BranchNode::new(
2728 vec![
2729 RlpNode::word_rlp(&B256::repeat_byte(1)),
2730 RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
2731 ],
2732 TrieMask::new(0b11),
2733 ));
2734
2735 let mut sparse = RevealedSparseTrie::from_root(
2736 branch.clone(),
2737 TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
2738 false,
2739 )
2740 .unwrap();
2741
2742 sparse
2748 .reveal_node(
2749 Nibbles::default(),
2750 branch,
2751 TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
2752 )
2753 .unwrap();
2754 sparse
2755 .reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), TrieMasks::none())
2756 .unwrap();
2757
2758 let sparse_old = sparse.clone();
2760 assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2])), Ok(()));
2761 assert_eq!(sparse, sparse_old);
2762 }
2763
2764 #[test]
2765 fn sparse_trie_fuzz() {
2766 const KEY_NIBBLES_LEN: usize = 3;
2770
2771 fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
2772 {
2773 let mut state = BTreeMap::default();
2774 let provider_factory = create_test_provider_factory();
2775 let mut sparse = RevealedSparseTrie::default().with_updates(true);
2776
2777 for (update, keys_to_delete) in updates {
2778 for (key, account) in update.clone() {
2780 let account = account.into_trie_account(EMPTY_ROOT_HASH);
2781 let mut account_rlp = Vec::new();
2782 account.encode(&mut account_rlp);
2783 sparse.update_leaf(key, account_rlp).unwrap();
2784 }
2785 let mut updated_sparse = sparse.clone();
2789 let sparse_root = updated_sparse.root();
2790 let sparse_updates = updated_sparse.take_updates();
2791
2792 state.extend(update);
2794 let provider = provider_factory.provider().unwrap();
2795 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
2796 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2797 run_hash_builder(
2798 state.clone(),
2799 trie_cursor.account_trie_cursor().unwrap(),
2800 Default::default(),
2801 state.keys().cloned().collect::<Vec<_>>(),
2802 );
2803
2804 let provider_rw = provider_factory.provider_rw().unwrap();
2806 provider_rw.write_trie_updates(&hash_builder_updates).unwrap();
2807 provider_rw.commit().unwrap();
2808
2809 assert_eq!(sparse_root, hash_builder_root);
2811 pretty_assertions::assert_eq!(
2813 BTreeMap::from_iter(sparse_updates.updated_nodes),
2814 BTreeMap::from_iter(hash_builder_updates.account_nodes)
2815 );
2816 assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
2818
2819 for key in &keys_to_delete {
2822 state.remove(key).unwrap();
2823 sparse.remove_leaf(key).unwrap();
2824 }
2825
2826 let mut updated_sparse = sparse.clone();
2830 let sparse_root = updated_sparse.root();
2831 let sparse_updates = updated_sparse.take_updates();
2832
2833 let provider = provider_factory.provider().unwrap();
2834 let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
2835 let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2836 run_hash_builder(
2837 state.clone(),
2838 trie_cursor.account_trie_cursor().unwrap(),
2839 keys_to_delete
2840 .iter()
2841 .map(|nibbles| B256::from_slice(&nibbles.pack()))
2842 .collect(),
2843 state.keys().cloned().collect::<Vec<_>>(),
2844 );
2845
2846 let provider_rw = provider_factory.provider_rw().unwrap();
2848 provider_rw.write_trie_updates(&hash_builder_updates).unwrap();
2849 provider_rw.commit().unwrap();
2850
2851 assert_eq!(sparse_root, hash_builder_root);
2853 pretty_assertions::assert_eq!(
2855 BTreeMap::from_iter(sparse_updates.updated_nodes),
2856 BTreeMap::from_iter(hash_builder_updates.account_nodes)
2857 );
2858 assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
2860 }
2861 }
2862 }
2863
2864 fn transform_updates(
2865 updates: Vec<BTreeMap<Nibbles, Account>>,
2866 mut rng: impl rand_08::Rng,
2867 ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
2868 let mut keys = BTreeSet::new();
2869 updates
2870 .into_iter()
2871 .map(|update| {
2872 keys.extend(update.keys().cloned());
2873
2874 let keys_to_delete_len = update.len() / 2;
2875 let keys_to_delete = (0..keys_to_delete_len)
2876 .map(|_| {
2877 let key = rand_08::seq::IteratorRandom::choose(keys.iter(), &mut rng)
2878 .unwrap()
2879 .clone();
2880 keys.take(&key).unwrap()
2881 })
2882 .collect();
2883
2884 (update, keys_to_delete)
2885 })
2886 .collect::<Vec<_>>()
2887 }
2888
2889 proptest!(ProptestConfig::with_cases(10), |(
2890 updates in proptest::collection::vec(
2891 proptest::collection::btree_map(
2892 any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
2893 arb::<Account>(),
2894 1..50,
2895 ),
2896 1..50,
2897 ).prop_perturb(transform_updates)
2898 )| {
2899 test(updates)
2900 });
2901 }
2902
2903 #[test]
2915 fn sparse_trie_reveal_node_1() {
2916 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00]));
2917 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01]));
2918 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x02]));
2919 let value = || Account::default();
2920 let value_encoded = || {
2921 let mut account_rlp = Vec::new();
2922 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2923 account_rlp
2924 };
2925
2926 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
2928 run_hash_builder(
2929 [(key1(), value()), (key3(), value())],
2930 NoopAccountTrieCursor::default(),
2931 Default::default(),
2932 [Nibbles::default()],
2933 );
2934 let mut sparse = RevealedSparseTrie::from_root(
2935 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
2936 TrieMasks {
2937 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
2938 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
2939 },
2940 false,
2941 )
2942 .unwrap();
2943
2944 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
2946 run_hash_builder(
2947 [(key1(), value()), (key3(), value())],
2948 NoopAccountTrieCursor::default(),
2949 Default::default(),
2950 [key1()],
2951 );
2952 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
2953 let hash_mask = branch_node_hash_masks.get(&path).copied();
2954 let tree_mask = branch_node_tree_masks.get(&path).copied();
2955 sparse
2956 .reveal_node(
2957 path,
2958 TrieNode::decode(&mut &node[..]).unwrap(),
2959 TrieMasks { hash_mask, tree_mask },
2960 )
2961 .unwrap();
2962 }
2963
2964 assert_eq!(
2966 sparse.nodes.get(&Nibbles::default()),
2967 Some(&SparseNode::new_branch(0b101.into()))
2968 );
2969
2970 sparse.update_leaf(key2(), value_encoded()).unwrap();
2972
2973 assert_eq!(
2975 sparse.nodes.get(&Nibbles::default()),
2976 Some(&SparseNode::new_branch(0b111.into()))
2977 );
2978
2979 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
2981 run_hash_builder(
2982 [(key1(), value()), (key3(), value())],
2983 NoopAccountTrieCursor::default(),
2984 Default::default(),
2985 [key3()],
2986 );
2987 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
2988 let hash_mask = branch_node_hash_masks.get(&path).copied();
2989 let tree_mask = branch_node_tree_masks.get(&path).copied();
2990 sparse
2991 .reveal_node(
2992 path,
2993 TrieNode::decode(&mut &node[..]).unwrap(),
2994 TrieMasks { hash_mask, tree_mask },
2995 )
2996 .unwrap();
2997 }
2998
2999 assert_eq!(
3001 sparse.nodes.get(&Nibbles::default()),
3002 Some(&SparseNode::new_branch(0b111.into()))
3003 );
3004
3005 let (_, _, hash_builder_proof_nodes, _, _) = run_hash_builder(
3008 [(key1(), value()), (key2(), value()), (key3(), value())],
3009 NoopAccountTrieCursor::default(),
3010 Default::default(),
3011 [key1(), key2(), key3()],
3012 );
3013
3014 assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
3015 }
3016
3017 #[test]
3028 fn sparse_trie_reveal_node_2() {
3029 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x00]));
3030 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x01]));
3031 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x02]));
3032 let value = || Account::default();
3033
3034 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3036 run_hash_builder(
3037 [(key1(), value()), (key2(), value()), (key3(), value())],
3038 NoopAccountTrieCursor::default(),
3039 Default::default(),
3040 [Nibbles::default()],
3041 );
3042 let mut sparse = RevealedSparseTrie::from_root(
3043 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3044 TrieMasks {
3045 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3046 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3047 },
3048 false,
3049 )
3050 .unwrap();
3051
3052 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3055 run_hash_builder(
3056 [(key1(), value()), (key2(), value()), (key3(), value())],
3057 NoopAccountTrieCursor::default(),
3058 Default::default(),
3059 [key1(), Nibbles::from_nibbles_unchecked([0x01])],
3060 );
3061 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3062 let hash_mask = branch_node_hash_masks.get(&path).copied();
3063 let tree_mask = branch_node_tree_masks.get(&path).copied();
3064 sparse
3065 .reveal_node(
3066 path,
3067 TrieNode::decode(&mut &node[..]).unwrap(),
3068 TrieMasks { hash_mask, tree_mask },
3069 )
3070 .unwrap();
3071 }
3072
3073 assert_eq!(
3075 sparse.nodes.get(&Nibbles::default()),
3076 Some(&SparseNode::new_branch(0b11.into()))
3077 );
3078
3079 sparse.remove_leaf(&key1()).unwrap();
3081
3082 assert_eq!(
3084 sparse.nodes.get(&Nibbles::default()),
3085 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3086 );
3087
3088 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3090 run_hash_builder(
3091 [(key1(), value()), (key2(), value()), (key3(), value())],
3092 NoopAccountTrieCursor::default(),
3093 Default::default(),
3094 [key2()],
3095 );
3096 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3097 let hash_mask = branch_node_hash_masks.get(&path).copied();
3098 let tree_mask = branch_node_tree_masks.get(&path).copied();
3099 sparse
3100 .reveal_node(
3101 path,
3102 TrieNode::decode(&mut &node[..]).unwrap(),
3103 TrieMasks { hash_mask, tree_mask },
3104 )
3105 .unwrap();
3106 }
3107
3108 assert_eq!(
3110 sparse.nodes.get(&Nibbles::default()),
3111 Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3112 );
3113 }
3114
3115 #[test]
3124 fn sparse_trie_reveal_node_3() {
3125 let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x01]));
3126 let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x02]));
3127 let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x00]));
3128 let value = || Account::default();
3129 let value_encoded = || {
3130 let mut account_rlp = Vec::new();
3131 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3132 account_rlp
3133 };
3134
3135 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3137 run_hash_builder(
3138 [(key1(), value()), (key2(), value())],
3139 NoopAccountTrieCursor::default(),
3140 Default::default(),
3141 [Nibbles::default()],
3142 );
3143 let mut sparse = RevealedSparseTrie::from_root(
3144 TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3145 TrieMasks {
3146 hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3147 tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3148 },
3149 false,
3150 )
3151 .unwrap();
3152
3153 assert_matches!(
3155 sparse.nodes.get(&Nibbles::default()),
3156 Some(SparseNode::Extension { key, hash: None, store_in_db_trie: None }) if *key == Nibbles::from_nibbles([0x00])
3157 );
3158
3159 sparse.update_leaf(key3(), value_encoded()).unwrap();
3161
3162 assert_matches!(
3164 sparse.nodes.get(&Nibbles::default()),
3165 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
3166 );
3167
3168 let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3170 run_hash_builder(
3171 [(key1(), value()), (key2(), value())],
3172 NoopAccountTrieCursor::default(),
3173 Default::default(),
3174 [key1()],
3175 );
3176 for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3177 let hash_mask = branch_node_hash_masks.get(&path).copied();
3178 let tree_mask = branch_node_tree_masks.get(&path).copied();
3179 sparse
3180 .reveal_node(
3181 path,
3182 TrieNode::decode(&mut &node[..]).unwrap(),
3183 TrieMasks { hash_mask, tree_mask },
3184 )
3185 .unwrap();
3186 }
3187
3188 assert_matches!(
3190 sparse.nodes.get(&Nibbles::default()),
3191 Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
3192 );
3193 }
3194
3195 #[test]
3196 fn sparse_trie_get_changed_nodes_at_depth() {
3197 let mut sparse = RevealedSparseTrie::default();
3198
3199 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3200
3201 sparse
3214 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone())
3215 .unwrap();
3216 sparse
3217 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone())
3218 .unwrap();
3219 sparse
3220 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone())
3221 .unwrap();
3222 sparse
3223 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone())
3224 .unwrap();
3225 sparse
3226 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone())
3227 .unwrap();
3228 sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap();
3229
3230 assert_eq!(
3231 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 0),
3232 (vec![(0, Nibbles::default())], PrefixSetMut::default())
3233 );
3234 assert_eq!(
3235 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 1),
3236 (vec![(1, Nibbles::from_nibbles_unchecked([0x5]))], [Nibbles::default()].into())
3237 );
3238 assert_eq!(
3239 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 2),
3240 (
3241 vec![
3242 (2, Nibbles::from_nibbles_unchecked([0x5, 0x0])),
3243 (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3244 (2, Nibbles::from_nibbles_unchecked([0x5, 0x3]))
3245 ],
3246 [Nibbles::default(), Nibbles::from_nibbles_unchecked([0x5])].into()
3247 )
3248 );
3249 assert_eq!(
3250 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 3),
3251 (
3252 vec![
3253 (3, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3])),
3254 (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3255 (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1])),
3256 (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3]))
3257 ],
3258 [
3259 Nibbles::default(),
3260 Nibbles::from_nibbles_unchecked([0x5]),
3261 Nibbles::from_nibbles_unchecked([0x5, 0x0]),
3262 Nibbles::from_nibbles_unchecked([0x5, 0x3])
3263 ]
3264 .into()
3265 )
3266 );
3267 assert_eq!(
3268 sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 4),
3269 (
3270 vec![
3271 (4, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x1])),
3272 (4, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x3])),
3273 (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3274 (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1])),
3275 (4, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x0])),
3276 (4, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x2]))
3277 ],
3278 [
3279 Nibbles::default(),
3280 Nibbles::from_nibbles_unchecked([0x5]),
3281 Nibbles::from_nibbles_unchecked([0x5, 0x0]),
3282 Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3]),
3283 Nibbles::from_nibbles_unchecked([0x5, 0x3]),
3284 Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3])
3285 ]
3286 .into()
3287 )
3288 );
3289 }
3290
3291 #[test]
3292 fn hash_builder_branch_hash_mask() {
3293 let key1 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x00]));
3294 let key2 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x01]));
3295 let value = || Account { bytecode_hash: Some(B256::repeat_byte(1)), ..Default::default() };
3296 let value_encoded = || {
3297 let mut account_rlp = Vec::new();
3298 value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3299 account_rlp
3300 };
3301
3302 let (hash_builder_root, hash_builder_updates, _, _, _) = run_hash_builder(
3303 [(key1(), value()), (key2(), value())],
3304 NoopAccountTrieCursor::default(),
3305 Default::default(),
3306 [Nibbles::default()],
3307 );
3308 let mut sparse = RevealedSparseTrie::default();
3309 sparse.update_leaf(key1(), value_encoded()).unwrap();
3310 sparse.update_leaf(key2(), value_encoded()).unwrap();
3311 let sparse_root = sparse.root();
3312 let sparse_updates = sparse.take_updates();
3313
3314 assert_eq!(sparse_root, hash_builder_root);
3315 assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
3316 }
3317
3318 #[test]
3319 fn sparse_trie_wipe() {
3320 let mut sparse = RevealedSparseTrie::default().with_updates(true);
3321
3322 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3323
3324 sparse
3337 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone())
3338 .unwrap();
3339 sparse
3340 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone())
3341 .unwrap();
3342 sparse
3343 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone())
3344 .unwrap();
3345 sparse
3346 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone())
3347 .unwrap();
3348 sparse
3349 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone())
3350 .unwrap();
3351 sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap();
3352
3353 sparse.wipe();
3354
3355 assert_eq!(sparse.root(), EMPTY_ROOT_HASH);
3356 }
3357
3358 #[test]
3359 fn sparse_trie_display() {
3360 let mut sparse = RevealedSparseTrie::default();
3361
3362 let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3363
3364 sparse
3377 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone())
3378 .unwrap();
3379 sparse
3380 .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone())
3381 .unwrap();
3382 sparse
3383 .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone())
3384 .unwrap();
3385 sparse
3386 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone())
3387 .unwrap();
3388 sparse
3389 .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone())
3390 .unwrap();
3391 sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap();
3392
3393 let normal_printed = format!("{sparse}");
3394 let expected = "\
3395Root -> Extension { key: Nibbles(0x05), hash: None, store_in_db_trie: None }
33965 -> Branch { state_mask: TrieMask(0000000000001101), hash: None, store_in_db_trie: None }
339750 -> Extension { key: Nibbles(0x0203), hash: None, store_in_db_trie: None }
33985023 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
339950231 -> Leaf { key: Nibbles(0x), hash: None }
340050233 -> Leaf { key: Nibbles(0x), hash: None }
340152013 -> Leaf { key: Nibbles(0x000103), hash: None }
340253 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
340353102 -> Leaf { key: Nibbles(0x0002), hash: None }
3404533 -> Branch { state_mask: TrieMask(0000000000000101), hash: None, store_in_db_trie: None }
340553302 -> Leaf { key: Nibbles(0x02), hash: None }
340653320 -> Leaf { key: Nibbles(0x00), hash: None }
3407";
3408 assert_eq!(normal_printed, expected);
3409
3410 let alternate_printed = format!("{sparse:#}");
3411 let expected = "\
3412Root -> Extension { key: Nibbles(0x05), hash: None, store_in_db_trie: None }
3413 5 -> Branch { state_mask: TrieMask(0000000000001101), hash: None, store_in_db_trie: None }
3414 50 -> Extension { key: Nibbles(0x0203), hash: None, store_in_db_trie: None }
3415 5023 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
3416 50231 -> Leaf { key: Nibbles(0x), hash: None }
3417 50233 -> Leaf { key: Nibbles(0x), hash: None }
3418 52013 -> Leaf { key: Nibbles(0x000103), hash: None }
3419 53 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
3420 53102 -> Leaf { key: Nibbles(0x0002), hash: None }
3421 533 -> Branch { state_mask: TrieMask(0000000000000101), hash: None, store_in_db_trie: None }
3422 53302 -> Leaf { key: Nibbles(0x02), hash: None }
3423 53320 -> Leaf { key: Nibbles(0x00), hash: None }
3424";
3425
3426 assert_eq!(alternate_printed, expected);
3427 }
3428}