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