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