Skip to main content

miden_crypto/merkle/smt/full/
mod.rs

1use alloc::{string::ToString, vec::Vec};
2
3use super::{
4    EMPTY_WORD, EmptySubtreeRoots, InnerNode, InnerNodeInfo, InnerNodes, LeafIndex, MerkleError,
5    MutationSet, NodeIndex, SparseMerklePath, SparseMerkleTree, SparseMerkleTreeReader, Word,
6};
7
8mod error;
9pub use error::{SmtLeafError, SmtProofError};
10
11mod leaf;
12pub use leaf::SmtLeaf;
13
14mod proof;
15pub use proof::SmtProof;
16
17use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
18
19// Concurrent implementation
20#[cfg(feature = "concurrent")]
21pub(in crate::merkle::smt) mod concurrent;
22
23#[cfg(test)]
24mod tests;
25
26// CONSTANTS
27// ================================================================================================
28
29/// The depth of the sparse Merkle tree.
30///
31/// All leaves in this SMT are located at depth 64.
32pub const SMT_DEPTH: u8 = 64;
33
34/// The maximum number of entries allowed in a multiple leaf.
35pub const MAX_LEAF_ENTRIES: usize = 1024;
36
37// SMT
38// ================================================================================================
39
40type Leaves = super::Leaves<SmtLeaf>;
41
42/// Sparse Merkle tree mapping 256-bit keys to 256-bit values. Both keys and values are represented
43/// by 4 field elements.
44///
45/// All leaves sit at depth 64. The most significant element of the key is used to identify the leaf
46/// to which the key maps.
47///
48/// A leaf is either empty, or holds one or more key-value pairs. An empty leaf hashes to the empty
49/// word. Otherwise, a leaf hashes to the hash of its key-value pairs, ordered by key first, value
50/// second.
51///
52/// ```text
53/// depth
54/// T  0                  Root
55/// │  .                  /  \
56/// │  1              left   right
57/// │  .             /  \    /  \
58/// │
59/// │          .. .. .. .. .. .. .. ..
60/// │
61/// │  63
62/// │           /  \        /   \           \
63/// │  ↓       /    \      /     \           \
64/// │  64   Leaf₀  Leaf₁  Leaf₂  Leaf₃  ...  Leaf₂⁶⁴₋₂³²
65///        0x0..0 0x0..1 0x0..2 0x0..3      0xFFFFFFFF00000000
66///
67/// The digest is 256 bits, or 4 field elements:
68/// [elem₀, elem₁, elem₂, elem₃]
69///                         ↑
70///         Most significant element determines leaf
71///         index, mapping into the actual Leaf lookup
72///         table where the values are stored.
73///
74/// Zooming into a leaf, i.e. Leaf₁:
75/// ┌─────────────────────────────────────────────────┐
76/// │            Leaf₁ (index: 0x0..1)                │
77/// ├─────────────────────────────────────────────────┤
78/// │ Possible states:                                │
79/// │                                                 │
80/// │ 1. Empty leaf:                                  │
81/// │    └─ hash = EMPTY_WORD                         │
82/// │                                                 │
83/// │ 2. Single entry:                                │
84/// │    └─ (key₁, value₁)                            │
85/// │    └─ hash = H(key₁, value₁)                    │
86/// │                                                 │
87/// │ 3. Multiple entries:                            │
88/// │    └─ (key₁, value₁)                            │
89/// │    └─ (key₂, value₂)                            │
90/// │    └─ ...                                       │
91/// │    └─ hash = H(key₁, value₁, key₂, value₂, ...) │
92/// └─────────────────────────────────────────────────┘
93///
94/// Leaf states:
95/// - Empty: hashes to EMPTY_WORD
96/// - Non-empty: contains (key, value) pairs
97///              hash = H(key₁, value₁, key₂, value₂, ...)
98/// ```
99#[derive(Debug, Clone, PartialEq, Eq)]
100#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
101pub struct Smt {
102    root: Word,
103    num_entries: usize,
104    leaves: Leaves,
105    inner_nodes: InnerNodes,
106}
107
108impl Smt {
109    // CONSTANTS
110    // --------------------------------------------------------------------------------------------
111    /// The default value used to compute the hash of empty leaves
112    pub const EMPTY_VALUE: Word = <Self as SparseMerkleTreeReader<SMT_DEPTH>>::EMPTY_VALUE;
113
114    // CONSTRUCTORS
115    // --------------------------------------------------------------------------------------------
116
117    /// Returns a new [Smt].
118    ///
119    /// All leaves in the returned tree are set to [Self::EMPTY_VALUE].
120    pub fn new() -> Self {
121        let root = *EmptySubtreeRoots::entry(SMT_DEPTH, 0);
122
123        Self {
124            root,
125            num_entries: 0,
126            inner_nodes: Default::default(),
127            leaves: Default::default(),
128        }
129    }
130
131    /// Returns a new [Smt] instantiated with leaves set as specified by the provided entries.
132    ///
133    /// If the `concurrent` feature is enabled, this function uses a parallel implementation to
134    /// process the entries efficiently, otherwise it defaults to the sequential implementation.
135    ///
136    /// All leaves omitted from the entries list are set to [Self::EMPTY_VALUE].
137    ///
138    /// # Errors
139    /// Returns an error if:
140    /// - the provided entries contain multiple values for the same key.
141    /// - inserting a key-value pair would exceed [`MAX_LEAF_ENTRIES`] (1024 entries) in a leaf.
142    pub fn with_entries(
143        entries: impl IntoIterator<Item = (Word, Word)>,
144    ) -> Result<Self, MerkleError> {
145        #[cfg(feature = "concurrent")]
146        {
147            Self::with_entries_concurrent(entries)
148        }
149        #[cfg(not(feature = "concurrent"))]
150        {
151            Self::with_entries_sequential(entries)
152        }
153    }
154
155    /// Similar to [`Self::with_entries`] but avoids the overhead of sorting if the entries are
156    /// already sorted by leaf index.
157    ///
158    /// This only applies if the "concurrent" feature is enabled. Without the feature, the behavior
159    /// is equivalent to [`Self::with_entries`].
160    ///
161    /// When the "concurrent" feature is enabled, entries must be sorted by
162    /// `LeafIndex::<SMT_DEPTH>::from(key).position()`, not by key.
163    ///
164    /// # Examples
165    ///
166    /// ```
167    /// use miden_crypto::{
168    ///     Felt, Word,
169    ///     merkle::smt::{LeafIndex, SMT_DEPTH, Smt},
170    /// };
171    ///
172    /// fn word(a: u64, b: u64, c: u64, d: u64) -> Word {
173    ///     Word::new([
174    ///         Felt::new_unchecked(a),
175    ///         Felt::new_unchecked(b),
176    ///         Felt::new_unchecked(c),
177    ///         Felt::new_unchecked(d),
178    ///     ])
179    /// }
180    ///
181    /// let mut entries = vec![
182    ///     (word(1, 0, 0, 3), word(10, 0, 0, 0)),
183    ///     (word(0, 0, 0, 1), word(20, 0, 0, 0)),
184    ///     (word(0, 1, 0, 2), word(30, 0, 0, 0)),
185    /// ];
186    ///
187    /// let expected = Smt::with_entries(entries.clone()).unwrap();
188    /// entries.sort_by_key(|(key, _)| LeafIndex::<SMT_DEPTH>::from(*key).position());
189    /// let actual = Smt::with_sorted_entries(entries).unwrap();
190    ///
191    /// assert_eq!(actual, expected);
192    /// ```
193    ///
194    /// # Errors
195    /// Returns an error if inserting a key-value pair would exceed [`MAX_LEAF_ENTRIES`] (1024
196    /// entries) in a leaf.
197    pub fn with_sorted_entries(
198        entries: impl IntoIterator<Item = (Word, Word)>,
199    ) -> Result<Self, MerkleError> {
200        #[cfg(feature = "concurrent")]
201        {
202            Self::with_sorted_entries_concurrent(entries)
203        }
204        #[cfg(not(feature = "concurrent"))]
205        {
206            Self::with_entries_sequential(entries)
207        }
208    }
209
210    /// Returns a new [Smt] instantiated with leaves set as specified by the provided entries.
211    ///
212    /// This sequential implementation processes entries one at a time to build the tree.
213    /// All leaves omitted from the entries list are set to [Self::EMPTY_VALUE].
214    ///
215    /// # Errors
216    /// Returns an error if:
217    /// - the provided entries contain multiple values for the same key.
218    /// - inserting a key-value pair would exceed [`MAX_LEAF_ENTRIES`] (1024 entries) in a leaf.
219    #[cfg(any(not(feature = "concurrent"), fuzzing, feature = "fuzzing", test))]
220    fn with_entries_sequential(
221        entries: impl IntoIterator<Item = (Word, Word)>,
222    ) -> Result<Self, MerkleError> {
223        use alloc::collections::BTreeSet;
224
225        // create an empty tree
226        let mut tree = Self::new();
227
228        // This being a sparse data structure, the EMPTY_WORD is not assigned to the `BTreeMap`, so
229        // entries with the empty value need additional tracking.
230        let mut key_set_to_zero = BTreeSet::new();
231
232        for (key, value) in entries {
233            let old_value = tree.insert(key, value)?;
234
235            if old_value != EMPTY_WORD || key_set_to_zero.contains(&key) {
236                return Err(MerkleError::DuplicateValuesForIndex(
237                    LeafIndex::<SMT_DEPTH>::from(key).position(),
238                ));
239            }
240
241            if value == EMPTY_WORD {
242                key_set_to_zero.insert(key);
243            };
244        }
245        Ok(tree)
246    }
247
248    /// Returns a new [`Smt`] instantiated from already computed leaves and nodes.
249    ///
250    /// This function performs minimal consistency checking. It is the caller's responsibility to
251    /// ensure the passed arguments are correct and consistent with each other.
252    ///
253    /// # Panics
254    /// With debug assertions on, this function panics if `root` does not match the root node in
255    /// `inner_nodes`.
256    pub fn from_raw_parts(inner_nodes: InnerNodes, leaves: Leaves, root: Word) -> Self {
257        if cfg!(debug_assertions) {
258            let root_node_hash = inner_nodes
259                .get(&NodeIndex::root())
260                .map(InnerNode::hash)
261                .unwrap_or(Self::EMPTY_ROOT);
262
263            assert_eq!(root_node_hash, root);
264        }
265        let num_entries = leaves.values().map(SmtLeaf::num_entries).sum();
266        Self { root, inner_nodes, leaves, num_entries }
267    }
268
269    // PUBLIC ACCESSORS
270    // --------------------------------------------------------------------------------------------
271
272    /// Returns the depth of the tree
273    pub const fn depth(&self) -> u8 {
274        SMT_DEPTH
275    }
276
277    /// Returns the root of the tree
278    pub fn root(&self) -> Word {
279        <Self as SparseMerkleTreeReader<SMT_DEPTH>>::root(self)
280    }
281
282    /// Returns the number of non-empty leaves in this tree.
283    ///
284    /// Note that this may return a different value from [Self::num_entries()] as a single leaf may
285    /// contain more than one key-value pair.
286    pub fn num_leaves(&self) -> usize {
287        self.leaves.len()
288    }
289
290    /// Returns the number of key-value pairs with non-default values in this tree.
291    ///
292    /// Note that this may return a different value from [Self::num_leaves()] as a single leaf may
293    /// contain more than one key-value pair.
294    pub fn num_entries(&self) -> usize {
295        self.num_entries
296    }
297
298    /// Returns the leaf to which `key` maps
299    pub fn get_leaf(&self, key: &Word) -> SmtLeaf {
300        <Self as SparseMerkleTreeReader<SMT_DEPTH>>::get_leaf(self, key)
301    }
302
303    /// Returns the leaf corresponding to the provided `index`.
304    pub fn get_leaf_by_index(&self, index: LeafIndex<SMT_DEPTH>) -> Option<SmtLeaf> {
305        self.leaves.get(&index.position()).cloned()
306    }
307
308    /// Returns the value associated with `key`
309    pub fn get_value(&self, key: &Word) -> Word {
310        <Self as SparseMerkleTreeReader<SMT_DEPTH>>::get_value(self, key)
311    }
312
313    /// Returns an opening of the leaf associated with `key`. Conceptually, an opening is a Merkle
314    /// path to the leaf, as well as the leaf itself.
315    pub fn open(&self, key: &Word) -> SmtProof {
316        <Self as SparseMerkleTreeReader<SMT_DEPTH>>::open(self, key)
317    }
318
319    /// Returns a boolean value indicating whether the SMT is empty.
320    pub fn is_empty(&self) -> bool {
321        debug_assert_eq!(self.leaves.is_empty(), self.root == Self::EMPTY_ROOT);
322        self.root == Self::EMPTY_ROOT
323    }
324
325    // ITERATORS
326    // --------------------------------------------------------------------------------------------
327
328    /// Returns an iterator over the leaves of this [`Smt`] in arbitrary order.
329    pub fn leaves(&self) -> impl Iterator<Item = (LeafIndex<SMT_DEPTH>, &SmtLeaf)> {
330        self.leaves
331            .iter()
332            .map(|(leaf_index, leaf)| (LeafIndex::new_max_depth(*leaf_index), leaf))
333    }
334
335    /// Returns an iterator over the key-value pairs of this [Smt] in arbitrary order.
336    pub fn entries(&self) -> impl Iterator<Item = &(Word, Word)> {
337        self.leaves().flat_map(|(_, leaf)| leaf.entries())
338    }
339
340    /// Returns an iterator over the inner nodes of this [Smt].
341    pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
342        self.inner_nodes.values().map(|e| InnerNodeInfo {
343            value: e.hash(),
344            left: e.left,
345            right: e.right,
346        })
347    }
348
349    /// Returns an iterator over the [`InnerNode`] and the respective [`NodeIndex`] of the [`Smt`].
350    pub fn inner_node_indices(&self) -> impl Iterator<Item = (NodeIndex, InnerNode)> + '_ {
351        self.inner_nodes.iter().map(|(idx, inner)| (*idx, inner.clone()))
352    }
353
354    // STATE MUTATORS
355    // --------------------------------------------------------------------------------------------
356
357    /// Inserts a value at the specified key, returning the previous value associated with that key.
358    /// Recall that by definition, any key that hasn't been updated is associated with
359    /// [`Self::EMPTY_VALUE`].
360    ///
361    /// This also recomputes all hashes between the leaf (associated with the key) and the root,
362    /// updating the root itself.
363    ///
364    /// # Errors
365    /// Returns an error if inserting the key-value pair would exceed [`MAX_LEAF_ENTRIES`] (1024
366    /// entries) in the leaf.
367    pub fn insert(&mut self, key: Word, value: Word) -> Result<Word, MerkleError> {
368        <Self as SparseMerkleTree<SMT_DEPTH>>::insert(self, key, value)
369    }
370
371    /// Computes what changes are necessary to insert the specified key-value pairs into this Merkle
372    /// tree, allowing for validation before applying those changes.
373    ///
374    /// This method returns a [`MutationSet`], which contains all the information for inserting
375    /// `kv_pairs` into this Merkle tree already calculated, including the new root hash, which can
376    /// be queried with [`MutationSet::root()`]. Once a mutation set is returned,
377    /// [`Smt::apply_mutations()`] can be called in order to commit these changes to the Merkle
378    /// tree, or [`drop()`] to discard them.
379    ///
380    /// # Errors
381    ///
382    /// - [`MerkleError::DuplicateValuesForIndex`] if `kv_pairs` contains the same key more than
383    ///   once.
384    /// - [`MerkleError::TooManyLeafEntries`] if mutations would exceed 1024 entries in a leaf.
385    ///
386    /// # Example
387    ///
388    /// ```
389    /// # use miden_crypto::{Felt, Word};
390    /// # use miden_crypto::merkle::{EmptySubtreeRoots, smt::{Smt, SMT_DEPTH}};
391    /// let mut smt = Smt::new();
392    /// let pair = (Word::default(), Word::default());
393    /// let mutations = smt.compute_mutations(vec![pair]).unwrap();
394    /// assert_eq!(mutations.root(), *EmptySubtreeRoots::entry(SMT_DEPTH, 0));
395    /// smt.apply_mutations(mutations).unwrap();
396    /// assert_eq!(smt.root(), *EmptySubtreeRoots::entry(SMT_DEPTH, 0));
397    /// ```
398    pub fn compute_mutations(
399        &self,
400        kv_pairs: impl IntoIterator<Item = (Word, Word)>,
401    ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, MerkleError> {
402        #[cfg(feature = "concurrent")]
403        {
404            self.compute_mutations_concurrent(kv_pairs)
405        }
406        #[cfg(not(feature = "concurrent"))]
407        {
408            <Self as SparseMerkleTreeReader<SMT_DEPTH>>::compute_mutations(self, kv_pairs)
409        }
410    }
411
412    /// Applies the prospective mutations computed with [`Smt::compute_mutations()`] to this tree.
413    ///
414    /// # Errors
415    /// If `mutations` was computed on a tree with a different root than this one, returns
416    /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
417    /// the `mutations` were computed against, and the second item is the actual current root of
418    /// this tree.
419    pub fn apply_mutations(
420        &mut self,
421        mutations: MutationSet<SMT_DEPTH, Word, Word>,
422    ) -> Result<(), MerkleError> {
423        <Self as SparseMerkleTree<SMT_DEPTH>>::apply_mutations(self, mutations)
424    }
425
426    /// Applies the prospective mutations computed with [`Smt::compute_mutations()`] to this tree
427    /// and returns the reverse mutation set.
428    ///
429    /// Applying the reverse mutation sets to the updated tree will revert the changes.
430    ///
431    /// # Errors
432    /// If `mutations` was computed on a tree with a different root than this one, returns
433    /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
434    /// the `mutations` were computed against, and the second item is the actual current root of
435    /// this tree.
436    pub fn apply_mutations_with_reversion(
437        &mut self,
438        mutations: MutationSet<SMT_DEPTH, Word, Word>,
439    ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, MerkleError> {
440        <Self as SparseMerkleTree<SMT_DEPTH>>::apply_mutations_with_reversion(self, mutations)
441    }
442
443    // HELPERS
444    // --------------------------------------------------------------------------------------------
445
446    /// Inserts `value` at leaf index pointed to by `key`. `value` is guaranteed to not be the empty
447    /// value, such that this is indeed an insertion.
448    ///
449    /// # Errors
450    /// Returns an error if inserting the key-value pair would exceed [`MAX_LEAF_ENTRIES`] (1024
451    /// entries) in the leaf.
452    fn perform_insert(&mut self, key: Word, value: Word) -> Result<Option<Word>, MerkleError> {
453        debug_assert_ne!(value, Self::EMPTY_VALUE);
454
455        let leaf_index: LeafIndex<SMT_DEPTH> = Self::key_to_leaf_index(&key);
456
457        match self.leaves.get_mut(&leaf_index.position()) {
458            Some(leaf) => {
459                let prev_entries = leaf.num_entries();
460                let result = leaf.insert(key, value).map_err(|e| match e {
461                    SmtLeafError::TooManyLeafEntries { actual } => {
462                        MerkleError::TooManyLeafEntries { actual }
463                    },
464                    other => panic!("unexpected SmtLeaf::insert error: {:?}", other),
465                })?;
466                let current_entries = leaf.num_entries();
467                self.num_entries += current_entries - prev_entries;
468                Ok(result)
469            },
470            None => {
471                self.leaves.insert(leaf_index.position(), SmtLeaf::Single((key, value)));
472                self.num_entries += 1;
473                Ok(None)
474            },
475        }
476    }
477
478    /// Removes key-value pair at leaf index pointed to by `key` if it exists.
479    fn perform_remove(&mut self, key: Word) -> Option<Word> {
480        let leaf_index: LeafIndex<SMT_DEPTH> = Self::key_to_leaf_index(&key);
481
482        if let Some(leaf) = self.leaves.get_mut(&leaf_index.position()) {
483            let prev_entries = leaf.num_entries();
484            let (old_value, is_empty) = leaf.remove(key);
485            let current_entries = leaf.num_entries();
486            self.num_entries -= prev_entries - current_entries;
487            if is_empty {
488                self.leaves.remove(&leaf_index.position());
489            }
490            old_value
491        } else {
492            // there's nothing stored at the leaf; nothing to update
493            None
494        }
495    }
496}
497
498impl SparseMerkleTreeReader<SMT_DEPTH> for Smt {
499    type Key = Word;
500    type Value = Word;
501    type Leaf = SmtLeaf;
502    type Opening = SmtProof;
503
504    const EMPTY_VALUE: Self::Value = EMPTY_WORD;
505    const EMPTY_ROOT: Word = *EmptySubtreeRoots::entry(SMT_DEPTH, 0);
506
507    fn root(&self) -> Word {
508        self.root
509    }
510
511    fn get_inner_node(&self, index: NodeIndex) -> InnerNode {
512        self.inner_nodes
513            .get(&index)
514            .cloned()
515            .unwrap_or_else(|| EmptySubtreeRoots::get_inner_node(SMT_DEPTH, index.depth()))
516    }
517
518    fn get_value(&self, key: &Self::Key) -> Self::Value {
519        let leaf_pos = LeafIndex::<SMT_DEPTH>::from(*key).position();
520
521        match self.leaves.get(&leaf_pos) {
522            Some(leaf) => leaf.get_value(key).unwrap_or_default(),
523            None => EMPTY_WORD,
524        }
525    }
526
527    fn get_leaf(&self, key: &Word) -> Self::Leaf {
528        let leaf_pos = LeafIndex::<SMT_DEPTH>::from(*key).position();
529
530        match self.leaves.get(&leaf_pos) {
531            Some(leaf) => leaf.clone(),
532            None => SmtLeaf::new_empty((*key).into()),
533        }
534    }
535
536    fn hash_leaf(leaf: &Self::Leaf) -> Word {
537        leaf.hash()
538    }
539
540    fn construct_prospective_leaf(
541        &self,
542        mut existing_leaf: SmtLeaf,
543        key: &Word,
544        value: &Word,
545    ) -> Result<SmtLeaf, SmtLeafError> {
546        debug_assert_eq!(existing_leaf.index(), Self::key_to_leaf_index(key));
547
548        match existing_leaf {
549            SmtLeaf::Empty(_) => Ok(SmtLeaf::new_single(*key, *value)),
550            _ => {
551                if *value != EMPTY_WORD {
552                    existing_leaf.insert(*key, *value)?;
553                } else {
554                    existing_leaf.remove(*key);
555                }
556
557                Ok(existing_leaf)
558            },
559        }
560    }
561
562    fn key_to_leaf_index(key: &Word) -> LeafIndex<SMT_DEPTH> {
563        let most_significant_felt = key[3];
564        LeafIndex::new_max_depth(most_significant_felt.as_canonical_u64())
565    }
566
567    fn path_and_leaf_to_opening(path: SparseMerklePath, leaf: SmtLeaf) -> SmtProof {
568        SmtProof::new_unchecked(path, leaf)
569    }
570}
571
572impl SparseMerkleTree<SMT_DEPTH> for Smt {
573    fn set_root(&mut self, root: Word) {
574        self.root = root;
575    }
576
577    fn insert_inner_node(&mut self, index: NodeIndex, inner_node: InnerNode) -> Option<InnerNode> {
578        if inner_node == EmptySubtreeRoots::get_inner_node(SMT_DEPTH, index.depth()) {
579            self.remove_inner_node(index)
580        } else {
581            self.inner_nodes.insert(index, inner_node)
582        }
583    }
584
585    fn remove_inner_node(&mut self, index: NodeIndex) -> Option<InnerNode> {
586        self.inner_nodes.remove(&index)
587    }
588
589    fn insert_value(
590        &mut self,
591        key: Self::Key,
592        value: Self::Value,
593    ) -> Result<Option<Self::Value>, MerkleError> {
594        // inserting an `EMPTY_VALUE` is equivalent to removing any value associated with `key`
595        if value != Self::EMPTY_VALUE {
596            self.perform_insert(key, value)
597        } else {
598            Ok(self.perform_remove(key))
599        }
600    }
601}
602
603impl Default for Smt {
604    fn default() -> Self {
605        Self::new()
606    }
607}
608
609// CONVERSIONS
610// ================================================================================================
611
612impl From<Word> for LeafIndex<SMT_DEPTH> {
613    fn from(value: Word) -> Self {
614        // We use the most significant `Felt` of a `Word` as the leaf index.
615        Self::new_max_depth(value[3].as_canonical_u64())
616    }
617}
618
619// SERIALIZATION
620// ================================================================================================
621
622impl Serializable for Smt {
623    fn write_into<W: ByteWriter>(&self, target: &mut W) {
624        // Write the number of filled leaves for this Smt
625        target.write_usize(self.entries().count());
626
627        // Write each (key, value) pair
628        for (key, value) in self.entries() {
629            target.write(key);
630            target.write(value);
631        }
632    }
633
634    fn get_size_hint(&self) -> usize {
635        let entries_count = self.entries().count();
636
637        // Each entry is the size of a digest plus a word.
638        entries_count.get_size_hint()
639            + entries_count * (Word::SERIALIZED_SIZE + EMPTY_WORD.get_size_hint())
640    }
641}
642
643impl Deserializable for Smt {
644    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
645        // Read the number of filled leaves for this Smt
646        let num_filled_leaves = source.read_usize()?;
647
648        // Use read_many_iter to avoid eager allocation and respect BudgetedReader limits
649        let entries: Vec<(Word, Word)> =
650            source.read_many_iter(num_filled_leaves)?.collect::<Result<_, _>>()?;
651
652        Self::with_entries(entries)
653            .map_err(|err| DeserializationError::InvalidValue(err.to_string()))
654    }
655
656    /// Minimum serialized size: vint64 length prefix (0 entries).
657    fn min_serialized_size() -> usize {
658        1
659    }
660}
661
662// FUZZING
663// ================================================================================================
664
665#[cfg(any(fuzzing, feature = "fuzzing"))]
666impl Smt {
667    pub fn fuzz_with_entries_sequential(
668        entries: impl IntoIterator<Item = (Word, Word)>,
669    ) -> Result<Smt, MerkleError> {
670        Self::with_entries_sequential(entries)
671    }
672
673    pub fn fuzz_compute_mutations_sequential(
674        &self,
675        kv_pairs: impl IntoIterator<Item = (Word, Word)>,
676    ) -> MutationSet<SMT_DEPTH, Word, Word> {
677        <Self as SparseMerkleTreeReader<SMT_DEPTH>>::compute_mutations(self, kv_pairs)
678            .expect("Failed to compute mutations in fuzzing")
679    }
680}
681
682// TESTS
683// ================================================================================================
684
685#[cfg(test)]
686use crate::Felt;
687
688#[test]
689fn test_smt_serialization_deserialization() {
690    // Smt for default types (empty map)
691    let smt_default = Smt::default();
692    let bytes = smt_default.to_bytes();
693    assert_eq!(smt_default, Smt::read_from_bytes(&bytes).unwrap());
694    assert_eq!(bytes.len(), smt_default.get_size_hint());
695
696    // Smt with values
697    let smt_leaves_2: [(Word, Word); 2] = [
698        (
699            Word::new([
700                Felt::new_unchecked(105),
701                Felt::new_unchecked(106),
702                Felt::new_unchecked(107),
703                Felt::new_unchecked(108),
704            ]),
705            [
706                Felt::new_unchecked(5_u64),
707                Felt::new_unchecked(6_u64),
708                Felt::new_unchecked(7_u64),
709                Felt::new_unchecked(8_u64),
710            ]
711            .into(),
712        ),
713        (
714            Word::new([
715                Felt::new_unchecked(101),
716                Felt::new_unchecked(102),
717                Felt::new_unchecked(103),
718                Felt::new_unchecked(104),
719            ]),
720            [
721                Felt::new_unchecked(1_u64),
722                Felt::new_unchecked(2_u64),
723                Felt::new_unchecked(3_u64),
724                Felt::new_unchecked(4_u64),
725            ]
726            .into(),
727        ),
728    ];
729    let smt = Smt::with_entries(smt_leaves_2).unwrap();
730
731    let bytes = smt.to_bytes();
732    assert_eq!(smt, Smt::read_from_bytes(&bytes).unwrap());
733    assert_eq!(bytes.len(), smt.get_size_hint());
734}
735
736#[test]
737fn smt_with_sorted_entries() {
738    // Smt with sorted values
739    let smt_leaves_2: [(Word, Word); 2] = [
740        (
741            Word::new([
742                Felt::new_unchecked(101),
743                Felt::new_unchecked(102),
744                Felt::new_unchecked(103),
745                Felt::new_unchecked(104),
746            ]),
747            [
748                Felt::new_unchecked(1_u64),
749                Felt::new_unchecked(2_u64),
750                Felt::new_unchecked(3_u64),
751                Felt::new_unchecked(4_u64),
752            ]
753            .into(),
754        ),
755        (
756            Word::new([
757                Felt::new_unchecked(105),
758                Felt::new_unchecked(106),
759                Felt::new_unchecked(107),
760                Felt::new_unchecked(108),
761            ]),
762            [
763                Felt::new_unchecked(5_u64),
764                Felt::new_unchecked(6_u64),
765                Felt::new_unchecked(7_u64),
766                Felt::new_unchecked(8_u64),
767            ]
768            .into(),
769        ),
770    ];
771
772    let smt = Smt::with_sorted_entries(smt_leaves_2).unwrap();
773    let expected_smt = Smt::with_entries(smt_leaves_2).unwrap();
774
775    assert_eq!(smt, expected_smt);
776}