reth_trie_sparse/
trie.rs

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