miden_crypto/merkle/smt/full/
mod.rs

1use alloc::{
2    collections::{BTreeMap, BTreeSet},
3    string::ToString,
4    vec::Vec,
5};
6
7use super::{
8    EmptySubtreeRoots, Felt, InnerNode, InnerNodeInfo, LeafIndex, MerkleError, MerklePath,
9    MutationSet, NodeIndex, Rpo256, RpoDigest, SparseMerkleTree, Word, EMPTY_WORD,
10};
11
12mod error;
13pub use error::{SmtLeafError, SmtProofError};
14
15mod leaf;
16pub use leaf::SmtLeaf;
17
18mod proof;
19pub use proof::SmtProof;
20use winter_utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
21
22#[cfg(test)]
23mod tests;
24
25// CONSTANTS
26// ================================================================================================
27
28pub const SMT_DEPTH: u8 = 64;
29
30// SMT
31// ================================================================================================
32
33/// Sparse Merkle tree mapping 256-bit keys to 256-bit values. Both keys and values are represented
34/// by 4 field elements.
35///
36/// All leaves sit at depth 64. The most significant element of the key is used to identify the leaf
37/// to which the key maps.
38///
39/// A leaf is either empty, or holds one or more key-value pairs. An empty leaf hashes to the empty
40/// word. Otherwise, a leaf hashes to the hash of its key-value pairs, ordered by key first, value
41/// second.
42#[derive(Debug, Clone, PartialEq, Eq)]
43#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
44pub struct Smt {
45    root: RpoDigest,
46    // pub(super) for use in PartialSmt.
47    pub(super) leaves: BTreeMap<u64, SmtLeaf>,
48    inner_nodes: BTreeMap<NodeIndex, InnerNode>,
49}
50
51impl Smt {
52    // CONSTANTS
53    // --------------------------------------------------------------------------------------------
54    /// The default value used to compute the hash of empty leaves
55    pub const EMPTY_VALUE: Word = <Self as SparseMerkleTree<SMT_DEPTH>>::EMPTY_VALUE;
56
57    // CONSTRUCTORS
58    // --------------------------------------------------------------------------------------------
59
60    /// Returns a new [Smt].
61    ///
62    /// All leaves in the returned tree are set to [Self::EMPTY_VALUE].
63    pub fn new() -> Self {
64        let root = *EmptySubtreeRoots::entry(SMT_DEPTH, 0);
65
66        Self {
67            root,
68            leaves: BTreeMap::new(),
69            inner_nodes: BTreeMap::new(),
70        }
71    }
72
73    /// Returns a new [Smt] instantiated with leaves set as specified by the provided entries.
74    ///
75    /// All leaves omitted from the entries list are set to [Self::EMPTY_VALUE].
76    ///
77    /// # Errors
78    /// Returns an error if the provided entries contain multiple values for the same key.
79    pub fn with_entries(
80        entries: impl IntoIterator<Item = (RpoDigest, Word)>,
81    ) -> Result<Self, MerkleError> {
82        // create an empty tree
83        let mut tree = Self::new();
84
85        // This being a sparse data structure, the EMPTY_WORD is not assigned to the `BTreeMap`, so
86        // entries with the empty value need additional tracking.
87        let mut key_set_to_zero = BTreeSet::new();
88
89        for (key, value) in entries {
90            let old_value = tree.insert(key, value);
91
92            if old_value != EMPTY_WORD || key_set_to_zero.contains(&key) {
93                return Err(MerkleError::DuplicateValuesForIndex(
94                    LeafIndex::<SMT_DEPTH>::from(key).value(),
95                ));
96            }
97
98            if value == EMPTY_WORD {
99                key_set_to_zero.insert(key);
100            };
101        }
102        Ok(tree)
103    }
104
105    // PUBLIC ACCESSORS
106    // --------------------------------------------------------------------------------------------
107
108    /// Returns the depth of the tree
109    pub const fn depth(&self) -> u8 {
110        SMT_DEPTH
111    }
112
113    /// Returns the root of the tree
114    pub fn root(&self) -> RpoDigest {
115        <Self as SparseMerkleTree<SMT_DEPTH>>::root(self)
116    }
117
118    /// Returns the number of non-empty leaves in this tree.
119    pub fn num_leaves(&self) -> usize {
120        self.leaves.len()
121    }
122
123    /// Returns the leaf to which `key` maps
124    pub fn get_leaf(&self, key: &RpoDigest) -> SmtLeaf {
125        <Self as SparseMerkleTree<SMT_DEPTH>>::get_leaf(self, key)
126    }
127
128    /// Returns the value associated with `key`
129    pub fn get_value(&self, key: &RpoDigest) -> Word {
130        <Self as SparseMerkleTree<SMT_DEPTH>>::get_value(self, key)
131    }
132
133    /// Returns an opening of the leaf associated with `key`. Conceptually, an opening is a Merkle
134    /// path to the leaf, as well as the leaf itself.
135    pub fn open(&self, key: &RpoDigest) -> SmtProof {
136        <Self as SparseMerkleTree<SMT_DEPTH>>::open(self, key)
137    }
138
139    /// Returns a boolean value indicating whether the SMT is empty.
140    pub fn is_empty(&self) -> bool {
141        debug_assert_eq!(self.leaves.is_empty(), self.root == Self::EMPTY_ROOT);
142        self.root == Self::EMPTY_ROOT
143    }
144
145    // ITERATORS
146    // --------------------------------------------------------------------------------------------
147
148    /// Returns an iterator over the leaves of this [Smt].
149    pub fn leaves(&self) -> impl Iterator<Item = (LeafIndex<SMT_DEPTH>, &SmtLeaf)> {
150        self.leaves
151            .iter()
152            .map(|(leaf_index, leaf)| (LeafIndex::new_max_depth(*leaf_index), leaf))
153    }
154
155    /// Returns an iterator over the key-value pairs of this [Smt].
156    pub fn entries(&self) -> impl Iterator<Item = &(RpoDigest, Word)> {
157        self.leaves().flat_map(|(_, leaf)| leaf.entries())
158    }
159
160    /// Returns an iterator over the inner nodes of this [Smt].
161    pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
162        self.inner_nodes.values().map(|e| InnerNodeInfo {
163            value: e.hash(),
164            left: e.left,
165            right: e.right,
166        })
167    }
168
169    // STATE MUTATORS
170    // --------------------------------------------------------------------------------------------
171
172    /// Inserts a value at the specified key, returning the previous value associated with that key.
173    /// Recall that by definition, any key that hasn't been updated is associated with
174    /// [`Self::EMPTY_VALUE`].
175    ///
176    /// This also recomputes all hashes between the leaf (associated with the key) and the root,
177    /// updating the root itself.
178    pub fn insert(&mut self, key: RpoDigest, value: Word) -> Word {
179        <Self as SparseMerkleTree<SMT_DEPTH>>::insert(self, key, value)
180    }
181
182    /// Computes what changes are necessary to insert the specified key-value pairs into this Merkle
183    /// tree, allowing for validation before applying those changes.
184    ///
185    /// This method returns a [`MutationSet`], which contains all the information for inserting
186    /// `kv_pairs` into this Merkle tree already calculated, including the new root hash, which can
187    /// be queried with [`MutationSet::root()`]. Once a mutation set is returned,
188    /// [`Smt::apply_mutations()`] can be called in order to commit these changes to the Merkle
189    /// tree, or [`drop()`] to discard them.
190    ///
191    /// # Example
192    /// ```
193    /// # use miden_crypto::{hash::rpo::RpoDigest, Felt, Word};
194    /// # use miden_crypto::merkle::{Smt, EmptySubtreeRoots, SMT_DEPTH};
195    /// let mut smt = Smt::new();
196    /// let pair = (RpoDigest::default(), Word::default());
197    /// let mutations = smt.compute_mutations(vec![pair]);
198    /// assert_eq!(mutations.root(), *EmptySubtreeRoots::entry(SMT_DEPTH, 0));
199    /// smt.apply_mutations(mutations);
200    /// assert_eq!(smt.root(), *EmptySubtreeRoots::entry(SMT_DEPTH, 0));
201    /// ```
202    pub fn compute_mutations(
203        &self,
204        kv_pairs: impl IntoIterator<Item = (RpoDigest, Word)>,
205    ) -> MutationSet<SMT_DEPTH, RpoDigest, Word> {
206        <Self as SparseMerkleTree<SMT_DEPTH>>::compute_mutations(self, kv_pairs)
207    }
208
209    /// Applies the prospective mutations computed with [`Smt::compute_mutations()`] to this tree.
210    ///
211    /// # Errors
212    /// If `mutations` was computed on a tree with a different root than this one, returns
213    /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
214    /// the `mutations` were computed against, and the second item is the actual current root of
215    /// this tree.
216    pub fn apply_mutations(
217        &mut self,
218        mutations: MutationSet<SMT_DEPTH, RpoDigest, Word>,
219    ) -> Result<(), MerkleError> {
220        <Self as SparseMerkleTree<SMT_DEPTH>>::apply_mutations(self, mutations)
221    }
222
223    /// Applies the prospective mutations computed with [`Smt::compute_mutations()`] to this tree
224    /// and returns the reverse mutation set.
225    ///
226    /// Applying the reverse mutation sets to the updated tree will revert the changes.
227    ///
228    /// # Errors
229    /// If `mutations` was computed on a tree with a different root than this one, returns
230    /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
231    /// the `mutations` were computed against, and the second item is the actual current root of
232    /// this tree.
233    pub fn apply_mutations_with_reversion(
234        &mut self,
235        mutations: MutationSet<SMT_DEPTH, RpoDigest, Word>,
236    ) -> Result<MutationSet<SMT_DEPTH, RpoDigest, Word>, MerkleError> {
237        <Self as SparseMerkleTree<SMT_DEPTH>>::apply_mutations_with_reversion(self, mutations)
238    }
239
240    // HELPERS
241    // --------------------------------------------------------------------------------------------
242
243    /// Inserts `value` at leaf index pointed to by `key`. `value` is guaranteed to not be the empty
244    /// value, such that this is indeed an insertion.
245    fn perform_insert(&mut self, key: RpoDigest, value: Word) -> Option<Word> {
246        debug_assert_ne!(value, Self::EMPTY_VALUE);
247
248        let leaf_index: LeafIndex<SMT_DEPTH> = Self::key_to_leaf_index(&key);
249
250        match self.leaves.get_mut(&leaf_index.value()) {
251            Some(leaf) => leaf.insert(key, value),
252            None => {
253                self.leaves.insert(leaf_index.value(), SmtLeaf::Single((key, value)));
254
255                None
256            },
257        }
258    }
259
260    /// Removes key-value pair at leaf index pointed to by `key` if it exists.
261    fn perform_remove(&mut self, key: RpoDigest) -> Option<Word> {
262        let leaf_index: LeafIndex<SMT_DEPTH> = Self::key_to_leaf_index(&key);
263
264        if let Some(leaf) = self.leaves.get_mut(&leaf_index.value()) {
265            let (old_value, is_empty) = leaf.remove(key);
266            if is_empty {
267                self.leaves.remove(&leaf_index.value());
268            }
269            old_value
270        } else {
271            // there's nothing stored at the leaf; nothing to update
272            None
273        }
274    }
275}
276
277impl SparseMerkleTree<SMT_DEPTH> for Smt {
278    type Key = RpoDigest;
279    type Value = Word;
280    type Leaf = SmtLeaf;
281    type Opening = SmtProof;
282
283    const EMPTY_VALUE: Self::Value = EMPTY_WORD;
284    const EMPTY_ROOT: RpoDigest = *EmptySubtreeRoots::entry(SMT_DEPTH, 0);
285
286    fn root(&self) -> RpoDigest {
287        self.root
288    }
289
290    fn set_root(&mut self, root: RpoDigest) {
291        self.root = root;
292    }
293
294    fn get_inner_node(&self, index: NodeIndex) -> InnerNode {
295        self.inner_nodes
296            .get(&index)
297            .cloned()
298            .unwrap_or_else(|| EmptySubtreeRoots::get_inner_node(SMT_DEPTH, index.depth()))
299    }
300
301    fn insert_inner_node(&mut self, index: NodeIndex, inner_node: InnerNode) -> Option<InnerNode> {
302        self.inner_nodes.insert(index, inner_node)
303    }
304
305    fn remove_inner_node(&mut self, index: NodeIndex) -> Option<InnerNode> {
306        self.inner_nodes.remove(&index)
307    }
308
309    fn insert_value(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value> {
310        // inserting an `EMPTY_VALUE` is equivalent to removing any value associated with `key`
311        if value != Self::EMPTY_VALUE {
312            self.perform_insert(key, value)
313        } else {
314            self.perform_remove(key)
315        }
316    }
317
318    fn get_value(&self, key: &Self::Key) -> Self::Value {
319        let leaf_pos = LeafIndex::<SMT_DEPTH>::from(*key).value();
320
321        match self.leaves.get(&leaf_pos) {
322            Some(leaf) => leaf.get_value(key).unwrap_or_default(),
323            None => EMPTY_WORD,
324        }
325    }
326
327    fn get_leaf(&self, key: &RpoDigest) -> Self::Leaf {
328        let leaf_pos = LeafIndex::<SMT_DEPTH>::from(*key).value();
329
330        match self.leaves.get(&leaf_pos) {
331            Some(leaf) => leaf.clone(),
332            None => SmtLeaf::new_empty(key.into()),
333        }
334    }
335
336    fn hash_leaf(leaf: &Self::Leaf) -> RpoDigest {
337        leaf.hash()
338    }
339
340    fn construct_prospective_leaf(
341        &self,
342        mut existing_leaf: SmtLeaf,
343        key: &RpoDigest,
344        value: &Word,
345    ) -> SmtLeaf {
346        debug_assert_eq!(existing_leaf.index(), Self::key_to_leaf_index(key));
347
348        match existing_leaf {
349            SmtLeaf::Empty(_) => SmtLeaf::new_single(*key, *value),
350            _ => {
351                if *value != EMPTY_WORD {
352                    existing_leaf.insert(*key, *value);
353                } else {
354                    existing_leaf.remove(*key);
355                }
356
357                existing_leaf
358            },
359        }
360    }
361
362    fn key_to_leaf_index(key: &RpoDigest) -> LeafIndex<SMT_DEPTH> {
363        let most_significant_felt = key[3];
364        LeafIndex::new_max_depth(most_significant_felt.as_int())
365    }
366
367    fn path_and_leaf_to_opening(path: MerklePath, leaf: SmtLeaf) -> SmtProof {
368        SmtProof::new_unchecked(path, leaf)
369    }
370}
371
372impl Default for Smt {
373    fn default() -> Self {
374        Self::new()
375    }
376}
377
378// CONVERSIONS
379// ================================================================================================
380
381impl From<Word> for LeafIndex<SMT_DEPTH> {
382    fn from(value: Word) -> Self {
383        // We use the most significant `Felt` of a `Word` as the leaf index.
384        Self::new_max_depth(value[3].as_int())
385    }
386}
387
388impl From<RpoDigest> for LeafIndex<SMT_DEPTH> {
389    fn from(value: RpoDigest) -> Self {
390        Word::from(value).into()
391    }
392}
393
394impl From<&RpoDigest> for LeafIndex<SMT_DEPTH> {
395    fn from(value: &RpoDigest) -> Self {
396        Word::from(value).into()
397    }
398}
399
400// SERIALIZATION
401// ================================================================================================
402
403impl Serializable for Smt {
404    fn write_into<W: ByteWriter>(&self, target: &mut W) {
405        // Write the number of filled leaves for this Smt
406        target.write_usize(self.entries().count());
407
408        // Write each (key, value) pair
409        for (key, value) in self.entries() {
410            target.write(key);
411            target.write(value);
412        }
413    }
414
415    fn get_size_hint(&self) -> usize {
416        let entries_count = self.entries().count();
417
418        // Each entry is the size of a digest plus a word.
419        entries_count.get_size_hint()
420            + entries_count * (RpoDigest::SERIALIZED_SIZE + EMPTY_WORD.get_size_hint())
421    }
422}
423
424impl Deserializable for Smt {
425    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
426        // Read the number of filled leaves for this Smt
427        let num_filled_leaves = source.read_usize()?;
428        let mut entries = Vec::with_capacity(num_filled_leaves);
429
430        for _ in 0..num_filled_leaves {
431            let key = source.read()?;
432            let value = source.read()?;
433            entries.push((key, value));
434        }
435
436        Self::with_entries(entries)
437            .map_err(|err| DeserializationError::InvalidValue(err.to_string()))
438    }
439}
440
441// TESTS
442// ================================================================================================
443
444#[test]
445fn test_smt_serialization_deserialization() {
446    // Smt for default types (empty map)
447    let smt_default = Smt::default();
448    let bytes = smt_default.to_bytes();
449    assert_eq!(smt_default, Smt::read_from_bytes(&bytes).unwrap());
450    assert_eq!(bytes.len(), smt_default.get_size_hint());
451
452    // Smt with values
453    let smt_leaves_2: [(RpoDigest, Word); 2] = [
454        (
455            RpoDigest::new([Felt::new(101), Felt::new(102), Felt::new(103), Felt::new(104)]),
456            [Felt::new(1_u64), Felt::new(2_u64), Felt::new(3_u64), Felt::new(4_u64)],
457        ),
458        (
459            RpoDigest::new([Felt::new(105), Felt::new(106), Felt::new(107), Felt::new(108)]),
460            [Felt::new(5_u64), Felt::new(6_u64), Felt::new(7_u64), Felt::new(8_u64)],
461        ),
462    ];
463    let smt = Smt::with_entries(smt_leaves_2).unwrap();
464
465    let bytes = smt.to_bytes();
466    assert_eq!(smt, Smt::read_from_bytes(&bytes).unwrap());
467    assert_eq!(bytes.len(), smt.get_size_hint());
468}