reth_trie_sparse/
trie.rs

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