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}