reth_trie_sparse/
trie.rs

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/// Struct for passing around `hash_mask` and `tree_mask`
26#[derive(Debug)]
27pub struct TrieMasks {
28    /// Branch node hash mask, if any.
29    pub hash_mask: Option<TrieMask>,
30    /// Branch node tree mask, if any.
31    pub tree_mask: Option<TrieMask>,
32}
33
34impl TrieMasks {
35    /// Helper function, returns both fields `hash_mask` and `tree_mask` as [`None`]
36    pub const fn none() -> Self {
37        Self { hash_mask: None, tree_mask: None }
38    }
39}
40
41/// Inner representation of the sparse trie.
42/// Sparse trie is blind by default until nodes are revealed.
43#[derive(PartialEq, Eq)]
44pub enum SparseTrie<P = DefaultBlindedProvider> {
45    /// None of the trie nodes are known.
46    Blind,
47    /// The trie nodes have been revealed.
48    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    /// Creates new blind trie.
68    pub const fn blind() -> Self {
69        Self::Blind
70    }
71
72    /// Creates new revealed empty trie.
73    pub fn revealed_empty() -> Self {
74        Self::Revealed(Box::default())
75    }
76
77    /// Reveals the root node if the trie is blinded.
78    ///
79    /// # Returns
80    ///
81    /// Mutable reference to [`RevealedSparseTrie`].
82    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    /// Returns `true` if the sparse trie has no revealed nodes.
94    pub const fn is_blind(&self) -> bool {
95        matches!(self, Self::Blind)
96    }
97
98    /// Returns reference to revealed sparse trie if the trie is not blind.
99    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    /// Returns mutable reference to revealed sparse trie if the trie is not blind.
108    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    /// Reveals the root node if the trie is blinded.
117    ///
118    /// # Returns
119    ///
120    /// Mutable reference to [`RevealedSparseTrie`].
121    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    /// Wipe the trie, removing all values and nodes, and replacing the root with an empty node.
140    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    /// Calculates and returns the trie root if the trie has been revealed.
147    pub fn root(&mut self) -> Option<B256> {
148        Some(self.as_revealed_mut()?.root())
149    }
150
151    /// Returns both the trie root and takes sparse trie updates if the trie has been revealed.
152    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    /// Update the leaf node.
160    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    /// Remove the leaf node.
167    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/// The representation of revealed sparse trie.
175///
176/// ## Invariants
177///
178/// - The root node is always present in `nodes` collection.
179/// - Each leaf entry in `nodes` collection must have a corresponding entry in `values` collection.
180///   The opposite is also true.
181/// - All keys in `values` collection are full leaf paths.
182#[derive(Clone, PartialEq, Eq)]
183pub struct RevealedSparseTrie<P = DefaultBlindedProvider> {
184    /// Blinded node provider.
185    provider: P,
186    /// All trie nodes.
187    nodes: HashMap<Nibbles, SparseNode>,
188    /// All branch node tree masks.
189    branch_node_tree_masks: HashMap<Nibbles, TrieMask>,
190    /// All branch node hash masks.
191    branch_node_hash_masks: HashMap<Nibbles, TrieMask>,
192    /// All leaf values.
193    values: HashMap<Nibbles, Vec<u8>>,
194    /// Prefix set.
195    prefix_set: PrefixSetMut,
196    /// Retained trie updates.
197    updates: Option<SparseTrieUpdates>,
198    /// Reusable buffer for RLP encoding of nodes.
199    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
216/// Turns a [`Nibbles`] into a [`String`] by concatenating each nibbles' hex character.
217fn 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        // This prints the trie in preorder traversal, using a stack
225        let mut stack = Vec::new();
226        let mut visited = HashSet::new();
227
228        // 4 spaces as indent per level
229        const INDENT: &str = "    ";
230
231        // Track both path and depth
232        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            // Add indentation if alternate flag (#) is set
240            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                    // we want to append the key to the path
252                    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                    // push the child node onto the stack with increased depth
262                    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    /// Create new revealed sparse trie from the given root node.
305    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    /// Create new revealed sparse trie from the given root node.
328    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    /// Set new blinded node provider on sparse trie.
350    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    /// Set the retention of branch node updates and deletions.
364    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    /// Returns a reference to the retained sparse node updates without taking them.
372    pub fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
373        self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
374    }
375
376    /// Returns reference to all trie nodes.
377    pub const fn nodes_ref(&self) -> &HashMap<Nibbles, SparseNode> {
378        &self.nodes
379    }
380
381    /// Returns a reference to the leaf value if present.
382    pub fn get_leaf_value(&self, path: &Nibbles) -> Option<&Vec<u8>> {
383        self.values.get(path)
384    }
385
386    /// Takes and returns the retained sparse node updates
387    pub fn take_updates(&mut self) -> SparseTrieUpdates {
388        self.updates.take().unwrap_or_default()
389    }
390
391    /// Reserves capacity for at least `additional` more nodes to be inserted.
392    pub fn reserve_nodes(&mut self, additional: usize) {
393        self.nodes.reserve(additional);
394    }
395
396    /// Reveal the trie node only if it was not known already.
397    pub fn reveal_node(
398        &mut self,
399        path: Nibbles,
400        node: TrieNode,
401        masks: TrieMasks,
402    ) -> SparseTrieResult<()> {
403        // If the node is already revealed and it's not a hash node, do nothing.
404        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                        // Blinded nodes can be replaced.
434                        SparseNode::Hash(hash) => {
435                            entry.insert(SparseNode::Branch {
436                                state_mask: branch.state_mask,
437                                // Memoize the hash of a previously blinded node in a new branch
438                                // node.
439                                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                        // Branch node already exists, or an extension node was placed where a
447                        // branch node was before.
448                        SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
449                        // All other node types can't be handled.
450                        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                            // Memoize the hash of a previously blinded node in a new extension
471                            // node.
472                            hash: Some(*hash),
473                            store_in_db_trie: None,
474                        });
475                        self.reveal_node_or_hash(child_path, &ext.child)?;
476                    }
477                    // Extension node already exists, or an extension node was placed where a branch
478                    // node was before.
479                    SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
480                    // All other node types can't be handled.
481                    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                            // Memoize the hash of a previously blinded node in a new leaf
505                            // node.
506                            hash: Some(*hash),
507                        });
508                    }
509                    // Left node already exists.
510                    SparseNode::Leaf { .. } => {}
511                    // All other node types can't be handled.
512                    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                    // Hash node with a different hash can't be handled.
540                    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    /// Traverse trie nodes down to the leaf node and collect all nodes along the path.
560    fn take_nodes_for_path(&mut self, path: &Nibbles) -> SparseTrieResult<Vec<RemovedSparseNode>> {
561        let mut current = Nibbles::default(); // Start traversal from the root
562        let mut nodes = Vec::new(); // Collect traversed nodes
563
564        while let Some(node) = self.nodes.remove(&current) {
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                    // Leaf node is always the one that we're deleting, and no other leaf nodes can
572                    // be found during traversal.
573
574                    #[cfg(debug_assertions)]
575                    {
576                        let mut current = current.clone();
577                        current.extend_from_slice_unchecked(_key);
578                        assert_eq!(&current, 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(&current),
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                    // If the branch node has a child that is a leaf node that we're removing,
611                    // we need to unset this nibble.
612                    // Any other branch nodes will not require unsetting the nibble, because
613                    // deleting one leaf node can not remove the whole path
614                    // where the branch node is located.
615                    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                                // Get full path of the leaf node
623                                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    /// Wipe the trie, removing all values and nodes, and replacing the root with an empty node.
645    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    /// Return the root of the sparse trie.
653    /// Updates all remaining dirty nodes before calculating the root.
654    pub fn root(&mut self) -> B256 {
655        // Take the current prefix set
656        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    /// Update hashes of the nodes that are located at a level deeper than or equal to the provided
666    /// depth. Root node has a level of 0.
667    pub fn update_rlp_node_level(&mut self, depth: usize) {
668        // Take the current prefix set
669        let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
670        let mut buffers = RlpNodeBuffers::default();
671
672        // Get the nodes that have changed at the given depth.
673        let (targets, new_prefix_set) = self.get_changed_nodes_at_depth(&mut prefix_set, depth);
674        // Update the prefix set to the prefix set of the nodes that still need to be updated.
675        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    /// Returns a list of levels and paths to the nodes that were changed according to the prefix
689    /// set and are located at the provided depth when counting from the root node. If there's a
690    /// leaf at a depth less than the provided depth, it will be included in the result.
691    ///
692    /// Additionally, returns a new prefix set containing the paths that will not be updated, thus
693    /// need re-calculation.
694    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    /// Look up or calculate the RLP of the node at the root path.
753    ///
754    /// # Panics
755    ///
756    /// If the node at provided path does not exist.
757    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    /// Look up or calculate the RLP of the node at the given path specified in [`RlpNodeBuffers`].
763    ///
764    /// # Panics
765    ///
766    /// If the node at provided path does not exist.
767    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            // Check if the path is in the prefix set.
789            // First, check the cached value. If it's `None`, then check the prefix set, and update
790            // the cached value.
791            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                                // Inherit the `store_in_db_trie` flag from the child node, which is
846                                // always the branch node
847                                store_in_db_trie: store_in_db_trie_value,
848                            },
849                        )
850                    } else {
851                        // need to get rlp node for child first
852                        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                    // Walk children in a reverse order from `f` to `0`, so we pop the `0` first
880                    // from the stack and keep walking in the sorted order.
881                    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                            // Update the masks only if we need to retain trie updates
906                            if retain_updates {
907                                // SAFETY: it's a child, so it's never empty
908                                let last_child_nibble = child_path.last().unwrap();
909
910                                // Determine whether we need to set trie mask bit.
911                                let should_set_tree_mask_bit = if let Some(store_in_db_trie) =
912                                    child_node_type.store_in_db_trie()
913                                {
914                                    // A branch or an extension node explicitly set the
915                                    // `store_in_db_trie` flag
916                                    store_in_db_trie
917                                } else {
918                                    // A blinded node has the tree mask bit set
919                                    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                                // Set the hash mask. If a child node is a revealed branch node OR
929                                // is a blinded node that has its hash mask bit set according to the
930                                // database, set the hash mask bit and save the hash.
931                                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                            // Insert children in the resulting buffer in a normal order,
947                            // because initially we iterated in reverse.
948                            // SAFETY: i < len and len is never 0
949                            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                    // Save a branch node update only if it's not a root node, and we need to
985                    // persist updates.
986                    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                            // Store in DB trie if there are either any children that are stored in
992                            // the DB trie, or any children represent hashed values
993                            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                            // If new tree and hash masks are empty, but previously they weren't, we
1011                            // need to remove the node update and add the node itself to the list of
1012                            // removed nodes.
1013                            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                            // If new tree and hash masks are empty, and they were previously empty
1024                            // as well, we need to remove the node update.
1025                            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/// Error type for a leaf lookup operation
1061#[derive(Debug, Clone, PartialEq, Eq)]
1062pub enum LeafLookupError {
1063    /// The path leads to a blinded node, cannot determine if leaf exists.
1064    /// This means the witness is not complete.
1065    BlindedNode {
1066        /// Path to the blinded node.
1067        path: Nibbles,
1068        /// Hash of the blinded node.
1069        hash: B256,
1070    },
1071    /// The path leads to a leaf with a different value than expected.
1072    /// This means the witness is malformed.
1073    ValueMismatch {
1074        /// Path to the leaf.
1075        path: Nibbles,
1076        /// Expected value.
1077        expected: Option<Vec<u8>>,
1078        /// Actual value found.
1079        actual: Vec<u8>,
1080    },
1081}
1082
1083/// Success value for a leaf lookup operation
1084#[derive(Debug, Clone, PartialEq, Eq)]
1085pub enum LeafLookup {
1086    /// Leaf exists with expected value.
1087    Exists,
1088    /// Leaf does not exist (exclusion proof found).
1089    NonExistent {
1090        /// Path where the search diverged from the target path.
1091        diverged_at: Nibbles,
1092    },
1093}
1094
1095impl<P: BlindedProvider> RevealedSparseTrie<P> {
1096    /// Attempts to find a leaf node at the specified path.
1097    ///
1098    /// This method traverses the trie from the root down to the given path, checking
1099    /// if a leaf exists at that path. It can be used to verify the existence of a leaf
1100    /// or to generate an exclusion proof (proof that a leaf does not exist).
1101    ///
1102    /// # Parameters
1103    ///
1104    /// - `path`: The path to search for.
1105    /// - `expected_value`: Optional expected value. If provided, will verify the leaf value
1106    ///   matches.
1107    ///
1108    /// # Returns
1109    ///
1110    /// - `Ok(LeafLookup::Exists)` if the leaf exists with the expected value.
1111    /// - `Ok(LeafLookup::NonExistent)` if the leaf definitely does not exist (exclusion proof).
1112    /// - `Err(LeafLookupError)` if the search encountered a blinded node or found a different
1113    ///   value.
1114    pub fn find_leaf(
1115        &self,
1116        path: &Nibbles,
1117        expected_value: Option<&Vec<u8>>,
1118    ) -> Result<LeafLookup, LeafLookupError> {
1119        // Helper function to check if a value matches the expected value
1120        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(); // Start at the root
1138
1139        // Inclusion proof
1140        //
1141        // First, do a quick check if the value exists in our values map.
1142        // We assume that if there exists a leaf node, then its value will
1143        // be in the `values` map.
1144        if let Some(actual_value) = self.values.get(path) {
1145            // We found the leaf, check if the value matches (if expected value was provided)
1146            check_value_match(actual_value, expected_value, path)?;
1147            return Ok(LeafLookup::Exists);
1148        }
1149
1150        // If the value does not exist in the `values` map, then this means that the leaf either:
1151        // - Does not exist in the trie
1152        // - Is missing from the witness
1153        // We traverse the trie to find the location where this leaf would have been, showing
1154        // that it is not in the trie. Or we find a blinded node, showing that the witness is
1155        // not complete.
1156        while current.len() < path.len() {
1157            match self.nodes.get(&current) {
1158                Some(SparseNode::Empty) | None => {
1159                    // None implies no node is at the current path (even in the full trie)
1160                    // Empty node means there is a node at this path and it is "Empty"
1161                    return Ok(LeafLookup::NonExistent { diverged_at: current });
1162                }
1163                Some(&SparseNode::Hash(hash)) => {
1164                    // We hit a blinded node - cannot determine if leaf exists
1165                    return Err(LeafLookupError::BlindedNode { path: current.clone(), hash });
1166                }
1167                Some(SparseNode::Leaf { key, .. }) => {
1168                    // We found a leaf node before reaching our target depth
1169
1170                    // Temporarily append the leaf key to `current`
1171                    let saved_len = current.len();
1172                    current.extend_from_slice_unchecked(key);
1173
1174                    if &current == path {
1175                        // This should have been handled by our initial values map check
1176                        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                    // The leaf node's path doesn't match our target path,
1185                    // providing an exclusion proof
1186                    return Ok(LeafLookup::NonExistent { diverged_at });
1187                }
1188                Some(SparseNode::Extension { key, .. }) => {
1189                    // Temporarily append the extension key to `current`
1190                    let saved_len = current.len();
1191                    current.extend_from_slice_unchecked(key);
1192
1193                    if path.len() < current.len() || !path.starts_with(&current) {
1194                        let diverged_at = current.slice(..saved_len);
1195                        current.truncate(saved_len); // restore
1196                        return Ok(LeafLookup::NonExistent { diverged_at });
1197                    }
1198                    // Prefix matched, so we keep walking with the longer `current`.
1199                }
1200                Some(SparseNode::Branch { state_mask, .. }) => {
1201                    // Check if branch has a child at the next nibble in our path
1202                    let nibble = path[current.len()];
1203                    if !state_mask.is_bit_set(nibble) {
1204                        // No child at this nibble - exclusion proof
1205                        return Ok(LeafLookup::NonExistent { diverged_at: current });
1206                    }
1207
1208                    // Continue down the branch
1209                    current.push_unchecked(nibble);
1210                }
1211            }
1212        }
1213
1214        // We've traversed to the end of the path and didn't find a leaf
1215        // Check if there's a node exactly at our target path
1216        match self.nodes.get(path) {
1217            Some(SparseNode::Leaf { key, .. }) if key.is_empty() => {
1218                // We found a leaf with an empty key (exact match)
1219                // This should be handled by the values map check above
1220                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                // No leaf at exactly the target path
1230                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        // If we get here, there's no leaf at the target path
1240        Ok(LeafLookup::NonExistent { diverged_at: current })
1241    }
1242
1243    /// Update the leaf node with provided value.
1244    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            // trie structure unchanged, return immediately
1249            return Ok(())
1250        }
1251
1252        let mut current = Nibbles::default();
1253        while let Some(node) = self.nodes.get_mut(&current) {
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                    // this leaf is being updated
1266                    if current == path {
1267                        unreachable!("we already checked leaf presence in the beginning");
1268                    }
1269
1270                    // find the common prefix
1271                    let common = current.common_prefix_length(&path);
1272
1273                    // update existing node
1274                    let new_ext_key = current.slice(current.len() - current_key.len()..common);
1275                    *node = SparseNode::new_ext(new_ext_key);
1276
1277                    // create a branch node and corresponding leaves
1278                    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(&current) {
1298                        // find the common prefix
1299                        let common = current.common_prefix_length(&path);
1300                        *key = current.slice(current.len() - key.len()..common);
1301
1302                        // If branch node updates retention is enabled, we need to query the
1303                        // extension node child to later set the hash mask for a parent branch node
1304                        // correctly.
1305                        if self.updates.is_some() {
1306                            // Check if the extension node child is a hash that needs to be revealed
1307                            if self.nodes.get(&current).unwrap().is_hash() {
1308                                if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1309                                    self.provider.blinded_node(&current)?
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                        // create state mask for new branch node
1330                        // NOTE: this might overwrite the current extension node
1331                        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                        // create new leaf
1336                        let new_leaf = SparseNode::new_leaf(path.slice(common + 1..));
1337                        self.nodes.insert(path.slice(..=common), new_leaf);
1338
1339                        // recreate extension to previous child if needed
1340                        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    /// Remove leaf node from the trie.
1365    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                // Leaf is present in the trie, but it's blinded.
1369                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            // Leaf is not present in the trie.
1374            return Ok(())
1375        }
1376        self.prefix_set.insert(path.clone());
1377
1378        // If the path wasn't present in `values`, we still need to walk the trie and ensure that
1379        // there is no node at the path. When a leaf node is a blinded `Hash`, it will have an entry
1380        // in `nodes`, but not in the `values`.
1381
1382        let mut removed_nodes = self.take_nodes_for_path(path)?;
1383        trace!(target: "trie::sparse", ?path, ?removed_nodes, "Removed nodes for path");
1384        // Pop the first node from the stack which is the leaf node we want to remove.
1385        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 we don't have any other removed nodes, insert an empty node at the root.
1395        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        // Walk the stack of removed nodes from the back and re-insert them back into the trie,
1403        // adjusting the node type as needed.
1404        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                    // If the node is an extension node, we need to look at its child to see if we
1417                    // need to merge them.
1418                    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                        // For a leaf node, we collapse the extension node into a leaf node,
1426                        // extending the key. While it's impossible to encounter an extension node
1427                        // followed by a leaf node in a complete trie, it's possible here because we
1428                        // could have downgraded the extension node's child into a leaf node from
1429                        // another node type.
1430                        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                        // For an extension node, we collapse them into one extension node,
1438                        // extending the key
1439                        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                        // For a branch node, we just leave the extension node as-is.
1447                        SparseNode::Branch { .. } => removed_node.node,
1448                    }
1449                }
1450                &SparseNode::Branch { mut state_mask, hash: _, store_in_db_trie: _ } => {
1451                    // If the node is a branch node, we need to check the number of children left
1452                    // after deleting the child at the given nibble.
1453
1454                    if let Some(removed_nibble) = removed_node.unset_branch_nibble {
1455                        state_mask.unset_bit(removed_nibble);
1456                    }
1457
1458                    // If only one child is left set in the branch node, we need to collapse it.
1459                    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                        // Get full path of the only child node left.
1464                        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                        // Get the only child node.
1492                        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                            // If the only child is a leaf node, we downgrade the branch node into a
1505                            // leaf node, prepending the nibble to the key, and delete the old
1506                            // child.
1507                            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                            // If the only child node is an extension node, we downgrade the branch
1515                            // node into an even longer extension node, prepending the nibble to the
1516                            // key, and delete the old child.
1517                            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                            // If the only child is a branch node, we downgrade the current branch
1525                            // node into a one-nibble extension node.
1526                            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                    // If more than one child is left set in the branch, we just re-insert it as-is.
1543                    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/// Enum representing sparse trie node type.
1563#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1564enum SparseNodeType {
1565    /// Empty trie node.
1566    Empty,
1567    /// The hash of the node that was not revealed.
1568    Hash,
1569    /// Sparse leaf node.
1570    Leaf,
1571    /// Sparse extension node.
1572    Extension {
1573        /// A flag indicating whether the extension node should be stored in the database.
1574        store_in_db_trie: Option<bool>,
1575    },
1576    /// Sparse branch node.
1577    Branch {
1578        /// A flag indicating whether the branch node should be stored in the database.
1579        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/// Enum representing trie nodes in sparse trie.
1603#[derive(Debug, Clone, PartialEq, Eq)]
1604pub enum SparseNode {
1605    /// Empty trie node.
1606    Empty,
1607    /// The hash of the node that was not revealed.
1608    Hash(B256),
1609    /// Sparse leaf node with remaining key suffix.
1610    Leaf {
1611        /// Remaining key suffix for the leaf node.
1612        key: Nibbles,
1613        /// Pre-computed hash of the sparse node.
1614        /// Can be reused unless this trie path has been updated.
1615        hash: Option<B256>,
1616    },
1617    /// Sparse extension node with key.
1618    Extension {
1619        /// The key slice stored by this extension node.
1620        key: Nibbles,
1621        /// Pre-computed hash of the sparse node.
1622        /// Can be reused unless this trie path has been updated.
1623        ///
1624        /// If [`None`], then the value is not known and should be calculated from scratch.
1625        hash: Option<B256>,
1626        /// Pre-computed flag indicating whether the trie node should be stored in the database.
1627        /// Can be reused unless this trie path has been updated.
1628        ///
1629        /// If [`None`], then the value is not known and should be calculated from scratch.
1630        store_in_db_trie: Option<bool>,
1631    },
1632    /// Sparse branch node with state mask.
1633    Branch {
1634        /// The bitmask representing children present in the branch node.
1635        state_mask: TrieMask,
1636        /// Pre-computed hash of the sparse node.
1637        /// Can be reused unless this trie path has been updated.
1638        ///
1639        /// If [`None`], then the value is not known and should be calculated from scratch.
1640        hash: Option<B256>,
1641        /// Pre-computed flag indicating whether the trie node should be stored in the database.
1642        /// Can be reused unless this trie path has been updated.
1643        ///
1644        /// If [`None`], then the value is not known and should be calculated from scratch.
1645        store_in_db_trie: Option<bool>,
1646    },
1647}
1648
1649impl SparseNode {
1650    /// Create new sparse node from [`TrieNode`].
1651    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    /// Create new [`SparseNode::Branch`] from state mask.
1661    pub const fn new_branch(state_mask: TrieMask) -> Self {
1662        Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1663    }
1664
1665    /// Create new [`SparseNode::Branch`] with two bits set.
1666    pub const fn new_split_branch(bit_a: u8, bit_b: u8) -> Self {
1667        let state_mask = TrieMask::new(
1668            // set bits for both children
1669            (1u16 << bit_a) | (1u16 << bit_b),
1670        );
1671        Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1672    }
1673
1674    /// Create new [`SparseNode::Extension`] from the key slice.
1675    pub const fn new_ext(key: Nibbles) -> Self {
1676        Self::Extension { key, hash: None, store_in_db_trie: None }
1677    }
1678
1679    /// Create new [`SparseNode::Leaf`] from leaf key and value.
1680    pub const fn new_leaf(key: Nibbles) -> Self {
1681        Self::Leaf { key, hash: None }
1682    }
1683
1684    /// Returns `true` if the node is a hash node.
1685    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/// Collection of reusable buffers for [`RevealedSparseTrie::rlp_node`].
1698#[derive(Debug, Default)]
1699pub struct RlpNodeBuffers {
1700    /// Stack of RLP node paths
1701    path_stack: Vec<RlpNodePathStackItem>,
1702    /// Stack of RLP nodes
1703    rlp_node_stack: Vec<RlpNodeStackItem>,
1704    /// Reusable branch child path
1705    branch_child_buf: SmallVec<[Nibbles; 16]>,
1706    /// Reusable branch value stack
1707    branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
1708}
1709
1710impl RlpNodeBuffers {
1711    /// Creates a new instance of buffers with the root path on the stack.
1712    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/// RLP node path stack item.
1727#[derive(Debug)]
1728struct RlpNodePathStackItem {
1729    /// Level at which the node is located. Higher numbers correspond to lower levels in the trie.
1730    level: usize,
1731    /// Path to the node.
1732    path: Nibbles,
1733    /// Whether the path is in the prefix set. If [`None`], then unknown yet.
1734    is_in_prefix_set: Option<bool>,
1735}
1736
1737/// RLP node stack item.
1738#[derive(Debug)]
1739struct RlpNodeStackItem {
1740    /// Path to the node.
1741    path: Nibbles,
1742    /// RLP node.
1743    rlp_node: RlpNode,
1744    /// Type of the node.
1745    node_type: SparseNodeType,
1746}
1747
1748/// The aggregation of sparse trie updates.
1749#[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    /// Create new wiped sparse trie updates.
1758    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    // Assuming this exists
1769    use alloy_rlp::Encodable;
1770    use assert_matches::assert_matches;
1771    use reth_primitives_traits::Account;
1772    use reth_trie_common::LeafNode;
1773
1774    // Helper to create some test values
1775    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        // Create a simple trie with one leaf
1789        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        // Check that the leaf exists
1796        let result = sparse.find_leaf(&path, None);
1797        assert_matches!(result, Ok(LeafLookup::Exists));
1798
1799        // Check with expected value matching
1800        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        // Create a simple trie with one leaf
1807        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        // Check with wrong expected value
1815        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        // Empty trie
1825        let sparse = RevealedSparseTrie::default();
1826        let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
1827
1828        // Leaf should not exist
1829        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        // In an empty trie, the search diverges immediately at the root.
1844        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]); // Creates branch at 0x12
1872        let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]); // Belongs to same branch
1873        let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]); // Diverges at nibble 7
1874
1875        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        // Diverged at the branch node because nibble '7' is not present.
1881        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        // This will create an extension node at root with key 0x12
1889        let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
1890        // This path diverges from the extension key
1891        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        // Diverged where the extension node started because the path doesn't match its key prefix.
1898        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        // Diverged when it hit the leaf node at the root, because the search path is longer
1913        // than the leaf's key stored there. The code returns the path of the node (root)
1914        // where the divergence occurred.
1915        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]); // Creates branch at 0x12
1923        let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]);
1924        let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2]); // Path of the branch itself
1925
1926        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        // The path ends, but the node at the path is a branch, not a leaf.
1932        // Diverged at the parent of the node found at the search path.
1933        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        // Scenario: The node *at* the leaf path is blinded.
1940        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        // Create path to the blinded node
1945        nodes.insert(
1946            Nibbles::default(),
1947            SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x1, 0x2])),
1948        ); // Ext 0x12
1949        nodes.insert(
1950            Nibbles::from_nibbles_unchecked([0x1, 0x2]),
1951            SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x3])),
1952        ); // Ext 0x123
1953        nodes.insert(
1954            Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3]),
1955            SparseNode::new_branch(TrieMask::new(0b10000)),
1956        ); // Branch at 0x123, child 4
1957        nodes.insert(leaf_path.clone(), SparseNode::Hash(blinded_hash)); // Blinded node at 0x1234
1958
1959        let sparse = RevealedSparseTrie {
1960            provider: DefaultBlindedProvider,
1961            nodes,
1962            branch_node_tree_masks: Default::default(),
1963            branch_node_hash_masks: Default::default(),
1964            /* The value is not in the values map, or else it would early return */
1965            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        // Should error because it hit the blinded node exactly at the leaf path
1974        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        // Root is a branch with child 0x1 (blinded) and 0x5 (revealed leaf)
1988        // So we set Bit 1 and Bit 5 in the state_mask
1989        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        // Should error because it hit the blinded node at path 0x1
2017        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]); // Path of the blinded node itself
2026        let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); // Path we will search for
2027
2028        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        // 1. Construct the RLP representation of the children for the root branch
2034        let rlp_node_child1 = RlpNode::word_rlp(&blinded_hash); // Blinded node
2035
2036        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        // 2. Construct the root BranchNode using the RLP of its children
2042        // The stack order depends on the bit indices (1 and 5)
2043        let root_branch_node = reth_trie_common::BranchNode::new(
2044            vec![rlp_node_child1, rlp_node_child5], // Child 1 first, then Child 5
2045            TrieMask::new(0b100010),                // Mask with bits 1 and 5 set
2046        );
2047        let root_trie_node = TrieNode::Branch(root_branch_node);
2048
2049        // 3. Initialize the sparse trie using from_root
2050        // This will internally create Hash nodes for paths "1" and "5" initially.
2051        let mut sparse = RevealedSparseTrie::from_root(root_trie_node, TrieMasks::none(), false)
2052            .expect("Failed to create trie from root");
2053
2054        // Assertions before we reveal child5
2055        assert_matches!(sparse.nodes.get(&Nibbles::default()), Some(SparseNode::Branch { state_mask, .. }) if *state_mask == TrieMask::new(0b100010)); // Here we check that 1 and 5 are set in the state_mask
2056        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()); // Child 5 is initially a hash of its RLP
2058        assert!(sparse.values.is_empty());
2059
2060        // 4. Explicitly reveal the leaf node for child 5
2061        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        // Assertions after we reveal child 5
2070        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        // 5. Assert the expected error
2078        // Should error because it hit the blinded node at path "1" only node at "5" was revealed
2079        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    /// Pad nibbles to the length of a B256 hash with zeros on the left.
2113    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    /// Pad nibbles to the length of a B256 hash with zeros on the right.
2121    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    /// Calculate the state root by feeding the provided state to the hash builder and retaining the
2127    /// proofs for the provided targets.
2128    ///
2129    /// Returns the state root and the retained proof nodes.
2130    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    /// Assert that the sparse trie nodes and the proof nodes from the hash builder are equal.
2200    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                // Both nodes are empty
2218                (TrieNode::EmptyRoot, SparseNode::Empty) => true,
2219                // Both nodes are branches and have the same state mask
2220                (
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                // Both nodes are extensions and have the same key
2225                (
2226                    TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
2227                    SparseNode::Extension { key: sparse_key, .. },
2228                ) |
2229                // Both nodes are leaves and have the same key
2230                (
2231                    TrieNode::Leaf(LeafNode { key: proof_key, .. }),
2232                    SparseNode::Leaf { key: sparse_key, .. },
2233                ) => proof_key == sparse_key,
2234                // Empty and hash nodes are specific to the sparse trie, skip them
2235                (_, 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        // Extension (Key = 5)
2462        // └── Branch (Mask = 1011)
2463        //     ├── 0 -> Extension (Key = 23)
2464        //     │        └── Branch (Mask = 0101)
2465        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231)
2466        //     │              └── 3 -> Leaf (Key = 3, Path = 50233)
2467        //     ├── 2 -> Leaf (Key = 013, Path = 52013)
2468        //     └── 3 -> Branch (Mask = 0101)
2469        //                ├── 1 -> Leaf (Key = 3102, Path = 53102)
2470        //                └── 3 -> Branch (Mask = 1010)
2471        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302)
2472        //                       └── 2 -> Leaf (Key = 3320, Path = 53320)
2473        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        // Extension (Key = 5)
2518        // └── Branch (Mask = 1001)
2519        //     ├── 0 -> Extension (Key = 23)
2520        //     │        └── Branch (Mask = 0101)
2521        //     │              ├── 1 -> Leaf (Key = 0231, Path = 50231)
2522        //     │              └── 3 -> Leaf (Key = 0233, Path = 50233)
2523        //     └── 3 -> Branch (Mask = 0101)
2524        //                ├── 1 -> Leaf (Key = 3102, Path = 53102)
2525        //                └── 3 -> Branch (Mask = 1010)
2526        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302)
2527        //                       └── 2 -> Leaf (Key = 3320, Path = 53320)
2528        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        // Extension (Key = 5)
2569        // └── Branch (Mask = 1001)
2570        //     ├── 0 -> Leaf (Key = 0233, Path = 50233)
2571        //     └── 3 -> Branch (Mask = 0101)
2572        //                ├── 1 -> Leaf (Key = 3102, Path = 53102)
2573        //                └── 3 -> Branch (Mask = 1010)
2574        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302)
2575        //                       └── 2 -> Leaf (Key = 3320, Path = 53320)
2576        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        // Extension (Key = 5)
2605        // └── Branch (Mask = 1001)
2606        //     ├── 0 -> Leaf (Key = 0233, Path = 50233)
2607        //     └── 3 -> Branch (Mask = 1010)
2608        //                ├── 0 -> Leaf (Key = 3302, Path = 53302)
2609        //                └── 2 -> Leaf (Key = 3320, Path = 53320)
2610        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        // Extension (Key = 5)
2638        // └── Branch (Mask = 1001)
2639        //     ├── 0 -> Leaf (Key = 0233, Path = 50233)
2640        //     └── 3 -> Leaf (Key = 3302, Path = 53302)
2641        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        // Leaf (Key = 53302)
2660        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        // Empty
2671        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        // Reveal a branch node and one of its children
2699        //
2700        // Branch (Mask = 11)
2701        // ├── 0 -> Hash (Path = 0)
2702        // └── 1 -> Leaf (Path = 1)
2703        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        // Removing a blinded leaf should result in an error
2715        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        // Reveal a branch node and one of its children
2743        //
2744        // Branch (Mask = 11)
2745        // ├── 0 -> Hash (Path = 0)
2746        // └── 1 -> Leaf (Path = 1)
2747        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        // Removing a non-existent leaf should be a noop
2759        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        // Having only the first 3 nibbles set, we narrow down the range of keys
2767        // to 4096 different hashes. It allows us to generate collisions more likely
2768        // to test the sparse trie updates.
2769        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                    // Insert state updates into the sparse trie and calculate the root
2779                    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                    // We need to clone the sparse trie, so that all updated branch nodes are
2786                    // preserved, and not only those that were changed after the last call to
2787                    // `root()`.
2788                    let mut updated_sparse = sparse.clone();
2789                    let sparse_root = updated_sparse.root();
2790                    let sparse_updates = updated_sparse.take_updates();
2791
2792                    // Insert state updates into the hash builder and calculate the root
2793                    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                    // Write trie updates to the database
2805                    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 that the sparse trie root matches the hash builder root
2810                    assert_eq!(sparse_root, hash_builder_root);
2811                    // Assert that the sparse trie updates match the hash builder updates
2812                    pretty_assertions::assert_eq!(
2813                        BTreeMap::from_iter(sparse_updates.updated_nodes),
2814                        BTreeMap::from_iter(hash_builder_updates.account_nodes)
2815                    );
2816                    // Assert that the sparse trie nodes match the hash builder proof nodes
2817                    assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
2818
2819                    // Delete some keys from both the hash builder and the sparse trie and check
2820                    // that the sparse trie root still matches the hash builder root
2821                    for key in &keys_to_delete {
2822                        state.remove(key).unwrap();
2823                        sparse.remove_leaf(key).unwrap();
2824                    }
2825
2826                    // We need to clone the sparse trie, so that all updated branch nodes are
2827                    // preserved, and not only those that were changed after the last call to
2828                    // `root()`.
2829                    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                    // Write trie updates to the database
2847                    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 that the sparse trie root matches the hash builder root
2852                    assert_eq!(sparse_root, hash_builder_root);
2853                    // Assert that the sparse trie updates match the hash builder updates
2854                    pretty_assertions::assert_eq!(
2855                        BTreeMap::from_iter(sparse_updates.updated_nodes),
2856                        BTreeMap::from_iter(hash_builder_updates.account_nodes)
2857                    );
2858                    // Assert that the sparse trie nodes match the hash builder proof nodes
2859                    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    /// We have three leaves that share the same prefix: 0x00, 0x01 and 0x02. Hash builder trie has
2904    /// only nodes 0x00 and 0x01, and we have proofs for them. Node B is new and inserted in the
2905    /// sparse trie first.
2906    ///
2907    /// 1. Reveal the hash builder proof to leaf 0x00 in the sparse trie.
2908    /// 2. Insert leaf 0x01 into the sparse trie.
2909    /// 3. Reveal the hash builder proof to leaf 0x02 in the sparse trie.
2910    ///
2911    /// The hash builder proof to the leaf 0x02 didn't have the leaf 0x01 at the corresponding
2912    /// nibble of the branch node, so we need to adjust the branch node instead of fully
2913    /// replacing it.
2914    #[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        // Generate the proof for the root node and initialize the sparse trie with it
2927        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        // Generate the proof for the first key and reveal it in the sparse trie
2945        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        // Check that the branch node exists with only two nibbles set
2965        assert_eq!(
2966            sparse.nodes.get(&Nibbles::default()),
2967            Some(&SparseNode::new_branch(0b101.into()))
2968        );
2969
2970        // Insert the leaf for the second key
2971        sparse.update_leaf(key2(), value_encoded()).unwrap();
2972
2973        // Check that the branch node was updated and another nibble was set
2974        assert_eq!(
2975            sparse.nodes.get(&Nibbles::default()),
2976            Some(&SparseNode::new_branch(0b111.into()))
2977        );
2978
2979        // Generate the proof for the third key and reveal it in the sparse trie
2980        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        // Check that nothing changed in the branch node
3000        assert_eq!(
3001            sparse.nodes.get(&Nibbles::default()),
3002            Some(&SparseNode::new_branch(0b111.into()))
3003        );
3004
3005        // Generate the nodes for the full trie with all three key using the hash builder, and
3006        // compare them to the sparse trie
3007        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    /// We have three leaves: 0x0000, 0x0101, and 0x0102. Hash builder trie has all nodes, and we
3018    /// have proofs for them.
3019    ///
3020    /// 1. Reveal the hash builder proof to leaf 0x00 in the sparse trie.
3021    /// 2. Remove leaf 0x00 from the sparse trie (that will remove the branch node and create an
3022    ///    extension node with the key 0x0000).
3023    /// 3. Reveal the hash builder proof to leaf 0x0101 in the sparse trie.
3024    ///
3025    /// The hash builder proof to the leaf 0x0101 had a branch node in the path, but we turned it
3026    /// into an extension node, so it should ignore this node.
3027    #[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        // Generate the proof for the root node and initialize the sparse trie with it
3035        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        // Generate the proof for the children of the root branch node and reveal it in the sparse
3053        // trie
3054        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        // Check that the branch node exists
3074        assert_eq!(
3075            sparse.nodes.get(&Nibbles::default()),
3076            Some(&SparseNode::new_branch(0b11.into()))
3077        );
3078
3079        // Remove the leaf for the first key
3080        sparse.remove_leaf(&key1()).unwrap();
3081
3082        // Check that the branch node was turned into an extension node
3083        assert_eq!(
3084            sparse.nodes.get(&Nibbles::default()),
3085            Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3086        );
3087
3088        // Generate the proof for the third key and reveal it in the sparse trie
3089        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        // Check that nothing changed in the extension node
3109        assert_eq!(
3110            sparse.nodes.get(&Nibbles::default()),
3111            Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3112        );
3113    }
3114
3115    /// We have two leaves that share the same prefix: 0x0001 and 0x0002, and a leaf with a
3116    /// different prefix: 0x0100. Hash builder trie has only the first two leaves, and we have
3117    /// proofs for them.
3118    ///
3119    /// 1. Insert the leaf 0x0100 into the sparse trie, and check that the root extension node was
3120    ///    turned into a branch node.
3121    /// 2. Reveal the leaf 0x0001 in the sparse trie, and check that the root branch node wasn't
3122    ///    overwritten with the extension node from the proof.
3123    #[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        // Generate the proof for the root node and initialize the sparse trie with it
3136        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        // Check that the root extension node exists
3154        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        // Insert the leaf with a different prefix
3160        sparse.update_leaf(key3(), value_encoded()).unwrap();
3161
3162        // Check that the extension node was turned into a branch node
3163        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        // Generate the proof for the first key and reveal it in the sparse trie
3169        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        // Check that the branch node wasn't overwritten by the extension node in the proof
3189        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        // Extension (Key = 5) – Level 0
3202        // └── Branch (Mask = 1011) – Level 1
3203        //     ├── 0 -> Extension (Key = 23) – Level 2
3204        //     │        └── Branch (Mask = 0101) – Level 3
3205        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231) – Level 4
3206        //     │              └── 3 -> Leaf (Key = 3, Path = 50233) – Level 4
3207        //     ├── 2 -> Leaf (Key = 013, Path = 52013) – Level 2
3208        //     └── 3 -> Branch (Mask = 0101) – Level 2
3209        //                ├── 1 -> Leaf (Key = 3102, Path = 53102) – Level 3
3210        //                └── 3 -> Branch (Mask = 1010) – Level 3
3211        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4
3212        //                       └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4
3213        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        // Extension (Key = 5) – Level 0
3325        // └── Branch (Mask = 1011) – Level 1
3326        //     ├── 0 -> Extension (Key = 23) – Level 2
3327        //     │        └── Branch (Mask = 0101) – Level 3
3328        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231) – Level 4
3329        //     │              └── 3 -> Leaf (Key = 3, Path = 50233) – Level 4
3330        //     ├── 2 -> Leaf (Key = 013, Path = 52013) – Level 2
3331        //     └── 3 -> Branch (Mask = 0101) – Level 2
3332        //                ├── 1 -> Leaf (Key = 3102, Path = 53102) – Level 3
3333        //                └── 3 -> Branch (Mask = 1010) – Level 3
3334        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4
3335        //                       └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4
3336        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        // Extension (Key = 5) – Level 0
3365        // └── Branch (Mask = 1011) – Level 1
3366        //     ├── 0 -> Extension (Key = 23) – Level 2
3367        //     │        └── Branch (Mask = 0101) – Level 3
3368        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231) – Level 4
3369        //     │              └── 3 -> Leaf (Key = 3, Path = 50233) – Level 4
3370        //     ├── 2 -> Leaf (Key = 013, Path = 52013) – Level 2
3371        //     └── 3 -> Branch (Mask = 0101) – Level 2
3372        //                ├── 1 -> Leaf (Key = 3102, Path = 53102) – Level 3
3373        //                └── 3 -> Branch (Mask = 1010) – Level 3
3374        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4
3375        //                       └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4
3376        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}