reth_trie_sparse/
trie.rs

1use crate::{
2    provider::{RevealedNode, TrieNodeProvider},
3    LeafLookup, LeafLookupError, RevealedSparseNode, SparseTrieInterface, SparseTrieUpdates,
4    TrieMasks,
5};
6use alloc::{
7    borrow::Cow,
8    boxed::Box,
9    fmt,
10    string::{String, ToString},
11    vec,
12    vec::Vec,
13};
14use alloy_primitives::{
15    hex, keccak256,
16    map::{Entry, HashMap, HashSet},
17    B256,
18};
19use alloy_rlp::Decodable;
20use reth_execution_errors::{SparseTrieErrorKind, SparseTrieResult};
21use reth_trie_common::{
22    prefix_set::{PrefixSet, PrefixSetMut},
23    BranchNodeCompact, BranchNodeRef, ExtensionNodeRef, LeafNodeRef, Nibbles, RlpNode, TrieMask,
24    TrieNode, CHILD_INDEX_RANGE, EMPTY_ROOT_HASH,
25};
26use smallvec::SmallVec;
27use tracing::{debug, instrument, trace};
28
29/// The level below which the sparse trie hashes are calculated in
30/// [`SerialSparseTrie::update_subtrie_hashes`].
31const SPARSE_TRIE_SUBTRIE_HASHES_LEVEL: usize = 2;
32
33/// A sparse trie that is either in a "blind" state (no nodes are revealed, root node hash is
34/// unknown) or in a "revealed" state (root node has been revealed and the trie can be updated).
35///
36/// In blind mode the trie does not contain any decoded node data, which saves memory but
37/// prevents direct access to node contents. The revealed mode stores decoded nodes along
38/// with additional information such as values, allowing direct manipulation.
39///
40/// The sparse trie design is optimised for:
41/// 1. Memory efficiency - only revealed nodes are loaded into memory
42/// 2. Update tracking - changes to the trie structure can be tracked and selectively persisted
43/// 3. Incremental operations - nodes can be revealed as needed without loading the entire trie.
44///    This is what gives rise to the notion of a "sparse" trie.
45#[derive(PartialEq, Eq, Debug, Clone)]
46pub enum SparseTrie<T = SerialSparseTrie> {
47    /// The trie is blind -- no nodes have been revealed
48    ///
49    /// This is the default state. In this state, the trie cannot be directly queried or modified
50    /// until nodes are revealed.
51    ///
52    /// In this state the `SparseTrie` can optionally carry with it a cleared `SerialSparseTrie`.
53    /// This allows for reusing the trie's allocations between payload executions.
54    Blind(Option<Box<T>>),
55    /// Some nodes in the Trie have been revealed.
56    ///
57    /// In this state, the trie can be queried and modified for the parts
58    /// that have been revealed. Other parts remain blind and require revealing
59    /// before they can be accessed.
60    Revealed(Box<T>),
61}
62
63impl<T: Default> Default for SparseTrie<T> {
64    fn default() -> Self {
65        Self::Blind(None)
66    }
67}
68
69impl<T: SparseTrieInterface + Default> SparseTrie<T> {
70    /// Creates a new revealed but empty sparse trie with `SparseNode::Empty` as root node.
71    ///
72    /// # Examples
73    ///
74    /// ```
75    /// use reth_trie_sparse::{provider::DefaultTrieNodeProvider, SerialSparseTrie, SparseTrie};
76    ///
77    /// let trie = SparseTrie::<SerialSparseTrie>::revealed_empty();
78    /// assert!(!trie.is_blind());
79    /// ```
80    pub fn revealed_empty() -> Self {
81        Self::Revealed(Box::default())
82    }
83
84    /// Reveals the root node, converting a blind trie into a revealed one.
85    ///
86    /// If the trie is blinded, its root node is replaced with `root`.
87    ///
88    /// The `masks` are used to determine how the node's children are stored.
89    /// The `retain_updates` flag controls whether changes to the trie structure
90    /// should be tracked.
91    ///
92    /// # Returns
93    ///
94    /// A mutable reference to the underlying [`SparseTrieInterface`].
95    pub fn reveal_root(
96        &mut self,
97        root: TrieNode,
98        masks: TrieMasks,
99        retain_updates: bool,
100    ) -> SparseTrieResult<&mut T> {
101        // if `Blind`, we initialize the revealed trie with the given root node, using a
102        // pre-allocated trie if available.
103        if self.is_blind() {
104            let mut revealed_trie = if let Self::Blind(Some(cleared_trie)) = core::mem::take(self) {
105                cleared_trie
106            } else {
107                Box::default()
108            };
109
110            *revealed_trie = revealed_trie.with_root(root, masks, retain_updates)?;
111            *self = Self::Revealed(revealed_trie);
112        }
113
114        Ok(self.as_revealed_mut().unwrap())
115    }
116}
117
118impl<T: SparseTrieInterface> SparseTrie<T> {
119    /// Creates a new blind sparse trie.
120    ///
121    /// # Examples
122    ///
123    /// ```
124    /// use reth_trie_sparse::{provider::DefaultTrieNodeProvider, SerialSparseTrie, SparseTrie};
125    ///
126    /// let trie = SparseTrie::<SerialSparseTrie>::blind();
127    /// assert!(trie.is_blind());
128    /// let trie = SparseTrie::<SerialSparseTrie>::default();
129    /// assert!(trie.is_blind());
130    /// ```
131    pub const fn blind() -> Self {
132        Self::Blind(None)
133    }
134
135    /// Creates a new blind sparse trie, clearing and later reusing the given
136    /// [`SparseTrieInterface`].
137    pub fn blind_from(mut trie: T) -> Self {
138        trie.clear();
139        Self::Blind(Some(Box::new(trie)))
140    }
141
142    /// Returns `true` if the sparse trie has no revealed nodes.
143    pub const fn is_blind(&self) -> bool {
144        matches!(self, Self::Blind(_))
145    }
146
147    /// Returns `true` if the sparse trie is revealed.
148    pub const fn is_revealed(&self) -> bool {
149        matches!(self, Self::Revealed(_))
150    }
151
152    /// Returns an immutable reference to the underlying revealed sparse trie.
153    ///
154    /// Returns `None` if the trie is blinded.
155    pub const fn as_revealed_ref(&self) -> Option<&T> {
156        if let Self::Revealed(revealed) = self {
157            Some(revealed)
158        } else {
159            None
160        }
161    }
162
163    /// Returns a mutable reference to the underlying revealed sparse trie.
164    ///
165    /// Returns `None` if the trie is blinded.
166    pub fn as_revealed_mut(&mut self) -> Option<&mut T> {
167        if let Self::Revealed(revealed) = self {
168            Some(revealed)
169        } else {
170            None
171        }
172    }
173
174    /// Wipes the trie by removing all nodes and values,
175    /// and resetting the trie to only contain an empty root node.
176    ///
177    /// Note: This method will error if the trie is blinded.
178    pub fn wipe(&mut self) -> SparseTrieResult<()> {
179        let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
180        revealed.wipe();
181        Ok(())
182    }
183
184    /// Calculates the root hash of the trie.
185    ///
186    /// This will update any remaining dirty nodes before computing the root hash.
187    /// "dirty" nodes are nodes that need their hashes to be recomputed because one or more of their
188    /// children's hashes have changed.
189    ///
190    /// # Returns
191    ///
192    /// - `Some(B256)` with the calculated root hash if the trie is revealed.
193    /// - `None` if the trie is still blind.
194    pub fn root(&mut self) -> Option<B256> {
195        Some(self.as_revealed_mut()?.root())
196    }
197
198    /// Returns the root hash along with any accumulated update information.
199    ///
200    /// This is useful for when you need both the root hash and information about
201    /// what nodes were modified, which can be used to efficiently update
202    /// an external database.
203    ///
204    /// # Returns
205    ///
206    /// An `Option` tuple consisting of:
207    ///  - The trie root hash (`B256`).
208    ///  - A [`SparseTrieUpdates`] structure containing information about updated nodes.
209    ///  - `None` if the trie is still blind.
210    pub fn root_with_updates(&mut self) -> Option<(B256, SparseTrieUpdates)> {
211        let revealed = self.as_revealed_mut()?;
212        Some((revealed.root(), revealed.take_updates()))
213    }
214
215    /// Returns a [`SparseTrie::Blind`] based on this one. If this instance was revealed, or was
216    /// itself a `Blind` with a pre-allocated [`SparseTrieInterface`], this will return
217    /// a `Blind` carrying a cleared pre-allocated [`SparseTrieInterface`].
218    pub fn clear(self) -> Self {
219        match self {
220            Self::Blind(_) => self,
221            Self::Revealed(mut trie) => {
222                trie.clear();
223                Self::Blind(Some(trie))
224            }
225        }
226    }
227
228    /// Updates (or inserts) a leaf at the given key path with the specified RLP-encoded value.
229    ///
230    /// # Errors
231    ///
232    /// Returns an error if the trie is still blind, or if the update fails.
233    #[instrument(level = "trace", target = "trie::sparse", skip_all)]
234    pub fn update_leaf(
235        &mut self,
236        path: Nibbles,
237        value: Vec<u8>,
238        provider: impl TrieNodeProvider,
239    ) -> SparseTrieResult<()> {
240        let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
241        revealed.update_leaf(path, value, provider)?;
242        Ok(())
243    }
244
245    /// Removes a leaf node at the specified key path.
246    ///
247    /// # Errors
248    ///
249    /// Returns an error if the trie is still blind, or if the leaf cannot be removed
250    #[instrument(level = "trace", target = "trie::sparse", skip_all)]
251    pub fn remove_leaf(
252        &mut self,
253        path: &Nibbles,
254        provider: impl TrieNodeProvider,
255    ) -> SparseTrieResult<()> {
256        let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
257        revealed.remove_leaf(path, provider)?;
258        Ok(())
259    }
260
261    /// Shrinks the capacity of the sparse trie's node storage.
262    /// Works for both revealed and blind tries with allocated storage.
263    pub fn shrink_nodes_to(&mut self, size: usize) {
264        match self {
265            Self::Blind(Some(trie)) | Self::Revealed(trie) => {
266                trie.shrink_nodes_to(size);
267            }
268            _ => {}
269        }
270    }
271
272    /// Shrinks the capacity of the sparse trie's value storage.
273    /// Works for both revealed and blind tries with allocated storage.
274    pub fn shrink_values_to(&mut self, size: usize) {
275        match self {
276            Self::Blind(Some(trie)) | Self::Revealed(trie) => {
277                trie.shrink_values_to(size);
278            }
279            _ => {}
280        }
281    }
282}
283
284/// The representation of revealed sparse trie.
285///
286/// The revealed sparse trie contains the actual trie structure with nodes, values, and
287/// tracking for changes. It supports operations like inserting, updating, and removing
288/// nodes.
289///
290///
291/// ## Invariants
292///
293/// - The root node is always present in `nodes` collection.
294/// - Each leaf entry in `nodes` collection must have a corresponding entry in `values` collection.
295///   The opposite is also true.
296/// - All keys in `values` collection are full leaf paths.
297#[derive(Clone, PartialEq, Eq)]
298pub struct SerialSparseTrie {
299    /// Map from a path (nibbles) to its corresponding sparse trie node.
300    /// This contains all of the revealed nodes in trie.
301    nodes: HashMap<Nibbles, SparseNode>,
302    /// When a branch is set, the corresponding child subtree is stored in the database.
303    branch_node_tree_masks: HashMap<Nibbles, TrieMask>,
304    /// When a bit is set, the corresponding child is stored as a hash in the database.
305    branch_node_hash_masks: HashMap<Nibbles, TrieMask>,
306    /// Map from leaf key paths to their values.
307    /// All values are stored here instead of directly in leaf nodes.
308    values: HashMap<Nibbles, Vec<u8>>,
309    /// Set of prefixes (key paths) that have been marked as updated.
310    /// This is used to track which parts of the trie need to be recalculated.
311    prefix_set: PrefixSetMut,
312    /// Optional tracking of trie updates for later use.
313    updates: Option<SparseTrieUpdates>,
314    /// Reusable buffer for RLP encoding of nodes.
315    rlp_buf: Vec<u8>,
316}
317
318impl fmt::Debug for SerialSparseTrie {
319    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
320        f.debug_struct("SerialSparseTrie")
321            .field("nodes", &self.nodes)
322            .field("branch_tree_masks", &self.branch_node_tree_masks)
323            .field("branch_hash_masks", &self.branch_node_hash_masks)
324            .field("values", &self.values)
325            .field("prefix_set", &self.prefix_set)
326            .field("updates", &self.updates)
327            .field("rlp_buf", &hex::encode(&self.rlp_buf))
328            .finish_non_exhaustive()
329    }
330}
331
332/// Turns a [`Nibbles`] into a [`String`] by concatenating each nibbles' hex character.
333fn encode_nibbles(nibbles: &Nibbles) -> String {
334    let encoded = hex::encode(nibbles.pack());
335    encoded[..nibbles.len()].to_string()
336}
337
338impl fmt::Display for SerialSparseTrie {
339    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340        // This prints the trie in preorder traversal, using a stack
341        let mut stack = Vec::new();
342        let mut visited = HashSet::new();
343
344        // 4 spaces as indent per level
345        const INDENT: &str = "    ";
346
347        // Track both path and depth
348        stack.push((Nibbles::default(), self.nodes_ref().get(&Nibbles::default()).unwrap(), 0));
349
350        while let Some((path, node, depth)) = stack.pop() {
351            if !visited.insert(path) {
352                continue;
353            }
354
355            // Add indentation if alternate flag (#) is set
356            if f.alternate() {
357                write!(f, "{}", INDENT.repeat(depth))?;
358            }
359
360            let packed_path = if depth == 0 { String::from("Root") } else { encode_nibbles(&path) };
361
362            match node {
363                SparseNode::Empty | SparseNode::Hash(_) => {
364                    writeln!(f, "{packed_path} -> {node:?}")?;
365                }
366                SparseNode::Leaf { key, .. } => {
367                    // we want to append the key to the path
368                    let mut full_path = path;
369                    full_path.extend(key);
370                    let packed_path = encode_nibbles(&full_path);
371
372                    writeln!(f, "{packed_path} -> {node:?}")?;
373                }
374                SparseNode::Extension { key, .. } => {
375                    writeln!(f, "{packed_path} -> {node:?}")?;
376
377                    // push the child node onto the stack with increased depth
378                    let mut child_path = path;
379                    child_path.extend(key);
380                    if let Some(child_node) = self.nodes_ref().get(&child_path) {
381                        stack.push((child_path, child_node, depth + 1));
382                    }
383                }
384                SparseNode::Branch { state_mask, .. } => {
385                    writeln!(f, "{packed_path} -> {node:?}")?;
386
387                    for i in CHILD_INDEX_RANGE.rev() {
388                        if state_mask.is_bit_set(i) {
389                            let mut child_path = path;
390                            child_path.push_unchecked(i);
391                            if let Some(child_node) = self.nodes_ref().get(&child_path) {
392                                stack.push((child_path, child_node, depth + 1));
393                            }
394                        }
395                    }
396                }
397            }
398        }
399
400        Ok(())
401    }
402}
403
404impl Default for SerialSparseTrie {
405    fn default() -> Self {
406        Self {
407            nodes: HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]),
408            branch_node_tree_masks: HashMap::default(),
409            branch_node_hash_masks: HashMap::default(),
410            values: HashMap::default(),
411            prefix_set: PrefixSetMut::default(),
412            updates: None,
413            rlp_buf: Vec::new(),
414        }
415    }
416}
417
418impl SparseTrieInterface for SerialSparseTrie {
419    fn with_root(
420        mut self,
421        root: TrieNode,
422        masks: TrieMasks,
423        retain_updates: bool,
424    ) -> SparseTrieResult<Self> {
425        self = self.with_updates(retain_updates);
426
427        // A fresh/cleared `SerialSparseTrie` has a `SparseNode::Empty` at its root. Delete that
428        // so we can reveal the new root node.
429        let path = Nibbles::default();
430        let _removed_root = self.nodes.remove(&path).expect("root node should exist");
431        debug_assert_eq!(_removed_root, SparseNode::Empty);
432
433        self.reveal_node(path, root, masks)?;
434        Ok(self)
435    }
436
437    fn with_updates(mut self, retain_updates: bool) -> Self {
438        if retain_updates {
439            self.updates = Some(SparseTrieUpdates::default());
440        }
441        self
442    }
443
444    fn reserve_nodes(&mut self, additional: usize) {
445        self.nodes.reserve(additional);
446    }
447    fn reveal_node(
448        &mut self,
449        path: Nibbles,
450        node: TrieNode,
451        masks: TrieMasks,
452    ) -> SparseTrieResult<()> {
453        trace!(target: "trie::sparse", ?path, ?node, ?masks, "reveal_node called");
454
455        // If the node is already revealed and it's not a hash node, do nothing.
456        if self.nodes.get(&path).is_some_and(|node| !node.is_hash()) {
457            return Ok(())
458        }
459
460        if let Some(tree_mask) = masks.tree_mask {
461            self.branch_node_tree_masks.insert(path, tree_mask);
462        }
463        if let Some(hash_mask) = masks.hash_mask {
464            self.branch_node_hash_masks.insert(path, hash_mask);
465        }
466
467        match node {
468            TrieNode::EmptyRoot => {
469                // For an empty root, ensure that we are at the root path.
470                debug_assert!(path.is_empty());
471                self.nodes.insert(path, SparseNode::Empty);
472            }
473            TrieNode::Branch(branch) => {
474                // For a branch node, iterate over all potential children
475                let mut stack_ptr = branch.as_ref().first_child_index();
476                for idx in CHILD_INDEX_RANGE {
477                    if branch.state_mask.is_bit_set(idx) {
478                        let mut child_path = path;
479                        child_path.push_unchecked(idx);
480                        // Reveal each child node or hash it has
481                        self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
482                        stack_ptr += 1;
483                    }
484                }
485                // Update the branch node entry in the nodes map, handling cases where a blinded
486                // node is now replaced with a revealed node.
487                match self.nodes.entry(path) {
488                    Entry::Occupied(mut entry) => match entry.get() {
489                        // Replace a hash node with a fully revealed branch node.
490                        SparseNode::Hash(hash) => {
491                            entry.insert(SparseNode::Branch {
492                                state_mask: branch.state_mask,
493                                // Memoize the hash of a previously blinded node in a new branch
494                                // node.
495                                hash: Some(*hash),
496                                store_in_db_trie: Some(
497                                    masks.hash_mask.is_some_and(|mask| !mask.is_empty()) ||
498                                        masks.tree_mask.is_some_and(|mask| !mask.is_empty()),
499                                ),
500                            });
501                        }
502                        // Branch node already exists, or an extension node was placed where a
503                        // branch node was before.
504                        SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
505                        // All other node types can't be handled.
506                        node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
507                            return Err(SparseTrieErrorKind::Reveal {
508                                path: *entry.key(),
509                                node: Box::new(node.clone()),
510                            }
511                            .into())
512                        }
513                    },
514                    Entry::Vacant(entry) => {
515                        entry.insert(SparseNode::new_branch(branch.state_mask));
516                    }
517                }
518            }
519            TrieNode::Extension(ext) => match self.nodes.entry(path) {
520                Entry::Occupied(mut entry) => match entry.get() {
521                    // Replace a hash node with a revealed extension node.
522                    SparseNode::Hash(hash) => {
523                        let mut child_path = *entry.key();
524                        child_path.extend(&ext.key);
525                        entry.insert(SparseNode::Extension {
526                            key: ext.key,
527                            // Memoize the hash of a previously blinded node in a new extension
528                            // node.
529                            hash: Some(*hash),
530                            store_in_db_trie: None,
531                        });
532                        self.reveal_node_or_hash(child_path, &ext.child)?;
533                    }
534                    // Extension node already exists, or an extension node was placed where a branch
535                    // node was before.
536                    SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
537                    // All other node types can't be handled.
538                    node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
539                        return Err(SparseTrieErrorKind::Reveal {
540                            path: *entry.key(),
541                            node: Box::new(node.clone()),
542                        }
543                        .into())
544                    }
545                },
546                Entry::Vacant(entry) => {
547                    let mut child_path = *entry.key();
548                    child_path.extend(&ext.key);
549                    entry.insert(SparseNode::new_ext(ext.key));
550                    self.reveal_node_or_hash(child_path, &ext.child)?;
551                }
552            },
553            TrieNode::Leaf(leaf) => match self.nodes.entry(path) {
554                Entry::Occupied(mut entry) => match entry.get() {
555                    // Replace a hash node with a revealed leaf node and store leaf node value.
556                    SparseNode::Hash(hash) => {
557                        let mut full = *entry.key();
558                        full.extend(&leaf.key);
559                        self.values.insert(full, leaf.value.clone());
560                        entry.insert(SparseNode::Leaf {
561                            key: leaf.key,
562                            // Memoize the hash of a previously blinded node in a new leaf
563                            // node.
564                            hash: Some(*hash),
565                        });
566                    }
567                    // Left node already exists.
568                    SparseNode::Leaf { .. } => {}
569                    // All other node types can't be handled.
570                    node @ (SparseNode::Empty |
571                    SparseNode::Extension { .. } |
572                    SparseNode::Branch { .. }) => {
573                        return Err(SparseTrieErrorKind::Reveal {
574                            path: *entry.key(),
575                            node: Box::new(node.clone()),
576                        }
577                        .into())
578                    }
579                },
580                Entry::Vacant(entry) => {
581                    let mut full = *entry.key();
582                    full.extend(&leaf.key);
583                    entry.insert(SparseNode::new_leaf(leaf.key));
584                    self.values.insert(full, leaf.value.clone());
585                }
586            },
587        }
588
589        Ok(())
590    }
591
592    fn reveal_nodes(&mut self, mut nodes: Vec<RevealedSparseNode>) -> SparseTrieResult<()> {
593        nodes.sort_unstable_by_key(|node| node.path);
594        for node in nodes {
595            self.reveal_node(node.path, node.node, node.masks)?;
596        }
597        Ok(())
598    }
599
600    #[instrument(level = "trace", target = "trie::sparse::serial", skip(self, provider))]
601    fn update_leaf<P: TrieNodeProvider>(
602        &mut self,
603        full_path: Nibbles,
604        value: Vec<u8>,
605        provider: P,
606    ) -> SparseTrieResult<()> {
607        self.prefix_set.insert(full_path);
608        let existing = self.values.insert(full_path, value);
609        if existing.is_some() {
610            // trie structure unchanged, return immediately
611            return Ok(())
612        }
613
614        let mut current = Nibbles::default();
615        while let Some(node) = self.nodes.get_mut(&current) {
616            match node {
617                SparseNode::Empty => {
618                    *node = SparseNode::new_leaf(full_path);
619                    break
620                }
621                &mut SparseNode::Hash(hash) => {
622                    return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
623                }
624                SparseNode::Leaf { key: current_key, .. } => {
625                    current.extend(current_key);
626
627                    // this leaf is being updated
628                    if current == full_path {
629                        unreachable!("we already checked leaf presence in the beginning");
630                    }
631
632                    // find the common prefix
633                    let common = current.common_prefix_length(&full_path);
634
635                    // update existing node
636                    let new_ext_key = current.slice(current.len() - current_key.len()..common);
637                    *node = SparseNode::new_ext(new_ext_key);
638
639                    // create a branch node and corresponding leaves
640                    self.nodes.reserve(3);
641                    self.nodes.insert(
642                        current.slice(..common),
643                        SparseNode::new_split_branch(
644                            current.get_unchecked(common),
645                            full_path.get_unchecked(common),
646                        ),
647                    );
648                    self.nodes.insert(
649                        full_path.slice(..=common),
650                        SparseNode::new_leaf(full_path.slice(common + 1..)),
651                    );
652                    self.nodes.insert(
653                        current.slice(..=common),
654                        SparseNode::new_leaf(current.slice(common + 1..)),
655                    );
656
657                    break;
658                }
659                SparseNode::Extension { key, .. } => {
660                    current.extend(key);
661
662                    if !full_path.starts_with(&current) {
663                        // find the common prefix
664                        let common = current.common_prefix_length(&full_path);
665                        *key = current.slice(current.len() - key.len()..common);
666
667                        // If branch node updates retention is enabled, we need to query the
668                        // extension node child to later set the hash mask for a parent branch node
669                        // correctly.
670                        if self.updates.is_some() {
671                            // Check if the extension node child is a hash that needs to be revealed
672                            if self.nodes.get(&current).unwrap().is_hash() {
673                                debug!(
674                                    target: "trie::sparse",
675                                    leaf_full_path = ?full_path,
676                                    child_path = ?current,
677                                    "Extension node child not revealed in update_leaf, falling back to db",
678                                );
679                                if let Some(RevealedNode { node, tree_mask, hash_mask }) =
680                                    provider.trie_node(&current)?
681                                {
682                                    let decoded = TrieNode::decode(&mut &node[..])?;
683                                    trace!(
684                                        target: "trie::sparse",
685                                        ?current,
686                                        ?decoded,
687                                        ?tree_mask,
688                                        ?hash_mask,
689                                        "Revealing extension node child",
690                                    );
691                                    self.reveal_node(
692                                        current,
693                                        decoded,
694                                        TrieMasks { hash_mask, tree_mask },
695                                    )?;
696                                }
697                            }
698                        }
699
700                        // create state mask for new branch node
701                        // NOTE: this might overwrite the current extension node
702                        self.nodes.reserve(3);
703                        let branch = SparseNode::new_split_branch(
704                            current.get_unchecked(common),
705                            full_path.get_unchecked(common),
706                        );
707                        self.nodes.insert(current.slice(..common), branch);
708
709                        // create new leaf
710                        let new_leaf = SparseNode::new_leaf(full_path.slice(common + 1..));
711                        self.nodes.insert(full_path.slice(..=common), new_leaf);
712
713                        // recreate extension to previous child if needed
714                        let key = current.slice(common + 1..);
715                        if !key.is_empty() {
716                            self.nodes.insert(current.slice(..=common), SparseNode::new_ext(key));
717                        }
718
719                        break;
720                    }
721                }
722                SparseNode::Branch { state_mask, .. } => {
723                    let nibble = full_path.get_unchecked(current.len());
724                    current.push_unchecked(nibble);
725                    if !state_mask.is_bit_set(nibble) {
726                        state_mask.set_bit(nibble);
727                        let new_leaf = SparseNode::new_leaf(full_path.slice(current.len()..));
728                        self.nodes.insert(current, new_leaf);
729                        break;
730                    }
731                }
732            };
733        }
734
735        Ok(())
736    }
737
738    #[instrument(level = "trace", target = "trie::sparse::serial", skip(self, provider))]
739    fn remove_leaf<P: TrieNodeProvider>(
740        &mut self,
741        full_path: &Nibbles,
742        provider: P,
743    ) -> SparseTrieResult<()> {
744        trace!(target: "trie::sparse", ?full_path, "remove_leaf called");
745
746        if self.values.remove(full_path).is_none() {
747            if let Some(&SparseNode::Hash(hash)) = self.nodes.get(full_path) {
748                // Leaf is present in the trie, but it's blinded.
749                return Err(SparseTrieErrorKind::BlindedNode { path: *full_path, hash }.into())
750            }
751
752            trace!(target: "trie::sparse", ?full_path, "Leaf node is not present in the trie");
753            // Leaf is not present in the trie.
754            return Ok(())
755        }
756        self.prefix_set.insert(*full_path);
757
758        // If the path wasn't present in `values`, we still need to walk the trie and ensure that
759        // there is no node at the path. When a leaf node is a blinded `Hash`, it will have an entry
760        // in `nodes`, but not in the `values`.
761
762        let mut removed_nodes = self.take_nodes_for_path(full_path)?;
763        // Pop the first node from the stack which is the leaf node we want to remove.
764        let mut child = removed_nodes.pop().expect("leaf exists");
765        #[cfg(debug_assertions)]
766        {
767            let mut child_path = child.path;
768            let SparseNode::Leaf { key, .. } = &child.node else { panic!("expected leaf node") };
769            child_path.extend(key);
770            assert_eq!(&child_path, full_path);
771        }
772
773        // If we don't have any other removed nodes, insert an empty node at the root.
774        if removed_nodes.is_empty() {
775            debug_assert!(self.nodes.is_empty());
776            self.nodes.insert(Nibbles::default(), SparseNode::Empty);
777
778            return Ok(())
779        }
780
781        // Walk the stack of removed nodes from the back and re-insert them back into the trie,
782        // adjusting the node type as needed.
783        while let Some(removed_node) = removed_nodes.pop() {
784            let removed_path = removed_node.path;
785
786            let new_node = match &removed_node.node {
787                SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
788                &SparseNode::Hash(hash) => {
789                    return Err(SparseTrieErrorKind::BlindedNode { path: removed_path, hash }.into())
790                }
791                SparseNode::Leaf { .. } => {
792                    unreachable!("we already popped the leaf node")
793                }
794                SparseNode::Extension { key, .. } => {
795                    // If the node is an extension node, we need to look at its child to see if we
796                    // need to merge them.
797                    match &child.node {
798                        SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
799                        &SparseNode::Hash(hash) => {
800                            return Err(
801                                SparseTrieErrorKind::BlindedNode { path: child.path, hash }.into()
802                            )
803                        }
804                        // For a leaf node, we collapse the extension node into a leaf node,
805                        // extending the key. While it's impossible to encounter an extension node
806                        // followed by a leaf node in a complete trie, it's possible here because we
807                        // could have downgraded the extension node's child into a leaf node from
808                        // another node type.
809                        SparseNode::Leaf { key: leaf_key, .. } => {
810                            self.nodes.remove(&child.path);
811
812                            let mut new_key = *key;
813                            new_key.extend(leaf_key);
814                            SparseNode::new_leaf(new_key)
815                        }
816                        // For an extension node, we collapse them into one extension node,
817                        // extending the key
818                        SparseNode::Extension { key: extension_key, .. } => {
819                            self.nodes.remove(&child.path);
820
821                            let mut new_key = *key;
822                            new_key.extend(extension_key);
823                            SparseNode::new_ext(new_key)
824                        }
825                        // For a branch node, we just leave the extension node as-is.
826                        SparseNode::Branch { .. } => removed_node.node,
827                    }
828                }
829                &SparseNode::Branch { mut state_mask, hash: _, store_in_db_trie: _ } => {
830                    // If the node is a branch node, we need to check the number of children left
831                    // after deleting the child at the given nibble.
832
833                    if let Some(removed_nibble) = removed_node.unset_branch_nibble {
834                        state_mask.unset_bit(removed_nibble);
835                    }
836
837                    // If only one child is left set in the branch node, we need to collapse it.
838                    if state_mask.count_bits() == 1 {
839                        let child_nibble =
840                            state_mask.first_set_bit_index().expect("state mask is not empty");
841
842                        // Get full path of the only child node left.
843                        let mut child_path = removed_path;
844                        child_path.push_unchecked(child_nibble);
845
846                        trace!(target: "trie::sparse", ?removed_path, ?child_path, "Branch node has only one child");
847
848                        // If the remaining child node is not yet revealed then we have to reveal
849                        // it here, otherwise it's not possible to know how to collapse the branch.
850                        let child = self.reveal_remaining_child_on_leaf_removal(
851                            &provider,
852                            full_path,
853                            &child_path,
854                            true, // recurse_into_extension
855                        )?;
856
857                        let mut delete_child = false;
858                        let new_node = match &child {
859                            SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
860                            &SparseNode::Hash(hash) => {
861                                return Err(SparseTrieErrorKind::BlindedNode {
862                                    path: child_path,
863                                    hash,
864                                }
865                                .into())
866                            }
867                            // If the only child is a leaf node, we downgrade the branch node into a
868                            // leaf node, prepending the nibble to the key, and delete the old
869                            // child.
870                            SparseNode::Leaf { key, .. } => {
871                                delete_child = true;
872
873                                let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
874                                new_key.extend(key);
875                                SparseNode::new_leaf(new_key)
876                            }
877                            // If the only child node is an extension node, we downgrade the branch
878                            // node into an even longer extension node, prepending the nibble to the
879                            // key, and delete the old child.
880                            SparseNode::Extension { key, .. } => {
881                                delete_child = true;
882
883                                let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
884                                new_key.extend(key);
885                                SparseNode::new_ext(new_key)
886                            }
887                            // If the only child is a branch node, we downgrade the current branch
888                            // node into a one-nibble extension node.
889                            SparseNode::Branch { .. } => {
890                                SparseNode::new_ext(Nibbles::from_nibbles_unchecked([child_nibble]))
891                            }
892                        };
893
894                        if delete_child {
895                            self.nodes.remove(&child_path);
896                        }
897
898                        if let Some(updates) = self.updates.as_mut() {
899                            updates.updated_nodes.remove(&removed_path);
900                            updates.removed_nodes.insert(removed_path);
901                        }
902
903                        new_node
904                    }
905                    // If more than one child is left set in the branch, we just re-insert it as-is.
906                    else {
907                        SparseNode::new_branch(state_mask)
908                    }
909                }
910            };
911
912            child = RemovedSparseNode {
913                path: removed_path,
914                node: new_node.clone(),
915                unset_branch_nibble: None,
916            };
917            trace!(target: "trie::sparse", ?removed_path, ?new_node, "Re-inserting the node");
918            self.nodes.insert(removed_path, new_node);
919        }
920
921        Ok(())
922    }
923
924    #[instrument(target = "trie::sparse::serial", skip(self))]
925    fn root(&mut self) -> B256 {
926        // Take the current prefix set
927        let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
928        let rlp_node = self.rlp_node_allocate(&mut prefix_set);
929        if let Some(root_hash) = rlp_node.as_hash() {
930            root_hash
931        } else {
932            keccak256(rlp_node)
933        }
934    }
935
936    fn update_subtrie_hashes(&mut self) {
937        self.update_rlp_node_level(SPARSE_TRIE_SUBTRIE_HASHES_LEVEL);
938    }
939
940    fn get_leaf_value(&self, full_path: &Nibbles) -> Option<&Vec<u8>> {
941        self.values.get(full_path)
942    }
943
944    fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
945        self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
946    }
947
948    fn take_updates(&mut self) -> SparseTrieUpdates {
949        self.updates.take().unwrap_or_default()
950    }
951
952    fn wipe(&mut self) {
953        self.nodes = HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]);
954        self.values = HashMap::default();
955        self.prefix_set = PrefixSetMut::all();
956        self.updates = self.updates.is_some().then(SparseTrieUpdates::wiped);
957    }
958
959    fn clear(&mut self) {
960        self.nodes.clear();
961        self.nodes.insert(Nibbles::default(), SparseNode::Empty);
962
963        self.branch_node_tree_masks.clear();
964        self.branch_node_hash_masks.clear();
965        self.values.clear();
966        self.prefix_set.clear();
967        self.updates = None;
968        self.rlp_buf.clear();
969    }
970
971    fn find_leaf(
972        &self,
973        full_path: &Nibbles,
974        expected_value: Option<&Vec<u8>>,
975    ) -> Result<LeafLookup, LeafLookupError> {
976        // Helper function to check if a value matches the expected value
977        #[inline]
978        fn check_value_match(
979            actual_value: &Vec<u8>,
980            expected_value: Option<&Vec<u8>>,
981            path: &Nibbles,
982        ) -> Result<(), LeafLookupError> {
983            if let Some(expected) = expected_value &&
984                actual_value != expected
985            {
986                return Err(LeafLookupError::ValueMismatch {
987                    path: *path,
988                    expected: Some(expected.clone()),
989                    actual: actual_value.clone(),
990                });
991            }
992            Ok(())
993        }
994
995        let mut current = Nibbles::default(); // Start at the root
996
997        // Inclusion proof
998        //
999        // First, do a quick check if the value exists in our values map.
1000        // We assume that if there exists a leaf node, then its value will
1001        // be in the `values` map.
1002        if let Some(actual_value) = self.values.get(full_path) {
1003            // We found the leaf, check if the value matches (if expected value was provided)
1004            check_value_match(actual_value, expected_value, full_path)?;
1005            return Ok(LeafLookup::Exists);
1006        }
1007
1008        // If the value does not exist in the `values` map, then this means that the leaf either:
1009        // - Does not exist in the trie
1010        // - Is missing from the witness
1011        // We traverse the trie to find the location where this leaf would have been, showing
1012        // that it is not in the trie. Or we find a blinded node, showing that the witness is
1013        // not complete.
1014        while current.len() < full_path.len() {
1015            match self.nodes.get(&current) {
1016                Some(SparseNode::Empty) | None => {
1017                    // None implies no node is at the current path (even in the full trie)
1018                    // Empty node means there is a node at this path and it is "Empty"
1019                    return Ok(LeafLookup::NonExistent);
1020                }
1021                Some(&SparseNode::Hash(hash)) => {
1022                    // We hit a blinded node - cannot determine if leaf exists
1023                    return Err(LeafLookupError::BlindedNode { path: current, hash });
1024                }
1025                Some(SparseNode::Leaf { key, .. }) => {
1026                    // We found a leaf node before reaching our target depth
1027                    current.extend(key);
1028                    if &current == full_path {
1029                        // This should have been handled by our initial values map check
1030                        if let Some(value) = self.values.get(full_path) {
1031                            check_value_match(value, expected_value, full_path)?;
1032                            return Ok(LeafLookup::Exists);
1033                        }
1034                    }
1035
1036                    // The leaf node's path doesn't match our target path,
1037                    // providing an exclusion proof
1038                    return Ok(LeafLookup::NonExistent);
1039                }
1040                Some(SparseNode::Extension { key, .. }) => {
1041                    // Temporarily append the extension key to `current`
1042                    let saved_len = current.len();
1043                    current.extend(key);
1044
1045                    if full_path.len() < current.len() || !full_path.starts_with(&current) {
1046                        current.truncate(saved_len); // restore
1047                        return Ok(LeafLookup::NonExistent);
1048                    }
1049                    // Prefix matched, so we keep walking with the longer `current`.
1050                }
1051                Some(SparseNode::Branch { state_mask, .. }) => {
1052                    // Check if branch has a child at the next nibble in our path
1053                    let nibble = full_path.get_unchecked(current.len());
1054                    if !state_mask.is_bit_set(nibble) {
1055                        // No child at this nibble - exclusion proof
1056                        return Ok(LeafLookup::NonExistent);
1057                    }
1058
1059                    // Continue down the branch
1060                    current.push_unchecked(nibble);
1061                }
1062            }
1063        }
1064
1065        // We've traversed to the end of the path and didn't find a leaf
1066        // Check if there's a node exactly at our target path
1067        match self.nodes.get(full_path) {
1068            Some(SparseNode::Leaf { key, .. }) if key.is_empty() => {
1069                // We found a leaf with an empty key (exact match)
1070                // This should be handled by the values map check above
1071                if let Some(value) = self.values.get(full_path) {
1072                    check_value_match(value, expected_value, full_path)?;
1073                    return Ok(LeafLookup::Exists);
1074                }
1075            }
1076            Some(&SparseNode::Hash(hash)) => {
1077                return Err(LeafLookupError::BlindedNode { path: *full_path, hash });
1078            }
1079            _ => {
1080                // No leaf at exactly the target path
1081                return Ok(LeafLookup::NonExistent);
1082            }
1083        }
1084
1085        // If we get here, there's no leaf at the target path
1086        Ok(LeafLookup::NonExistent)
1087    }
1088
1089    fn shrink_nodes_to(&mut self, size: usize) {
1090        self.nodes.shrink_to(size);
1091        self.branch_node_tree_masks.shrink_to(size);
1092        self.branch_node_hash_masks.shrink_to(size);
1093    }
1094
1095    fn shrink_values_to(&mut self, size: usize) {
1096        self.values.shrink_to(size);
1097    }
1098}
1099
1100impl SerialSparseTrie {
1101    /// Creates a new revealed sparse trie from the given root node.
1102    ///
1103    /// This function initializes the internal structures and then reveals the root.
1104    /// It is a convenient method to create a trie when you already have the root node available.
1105    ///
1106    /// # Arguments
1107    ///
1108    /// * `root` - The root node of the trie
1109    /// * `masks` - Trie masks for root branch node
1110    /// * `retain_updates` - Whether to track updates
1111    ///
1112    /// # Returns
1113    ///
1114    /// Self if successful, or an error if revealing fails.
1115    pub fn from_root(
1116        root: TrieNode,
1117        masks: TrieMasks,
1118        retain_updates: bool,
1119    ) -> SparseTrieResult<Self> {
1120        Self::default().with_root(root, masks, retain_updates)
1121    }
1122
1123    /// Returns a reference to the current sparse trie updates.
1124    ///
1125    /// If no updates have been made/recorded, returns an empty update set.
1126    pub fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
1127        self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
1128    }
1129
1130    /// Returns an immutable reference to all nodes in the sparse trie.
1131    pub const fn nodes_ref(&self) -> &HashMap<Nibbles, SparseNode> {
1132        &self.nodes
1133    }
1134
1135    /// Reveals either a node or its hash placeholder based on the provided child data.
1136    ///
1137    /// When traversing the trie, we often encounter references to child nodes that
1138    /// are either directly embedded or represented by their hash. This method
1139    /// handles both cases:
1140    ///
1141    /// 1. If the child data represents a hash (32+1=33 bytes), store it as a hash node
1142    /// 2. Otherwise, decode the data as a [`TrieNode`] and recursively reveal it using
1143    ///    `reveal_node`
1144    ///
1145    /// # Returns
1146    ///
1147    /// Returns `Ok(())` if successful, or an error if the node cannot be revealed.
1148    ///
1149    /// # Error Handling
1150    ///
1151    /// Will error if there's a conflict between a new hash node and an existing one
1152    /// at the same path
1153    fn reveal_node_or_hash(&mut self, path: Nibbles, child: &[u8]) -> SparseTrieResult<()> {
1154        if child.len() == B256::len_bytes() + 1 {
1155            let hash = B256::from_slice(&child[1..]);
1156            match self.nodes.entry(path) {
1157                Entry::Occupied(entry) => match entry.get() {
1158                    // Hash node with a different hash can't be handled.
1159                    SparseNode::Hash(previous_hash) if previous_hash != &hash => {
1160                        return Err(SparseTrieErrorKind::Reveal {
1161                            path: *entry.key(),
1162                            node: Box::new(SparseNode::Hash(hash)),
1163                        }
1164                        .into())
1165                    }
1166                    _ => {}
1167                },
1168                Entry::Vacant(entry) => {
1169                    entry.insert(SparseNode::Hash(hash));
1170                }
1171            }
1172            return Ok(())
1173        }
1174
1175        self.reveal_node(path, TrieNode::decode(&mut &child[..])?, TrieMasks::none())
1176    }
1177
1178    /// Traverse the trie from the root down to the leaf at the given path,
1179    /// removing and collecting all nodes along that path.
1180    ///
1181    /// This helper function is used during leaf removal to extract the nodes of the trie
1182    /// that will be affected by the deletion. These nodes are then re-inserted and modified
1183    /// as needed (collapsing extension nodes etc) given that the leaf has now been removed.
1184    ///
1185    /// # Returns
1186    ///
1187    /// Returns a vector of [`RemovedSparseNode`] representing the nodes removed during the
1188    /// traversal.
1189    ///
1190    /// # Errors
1191    ///
1192    /// Returns an error if a blinded node or an empty node is encountered unexpectedly,
1193    /// as these prevent proper removal of the leaf.
1194    fn take_nodes_for_path(&mut self, path: &Nibbles) -> SparseTrieResult<Vec<RemovedSparseNode>> {
1195        let mut current = Nibbles::default(); // Start traversal from the root
1196        let mut nodes = Vec::new(); // Collect traversed nodes
1197
1198        while let Some(node) = self.nodes.remove(&current) {
1199            match &node {
1200                SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
1201                &SparseNode::Hash(hash) => {
1202                    return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
1203                }
1204                SparseNode::Leaf { key: _key, .. } => {
1205                    // Leaf node is always the one that we're deleting, and no other leaf nodes can
1206                    // be found during traversal.
1207
1208                    #[cfg(debug_assertions)]
1209                    {
1210                        let mut current = current;
1211                        current.extend(_key);
1212                        assert_eq!(&current, path);
1213                    }
1214
1215                    nodes.push(RemovedSparseNode {
1216                        path: current,
1217                        node,
1218                        unset_branch_nibble: None,
1219                    });
1220                    break
1221                }
1222                SparseNode::Extension { key, .. } => {
1223                    #[cfg(debug_assertions)]
1224                    {
1225                        let mut current = current;
1226                        current.extend(key);
1227                        assert!(
1228                            path.starts_with(&current),
1229                            "path: {path:?}, current: {current:?}, key: {key:?}",
1230                        );
1231                    }
1232
1233                    let path = current;
1234                    current.extend(key);
1235                    nodes.push(RemovedSparseNode { path, node, unset_branch_nibble: None });
1236                }
1237                SparseNode::Branch { state_mask, .. } => {
1238                    let nibble = path.get_unchecked(current.len());
1239                    debug_assert!(
1240                        state_mask.is_bit_set(nibble),
1241                        "current: {current:?}, path: {path:?}, nibble: {nibble:?}, state_mask: {state_mask:?}",
1242                    );
1243
1244                    // If the branch node has a child that is a leaf node that we're removing,
1245                    // we need to unset this nibble.
1246                    // Any other branch nodes will not require unsetting the nibble, because
1247                    // deleting one leaf node can not remove the whole path
1248                    // where the branch node is located.
1249                    let mut child_path = current;
1250                    child_path.push_unchecked(nibble);
1251                    let unset_branch_nibble = self
1252                        .nodes
1253                        .get(&child_path)
1254                        .is_some_and(move |node| match node {
1255                            SparseNode::Leaf { key, .. } => {
1256                                // Get full path of the leaf node
1257                                child_path.extend(key);
1258                                &child_path == path
1259                            }
1260                            _ => false,
1261                        })
1262                        .then_some(nibble);
1263
1264                    nodes.push(RemovedSparseNode { path: current, node, unset_branch_nibble });
1265
1266                    current.push_unchecked(nibble);
1267                }
1268            }
1269        }
1270
1271        Ok(nodes)
1272    }
1273
1274    /// Called when a leaf is removed on a branch which has only one other remaining child. That
1275    /// child must be revealed in order to properly collapse the branch.
1276    ///
1277    /// If `recurse_into_extension` is true, and the remaining child is an extension node, then its
1278    /// child will be ensured to be revealed as well.
1279    ///
1280    /// ## Returns
1281    ///
1282    /// The node of the remaining child, whether it was already revealed or not.
1283    fn reveal_remaining_child_on_leaf_removal<P: TrieNodeProvider>(
1284        &mut self,
1285        provider: P,
1286        full_path: &Nibbles, // only needed for logs
1287        remaining_child_path: &Nibbles,
1288        recurse_into_extension: bool,
1289    ) -> SparseTrieResult<SparseNode> {
1290        let remaining_child_node = match self.nodes.get(remaining_child_path).unwrap() {
1291            SparseNode::Hash(_) => {
1292                debug!(
1293                    target: "trie::parallel_sparse",
1294                    child_path = ?remaining_child_path,
1295                    leaf_full_path = ?full_path,
1296                    "Node child not revealed in remove_leaf, falling back to db",
1297                );
1298                if let Some(RevealedNode { node, tree_mask, hash_mask }) =
1299                    provider.trie_node(remaining_child_path)?
1300                {
1301                    let decoded = TrieNode::decode(&mut &node[..])?;
1302                    trace!(
1303                        target: "trie::parallel_sparse",
1304                        ?remaining_child_path,
1305                        ?decoded,
1306                        ?tree_mask,
1307                        ?hash_mask,
1308                        "Revealing remaining blinded branch child"
1309                    );
1310                    self.reveal_node(
1311                        *remaining_child_path,
1312                        decoded,
1313                        TrieMasks { hash_mask, tree_mask },
1314                    )?;
1315                    self.nodes.get(remaining_child_path).unwrap().clone()
1316                } else {
1317                    return Err(SparseTrieErrorKind::NodeNotFoundInProvider {
1318                        path: *remaining_child_path,
1319                    }
1320                    .into())
1321                }
1322            }
1323            node => node.clone(),
1324        };
1325
1326        // If `recurse_into_extension` is true, and the remaining child is an extension node, then
1327        // its child will be ensured to be revealed as well. This is required for generation of
1328        // trie updates; without revealing the grandchild branch it's not always possible to know
1329        // if the tree mask bit should be set for the child extension on its parent branch.
1330        if let SparseNode::Extension { key, .. } = &remaining_child_node &&
1331            recurse_into_extension
1332        {
1333            let mut remaining_grandchild_path = *remaining_child_path;
1334            remaining_grandchild_path.extend(key);
1335
1336            trace!(
1337                target: "trie::parallel_sparse",
1338                remaining_grandchild_path = ?remaining_grandchild_path,
1339                child_path = ?remaining_child_path,
1340                leaf_full_path = ?full_path,
1341                "Revealing child of extension node, which is the last remaining child of the branch"
1342            );
1343
1344            self.reveal_remaining_child_on_leaf_removal(
1345                provider,
1346                full_path,
1347                &remaining_grandchild_path,
1348                false, // recurse_into_extension
1349            )?;
1350        }
1351
1352        Ok(remaining_child_node)
1353    }
1354
1355    /// Recalculates and updates the RLP hashes of nodes deeper than or equal to the specified
1356    /// `depth`.
1357    ///
1358    /// The root node is considered to be at level 0. This method is useful for optimizing
1359    /// hash recalculations after localized changes to the trie structure:
1360    ///
1361    /// This function identifies all nodes that have changed (based on the prefix set) at the given
1362    /// depth and recalculates their RLP representation.
1363    #[instrument(level = "trace", target = "trie::sparse::serial", skip(self))]
1364    pub fn update_rlp_node_level(&mut self, depth: usize) {
1365        // Take the current prefix set
1366        let mut prefix_set = core::mem::take(&mut self.prefix_set).freeze();
1367        let mut buffers = RlpNodeBuffers::default();
1368
1369        // Get the nodes that have changed at the given depth.
1370        let (targets, new_prefix_set) = self.get_changed_nodes_at_depth(&mut prefix_set, depth);
1371        // Update the prefix set to the prefix set of the nodes that still need to be updated.
1372        self.prefix_set = new_prefix_set;
1373
1374        trace!(target: "trie::sparse", ?depth, ?targets, "Updating nodes at depth");
1375
1376        let mut temp_rlp_buf = core::mem::take(&mut self.rlp_buf);
1377        for (level, path) in targets {
1378            buffers.path_stack.push(RlpNodePathStackItem {
1379                level,
1380                path,
1381                is_in_prefix_set: Some(true),
1382            });
1383            self.rlp_node(&mut prefix_set, &mut buffers, &mut temp_rlp_buf);
1384        }
1385        self.rlp_buf = temp_rlp_buf;
1386    }
1387
1388    /// Returns a list of (level, path) tuples identifying the nodes that have changed at the
1389    /// specified depth, along with a new prefix set for the paths above the provided depth that
1390    /// remain unchanged.
1391    ///
1392    /// Leaf nodes with a depth less than `depth` are returned too.
1393    ///
1394    /// This method helps optimize hash recalculations by identifying which specific
1395    /// nodes need to be updated at each level of the trie.
1396    ///
1397    /// # Parameters
1398    ///
1399    /// - `prefix_set`: The current prefix set tracking which paths need updates.
1400    /// - `depth`: The minimum depth (relative to the root) to include nodes in the targets.
1401    ///
1402    /// # Returns
1403    ///
1404    /// A tuple containing:
1405    /// - A vector of `(level, Nibbles)` pairs for nodes that require updates at or below the
1406    ///   specified depth.
1407    /// - A `PrefixSetMut` containing paths shallower than the specified depth that still need to be
1408    ///   tracked for future updates.
1409    #[instrument(level = "trace", target = "trie::sparse::serial", skip(self))]
1410    fn get_changed_nodes_at_depth(
1411        &self,
1412        prefix_set: &mut PrefixSet,
1413        depth: usize,
1414    ) -> (Vec<(usize, Nibbles)>, PrefixSetMut) {
1415        let mut unchanged_prefix_set = PrefixSetMut::default();
1416        let mut paths = Vec::from([(Nibbles::default(), 0)]);
1417        let mut targets = Vec::new();
1418
1419        while let Some((mut path, level)) = paths.pop() {
1420            match self.nodes.get(&path).unwrap() {
1421                SparseNode::Empty | SparseNode::Hash(_) => {}
1422                SparseNode::Leaf { key: _, hash } => {
1423                    if hash.is_some() && !prefix_set.contains(&path) {
1424                        continue
1425                    }
1426
1427                    targets.push((level, path));
1428                }
1429                SparseNode::Extension { key, hash, store_in_db_trie: _ } => {
1430                    if hash.is_some() && !prefix_set.contains(&path) {
1431                        continue
1432                    }
1433
1434                    if level >= depth {
1435                        targets.push((level, path));
1436                    } else {
1437                        unchanged_prefix_set.insert(path);
1438
1439                        path.extend(key);
1440                        paths.push((path, level + 1));
1441                    }
1442                }
1443                SparseNode::Branch { state_mask, hash, store_in_db_trie: _ } => {
1444                    if hash.is_some() && !prefix_set.contains(&path) {
1445                        continue
1446                    }
1447
1448                    if level >= depth {
1449                        targets.push((level, path));
1450                    } else {
1451                        unchanged_prefix_set.insert(path);
1452
1453                        for bit in CHILD_INDEX_RANGE.rev() {
1454                            if state_mask.is_bit_set(bit) {
1455                                let mut child_path = path;
1456                                child_path.push_unchecked(bit);
1457                                paths.push((child_path, level + 1));
1458                            }
1459                        }
1460                    }
1461                }
1462            }
1463        }
1464
1465        (targets, unchanged_prefix_set)
1466    }
1467
1468    /// Look up or calculate the RLP of the node at the root path.
1469    ///
1470    /// # Panics
1471    ///
1472    /// If the node at provided path does not exist.
1473    pub fn rlp_node_allocate(&mut self, prefix_set: &mut PrefixSet) -> RlpNode {
1474        let mut buffers = RlpNodeBuffers::new_with_root_path();
1475        let mut temp_rlp_buf = core::mem::take(&mut self.rlp_buf);
1476        let result = self.rlp_node(prefix_set, &mut buffers, &mut temp_rlp_buf);
1477        self.rlp_buf = temp_rlp_buf;
1478
1479        result
1480    }
1481
1482    /// Looks up or computes the RLP encoding of the node specified by the current
1483    /// path in the provided buffers.
1484    ///
1485    /// The function uses a stack (`RlpNodeBuffers::path_stack`) to track the traversal and
1486    /// accumulate RLP encodings.
1487    ///
1488    /// # Parameters
1489    ///
1490    /// - `prefix_set`: The set of trie paths that need their nodes updated.
1491    /// - `buffers`: The reusable buffers for stack management and temporary RLP values.
1492    ///
1493    /// # Panics
1494    ///
1495    /// If the node at provided path does not exist.
1496    #[instrument(level = "trace", target = "trie::sparse::serial", skip_all, ret(level = "trace"))]
1497    pub fn rlp_node(
1498        &mut self,
1499        prefix_set: &mut PrefixSet,
1500        buffers: &mut RlpNodeBuffers,
1501        rlp_buf: &mut Vec<u8>,
1502    ) -> RlpNode {
1503        let _starting_path = buffers.path_stack.last().map(|item| item.path);
1504
1505        'main: while let Some(RlpNodePathStackItem { level, path, mut is_in_prefix_set }) =
1506            buffers.path_stack.pop()
1507        {
1508            let node = self.nodes.get_mut(&path).unwrap();
1509            trace!(
1510                target: "trie::sparse",
1511                ?_starting_path,
1512                ?level,
1513                ?path,
1514                ?is_in_prefix_set,
1515                ?node,
1516                "Popped node from path stack"
1517            );
1518
1519            // Check if the path is in the prefix set.
1520            // First, check the cached value. If it's `None`, then check the prefix set, and update
1521            // the cached value.
1522            let mut prefix_set_contains =
1523                |path: &Nibbles| *is_in_prefix_set.get_or_insert_with(|| prefix_set.contains(path));
1524
1525            let (rlp_node, node_type) = match node {
1526                SparseNode::Empty => (RlpNode::word_rlp(&EMPTY_ROOT_HASH), SparseNodeType::Empty),
1527                SparseNode::Hash(hash) => (RlpNode::word_rlp(hash), SparseNodeType::Hash),
1528                SparseNode::Leaf { key, hash } => {
1529                    let mut path = path;
1530                    path.extend(key);
1531                    if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path)) {
1532                        (RlpNode::word_rlp(&hash), SparseNodeType::Leaf)
1533                    } else {
1534                        let value = self.values.get(&path).unwrap();
1535                        rlp_buf.clear();
1536                        let rlp_node = LeafNodeRef { key, value }.rlp(rlp_buf);
1537                        *hash = rlp_node.as_hash();
1538                        (rlp_node, SparseNodeType::Leaf)
1539                    }
1540                }
1541                SparseNode::Extension { key, hash, store_in_db_trie } => {
1542                    let mut child_path = path;
1543                    child_path.extend(key);
1544                    if let Some((hash, store_in_db_trie)) =
1545                        hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
1546                    {
1547                        (
1548                            RlpNode::word_rlp(&hash),
1549                            SparseNodeType::Extension { store_in_db_trie: Some(store_in_db_trie) },
1550                        )
1551                    } else if buffers.rlp_node_stack.last().is_some_and(|e| e.path == child_path) {
1552                        let RlpNodeStackItem {
1553                            path: _,
1554                            rlp_node: child,
1555                            node_type: child_node_type,
1556                        } = buffers.rlp_node_stack.pop().unwrap();
1557                        rlp_buf.clear();
1558                        let rlp_node = ExtensionNodeRef::new(key, &child).rlp(rlp_buf);
1559                        *hash = rlp_node.as_hash();
1560
1561                        let store_in_db_trie_value = child_node_type.store_in_db_trie();
1562
1563                        trace!(
1564                            target: "trie::sparse",
1565                            ?path,
1566                            ?child_path,
1567                            ?child_node_type,
1568                            "Extension node"
1569                        );
1570
1571                        *store_in_db_trie = store_in_db_trie_value;
1572
1573                        (
1574                            rlp_node,
1575                            SparseNodeType::Extension {
1576                                // Inherit the `store_in_db_trie` flag from the child node, which is
1577                                // always the branch node
1578                                store_in_db_trie: store_in_db_trie_value,
1579                            },
1580                        )
1581                    } else {
1582                        // need to get rlp node for child first
1583                        buffers.path_stack.extend([
1584                            RlpNodePathStackItem { level, path, is_in_prefix_set },
1585                            RlpNodePathStackItem {
1586                                level: level + 1,
1587                                path: child_path,
1588                                is_in_prefix_set: None,
1589                            },
1590                        ]);
1591                        continue
1592                    }
1593                }
1594                SparseNode::Branch { state_mask, hash, store_in_db_trie } => {
1595                    if let Some((hash, store_in_db_trie)) =
1596                        hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
1597                    {
1598                        buffers.rlp_node_stack.push(RlpNodeStackItem {
1599                            path,
1600                            rlp_node: RlpNode::word_rlp(&hash),
1601                            node_type: SparseNodeType::Branch {
1602                                store_in_db_trie: Some(store_in_db_trie),
1603                            },
1604                        });
1605                        continue
1606                    }
1607                    let retain_updates = self.updates.is_some() && prefix_set_contains(&path);
1608
1609                    buffers.branch_child_buf.clear();
1610                    // Walk children in a reverse order from `f` to `0`, so we pop the `0` first
1611                    // from the stack and keep walking in the sorted order.
1612                    for bit in CHILD_INDEX_RANGE.rev() {
1613                        if state_mask.is_bit_set(bit) {
1614                            let mut child = path;
1615                            child.push_unchecked(bit);
1616                            buffers.branch_child_buf.push(child);
1617                        }
1618                    }
1619
1620                    buffers
1621                        .branch_value_stack_buf
1622                        .resize(buffers.branch_child_buf.len(), Default::default());
1623                    let mut added_children = false;
1624
1625                    let mut tree_mask = TrieMask::default();
1626                    let mut hash_mask = TrieMask::default();
1627                    let mut hashes = Vec::new();
1628                    for (i, child_path) in buffers.branch_child_buf.iter().enumerate() {
1629                        if buffers.rlp_node_stack.last().is_some_and(|e| &e.path == child_path) {
1630                            let RlpNodeStackItem {
1631                                path: _,
1632                                rlp_node: child,
1633                                node_type: child_node_type,
1634                            } = buffers.rlp_node_stack.pop().unwrap();
1635
1636                            // Update the masks only if we need to retain trie updates
1637                            if retain_updates {
1638                                // SAFETY: it's a child, so it's never empty
1639                                let last_child_nibble = child_path.last().unwrap();
1640
1641                                // Determine whether we need to set trie mask bit.
1642                                let should_set_tree_mask_bit = if let Some(store_in_db_trie) =
1643                                    child_node_type.store_in_db_trie()
1644                                {
1645                                    // A branch or an extension node explicitly set the
1646                                    // `store_in_db_trie` flag
1647                                    store_in_db_trie
1648                                } else {
1649                                    // A blinded node has the tree mask bit set
1650                                    child_node_type.is_hash() &&
1651                                        self.branch_node_tree_masks.get(&path).is_some_and(
1652                                            |mask| mask.is_bit_set(last_child_nibble),
1653                                        )
1654                                };
1655                                if should_set_tree_mask_bit {
1656                                    tree_mask.set_bit(last_child_nibble);
1657                                }
1658
1659                                // Set the hash mask. If a child node is a revealed branch node OR
1660                                // is a blinded node that has its hash mask bit set according to the
1661                                // database, set the hash mask bit and save the hash.
1662                                let hash = child.as_hash().filter(|_| {
1663                                    child_node_type.is_branch() ||
1664                                        (child_node_type.is_hash() &&
1665                                            self.branch_node_hash_masks
1666                                                .get(&path)
1667                                                .is_some_and(|mask| {
1668                                                    mask.is_bit_set(last_child_nibble)
1669                                                }))
1670                                });
1671                                if let Some(hash) = hash {
1672                                    hash_mask.set_bit(last_child_nibble);
1673                                    hashes.push(hash);
1674                                }
1675                            }
1676
1677                            // Insert children in the resulting buffer in a normal order,
1678                            // because initially we iterated in reverse.
1679                            // SAFETY: i < len and len is never 0
1680                            let original_idx = buffers.branch_child_buf.len() - i - 1;
1681                            buffers.branch_value_stack_buf[original_idx] = child;
1682                            added_children = true;
1683                        } else {
1684                            debug_assert!(!added_children);
1685                            buffers.path_stack.push(RlpNodePathStackItem {
1686                                level,
1687                                path,
1688                                is_in_prefix_set,
1689                            });
1690                            buffers.path_stack.extend(buffers.branch_child_buf.drain(..).map(
1691                                |path| RlpNodePathStackItem {
1692                                    level: level + 1,
1693                                    path,
1694                                    is_in_prefix_set: None,
1695                                },
1696                            ));
1697                            continue 'main
1698                        }
1699                    }
1700
1701                    trace!(
1702                        target: "trie::sparse",
1703                        ?path,
1704                        ?tree_mask,
1705                        ?hash_mask,
1706                        "Branch node masks"
1707                    );
1708
1709                    rlp_buf.clear();
1710                    let branch_node_ref =
1711                        BranchNodeRef::new(&buffers.branch_value_stack_buf, *state_mask);
1712                    let rlp_node = branch_node_ref.rlp(rlp_buf);
1713                    *hash = rlp_node.as_hash();
1714
1715                    // Save a branch node update only if it's not a root node, and we need to
1716                    // persist updates.
1717                    let store_in_db_trie_value = if let Some(updates) =
1718                        self.updates.as_mut().filter(|_| retain_updates && !path.is_empty())
1719                    {
1720                        let store_in_db_trie = !tree_mask.is_empty() || !hash_mask.is_empty();
1721                        if store_in_db_trie {
1722                            // Store in DB trie if there are either any children that are stored in
1723                            // the DB trie, or any children represent hashed values
1724                            hashes.reverse();
1725                            let branch_node = BranchNodeCompact::new(
1726                                *state_mask,
1727                                tree_mask,
1728                                hash_mask,
1729                                hashes,
1730                                hash.filter(|_| path.is_empty()),
1731                            );
1732                            updates.updated_nodes.insert(path, branch_node);
1733                        } else if self
1734                            .branch_node_tree_masks
1735                            .get(&path)
1736                            .is_some_and(|mask| !mask.is_empty()) ||
1737                            self.branch_node_hash_masks
1738                                .get(&path)
1739                                .is_some_and(|mask| !mask.is_empty())
1740                        {
1741                            // If new tree and hash masks are empty, but previously they weren't, we
1742                            // need to remove the node update and add the node itself to the list of
1743                            // removed nodes.
1744                            updates.updated_nodes.remove(&path);
1745                            updates.removed_nodes.insert(path);
1746                        } else if self
1747                            .branch_node_tree_masks
1748                            .get(&path)
1749                            .is_none_or(|mask| mask.is_empty()) &&
1750                            self.branch_node_hash_masks
1751                                .get(&path)
1752                                .is_none_or(|mask| mask.is_empty())
1753                        {
1754                            // If new tree and hash masks are empty, and they were previously empty
1755                            // as well, we need to remove the node update.
1756                            updates.updated_nodes.remove(&path);
1757                        }
1758
1759                        store_in_db_trie
1760                    } else {
1761                        false
1762                    };
1763                    *store_in_db_trie = Some(store_in_db_trie_value);
1764
1765                    (
1766                        rlp_node,
1767                        SparseNodeType::Branch { store_in_db_trie: Some(store_in_db_trie_value) },
1768                    )
1769                }
1770            };
1771
1772            trace!(
1773                target: "trie::sparse",
1774                ?_starting_path,
1775                ?level,
1776                ?path,
1777                ?node,
1778                ?node_type,
1779                ?is_in_prefix_set,
1780                "Added node to rlp node stack"
1781            );
1782
1783            buffers.rlp_node_stack.push(RlpNodeStackItem { path, rlp_node, node_type });
1784        }
1785
1786        debug_assert_eq!(buffers.rlp_node_stack.len(), 1);
1787        buffers.rlp_node_stack.pop().unwrap().rlp_node
1788    }
1789}
1790
1791/// Enum representing sparse trie node type.
1792#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1793pub enum SparseNodeType {
1794    /// Empty trie node.
1795    Empty,
1796    /// A placeholder that stores only the hash for a node that has not been fully revealed.
1797    Hash,
1798    /// Sparse leaf node.
1799    Leaf,
1800    /// Sparse extension node.
1801    Extension {
1802        /// A flag indicating whether the extension node should be stored in the database.
1803        store_in_db_trie: Option<bool>,
1804    },
1805    /// Sparse branch node.
1806    Branch {
1807        /// A flag indicating whether the branch node should be stored in the database.
1808        store_in_db_trie: Option<bool>,
1809    },
1810}
1811
1812impl SparseNodeType {
1813    /// Returns true if the node is a hash node.
1814    pub const fn is_hash(&self) -> bool {
1815        matches!(self, Self::Hash)
1816    }
1817
1818    /// Returns true if the node is a branch node.
1819    pub const fn is_branch(&self) -> bool {
1820        matches!(self, Self::Branch { .. })
1821    }
1822
1823    /// Returns true if the node should be stored in the database.
1824    pub const fn store_in_db_trie(&self) -> Option<bool> {
1825        match *self {
1826            Self::Extension { store_in_db_trie } | Self::Branch { store_in_db_trie } => {
1827                store_in_db_trie
1828            }
1829            _ => None,
1830        }
1831    }
1832}
1833
1834/// Enum representing trie nodes in sparse trie.
1835#[derive(Debug, Clone, PartialEq, Eq)]
1836pub enum SparseNode {
1837    /// Empty trie node.
1838    Empty,
1839    /// The hash of the node that was not revealed.
1840    Hash(B256),
1841    /// Sparse leaf node with remaining key suffix.
1842    Leaf {
1843        /// Remaining key suffix for the leaf node.
1844        key: Nibbles,
1845        /// Pre-computed hash of the sparse node.
1846        /// Can be reused unless this trie path has been updated.
1847        hash: Option<B256>,
1848    },
1849    /// Sparse extension node with key.
1850    Extension {
1851        /// The key slice stored by this extension node.
1852        key: Nibbles,
1853        /// Pre-computed hash of the sparse node.
1854        /// Can be reused unless this trie path has been updated.
1855        ///
1856        /// If [`None`], then the value is not known and should be calculated from scratch.
1857        hash: Option<B256>,
1858        /// Pre-computed flag indicating whether the trie node should be stored in the database.
1859        /// Can be reused unless this trie path has been updated.
1860        ///
1861        /// If [`None`], then the value is not known and should be calculated from scratch.
1862        store_in_db_trie: Option<bool>,
1863    },
1864    /// Sparse branch node with state mask.
1865    Branch {
1866        /// The bitmask representing children present in the branch node.
1867        state_mask: TrieMask,
1868        /// Pre-computed hash of the sparse node.
1869        /// Can be reused unless this trie path has been updated.
1870        ///
1871        /// If [`None`], then the value is not known and should be calculated from scratch.
1872        hash: Option<B256>,
1873        /// Pre-computed flag indicating whether the trie node should be stored in the database.
1874        /// Can be reused unless this trie path has been updated.
1875        ///
1876        /// If [`None`], then the value is not known and should be calculated from scratch.
1877        store_in_db_trie: Option<bool>,
1878    },
1879}
1880
1881impl SparseNode {
1882    /// Create new sparse node from [`TrieNode`].
1883    pub fn from_node(node: TrieNode) -> Self {
1884        match node {
1885            TrieNode::EmptyRoot => Self::Empty,
1886            TrieNode::Leaf(leaf) => Self::new_leaf(leaf.key),
1887            TrieNode::Extension(ext) => Self::new_ext(ext.key),
1888            TrieNode::Branch(branch) => Self::new_branch(branch.state_mask),
1889        }
1890    }
1891
1892    /// Create new [`SparseNode::Branch`] from state mask.
1893    pub const fn new_branch(state_mask: TrieMask) -> Self {
1894        Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1895    }
1896
1897    /// Create new [`SparseNode::Branch`] with two bits set.
1898    pub const fn new_split_branch(bit_a: u8, bit_b: u8) -> Self {
1899        let state_mask = TrieMask::new(
1900            // set bits for both children
1901            (1u16 << bit_a) | (1u16 << bit_b),
1902        );
1903        Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1904    }
1905
1906    /// Create new [`SparseNode::Extension`] from the key slice.
1907    pub const fn new_ext(key: Nibbles) -> Self {
1908        Self::Extension { key, hash: None, store_in_db_trie: None }
1909    }
1910
1911    /// Create new [`SparseNode::Leaf`] from leaf key and value.
1912    pub const fn new_leaf(key: Nibbles) -> Self {
1913        Self::Leaf { key, hash: None }
1914    }
1915
1916    /// Returns `true` if the node is a hash node.
1917    pub const fn is_hash(&self) -> bool {
1918        matches!(self, Self::Hash(_))
1919    }
1920
1921    /// Returns the hash of the node if it exists.
1922    pub const fn hash(&self) -> Option<B256> {
1923        match self {
1924            Self::Empty => None,
1925            Self::Hash(hash) => Some(*hash),
1926            Self::Leaf { hash, .. } | Self::Extension { hash, .. } | Self::Branch { hash, .. } => {
1927                *hash
1928            }
1929        }
1930    }
1931
1932    /// Sets the hash of the node for testing purposes.
1933    ///
1934    /// For [`SparseNode::Empty`] and [`SparseNode::Hash`] nodes, this method does nothing.
1935    #[cfg(any(test, feature = "test-utils"))]
1936    pub const fn set_hash(&mut self, new_hash: Option<B256>) {
1937        match self {
1938            Self::Empty | Self::Hash(_) => {
1939                // Cannot set hash for Empty or Hash nodes
1940            }
1941            Self::Leaf { hash, .. } | Self::Extension { hash, .. } | Self::Branch { hash, .. } => {
1942                *hash = new_hash;
1943            }
1944        }
1945    }
1946}
1947
1948/// A helper struct used to store information about a node that has been removed
1949/// during a deletion operation.
1950#[derive(Debug)]
1951struct RemovedSparseNode {
1952    /// The path at which the node was located.
1953    path: Nibbles,
1954    /// The removed node
1955    node: SparseNode,
1956    /// For branch nodes, an optional nibble that should be unset due to the node being removed.
1957    ///
1958    /// During leaf deletion, this identifies the specific branch nibble path that
1959    /// connects to the leaf being deleted. Then when restructuring the trie after deletion,
1960    /// this nibble position will be cleared from the branch node's to
1961    /// indicate that the child no longer exists.
1962    ///
1963    /// This is only set for branch nodes that have a direct path to the leaf being deleted.
1964    unset_branch_nibble: Option<u8>,
1965}
1966
1967/// Collection of reusable buffers for [`SerialSparseTrie::rlp_node`] calculations.
1968///
1969/// These buffers reduce allocations when computing RLP representations during trie updates.
1970#[derive(Debug, Default)]
1971pub struct RlpNodeBuffers {
1972    /// Stack of RLP node paths
1973    path_stack: Vec<RlpNodePathStackItem>,
1974    /// Stack of RLP nodes
1975    rlp_node_stack: Vec<RlpNodeStackItem>,
1976    /// Reusable branch child path
1977    branch_child_buf: SmallVec<[Nibbles; 16]>,
1978    /// Reusable branch value stack
1979    branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
1980}
1981
1982impl RlpNodeBuffers {
1983    /// Creates a new instance of buffers with the root path on the stack.
1984    fn new_with_root_path() -> Self {
1985        Self {
1986            path_stack: vec![RlpNodePathStackItem {
1987                level: 0,
1988                path: Nibbles::default(),
1989                is_in_prefix_set: None,
1990            }],
1991            rlp_node_stack: Vec::new(),
1992            branch_child_buf: SmallVec::<[Nibbles; 16]>::new_const(),
1993            branch_value_stack_buf: SmallVec::<[RlpNode; 16]>::new_const(),
1994        }
1995    }
1996}
1997
1998/// RLP node path stack item.
1999#[derive(Clone, PartialEq, Eq, Debug)]
2000pub struct RlpNodePathStackItem {
2001    /// Level at which the node is located. Higher numbers correspond to lower levels in the trie.
2002    pub level: usize,
2003    /// Path to the node.
2004    pub path: Nibbles,
2005    /// Whether the path is in the prefix set. If [`None`], then unknown yet.
2006    pub is_in_prefix_set: Option<bool>,
2007}
2008
2009/// RLP node stack item.
2010#[derive(Clone, PartialEq, Eq, Debug)]
2011pub struct RlpNodeStackItem {
2012    /// Path to the node.
2013    pub path: Nibbles,
2014    /// RLP node.
2015    pub rlp_node: RlpNode,
2016    /// Type of the node.
2017    pub node_type: SparseNodeType,
2018}
2019
2020impl SparseTrieUpdates {
2021    /// Create new wiped sparse trie updates.
2022    pub fn wiped() -> Self {
2023        Self { wiped: true, ..Default::default() }
2024    }
2025
2026    /// Clears the updates, but keeps the backing data structures allocated.
2027    ///
2028    /// Sets `wiped` to `false`.
2029    pub fn clear(&mut self) {
2030        self.updated_nodes.clear();
2031        self.removed_nodes.clear();
2032        self.wiped = false;
2033    }
2034
2035    /// Extends the updates with another set of updates.
2036    pub fn extend(&mut self, other: Self) {
2037        self.updated_nodes.extend(other.updated_nodes);
2038        self.removed_nodes.extend(other.removed_nodes);
2039        self.wiped |= other.wiped;
2040    }
2041}
2042
2043#[cfg(test)]
2044mod find_leaf_tests {
2045    use super::*;
2046    use crate::provider::DefaultTrieNodeProvider;
2047    use alloy_rlp::Encodable;
2048    use assert_matches::assert_matches;
2049    use reth_primitives_traits::Account;
2050    use reth_trie_common::LeafNode;
2051
2052    // Helper to create some test values
2053    fn encode_value(nonce: u64) -> Vec<u8> {
2054        let account = Account { nonce, ..Default::default() };
2055        let trie_account = account.into_trie_account(EMPTY_ROOT_HASH);
2056        let mut buf = Vec::new();
2057        trie_account.encode(&mut buf);
2058        buf
2059    }
2060
2061    const VALUE_A: fn() -> Vec<u8> = || encode_value(1);
2062    const VALUE_B: fn() -> Vec<u8> = || encode_value(2);
2063
2064    #[test]
2065    fn find_leaf_existing_leaf() {
2066        // Create a simple trie with one leaf
2067        let provider = DefaultTrieNodeProvider;
2068        let mut sparse = SerialSparseTrie::default();
2069        let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
2070        let value = b"test_value".to_vec();
2071
2072        sparse.update_leaf(path, value.clone(), &provider).unwrap();
2073
2074        // Check that the leaf exists
2075        let result = sparse.find_leaf(&path, None);
2076        assert_matches!(result, Ok(LeafLookup::Exists));
2077
2078        // Check with expected value matching
2079        let result = sparse.find_leaf(&path, Some(&value));
2080        assert_matches!(result, Ok(LeafLookup::Exists));
2081    }
2082
2083    #[test]
2084    fn find_leaf_value_mismatch() {
2085        // Create a simple trie with one leaf
2086        let provider = DefaultTrieNodeProvider;
2087        let mut sparse = SerialSparseTrie::default();
2088        let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
2089        let value = b"test_value".to_vec();
2090        let wrong_value = b"wrong_value".to_vec();
2091
2092        sparse.update_leaf(path, value, &provider).unwrap();
2093
2094        // Check with wrong expected value
2095        let result = sparse.find_leaf(&path, Some(&wrong_value));
2096        assert_matches!(
2097            result,
2098            Err(LeafLookupError::ValueMismatch { path: p, expected: Some(e), actual: _a }) if p == path && e == wrong_value
2099        );
2100    }
2101
2102    #[test]
2103    fn find_leaf_not_found_empty_trie() {
2104        // Empty trie
2105        let sparse = SerialSparseTrie::default();
2106        let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
2107
2108        // Leaf should not exist
2109        let result = sparse.find_leaf(&path, None);
2110        assert_matches!(result, Ok(LeafLookup::NonExistent));
2111    }
2112
2113    #[test]
2114    fn find_leaf_empty_trie() {
2115        let sparse = SerialSparseTrie::default();
2116        let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2117
2118        let result = sparse.find_leaf(&path, None);
2119        assert_matches!(result, Ok(LeafLookup::NonExistent));
2120    }
2121
2122    #[test]
2123    fn find_leaf_exists_no_value_check() {
2124        let provider = DefaultTrieNodeProvider;
2125        let mut sparse = SerialSparseTrie::default();
2126        let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2127        sparse.update_leaf(path, VALUE_A(), &provider).unwrap();
2128
2129        let result = sparse.find_leaf(&path, None);
2130        assert_matches!(result, Ok(LeafLookup::Exists));
2131    }
2132
2133    #[test]
2134    fn find_leaf_exists_with_value_check_ok() {
2135        let provider = DefaultTrieNodeProvider;
2136        let mut sparse = SerialSparseTrie::default();
2137        let path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2138        let value = VALUE_A();
2139        sparse.update_leaf(path, value.clone(), &provider).unwrap();
2140
2141        let result = sparse.find_leaf(&path, Some(&value));
2142        assert_matches!(result, Ok(LeafLookup::Exists));
2143    }
2144
2145    #[test]
2146    fn find_leaf_exclusion_branch_divergence() {
2147        let provider = DefaultTrieNodeProvider;
2148        let mut sparse = SerialSparseTrie::default();
2149        let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); // Creates branch at 0x12
2150        let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]); // Belongs to same branch
2151        let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]); // Diverges at nibble 7
2152
2153        sparse.update_leaf(path1, VALUE_A(), &provider).unwrap();
2154        sparse.update_leaf(path2, VALUE_B(), &provider).unwrap();
2155
2156        let result = sparse.find_leaf(&search_path, None);
2157        assert_matches!(result, Ok(LeafLookup::NonExistent));
2158    }
2159
2160    #[test]
2161    fn find_leaf_exclusion_extension_divergence() {
2162        let provider = DefaultTrieNodeProvider;
2163        let mut sparse = SerialSparseTrie::default();
2164        // This will create an extension node at root with key 0x12
2165        let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
2166        // This path diverges from the extension key
2167        let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x7, 0x8]);
2168
2169        sparse.update_leaf(path1, VALUE_A(), &provider).unwrap();
2170
2171        let result = sparse.find_leaf(&search_path, None);
2172        assert_matches!(result, Ok(LeafLookup::NonExistent));
2173    }
2174
2175    #[test]
2176    fn find_leaf_exclusion_leaf_divergence() {
2177        let provider = DefaultTrieNodeProvider;
2178        let mut sparse = SerialSparseTrie::default();
2179        let existing_leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2180        let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]);
2181
2182        sparse.update_leaf(existing_leaf_path, VALUE_A(), &provider).unwrap();
2183
2184        let result = sparse.find_leaf(&search_path, None);
2185        assert_matches!(result, Ok(LeafLookup::NonExistent));
2186    }
2187
2188    #[test]
2189    fn find_leaf_exclusion_path_ends_at_branch() {
2190        let provider = DefaultTrieNodeProvider;
2191        let mut sparse = SerialSparseTrie::default();
2192        let path1 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); // Creates branch at 0x12
2193        let path2 = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x5, 0x6]);
2194        let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2]); // Path of the branch itself
2195
2196        sparse.update_leaf(path1, VALUE_A(), &provider).unwrap();
2197        sparse.update_leaf(path2, VALUE_B(), &provider).unwrap();
2198
2199        let result = sparse.find_leaf(&search_path, None);
2200        assert_matches!(result, Ok(LeafLookup::NonExistent));
2201    }
2202
2203    #[test]
2204    fn find_leaf_error_trie_node_at_leaf_path() {
2205        // Scenario: The node *at* the leaf path is blinded.
2206        let blinded_hash = B256::repeat_byte(0xBB);
2207        let leaf_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2208
2209        let mut nodes = alloy_primitives::map::HashMap::default();
2210        // Create path to the blinded node
2211        nodes.insert(
2212            Nibbles::default(),
2213            SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x1, 0x2])),
2214        ); // Ext 0x12
2215        nodes.insert(
2216            Nibbles::from_nibbles_unchecked([0x1, 0x2]),
2217            SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x3])),
2218        ); // Ext 0x123
2219        nodes.insert(
2220            Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3]),
2221            SparseNode::new_branch(TrieMask::new(0b10000)),
2222        ); // Branch at 0x123, child 4
2223        nodes.insert(leaf_path, SparseNode::Hash(blinded_hash)); // Blinded node at 0x1234
2224
2225        let sparse = SerialSparseTrie {
2226            nodes,
2227            branch_node_tree_masks: Default::default(),
2228            branch_node_hash_masks: Default::default(),
2229            /* The value is not in the values map, or else it would early return */
2230            values: Default::default(),
2231            prefix_set: Default::default(),
2232            updates: None,
2233            rlp_buf: Vec::new(),
2234        };
2235
2236        let result = sparse.find_leaf(&leaf_path, None);
2237
2238        // Should error because it hit the blinded node exactly at the leaf path
2239        assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2240            if path == leaf_path && hash == blinded_hash
2241        );
2242    }
2243
2244    #[test]
2245    fn find_leaf_error_trie_node() {
2246        let blinded_hash = B256::repeat_byte(0xAA);
2247        let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]);
2248        let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]);
2249
2250        let mut nodes = HashMap::default();
2251
2252        // Root is a branch with child 0x1 (blinded) and 0x5 (revealed leaf)
2253        // So we set Bit 1 and Bit 5 in the state_mask
2254        let state_mask = TrieMask::new(0b100010);
2255        nodes.insert(Nibbles::default(), SparseNode::new_branch(state_mask));
2256
2257        nodes.insert(path_to_blind, SparseNode::Hash(blinded_hash));
2258        let path_revealed = Nibbles::from_nibbles_unchecked([0x5]);
2259        let path_revealed_leaf = Nibbles::from_nibbles_unchecked([0x5, 0x6, 0x7, 0x8]);
2260        nodes.insert(
2261            path_revealed,
2262            SparseNode::new_leaf(Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8])),
2263        );
2264
2265        let mut values = HashMap::default();
2266        values.insert(path_revealed_leaf, VALUE_A());
2267
2268        let sparse = SerialSparseTrie {
2269            nodes,
2270            branch_node_tree_masks: Default::default(),
2271            branch_node_hash_masks: Default::default(),
2272            values,
2273            prefix_set: Default::default(),
2274            updates: None,
2275            rlp_buf: Vec::new(),
2276        };
2277
2278        let result = sparse.find_leaf(&search_path, None);
2279
2280        // Should error because it hit the blinded node at path 0x1
2281        assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2282            if path == path_to_blind && hash == blinded_hash
2283        );
2284    }
2285
2286    #[test]
2287    fn find_leaf_error_trie_node_via_reveal() {
2288        let blinded_hash = B256::repeat_byte(0xAA);
2289        let path_to_blind = Nibbles::from_nibbles_unchecked([0x1]); // Path of the blinded node itself
2290        let search_path = Nibbles::from_nibbles_unchecked([0x1, 0x2, 0x3, 0x4]); // Path we will search for
2291
2292        let revealed_leaf_prefix = Nibbles::from_nibbles_unchecked([0x5]);
2293        let revealed_leaf_suffix = Nibbles::from_nibbles_unchecked([0x6, 0x7, 0x8]);
2294        let revealed_leaf_full_path = Nibbles::from_nibbles_unchecked([0x5, 0x6, 0x7, 0x8]);
2295        let revealed_value = VALUE_A();
2296
2297        // 1. Construct the RLP representation of the children for the root branch
2298        let rlp_node_child1 = RlpNode::word_rlp(&blinded_hash); // Blinded node
2299
2300        let leaf_node_child5 = LeafNode::new(revealed_leaf_suffix, revealed_value.clone());
2301        let leaf_node_child5_rlp_buf = alloy_rlp::encode(&leaf_node_child5);
2302        let hash_of_child5 = keccak256(&leaf_node_child5_rlp_buf);
2303        let rlp_node_child5 = RlpNode::word_rlp(&hash_of_child5);
2304
2305        // 2. Construct the root BranchNode using the RLP of its children
2306        // The stack order depends on the bit indices (1 and 5)
2307        let root_branch_node = reth_trie_common::BranchNode::new(
2308            vec![rlp_node_child1, rlp_node_child5], // Child 1 first, then Child 5
2309            TrieMask::new(0b100010),                // Mask with bits 1 and 5 set
2310        );
2311        let root_trie_node = TrieNode::Branch(root_branch_node);
2312
2313        // 3. Initialize the sparse trie using from_root
2314        // This will internally create Hash nodes for paths "1" and "5" initially.
2315        let mut sparse = SerialSparseTrie::from_root(root_trie_node, TrieMasks::none(), false)
2316            .expect("Failed to create trie from root");
2317
2318        // Assertions before we reveal child5
2319        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
2320        assert_matches!(sparse.nodes.get(&path_to_blind), Some(SparseNode::Hash(h)) if *h == blinded_hash );
2321        assert!(sparse.nodes.get(&revealed_leaf_prefix).unwrap().is_hash()); // Child 5 is initially a hash of its RLP
2322        assert!(sparse.values.is_empty());
2323
2324        // 4. Explicitly reveal the leaf node for child 5
2325        sparse
2326            .reveal_node(revealed_leaf_prefix, TrieNode::Leaf(leaf_node_child5), TrieMasks::none())
2327            .expect("Failed to reveal leaf node");
2328
2329        // Assertions after we reveal child 5
2330        assert_matches!(sparse.nodes.get(&Nibbles::default()), Some(SparseNode::Branch { state_mask, .. }) if *state_mask == TrieMask::new(0b100010));
2331        assert_matches!(sparse.nodes.get(&path_to_blind), Some(SparseNode::Hash(h)) if *h == blinded_hash );
2332        assert_matches!(sparse.nodes.get(&revealed_leaf_prefix), Some(SparseNode::Leaf { key, .. }) if *key == revealed_leaf_suffix);
2333        assert_eq!(sparse.values.get(&revealed_leaf_full_path), Some(&revealed_value));
2334
2335        let result = sparse.find_leaf(&search_path, None);
2336
2337        // 5. Assert the expected error
2338        // Should error because it hit the blinded node at path "1" only node at "5" was revealed
2339        assert_matches!(result, Err(LeafLookupError::BlindedNode { path, hash })
2340            if path == path_to_blind && hash == blinded_hash
2341        );
2342    }
2343}
2344
2345#[cfg(test)]
2346mod tests {
2347    use super::*;
2348    use crate::provider::DefaultTrieNodeProvider;
2349    use alloy_primitives::{map::B256Set, U256};
2350    use alloy_rlp::Encodable;
2351    use assert_matches::assert_matches;
2352    use itertools::Itertools;
2353    use prop::sample::SizeRange;
2354    use proptest::prelude::*;
2355    use proptest_arbitrary_interop::arb;
2356    use reth_primitives_traits::Account;
2357    use reth_provider::{test_utils::create_test_provider_factory, TrieWriter};
2358    use reth_trie::{
2359        hashed_cursor::{noop::NoopHashedAccountCursor, HashedPostStateAccountCursor},
2360        node_iter::{TrieElement, TrieNodeIter},
2361        trie_cursor::{noop::NoopAccountTrieCursor, TrieCursor, TrieCursorFactory},
2362        walker::TrieWalker,
2363        BranchNode, ExtensionNode, HashedPostState, LeafNode,
2364    };
2365    use reth_trie_common::{
2366        proof::{ProofNodes, ProofRetainer},
2367        updates::TrieUpdates,
2368        HashBuilder,
2369    };
2370    use reth_trie_db::DatabaseTrieCursorFactory;
2371    use std::collections::{BTreeMap, BTreeSet};
2372
2373    /// Pad nibbles to the length of a B256 hash with zeros on the left.
2374    fn pad_nibbles_left(nibbles: Nibbles) -> Nibbles {
2375        let mut base =
2376            Nibbles::from_nibbles_unchecked(vec![0; B256::len_bytes() * 2 - nibbles.len()]);
2377        base.extend(&nibbles);
2378        base
2379    }
2380
2381    /// Pad nibbles to the length of a B256 hash with zeros on the right.
2382    fn pad_nibbles_right(mut nibbles: Nibbles) -> Nibbles {
2383        nibbles.extend(&Nibbles::from_nibbles_unchecked(vec![
2384            0;
2385            B256::len_bytes() * 2 - nibbles.len()
2386        ]));
2387        nibbles
2388    }
2389
2390    /// Calculate the state root by feeding the provided state to the hash builder and retaining the
2391    /// proofs for the provided targets.
2392    ///
2393    /// Returns the state root and the retained proof nodes.
2394    fn run_hash_builder(
2395        state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
2396        trie_cursor: impl TrieCursor,
2397        destroyed_accounts: B256Set,
2398        proof_targets: impl IntoIterator<Item = Nibbles>,
2399    ) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>, HashMap<Nibbles, TrieMask>)
2400    {
2401        let mut account_rlp = Vec::new();
2402
2403        let mut hash_builder = HashBuilder::default()
2404            .with_updates(true)
2405            .with_proof_retainer(ProofRetainer::from_iter(proof_targets));
2406
2407        let mut prefix_set = PrefixSetMut::default();
2408        prefix_set.extend_keys(state.clone().into_iter().map(|(nibbles, _)| nibbles));
2409        prefix_set.extend_keys(destroyed_accounts.iter().map(Nibbles::unpack));
2410        let walker = TrieWalker::<_>::state_trie(trie_cursor, prefix_set.freeze())
2411            .with_deletions_retained(true);
2412        let hashed_post_state = HashedPostState::default()
2413            .with_accounts(state.into_iter().map(|(nibbles, account)| {
2414                (nibbles.pack().into_inner().unwrap().into(), Some(account))
2415            }))
2416            .into_sorted();
2417        let mut node_iter = TrieNodeIter::state_trie(
2418            walker,
2419            HashedPostStateAccountCursor::new(
2420                NoopHashedAccountCursor::default(),
2421                hashed_post_state.accounts(),
2422            ),
2423        );
2424
2425        while let Some(node) = node_iter.try_next().unwrap() {
2426            match node {
2427                TrieElement::Branch(branch) => {
2428                    hash_builder.add_branch(branch.key, branch.value, branch.children_are_in_trie);
2429                }
2430                TrieElement::Leaf(key, account) => {
2431                    let account = account.into_trie_account(EMPTY_ROOT_HASH);
2432                    account.encode(&mut account_rlp);
2433
2434                    hash_builder.add_leaf(Nibbles::unpack(key), &account_rlp);
2435                    account_rlp.clear();
2436                }
2437            }
2438        }
2439        let root = hash_builder.root();
2440        let proof_nodes = hash_builder.take_proof_nodes();
2441        let branch_node_hash_masks = hash_builder
2442            .updated_branch_nodes
2443            .clone()
2444            .unwrap_or_default()
2445            .iter()
2446            .map(|(path, node)| (*path, node.hash_mask))
2447            .collect();
2448        let branch_node_tree_masks = hash_builder
2449            .updated_branch_nodes
2450            .clone()
2451            .unwrap_or_default()
2452            .iter()
2453            .map(|(path, node)| (*path, node.tree_mask))
2454            .collect();
2455
2456        let mut trie_updates = TrieUpdates::default();
2457        let removed_keys = node_iter.walker.take_removed_keys();
2458        trie_updates.finalize(hash_builder, removed_keys, destroyed_accounts);
2459
2460        (root, trie_updates, proof_nodes, branch_node_hash_masks, branch_node_tree_masks)
2461    }
2462
2463    /// Assert that the sparse trie nodes and the proof nodes from the hash builder are equal.
2464    fn assert_eq_sparse_trie_proof_nodes(sparse_trie: &SerialSparseTrie, proof_nodes: ProofNodes) {
2465        let proof_nodes = proof_nodes
2466            .into_nodes_sorted()
2467            .into_iter()
2468            .map(|(path, node)| (path, TrieNode::decode(&mut node.as_ref()).unwrap()));
2469
2470        let sparse_nodes = sparse_trie.nodes.iter().sorted_by_key(|(path, _)| *path);
2471
2472        for ((proof_node_path, proof_node), (sparse_node_path, sparse_node)) in
2473            proof_nodes.zip(sparse_nodes)
2474        {
2475            assert_eq!(&proof_node_path, sparse_node_path);
2476
2477            let equals = match (&proof_node, &sparse_node) {
2478                // Both nodes are empty
2479                (TrieNode::EmptyRoot, SparseNode::Empty) => true,
2480                // Both nodes are branches and have the same state mask
2481                (
2482                    TrieNode::Branch(BranchNode { state_mask: proof_state_mask, .. }),
2483                    SparseNode::Branch { state_mask: sparse_state_mask, .. },
2484                ) => proof_state_mask == sparse_state_mask,
2485                // Both nodes are extensions and have the same key
2486                (
2487                    TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
2488                    SparseNode::Extension { key: sparse_key, .. },
2489                ) |
2490                // Both nodes are leaves and have the same key
2491                (
2492                    TrieNode::Leaf(LeafNode { key: proof_key, .. }),
2493                    SparseNode::Leaf { key: sparse_key, .. },
2494                ) => proof_key == sparse_key,
2495                // Empty and hash nodes are specific to the sparse trie, skip them
2496                (_, SparseNode::Empty | SparseNode::Hash(_)) => continue,
2497                _ => false,
2498            };
2499            assert!(
2500                equals,
2501                "path: {proof_node_path:?}\nproof node: {proof_node:?}\nsparse node: {sparse_node:?}"
2502            );
2503        }
2504    }
2505
2506    #[test]
2507    fn sparse_trie_is_blind() {
2508        assert!(SparseTrie::<SerialSparseTrie>::blind().is_blind());
2509        assert!(!SparseTrie::<SerialSparseTrie>::revealed_empty().is_blind());
2510    }
2511
2512    #[test]
2513    fn sparse_trie_empty_update_one() {
2514        let key = Nibbles::unpack(B256::with_last_byte(42));
2515        let value = || Account::default();
2516        let value_encoded = || {
2517            let mut account_rlp = Vec::new();
2518            value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2519            account_rlp
2520        };
2521
2522        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2523            run_hash_builder(
2524                [(key, value())],
2525                NoopAccountTrieCursor::default(),
2526                Default::default(),
2527                [key],
2528            );
2529
2530        let provider = DefaultTrieNodeProvider;
2531        let mut sparse = SerialSparseTrie::default().with_updates(true);
2532        sparse.update_leaf(key, value_encoded(), &provider).unwrap();
2533        let sparse_root = sparse.root();
2534        let sparse_updates = sparse.take_updates();
2535
2536        assert_eq!(sparse_root, hash_builder_root);
2537        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2538        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2539    }
2540
2541    #[test]
2542    fn sparse_trie_empty_update_multiple_lower_nibbles() {
2543        reth_tracing::init_test_tracing();
2544
2545        let paths = (0..=16).map(|b| Nibbles::unpack(B256::with_last_byte(b))).collect::<Vec<_>>();
2546        let value = || Account::default();
2547        let value_encoded = || {
2548            let mut account_rlp = Vec::new();
2549            value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2550            account_rlp
2551        };
2552
2553        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2554            run_hash_builder(
2555                paths.iter().copied().zip(std::iter::repeat_with(value)),
2556                NoopAccountTrieCursor::default(),
2557                Default::default(),
2558                paths.clone(),
2559            );
2560
2561        let provider = DefaultTrieNodeProvider;
2562        let mut sparse = SerialSparseTrie::default().with_updates(true);
2563        for path in &paths {
2564            sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
2565        }
2566        let sparse_root = sparse.root();
2567        let sparse_updates = sparse.take_updates();
2568
2569        assert_eq!(sparse_root, hash_builder_root);
2570        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2571        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2572    }
2573
2574    #[test]
2575    fn sparse_trie_empty_update_multiple_upper_nibbles() {
2576        let paths = (239..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
2577        let value = || Account::default();
2578        let value_encoded = || {
2579            let mut account_rlp = Vec::new();
2580            value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2581            account_rlp
2582        };
2583
2584        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2585            run_hash_builder(
2586                paths.iter().copied().zip(std::iter::repeat_with(value)),
2587                NoopAccountTrieCursor::default(),
2588                Default::default(),
2589                paths.clone(),
2590            );
2591
2592        let provider = DefaultTrieNodeProvider;
2593        let mut sparse = SerialSparseTrie::default().with_updates(true);
2594        for path in &paths {
2595            sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
2596        }
2597        let sparse_root = sparse.root();
2598        let sparse_updates = sparse.take_updates();
2599
2600        assert_eq!(sparse_root, hash_builder_root);
2601        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2602        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2603    }
2604
2605    #[test]
2606    fn sparse_trie_empty_update_multiple() {
2607        let paths = (0..=255)
2608            .map(|b| {
2609                Nibbles::unpack(if b % 2 == 0 {
2610                    B256::repeat_byte(b)
2611                } else {
2612                    B256::with_last_byte(b)
2613                })
2614            })
2615            .collect::<Vec<_>>();
2616        let value = || Account::default();
2617        let value_encoded = || {
2618            let mut account_rlp = Vec::new();
2619            value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2620            account_rlp
2621        };
2622
2623        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2624            run_hash_builder(
2625                paths.iter().sorted_unstable().copied().zip(std::iter::repeat_with(value)),
2626                NoopAccountTrieCursor::default(),
2627                Default::default(),
2628                paths.clone(),
2629            );
2630
2631        let provider = DefaultTrieNodeProvider;
2632        let mut sparse = SerialSparseTrie::default().with_updates(true);
2633        for path in &paths {
2634            sparse.update_leaf(*path, value_encoded(), &provider).unwrap();
2635        }
2636        let sparse_root = sparse.root();
2637        let sparse_updates = sparse.take_updates();
2638
2639        assert_eq!(sparse_root, hash_builder_root);
2640        pretty_assertions::assert_eq!(
2641            BTreeMap::from_iter(sparse_updates.updated_nodes),
2642            BTreeMap::from_iter(hash_builder_updates.account_nodes)
2643        );
2644        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2645    }
2646
2647    #[test]
2648    fn sparse_trie_empty_update_repeated() {
2649        let paths = (0..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
2650        let old_value = Account { nonce: 1, ..Default::default() };
2651        let old_value_encoded = {
2652            let mut account_rlp = Vec::new();
2653            old_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2654            account_rlp
2655        };
2656        let new_value = Account { nonce: 2, ..Default::default() };
2657        let new_value_encoded = {
2658            let mut account_rlp = Vec::new();
2659            new_value.into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
2660            account_rlp
2661        };
2662
2663        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2664            run_hash_builder(
2665                paths.iter().copied().zip(std::iter::repeat_with(|| old_value)),
2666                NoopAccountTrieCursor::default(),
2667                Default::default(),
2668                paths.clone(),
2669            );
2670
2671        let provider = DefaultTrieNodeProvider;
2672        let mut sparse = SerialSparseTrie::default().with_updates(true);
2673        for path in &paths {
2674            sparse.update_leaf(*path, old_value_encoded.clone(), &provider).unwrap();
2675        }
2676        let sparse_root = sparse.root();
2677        let sparse_updates = sparse.updates_ref();
2678
2679        assert_eq!(sparse_root, hash_builder_root);
2680        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2681        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2682
2683        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
2684            run_hash_builder(
2685                paths.iter().copied().zip(std::iter::repeat_with(|| new_value)),
2686                NoopAccountTrieCursor::default(),
2687                Default::default(),
2688                paths.clone(),
2689            );
2690
2691        for path in &paths {
2692            sparse.update_leaf(*path, new_value_encoded.clone(), &provider).unwrap();
2693        }
2694        let sparse_root = sparse.root();
2695        let sparse_updates = sparse.take_updates();
2696
2697        assert_eq!(sparse_root, hash_builder_root);
2698        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2699        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2700    }
2701
2702    #[test]
2703    fn sparse_trie_remove_leaf() {
2704        reth_tracing::init_test_tracing();
2705
2706        let provider = DefaultTrieNodeProvider;
2707        let mut sparse = SerialSparseTrie::default();
2708
2709        let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
2710
2711        sparse
2712            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
2713            .unwrap();
2714        sparse
2715            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
2716            .unwrap();
2717        sparse
2718            .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
2719            .unwrap();
2720        sparse
2721            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
2722            .unwrap();
2723        sparse
2724            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
2725            .unwrap();
2726        sparse
2727            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
2728            .unwrap();
2729
2730        // Extension (Key = 5)
2731        // └── Branch (Mask = 1011)
2732        //     ├── 0 -> Extension (Key = 23)
2733        //     │        └── Branch (Mask = 0101)
2734        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231)
2735        //     │              └── 3 -> Leaf (Key = 3, Path = 50233)
2736        //     ├── 2 -> Leaf (Key = 013, Path = 52013)
2737        //     └── 3 -> Branch (Mask = 0101)
2738        //                ├── 1 -> Leaf (Key = 3102, Path = 53102)
2739        //                └── 3 -> Branch (Mask = 1010)
2740        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302)
2741        //                       └── 2 -> Leaf (Key = 3320, Path = 53320)
2742        pretty_assertions::assert_eq!(
2743            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2744            BTreeMap::from_iter([
2745                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2746                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1101.into())),
2747                (
2748                    Nibbles::from_nibbles([0x5, 0x0]),
2749                    SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
2750                ),
2751                (
2752                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
2753                    SparseNode::new_branch(0b1010.into())
2754                ),
2755                (
2756                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
2757                    SparseNode::new_leaf(Nibbles::default())
2758                ),
2759                (
2760                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
2761                    SparseNode::new_leaf(Nibbles::default())
2762                ),
2763                (
2764                    Nibbles::from_nibbles([0x5, 0x2]),
2765                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x1, 0x3]))
2766                ),
2767                (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2768                (
2769                    Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2770                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2771                ),
2772                (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2773                (
2774                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2775                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2776                ),
2777                (
2778                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2779                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2780                )
2781            ])
2782        );
2783
2784        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), &provider).unwrap();
2785
2786        // Extension (Key = 5)
2787        // └── Branch (Mask = 1001)
2788        //     ├── 0 -> Extension (Key = 23)
2789        //     │        └── Branch (Mask = 0101)
2790        //     │              ├── 1 -> Leaf (Key = 0231, Path = 50231)
2791        //     │              └── 3 -> Leaf (Key = 0233, Path = 50233)
2792        //     └── 3 -> Branch (Mask = 0101)
2793        //                ├── 1 -> Leaf (Key = 3102, Path = 53102)
2794        //                └── 3 -> Branch (Mask = 1010)
2795        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302)
2796        //                       └── 2 -> Leaf (Key = 3320, Path = 53320)
2797        pretty_assertions::assert_eq!(
2798            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2799            BTreeMap::from_iter([
2800                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2801                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2802                (
2803                    Nibbles::from_nibbles([0x5, 0x0]),
2804                    SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
2805                ),
2806                (
2807                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
2808                    SparseNode::new_branch(0b1010.into())
2809                ),
2810                (
2811                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
2812                    SparseNode::new_leaf(Nibbles::default())
2813                ),
2814                (
2815                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
2816                    SparseNode::new_leaf(Nibbles::default())
2817                ),
2818                (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2819                (
2820                    Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2821                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2822                ),
2823                (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2824                (
2825                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2826                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2827                ),
2828                (
2829                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2830                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2831                )
2832            ])
2833        );
2834
2835        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), &provider).unwrap();
2836
2837        // Extension (Key = 5)
2838        // └── Branch (Mask = 1001)
2839        //     ├── 0 -> Leaf (Key = 0233, Path = 50233)
2840        //     └── 3 -> Branch (Mask = 0101)
2841        //                ├── 1 -> Leaf (Key = 3102, Path = 53102)
2842        //                └── 3 -> Branch (Mask = 1010)
2843        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302)
2844        //                       └── 2 -> Leaf (Key = 3320, Path = 53320)
2845        pretty_assertions::assert_eq!(
2846            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2847            BTreeMap::from_iter([
2848                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2849                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2850                (
2851                    Nibbles::from_nibbles([0x5, 0x0]),
2852                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2853                ),
2854                (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
2855                (
2856                    Nibbles::from_nibbles([0x5, 0x3, 0x1]),
2857                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
2858                ),
2859                (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2860                (
2861                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2862                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2863                ),
2864                (
2865                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2866                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2867                )
2868            ])
2869        );
2870
2871        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), &provider).unwrap();
2872
2873        // Extension (Key = 5)
2874        // └── Branch (Mask = 1001)
2875        //     ├── 0 -> Leaf (Key = 0233, Path = 50233)
2876        //     └── 3 -> Branch (Mask = 1010)
2877        //                ├── 0 -> Leaf (Key = 3302, Path = 53302)
2878        //                └── 2 -> Leaf (Key = 3320, Path = 53320)
2879        pretty_assertions::assert_eq!(
2880            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2881            BTreeMap::from_iter([
2882                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2883                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2884                (
2885                    Nibbles::from_nibbles([0x5, 0x0]),
2886                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2887                ),
2888                (
2889                    Nibbles::from_nibbles([0x5, 0x3]),
2890                    SparseNode::new_ext(Nibbles::from_nibbles([0x3]))
2891                ),
2892                (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
2893                (
2894                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
2895                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
2896                ),
2897                (
2898                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
2899                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
2900                )
2901            ])
2902        );
2903
2904        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), &provider).unwrap();
2905
2906        // Extension (Key = 5)
2907        // └── Branch (Mask = 1001)
2908        //     ├── 0 -> Leaf (Key = 0233, Path = 50233)
2909        //     └── 3 -> Leaf (Key = 3302, Path = 53302)
2910        pretty_assertions::assert_eq!(
2911            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2912            BTreeMap::from_iter([
2913                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
2914                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
2915                (
2916                    Nibbles::from_nibbles([0x5, 0x0]),
2917                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
2918                ),
2919                (
2920                    Nibbles::from_nibbles([0x5, 0x3]),
2921                    SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x0, 0x2]))
2922                ),
2923            ])
2924        );
2925
2926        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), &provider).unwrap();
2927
2928        // Leaf (Key = 53302)
2929        pretty_assertions::assert_eq!(
2930            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2931            BTreeMap::from_iter([(
2932                Nibbles::default(),
2933                SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]))
2934            ),])
2935        );
2936
2937        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), &provider).unwrap();
2938
2939        // Empty
2940        pretty_assertions::assert_eq!(
2941            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
2942            BTreeMap::from_iter([(Nibbles::default(), SparseNode::Empty)])
2943        );
2944    }
2945
2946    #[test]
2947    fn sparse_trie_remove_leaf_blinded() {
2948        let leaf = LeafNode::new(
2949            Nibbles::default(),
2950            alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
2951        );
2952        let branch = TrieNode::Branch(BranchNode::new(
2953            vec![
2954                RlpNode::word_rlp(&B256::repeat_byte(1)),
2955                RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
2956            ],
2957            TrieMask::new(0b11),
2958        ));
2959
2960        let provider = DefaultTrieNodeProvider;
2961        let mut sparse = SerialSparseTrie::from_root(
2962            branch.clone(),
2963            TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
2964            false,
2965        )
2966        .unwrap();
2967
2968        // Reveal a branch node and one of its children
2969        //
2970        // Branch (Mask = 11)
2971        // ├── 0 -> Hash (Path = 0)
2972        // └── 1 -> Leaf (Path = 1)
2973        sparse
2974            .reveal_node(
2975                Nibbles::default(),
2976                branch,
2977                TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
2978            )
2979            .unwrap();
2980        sparse
2981            .reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), TrieMasks::none())
2982            .unwrap();
2983
2984        // Removing a blinded leaf should result in an error
2985        assert_matches!(
2986            sparse.remove_leaf(&Nibbles::from_nibbles([0x0]), &provider).map_err(|e| e.into_kind()),
2987            Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
2988        );
2989    }
2990
2991    #[test]
2992    fn sparse_trie_remove_leaf_non_existent() {
2993        let leaf = LeafNode::new(
2994            Nibbles::default(),
2995            alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
2996        );
2997        let branch = TrieNode::Branch(BranchNode::new(
2998            vec![
2999                RlpNode::word_rlp(&B256::repeat_byte(1)),
3000                RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
3001            ],
3002            TrieMask::new(0b11),
3003        ));
3004
3005        let provider = DefaultTrieNodeProvider;
3006        let mut sparse = SerialSparseTrie::from_root(
3007            branch.clone(),
3008            TrieMasks { hash_mask: Some(TrieMask::new(0b01)), tree_mask: None },
3009            false,
3010        )
3011        .unwrap();
3012
3013        // Reveal a branch node and one of its children
3014        //
3015        // Branch (Mask = 11)
3016        // ├── 0 -> Hash (Path = 0)
3017        // └── 1 -> Leaf (Path = 1)
3018        sparse
3019            .reveal_node(
3020                Nibbles::default(),
3021                branch,
3022                TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
3023            )
3024            .unwrap();
3025        sparse
3026            .reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), TrieMasks::none())
3027            .unwrap();
3028
3029        // Removing a non-existent leaf should be a noop
3030        let sparse_old = sparse.clone();
3031        assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2]), &provider), Ok(()));
3032        assert_eq!(sparse, sparse_old);
3033    }
3034
3035    #[test]
3036    fn sparse_trie_fuzz() {
3037        // Having only the first 3 nibbles set, we narrow down the range of keys
3038        // to 4096 different hashes. It allows us to generate collisions more likely
3039        // to test the sparse trie updates.
3040        const KEY_NIBBLES_LEN: usize = 3;
3041
3042        fn test(updates: Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)>) {
3043            {
3044                let mut state = BTreeMap::default();
3045                let default_provider = DefaultTrieNodeProvider;
3046                let provider_factory = create_test_provider_factory();
3047                let mut sparse = SerialSparseTrie::default().with_updates(true);
3048
3049                for (update, keys_to_delete) in updates {
3050                    // Insert state updates into the sparse trie and calculate the root
3051                    for (key, account) in update.clone() {
3052                        let account = account.into_trie_account(EMPTY_ROOT_HASH);
3053                        let mut account_rlp = Vec::new();
3054                        account.encode(&mut account_rlp);
3055                        sparse.update_leaf(key, account_rlp, &default_provider).unwrap();
3056                    }
3057                    // We need to clone the sparse trie, so that all updated branch nodes are
3058                    // preserved, and not only those that were changed after the last call to
3059                    // `root()`.
3060                    let mut updated_sparse = sparse.clone();
3061                    let sparse_root = updated_sparse.root();
3062                    let sparse_updates = updated_sparse.take_updates();
3063
3064                    // Insert state updates into the hash builder and calculate the root
3065                    state.extend(update);
3066                    let provider = provider_factory.provider().unwrap();
3067                    let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
3068                    let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
3069                        run_hash_builder(
3070                            state.clone(),
3071                            trie_cursor.account_trie_cursor().unwrap(),
3072                            Default::default(),
3073                            state.keys().copied(),
3074                        );
3075
3076                    // Extract account nodes before moving hash_builder_updates
3077                    let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
3078
3079                    // Write trie updates to the database
3080                    let provider_rw = provider_factory.provider_rw().unwrap();
3081                    provider_rw.write_trie_updates(hash_builder_updates).unwrap();
3082                    provider_rw.commit().unwrap();
3083
3084                    // Assert that the sparse trie root matches the hash builder root
3085                    assert_eq!(sparse_root, hash_builder_root);
3086                    // Assert that the sparse trie updates match the hash builder updates
3087                    pretty_assertions::assert_eq!(
3088                        BTreeMap::from_iter(sparse_updates.updated_nodes),
3089                        BTreeMap::from_iter(hash_builder_account_nodes)
3090                    );
3091                    // Assert that the sparse trie nodes match the hash builder proof nodes
3092                    assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
3093
3094                    // Delete some keys from both the hash builder and the sparse trie and check
3095                    // that the sparse trie root still matches the hash builder root
3096                    for key in &keys_to_delete {
3097                        state.remove(key).unwrap();
3098                        sparse.remove_leaf(key, &default_provider).unwrap();
3099                    }
3100
3101                    // We need to clone the sparse trie, so that all updated branch nodes are
3102                    // preserved, and not only those that were changed after the last call to
3103                    // `root()`.
3104                    let mut updated_sparse = sparse.clone();
3105                    let sparse_root = updated_sparse.root();
3106                    let sparse_updates = updated_sparse.take_updates();
3107
3108                    let provider = provider_factory.provider().unwrap();
3109                    let trie_cursor = DatabaseTrieCursorFactory::new(provider.tx_ref());
3110                    let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _, _) =
3111                        run_hash_builder(
3112                            state.clone(),
3113                            trie_cursor.account_trie_cursor().unwrap(),
3114                            keys_to_delete
3115                                .iter()
3116                                .map(|nibbles| B256::from_slice(&nibbles.pack()))
3117                                .collect(),
3118                            state.keys().copied(),
3119                        );
3120
3121                    // Extract account nodes before moving hash_builder_updates
3122                    let hash_builder_account_nodes = hash_builder_updates.account_nodes.clone();
3123
3124                    // Write trie updates to the database
3125                    let provider_rw = provider_factory.provider_rw().unwrap();
3126                    provider_rw.write_trie_updates(hash_builder_updates).unwrap();
3127                    provider_rw.commit().unwrap();
3128
3129                    // Assert that the sparse trie root matches the hash builder root
3130                    assert_eq!(sparse_root, hash_builder_root);
3131                    // Assert that the sparse trie updates match the hash builder updates
3132                    pretty_assertions::assert_eq!(
3133                        BTreeMap::from_iter(sparse_updates.updated_nodes),
3134                        BTreeMap::from_iter(hash_builder_account_nodes)
3135                    );
3136                    // Assert that the sparse trie nodes match the hash builder proof nodes
3137                    assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
3138                }
3139            }
3140        }
3141
3142        fn transform_updates(
3143            updates: Vec<BTreeMap<Nibbles, Account>>,
3144            mut rng: impl rand::Rng,
3145        ) -> Vec<(BTreeMap<Nibbles, Account>, BTreeSet<Nibbles>)> {
3146            let mut keys = BTreeSet::new();
3147            updates
3148                .into_iter()
3149                .map(|update| {
3150                    keys.extend(update.keys().copied());
3151
3152                    let keys_to_delete_len = update.len() / 2;
3153                    let keys_to_delete = (0..keys_to_delete_len)
3154                        .map(|_| {
3155                            let key =
3156                                *rand::seq::IteratorRandom::choose(keys.iter(), &mut rng).unwrap();
3157                            keys.take(&key).unwrap()
3158                        })
3159                        .collect();
3160
3161                    (update, keys_to_delete)
3162                })
3163                .collect::<Vec<_>>()
3164        }
3165
3166        proptest!(ProptestConfig::with_cases(10), |(
3167            updates in proptest::collection::vec(
3168                proptest::collection::btree_map(
3169                    any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
3170                    arb::<Account>(),
3171                    1..50,
3172                ),
3173                1..50,
3174            ).prop_perturb(transform_updates)
3175        )| {
3176            test(updates)
3177        });
3178    }
3179
3180    /// We have three leaves that share the same prefix: 0x00, 0x01 and 0x02. Hash builder trie has
3181    /// only nodes 0x00 and 0x02, and we have proofs for them. Node 0x01 is new and inserted in the
3182    /// sparse trie first.
3183    ///
3184    /// 1. Reveal the hash builder proof to leaf 0x00 in the sparse trie.
3185    /// 2. Insert leaf 0x01 into the sparse trie.
3186    /// 3. Reveal the hash builder proof to leaf 0x02 in the sparse trie.
3187    ///
3188    /// The hash builder proof to the leaf 0x02 didn't have the leaf 0x01 at the corresponding
3189    /// nibble of the branch node, so we need to adjust the branch node instead of fully
3190    /// replacing it.
3191    #[test]
3192    fn sparse_trie_reveal_node_1() {
3193        let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00]));
3194        let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01]));
3195        let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x02]));
3196        let value = || Account::default();
3197        let value_encoded = || {
3198            let mut account_rlp = Vec::new();
3199            value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3200            account_rlp
3201        };
3202
3203        // Generate the proof for the root node and initialize the sparse trie with it
3204        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3205            run_hash_builder(
3206                [(key1(), value()), (key3(), value())],
3207                NoopAccountTrieCursor::default(),
3208                Default::default(),
3209                [Nibbles::default()],
3210            );
3211
3212        let provider = DefaultTrieNodeProvider;
3213        let mut sparse = SerialSparseTrie::from_root(
3214            TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3215            TrieMasks {
3216                hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3217                tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3218            },
3219            false,
3220        )
3221        .unwrap();
3222
3223        // Generate the proof for the first key and reveal it in the sparse trie
3224        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3225            run_hash_builder(
3226                [(key1(), value()), (key3(), value())],
3227                NoopAccountTrieCursor::default(),
3228                Default::default(),
3229                [key1()],
3230            );
3231        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3232            let hash_mask = branch_node_hash_masks.get(&path).copied();
3233            let tree_mask = branch_node_tree_masks.get(&path).copied();
3234            sparse
3235                .reveal_node(
3236                    path,
3237                    TrieNode::decode(&mut &node[..]).unwrap(),
3238                    TrieMasks { hash_mask, tree_mask },
3239                )
3240                .unwrap();
3241        }
3242
3243        // Check that the branch node exists with only two nibbles set
3244        assert_eq!(
3245            sparse.nodes.get(&Nibbles::default()),
3246            Some(&SparseNode::new_branch(0b101.into()))
3247        );
3248
3249        // Insert the leaf for the second key
3250        sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
3251
3252        // Check that the branch node was updated and another nibble was set
3253        assert_eq!(
3254            sparse.nodes.get(&Nibbles::default()),
3255            Some(&SparseNode::new_branch(0b111.into()))
3256        );
3257
3258        // Generate the proof for the third key and reveal it in the sparse trie
3259        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3260            run_hash_builder(
3261                [(key1(), value()), (key3(), value())],
3262                NoopAccountTrieCursor::default(),
3263                Default::default(),
3264                [key3()],
3265            );
3266        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3267            let hash_mask = branch_node_hash_masks.get(&path).copied();
3268            let tree_mask = branch_node_tree_masks.get(&path).copied();
3269            sparse
3270                .reveal_node(
3271                    path,
3272                    TrieNode::decode(&mut &node[..]).unwrap(),
3273                    TrieMasks { hash_mask, tree_mask },
3274                )
3275                .unwrap();
3276        }
3277
3278        // Check that nothing changed in the branch node
3279        assert_eq!(
3280            sparse.nodes.get(&Nibbles::default()),
3281            Some(&SparseNode::new_branch(0b111.into()))
3282        );
3283
3284        // Generate the nodes for the full trie with all three key using the hash builder, and
3285        // compare them to the sparse trie
3286        let (_, _, hash_builder_proof_nodes, _, _) = run_hash_builder(
3287            [(key1(), value()), (key2(), value()), (key3(), value())],
3288            NoopAccountTrieCursor::default(),
3289            Default::default(),
3290            [key1(), key2(), key3()],
3291        );
3292
3293        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
3294    }
3295
3296    /// We have three leaves: 0x0000, 0x0101, and 0x0102. Hash builder trie has all nodes, and we
3297    /// have proofs for them.
3298    ///
3299    /// 1. Reveal the hash builder proof to leaf 0x00 in the sparse trie.
3300    /// 2. Remove leaf 0x00 from the sparse trie (that will remove the branch node and create an
3301    ///    extension node with the key 0x0000).
3302    /// 3. Reveal the hash builder proof to leaf 0x0101 in the sparse trie.
3303    ///
3304    /// The hash builder proof to the leaf 0x0101 had a branch node in the path, but we turned it
3305    /// into an extension node, so it should ignore this node.
3306    #[test]
3307    fn sparse_trie_reveal_node_2() {
3308        let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x00]));
3309        let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x01]));
3310        let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x02]));
3311        let value = || Account::default();
3312
3313        // Generate the proof for the root node and initialize the sparse trie with it
3314        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3315            run_hash_builder(
3316                [(key1(), value()), (key2(), value()), (key3(), value())],
3317                NoopAccountTrieCursor::default(),
3318                Default::default(),
3319                [Nibbles::default()],
3320            );
3321
3322        let provider = DefaultTrieNodeProvider;
3323        let mut sparse = SerialSparseTrie::from_root(
3324            TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3325            TrieMasks {
3326                hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3327                tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3328            },
3329            false,
3330        )
3331        .unwrap();
3332
3333        // Generate the proof for the children of the root branch node and reveal it in the sparse
3334        // trie
3335        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3336            run_hash_builder(
3337                [(key1(), value()), (key2(), value()), (key3(), value())],
3338                NoopAccountTrieCursor::default(),
3339                Default::default(),
3340                [key1(), Nibbles::from_nibbles_unchecked([0x01])],
3341            );
3342        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3343            let hash_mask = branch_node_hash_masks.get(&path).copied();
3344            let tree_mask = branch_node_tree_masks.get(&path).copied();
3345            sparse
3346                .reveal_node(
3347                    path,
3348                    TrieNode::decode(&mut &node[..]).unwrap(),
3349                    TrieMasks { hash_mask, tree_mask },
3350                )
3351                .unwrap();
3352        }
3353
3354        // Check that the branch node exists
3355        assert_eq!(
3356            sparse.nodes.get(&Nibbles::default()),
3357            Some(&SparseNode::new_branch(0b11.into()))
3358        );
3359
3360        // Remove the leaf for the first key
3361        sparse.remove_leaf(&key1(), &provider).unwrap();
3362
3363        // Check that the branch node was turned into an extension node
3364        assert_eq!(
3365            sparse.nodes.get(&Nibbles::default()),
3366            Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3367        );
3368
3369        // Generate the proof for the third key and reveal it in the sparse trie
3370        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3371            run_hash_builder(
3372                [(key1(), value()), (key2(), value()), (key3(), value())],
3373                NoopAccountTrieCursor::default(),
3374                Default::default(),
3375                [key2()],
3376            );
3377        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3378            let hash_mask = branch_node_hash_masks.get(&path).copied();
3379            let tree_mask = branch_node_tree_masks.get(&path).copied();
3380            sparse
3381                .reveal_node(
3382                    path,
3383                    TrieNode::decode(&mut &node[..]).unwrap(),
3384                    TrieMasks { hash_mask, tree_mask },
3385                )
3386                .unwrap();
3387        }
3388
3389        // Check that nothing changed in the extension node
3390        assert_eq!(
3391            sparse.nodes.get(&Nibbles::default()),
3392            Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
3393        );
3394    }
3395
3396    /// We have two leaves that share the same prefix: 0x0001 and 0x0002, and a leaf with a
3397    /// different prefix: 0x0100. Hash builder trie has only the first two leaves, and we have
3398    /// proofs for them.
3399    ///
3400    /// 1. Insert the leaf 0x0100 into the sparse trie, and check that the root extension node was
3401    ///    turned into a branch node.
3402    /// 2. Reveal the leaf 0x0001 in the sparse trie, and check that the root branch node wasn't
3403    ///    overwritten with the extension node from the proof.
3404    #[test]
3405    fn sparse_trie_reveal_node_3() {
3406        let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x01]));
3407        let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x02]));
3408        let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x00]));
3409        let value = || Account::default();
3410        let value_encoded = || {
3411            let mut account_rlp = Vec::new();
3412            value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3413            account_rlp
3414        };
3415
3416        // Generate the proof for the root node and initialize the sparse trie with it
3417        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3418            run_hash_builder(
3419                [(key1(), value()), (key2(), value())],
3420                NoopAccountTrieCursor::default(),
3421                Default::default(),
3422                [Nibbles::default()],
3423            );
3424
3425        let provider = DefaultTrieNodeProvider;
3426        let mut sparse = SerialSparseTrie::from_root(
3427            TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
3428            TrieMasks {
3429                hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(),
3430                tree_mask: branch_node_tree_masks.get(&Nibbles::default()).copied(),
3431            },
3432            false,
3433        )
3434        .unwrap();
3435
3436        // Check that the root extension node exists
3437        assert_matches!(
3438            sparse.nodes.get(&Nibbles::default()),
3439            Some(SparseNode::Extension { key, hash: None, store_in_db_trie: None }) if *key == Nibbles::from_nibbles([0x00])
3440        );
3441
3442        // Insert the leaf with a different prefix
3443        sparse.update_leaf(key3(), value_encoded(), &provider).unwrap();
3444
3445        // Check that the extension node was turned into a branch node
3446        assert_matches!(
3447            sparse.nodes.get(&Nibbles::default()),
3448            Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
3449        );
3450
3451        // Generate the proof for the first key and reveal it in the sparse trie
3452        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks, branch_node_tree_masks) =
3453            run_hash_builder(
3454                [(key1(), value()), (key2(), value())],
3455                NoopAccountTrieCursor::default(),
3456                Default::default(),
3457                [key1()],
3458            );
3459        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
3460            let hash_mask = branch_node_hash_masks.get(&path).copied();
3461            let tree_mask = branch_node_tree_masks.get(&path).copied();
3462            sparse
3463                .reveal_node(
3464                    path,
3465                    TrieNode::decode(&mut &node[..]).unwrap(),
3466                    TrieMasks { hash_mask, tree_mask },
3467                )
3468                .unwrap();
3469        }
3470
3471        // Check that the branch node wasn't overwritten by the extension node in the proof
3472        assert_matches!(
3473            sparse.nodes.get(&Nibbles::default()),
3474            Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
3475        );
3476    }
3477
3478    #[test]
3479    fn sparse_trie_get_changed_nodes_at_depth() {
3480        let provider = DefaultTrieNodeProvider;
3481        let mut sparse = SerialSparseTrie::default();
3482
3483        let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3484
3485        // Extension (Key = 5) – Level 0
3486        // └── Branch (Mask = 1011) – Level 1
3487        //     ├── 0 -> Extension (Key = 23) – Level 2
3488        //     │        └── Branch (Mask = 0101) – Level 3
3489        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231) – Level 4
3490        //     │              └── 3 -> Leaf (Key = 3, Path = 50233) – Level 4
3491        //     ├── 2 -> Leaf (Key = 013, Path = 52013) – Level 2
3492        //     └── 3 -> Branch (Mask = 0101) – Level 2
3493        //                ├── 1 -> Leaf (Key = 3102, Path = 53102) – Level 3
3494        //                └── 3 -> Branch (Mask = 1010) – Level 3
3495        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4
3496        //                       └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4
3497        sparse
3498            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3499            .unwrap();
3500        sparse
3501            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3502            .unwrap();
3503        sparse
3504            .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3505            .unwrap();
3506        sparse
3507            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
3508            .unwrap();
3509        sparse
3510            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
3511            .unwrap();
3512        sparse
3513            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
3514            .unwrap();
3515
3516        assert_eq!(
3517            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 0),
3518            (vec![(0, Nibbles::default())], PrefixSetMut::default())
3519        );
3520        assert_eq!(
3521            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 1),
3522            (vec![(1, Nibbles::from_nibbles_unchecked([0x5]))], [Nibbles::default()].into())
3523        );
3524        assert_eq!(
3525            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 2),
3526            (
3527                vec![
3528                    (2, Nibbles::from_nibbles_unchecked([0x5, 0x0])),
3529                    (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3530                    (2, Nibbles::from_nibbles_unchecked([0x5, 0x3]))
3531                ],
3532                [Nibbles::default(), Nibbles::from_nibbles_unchecked([0x5])].into()
3533            )
3534        );
3535        assert_eq!(
3536            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 3),
3537            (
3538                vec![
3539                    (3, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3])),
3540                    (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3541                    (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1])),
3542                    (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3]))
3543                ],
3544                [
3545                    Nibbles::default(),
3546                    Nibbles::from_nibbles_unchecked([0x5]),
3547                    Nibbles::from_nibbles_unchecked([0x5, 0x0]),
3548                    Nibbles::from_nibbles_unchecked([0x5, 0x3])
3549                ]
3550                .into()
3551            )
3552        );
3553        assert_eq!(
3554            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 4),
3555            (
3556                vec![
3557                    (4, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x1])),
3558                    (4, Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x3])),
3559                    (2, Nibbles::from_nibbles_unchecked([0x5, 0x2])),
3560                    (3, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1])),
3561                    (4, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x0])),
3562                    (4, Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x2]))
3563                ],
3564                [
3565                    Nibbles::default(),
3566                    Nibbles::from_nibbles_unchecked([0x5]),
3567                    Nibbles::from_nibbles_unchecked([0x5, 0x0]),
3568                    Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3]),
3569                    Nibbles::from_nibbles_unchecked([0x5, 0x3]),
3570                    Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3])
3571                ]
3572                .into()
3573            )
3574        );
3575    }
3576
3577    #[test]
3578    fn hash_builder_branch_hash_mask() {
3579        let key1 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x00]));
3580        let key2 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x01]));
3581        let value = || Account { bytecode_hash: Some(B256::repeat_byte(1)), ..Default::default() };
3582        let value_encoded = || {
3583            let mut account_rlp = Vec::new();
3584            value().into_trie_account(EMPTY_ROOT_HASH).encode(&mut account_rlp);
3585            account_rlp
3586        };
3587
3588        let (hash_builder_root, hash_builder_updates, _, _, _) = run_hash_builder(
3589            [(key1(), value()), (key2(), value())],
3590            NoopAccountTrieCursor::default(),
3591            Default::default(),
3592            [Nibbles::default()],
3593        );
3594
3595        let provider = DefaultTrieNodeProvider;
3596        let mut sparse = SerialSparseTrie::default();
3597        sparse.update_leaf(key1(), value_encoded(), &provider).unwrap();
3598        sparse.update_leaf(key2(), value_encoded(), &provider).unwrap();
3599        let sparse_root = sparse.root();
3600        let sparse_updates = sparse.take_updates();
3601
3602        assert_eq!(sparse_root, hash_builder_root);
3603        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
3604    }
3605
3606    #[test]
3607    fn sparse_trie_wipe() {
3608        let provider = DefaultTrieNodeProvider;
3609        let mut sparse = SerialSparseTrie::default().with_updates(true);
3610
3611        let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3612
3613        // Extension (Key = 5) – Level 0
3614        // └── Branch (Mask = 1011) – Level 1
3615        //     ├── 0 -> Extension (Key = 23) – Level 2
3616        //     │        └── Branch (Mask = 0101) – Level 3
3617        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231) – Level 4
3618        //     │              └── 3 -> Leaf (Key = 3, Path = 50233) – Level 4
3619        //     ├── 2 -> Leaf (Key = 013, Path = 52013) – Level 2
3620        //     └── 3 -> Branch (Mask = 0101) – Level 2
3621        //                ├── 1 -> Leaf (Key = 3102, Path = 53102) – Level 3
3622        //                └── 3 -> Branch (Mask = 1010) – Level 3
3623        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4
3624        //                       └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4
3625        sparse
3626            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3627            .unwrap();
3628        sparse
3629            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3630            .unwrap();
3631        sparse
3632            .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3633            .unwrap();
3634        sparse
3635            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
3636            .unwrap();
3637        sparse
3638            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
3639            .unwrap();
3640        sparse
3641            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
3642            .unwrap();
3643
3644        sparse.wipe();
3645
3646        assert_matches!(
3647            &sparse.updates,
3648            Some(SparseTrieUpdates{ updated_nodes, removed_nodes, wiped })
3649            if updated_nodes.is_empty() && removed_nodes.is_empty() && *wiped
3650        );
3651        assert_eq!(sparse.root(), EMPTY_ROOT_HASH);
3652    }
3653
3654    #[test]
3655    fn sparse_trie_clear() {
3656        // tests that if we fill a sparse trie with some nodes and then clear it, it has the same
3657        // contents as an empty sparse trie
3658        let provider = DefaultTrieNodeProvider;
3659        let mut sparse = SerialSparseTrie::default();
3660        let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3661        sparse
3662            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3663            .unwrap();
3664        sparse
3665            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3666            .unwrap();
3667        sparse
3668            .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3669            .unwrap();
3670        sparse
3671            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value, &provider)
3672            .unwrap();
3673
3674        sparse.clear();
3675
3676        let empty_trie = SerialSparseTrie::default();
3677        assert_eq!(empty_trie, sparse);
3678    }
3679
3680    #[test]
3681    fn sparse_trie_display() {
3682        let provider = DefaultTrieNodeProvider;
3683        let mut sparse = SerialSparseTrie::default();
3684
3685        let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
3686
3687        // Extension (Key = 5) – Level 0
3688        // └── Branch (Mask = 1011) – Level 1
3689        //     ├── 0 -> Extension (Key = 23) – Level 2
3690        //     │        └── Branch (Mask = 0101) – Level 3
3691        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231) – Level 4
3692        //     │              └── 3 -> Leaf (Key = 3, Path = 50233) – Level 4
3693        //     ├── 2 -> Leaf (Key = 013, Path = 52013) – Level 2
3694        //     └── 3 -> Branch (Mask = 0101) – Level 2
3695        //                ├── 1 -> Leaf (Key = 3102, Path = 53102) – Level 3
3696        //                └── 3 -> Branch (Mask = 1010) – Level 3
3697        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4
3698        //                       └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4
3699        sparse
3700            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider)
3701            .unwrap();
3702        sparse
3703            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider)
3704            .unwrap();
3705        sparse
3706            .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider)
3707            .unwrap();
3708        sparse
3709            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider)
3710            .unwrap();
3711        sparse
3712            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider)
3713            .unwrap();
3714        sparse
3715            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider)
3716            .unwrap();
3717
3718        let normal_printed = format!("{sparse}");
3719        let expected = "\
3720Root -> Extension { key: Nibbles(0x5), hash: None, store_in_db_trie: None }
37215 -> Branch { state_mask: TrieMask(0000000000001101), hash: None, store_in_db_trie: None }
372250 -> Extension { key: Nibbles(0x23), hash: None, store_in_db_trie: None }
37235023 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
372450231 -> Leaf { key: Nibbles(0x), hash: None }
372550233 -> Leaf { key: Nibbles(0x), hash: None }
372652013 -> Leaf { key: Nibbles(0x013), hash: None }
372753 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
372853102 -> Leaf { key: Nibbles(0x02), hash: None }
3729533 -> Branch { state_mask: TrieMask(0000000000000101), hash: None, store_in_db_trie: None }
373053302 -> Leaf { key: Nibbles(0x2), hash: None }
373153320 -> Leaf { key: Nibbles(0x0), hash: None }
3732";
3733        assert_eq!(normal_printed, expected);
3734
3735        let alternate_printed = format!("{sparse:#}");
3736        let expected = "\
3737Root -> Extension { key: Nibbles(0x5), hash: None, store_in_db_trie: None }
3738    5 -> Branch { state_mask: TrieMask(0000000000001101), hash: None, store_in_db_trie: None }
3739        50 -> Extension { key: Nibbles(0x23), hash: None, store_in_db_trie: None }
3740            5023 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
3741                50231 -> Leaf { key: Nibbles(0x), hash: None }
3742                50233 -> Leaf { key: Nibbles(0x), hash: None }
3743        52013 -> Leaf { key: Nibbles(0x013), hash: None }
3744        53 -> Branch { state_mask: TrieMask(0000000000001010), hash: None, store_in_db_trie: None }
3745            53102 -> Leaf { key: Nibbles(0x02), hash: None }
3746            533 -> Branch { state_mask: TrieMask(0000000000000101), hash: None, store_in_db_trie: None }
3747                53302 -> Leaf { key: Nibbles(0x2), hash: None }
3748                53320 -> Leaf { key: Nibbles(0x0), hash: None }
3749";
3750
3751        assert_eq!(alternate_printed, expected);
3752    }
3753}