Skip to main content

miden_crypto/merkle/mmr/
full.rs

1//! A fully materialized Merkle mountain range (MMR).
2//!
3//! A MMR is a forest structure, i.e. it is an ordered set of disjoint rooted trees. The trees are
4//! ordered by size, from the most to least number of leaves. Every tree is a perfect binary tree,
5//! meaning a tree has all its leaves at the same depth, and every inner node has a branch-factor
6//! of 2 with both children set.
7//!
8//! Additionally the structure only supports adding leaves to the right-most tree, the one with the
9//! least number of leaves. The structure preserves the invariant that each tree has different
10//! depths, i.e. as part of adding a new element to the forest the trees with same depth are
11//! merged, creating a new tree with depth d+1, this process is continued until the property is
12//! reestablished.
13use alloc::vec::Vec;
14
15use super::{
16    super::{InnerNodeInfo, MerklePath},
17    MmrDelta, MmrError, MmrPath, MmrPeaks, MmrProof,
18    forest::{Forest, TreeSizeIterator},
19    nodes_from_mask,
20};
21use crate::{
22    Word,
23    hash::poseidon2::Poseidon2,
24    utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
25};
26
27// MMR
28// ===============================================================================================
29
30/// A fully materialized Merkle Mountain Range, with every tree in the forest and all their
31/// elements.
32///
33/// Since this is a full representation of the MMR, elements are never removed and the MMR will
34/// grow roughly `O(2n)` in number of leaf elements.
35#[derive(Debug, Clone)]
36#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
37pub struct Mmr {
38    /// Refer to the `forest` method documentation for details of the semantics of this value.
39    pub(super) forest: Forest,
40
41    /// Contains every element of the forest.
42    ///
43    /// The trees are in postorder sequential representation. This representation allows for all
44    /// the elements of every tree in the forest to be stored in the same sequential buffer. It
45    /// also means new elements can be added to the forest, and merging of trees is very cheap with
46    /// no need to copy elements.
47    pub(super) nodes: Vec<Word>,
48}
49
50impl Default for Mmr {
51    fn default() -> Self {
52        Self::new()
53    }
54}
55
56impl Mmr {
57    // CONSTRUCTORS
58    // ============================================================================================
59
60    /// Constructor for an empty `Mmr`.
61    pub fn new() -> Mmr {
62        Mmr {
63            forest: Forest::empty(),
64            nodes: Vec::new(),
65        }
66    }
67
68    /// Constructs an MMR from an iterator of leaves.
69    ///
70    /// # Errors
71    /// Returns an error if the maximum forest size is exceeded.
72    pub fn try_from_iter<T: IntoIterator<Item = Word>>(values: T) -> Result<Self, MmrError> {
73        Self::try_from_iter_with_limit(values, Forest::MAX_LEAVES)
74    }
75
76    pub(crate) fn try_from_iter_with_limit<T: IntoIterator<Item = Word>>(
77        values: T,
78        max_leaves: usize,
79    ) -> Result<Self, MmrError> {
80        let mut mmr = Mmr::new();
81        let iter = values.into_iter();
82        let (lower, _) = iter.size_hint();
83        if lower > max_leaves {
84            return Err(MmrError::ForestSizeExceeded { requested: lower, max: max_leaves });
85        }
86        let mut count = 0usize;
87        for v in iter {
88            count += 1;
89            if count > max_leaves {
90                return Err(MmrError::ForestSizeExceeded { requested: count, max: max_leaves });
91            }
92            mmr.add(v)?;
93        }
94        Ok(mmr)
95    }
96
97    // ACCESSORS
98    // ============================================================================================
99
100    /// Returns the MMR forest representation. See [`Forest`].
101    pub const fn forest(&self) -> Forest {
102        self.forest
103    }
104
105    // FUNCTIONALITY
106    // ============================================================================================
107
108    /// Returns an [MmrProof] for the leaf at the specified position.
109    ///
110    /// Note: The leaf position is the 0-indexed number corresponding to the order the leaves were
111    /// added, this corresponds to the MMR size _prior_ to adding the element. So the 1st element
112    /// has position 0, the second position 1, and so on.
113    ///
114    /// # Errors
115    /// Returns an error if the specified leaf position is out of bounds for this MMR.
116    pub fn open(&self, pos: usize) -> Result<MmrProof, MmrError> {
117        self.open_at(pos, self.forest)
118    }
119
120    /// Returns an [MmrProof] for the leaf at the specified position using the state of the MMR
121    /// at the specified `forest`.
122    ///
123    /// Note: The leaf position is the 0-indexed number corresponding to the order the leaves were
124    /// added, this corresponds to the MMR size _prior_ to adding the element. So the 1st element
125    /// has position 0, the second position 1, and so on.
126    ///
127    /// # Errors
128    /// Returns an error if:
129    /// - The specified leaf position is out of bounds for this MMR.
130    /// - The specified `forest` value is not valid for this MMR.
131    pub fn open_at(&self, pos: usize, forest: Forest) -> Result<MmrProof, MmrError> {
132        if forest > self.forest {
133            return Err(MmrError::ForestOutOfBounds(forest.num_leaves(), self.forest.num_leaves()));
134        }
135        let (leaf, path) = self.collect_merkle_path_and_value(pos, forest)?;
136
137        let path = MmrPath::new(forest, pos, MerklePath::new(path));
138
139        Ok(MmrProof::new(path, leaf))
140    }
141
142    /// Returns the leaf value at position `pos`.
143    ///
144    /// Note: The leaf position is the 0-indexed number corresponding to the order the leaves were
145    /// added, this corresponds to the MMR size _prior_ to adding the element. So the 1st element
146    /// has position 0, the second position 1, and so on.
147    pub fn get(&self, pos: usize) -> Result<Word, MmrError> {
148        let (value, _) = self.collect_merkle_path_and_value(pos, self.forest)?;
149
150        Ok(value)
151    }
152
153    /// Adds a new element to the MMR.
154    ///
155    /// # Errors
156    /// Returns an error if the MMR exceeds the maximum supported forest size.
157    pub fn add(&mut self, el: Word) -> Result<(), MmrError> {
158        // Fail early before mutating nodes.
159        let old_forest = self.forest;
160        self.forest.append_leaf()?;
161        // Note: every node is also a tree of size 1, adding an element to the forest creates a new
162        // rooted-tree of size 1. This may temporarily break the invariant that every tree in the
163        // forest has different sizes, the loop below will eagerly merge trees of same size and
164        // restore the invariant.
165        self.nodes.push(el);
166
167        let mut left_offset = self.nodes.len().saturating_sub(2);
168        let mut right = el;
169        let mut left_tree = 1usize;
170        while (old_forest.num_leaves() & left_tree) != 0 {
171            right = Poseidon2::merge(&[self.nodes[left_offset], right]);
172            self.nodes.push(right);
173
174            debug_assert!(left_tree <= Forest::MAX_LEAVES);
175            let left_nodes = left_tree * 2 - 1;
176            left_offset = left_offset.saturating_sub(left_nodes);
177
178            match left_tree.checked_shl(1) {
179                Some(next) => left_tree = next,
180                None => break,
181            }
182        }
183
184        Ok(())
185    }
186
187    /// Returns the current peaks of the MMR.
188    pub fn peaks(&self) -> MmrPeaks {
189        self.peaks_at(self.forest).expect("failed to get peaks at current forest")
190    }
191
192    /// Returns the peaks of the MMR at the state specified by `forest`.
193    ///
194    /// # Errors
195    /// Returns an error if the specified `forest` value is not valid for this MMR.
196    pub fn peaks_at(&self, forest: Forest) -> Result<MmrPeaks, MmrError> {
197        if forest > self.forest {
198            return Err(MmrError::ForestOutOfBounds(forest.num_leaves(), self.forest.num_leaves()));
199        }
200
201        let peaks: Vec<Word> = TreeSizeIterator::new(forest)
202            .rev()
203            .map(Forest::num_nodes)
204            .scan(0, |offset, el| {
205                *offset += el;
206                Some(*offset)
207            })
208            .map(|offset| self.nodes[offset - 1])
209            .collect();
210
211        // Safety: the invariant is maintained by the [Mmr]
212        let peaks = MmrPeaks::new(forest, peaks)?;
213
214        Ok(peaks)
215    }
216
217    /// Compute the required update to `original_forest`.
218    ///
219    /// The result is a packed sequence of the authentication elements required to update the trees
220    /// that have been merged together, followed by the new peaks of the [Mmr].
221    pub fn get_delta(&self, from_forest: Forest, to_forest: Forest) -> Result<MmrDelta, MmrError> {
222        if to_forest > self.forest {
223            return Err(MmrError::ForestOutOfBounds(
224                to_forest.num_leaves(),
225                self.forest.num_leaves(),
226            ));
227        }
228        if from_forest > to_forest {
229            return Err(MmrError::ForestOutOfBounds(
230                from_forest.num_leaves(),
231                to_forest.num_leaves(),
232            ));
233        }
234
235        if from_forest == to_forest {
236            return Ok(MmrDelta { forest: to_forest, data: Vec::new() });
237        }
238
239        let mut result = Vec::new();
240
241        // Find the largest tree in this [Mmr] which is new to `from_forest`.
242        let candidate_mask = to_forest.num_leaves() ^ from_forest.num_leaves();
243        let mut new_high = super::forest::largest_tree_from_mask(candidate_mask);
244
245        // Collect authentication nodes used for tree merges
246        // ----------------------------------------------------------------------------------------
247
248        // Find the trees from `from_forest` that have been merged into `new_high`.
249        let mut merges = from_forest & new_high.all_smaller_trees_unchecked();
250
251        // Find the peaks that are common to `from_forest` and this [Mmr]
252        let common_trees = from_forest ^ merges;
253
254        if !merges.is_empty() {
255            // Skip the smallest trees unknown to `from_forest`.
256            let mut target = merges.smallest_tree_unchecked();
257
258            // Collect siblings required to computed the merged tree's peak
259            while target < new_high {
260                // Computes the offset to the smallest know peak
261                // - common_trees: peaks unchanged in the current update, target comes after these.
262                // - merges: peaks that have not been merged so far, target comes after these.
263                // - target: tree from which to load the sibling. On the first iteration this is a
264                //   value known by the partial mmr, on subsequent iterations this value is to be
265                //   computed from the known peaks and provided authentication nodes.
266                let known_mask =
267                    common_trees.num_leaves() | merges.num_leaves() | target.num_leaves();
268                let known = nodes_from_mask(known_mask);
269                let sibling = target.num_nodes();
270                result.push(self.nodes[known + sibling - 1]);
271
272                // Update the target and account for tree merges
273                target = target.next_larger_tree()?;
274                while !(merges & target).is_empty() {
275                    target = target.next_larger_tree()?;
276                }
277                // Remove the merges done so far
278                merges ^= merges & target.all_smaller_trees_unchecked();
279            }
280        } else {
281            // The new high tree may not be the result of any merges, if it is smaller than all the
282            // trees of `from_forest`.
283            new_high = Forest::empty();
284        }
285
286        // Collect the new [Mmr] peaks
287        // ----------------------------------------------------------------------------------------
288
289        let mut new_peaks = to_forest ^ common_trees ^ new_high;
290        let old_peaks = to_forest ^ new_peaks;
291        let mut offset = old_peaks.num_nodes();
292        while !new_peaks.is_empty() {
293            let target = new_peaks.largest_tree_unchecked();
294            offset += target.num_nodes();
295            result.push(self.nodes[offset - 1]);
296            new_peaks ^= target;
297        }
298
299        Ok(MmrDelta { forest: to_forest, data: result })
300    }
301
302    /// An iterator over inner nodes in the MMR. The order of iteration is unspecified.
303    pub fn inner_nodes(&self) -> MmrNodes<'_> {
304        MmrNodes {
305            mmr: self,
306            forest: 0,
307            last_right: 0,
308            index: 0,
309        }
310    }
311
312    // UTILITIES
313    // ============================================================================================
314
315    /// Internal function used to collect the leaf value and its Merkle path.
316    ///
317    /// The arguments are relative to the target tree. To compute the opening of the second leaf
318    /// for a tree with depth 2 in the forest `0b110`:
319    ///
320    /// - `leaf_idx`: Position corresponding to the order the leaves were added.
321    /// - `forest`: State of the MMR.
322    fn collect_merkle_path_and_value(
323        &self,
324        leaf_idx: usize,
325        forest: Forest,
326    ) -> Result<(Word, Vec<Word>), MmrError> {
327        // find the target tree responsible for the MMR position
328        let tree_bit = forest
329            .leaf_to_corresponding_tree(leaf_idx)
330            .ok_or(MmrError::PositionNotFound(leaf_idx))?;
331
332        // isolate the trees before the target
333        let forest_before = forest.trees_larger_than(tree_bit);
334        let index_offset = forest_before.num_nodes();
335
336        // update the value position from global to the target tree
337        let relative_pos = leaf_idx - forest_before.num_leaves();
338
339        // see documentation of `leaf_to_corresponding_tree` for details
340        let tree_depth = (tree_bit + 1) as usize;
341        let mut path = Vec::with_capacity(tree_depth);
342
343        // The tree walk below goes from the root to the leaf, compute the root index to start
344        let mut forest_target: usize = 1usize << tree_bit;
345        let mut index = nodes_from_mask(forest_target) - 1;
346
347        // Loop until the leaf is reached
348        while forest_target > 1 {
349            // Update the depth of the tree to correspond to a subtree
350            forest_target >>= 1;
351
352            // compute the indices of the right and left subtrees based on the post-order
353            let right_offset = index - 1;
354            let left_offset = right_offset - nodes_from_mask(forest_target);
355
356            let left_or_right = relative_pos & forest_target;
357            let sibling = if left_or_right != 0 {
358                // going down the right subtree, the right child becomes the new root
359                index = right_offset;
360                // and the left child is the authentication
361                self.nodes[index_offset + left_offset]
362            } else {
363                index = left_offset;
364                self.nodes[index_offset + right_offset]
365            };
366
367            path.push(sibling);
368        }
369
370        debug_assert!(path.len() == tree_depth - 1);
371
372        // the rest of the codebase has the elements going from leaf to root, adjust it here for
373        // easy of use/consistency sake
374        path.reverse();
375
376        let value = self.nodes[index_offset + index];
377        Ok((value, path))
378    }
379}
380
381// CONVERSIONS
382// ================================================================================================
383
384// No TryFrom<T> impl: it conflicts with core’s blanket TryFrom<U> where U: Into<T>.
385
386// SERIALIZATION
387// ================================================================================================
388
389impl Serializable for Mmr {
390    fn write_into<W: ByteWriter>(&self, target: &mut W) {
391        self.forest.write_into(target);
392        self.nodes.write_into(target);
393    }
394}
395
396impl Deserializable for Mmr {
397    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
398        let forest = Forest::read_from(source)?;
399        let nodes = Vec::<Word>::read_from(source)?;
400        Ok(Self { forest, nodes })
401    }
402}
403
404// ITERATOR
405// ===============================================================================================
406
407/// Yields inner nodes of the [Mmr].
408pub struct MmrNodes<'a> {
409    /// [Mmr] being yielded, when its `forest` value is matched, the iterations is finished.
410    mmr: &'a Mmr,
411    /// Keeps track of the left nodes yielded so far waiting for a right pair, this matches the
412    /// semantics of the [Mmr]'s forest attribute, since that too works as a buffer of left nodes
413    /// waiting for a pair to be hashed together.
414    forest: usize,
415    /// Keeps track of the last right node yielded, after this value is set, the next iteration
416    /// will be its parent with its corresponding left node that has been yield already.
417    last_right: usize,
418    /// The current index in the `nodes` vector.
419    index: usize,
420}
421
422impl Iterator for MmrNodes<'_> {
423    type Item = InnerNodeInfo;
424
425    fn next(&mut self) -> Option<Self::Item> {
426        debug_assert!(self.last_right.count_ones() <= 1, "last_right tracks zero or one element");
427
428        // only parent nodes are emitted, remove the single node tree from the forest
429        let target = self.mmr.forest.without_single_leaf().num_leaves();
430
431        if self.forest < target {
432            if self.last_right == 0 {
433                // yield the left leaf
434                debug_assert!(self.last_right == 0, "left must be before right");
435                self.forest |= 1;
436                self.index += 1;
437
438                // yield the right leaf
439                debug_assert!((self.forest & 1) == 1, "right must be after left");
440                self.last_right |= 1;
441                self.index += 1;
442            };
443
444            debug_assert!(
445                self.forest & self.last_right != 0,
446                "parent requires both a left and right",
447            );
448
449            // compute the number of nodes in the right tree, this is the offset to the
450            // previous left parent
451            let right_nodes = Forest::new(self.last_right).unwrap().num_nodes();
452            // the next parent position is one above the position of the pair
453            let parent = self.last_right << 1;
454
455            // the left node has been paired and the current parent yielded, removed it from the
456            // forest
457            self.forest ^= self.last_right;
458            if self.forest & parent == 0 {
459                // this iteration yielded the left parent node
460                debug_assert!(self.forest & 1 == 0, "next iteration yields a left leaf");
461                self.last_right = 0;
462                self.forest ^= parent;
463            } else {
464                // the left node of the parent level has been yielded already, this iteration
465                // was the right parent. Next iteration yields their parent.
466                self.last_right = parent;
467            }
468
469            // yields a parent
470            let value = self.mmr.nodes[self.index];
471            let right = self.mmr.nodes[self.index - 1];
472            let left = self.mmr.nodes[self.index - 1 - right_nodes];
473            self.index += 1;
474            let node = InnerNodeInfo { value, left, right };
475
476            Some(node)
477        } else {
478            None
479        }
480    }
481}
482
483// TESTS
484// ================================================================================================
485#[cfg(test)]
486mod tests {
487    use alloc::vec::Vec;
488
489    use super::super::nodes_from_mask;
490    use crate::{
491        Felt, Word, ZERO,
492        merkle::mmr::{Forest, Mmr},
493        utils::{Deserializable, DeserializationError, Serializable},
494    };
495
496    #[test]
497    fn test_serialization() {
498        let nodes = (0u64..128u64)
499            .map(|value| Word::new([ZERO, ZERO, ZERO, Felt::new_unchecked(value)]))
500            .collect::<Vec<_>>();
501
502        let mmr = Mmr::try_from_iter(nodes).unwrap();
503        let serialized = mmr.to_bytes();
504        let deserialized = Mmr::read_from_bytes(&serialized).unwrap();
505        assert_eq!(mmr.forest, deserialized.forest);
506        assert_eq!(mmr.nodes, deserialized.nodes);
507    }
508
509    #[test]
510    fn test_deserialization_rejects_large_forest() {
511        let mut bytes = (Forest::MAX_LEAVES + 1).to_bytes();
512        bytes.extend_from_slice(&0usize.to_bytes()); // empty nodes vector
513
514        let result = Mmr::read_from_bytes(&bytes);
515        assert!(matches!(result, Err(DeserializationError::InvalidValue(_))));
516    }
517
518    #[test]
519    fn test_nodes_from_mask_at_max_leaves() {
520        let expected = (Forest::MAX_LEAVES as u128)
521            .saturating_mul(2)
522            .saturating_sub(Forest::MAX_LEAVES.count_ones() as u128);
523        assert!(expected <= usize::MAX as u128);
524        assert_eq!(nodes_from_mask(Forest::MAX_LEAVES), expected as usize);
525    }
526}