miden-crypto/src/merkle/mmr/peaks.rs
src/merkle/mmr/peaks.rsRaw
1use super::{
2 super::{RpoDigest, Vec, ZERO},
3 Felt, MmrError, MmrProof, Rpo256, Word,
4};
5
6// MMR PEAKS
7// ================================================================================================
8
9#[derive(Debug, Clone, PartialEq)]
10#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
11pub struct MmrPeaks {
12 /// The number of leaves is used to differentiate MMRs that have the same number of peaks. This
13 /// happens because the number of peaks goes up-and-down as the structure is used causing
14 /// existing trees to be merged and new ones to be created. As an example, every time the MMR
15 /// has a power-of-two number of leaves there is a single peak.
16 ///
17 /// Every tree in the MMR forest has a distinct power-of-two size, this means only the right-
18 /// most tree can have an odd number of elements (e.g. `1`). Additionally this means that the
19 /// bits in `num_leaves` conveniently encode the size of each individual tree.
20 ///
21 /// Examples:
22 ///
23 /// - With 5 leaves, the binary `0b101`. The number of set bits is equal the number
24 /// of peaks, in this case there are 2 peaks. The 0-indexed least-significant position of
25 /// the bit determines the number of elements of a tree, so the rightmost tree has `2**0`
26 /// elements and the left most has `2**2`.
27 /// - With 12 leaves, the binary is `0b1100`, this case also has 2 peaks, the
28 /// leftmost tree has `2**3=8` elements, and the right most has `2**2=4` elements.
29 num_leaves: usize,
30
31 /// All the peaks of every tree in the MMR forest. The peaks are always ordered by number of
32 /// leaves, starting from the peak with most children, to the one with least.
33 ///
34 /// Invariant: The length of `peaks` must be equal to the number of true bits in `num_leaves`.
35 peaks: Vec<RpoDigest>,
36}
37
38impl MmrPeaks {
39 pub fn new(num_leaves: usize, peaks: Vec<RpoDigest>) -> Result<Self, MmrError> {
40 if num_leaves.count_ones() as usize != peaks.len() {
41 return Err(MmrError::InvalidPeaks);
42 }
43
44 Ok(Self { num_leaves, peaks })
45 }
46
47 // ACCESSORS
48 // --------------------------------------------------------------------------------------------
49
50 /// Returns a count of the MMR's leaves.
51 pub fn num_leaves(&self) -> usize {
52 self.num_leaves
53 }
54
55 /// Returns the current peaks of the MMR.
56 pub fn peaks(&self) -> &[RpoDigest] {
57 &self.peaks
58 }
59
60 /// Returns the current num_leaves and peaks of the MMR.
61 pub fn into_parts(self) -> (usize, Vec<RpoDigest>) {
62 (self.num_leaves, self.peaks)
63 }
64
65 /// Hashes the peaks.
66 ///
67 /// The procedure will:
68 /// - Flatten and pad the peaks to a vector of Felts.
69 /// - Hash the vector of Felts.
70 pub fn hash_peaks(&self) -> RpoDigest {
71 Rpo256::hash_elements(&self.flatten_and_pad_peaks())
72 }
73
74 pub fn verify(&self, value: RpoDigest, opening: MmrProof) -> bool {
75 let root = &self.peaks[opening.peak_index()];
76 opening.merkle_path.verify(opening.relative_pos() as u64, value, root)
77 }
78
79 /// Flattens and pads the peaks to make hashing inside of the Miden VM easier.
80 ///
81 /// The procedure will:
82 /// - Flatten the vector of Words into a vector of Felts.
83 /// - Pad the peaks with ZERO to an even number of words, this removes the need to handle RPO
84 /// padding.
85 /// - Pad the peaks to a minimum length of 16 words, which reduces the constant cost of
86 /// hashing.
87 pub fn flatten_and_pad_peaks(&self) -> Vec<Felt> {
88 let num_peaks = self.peaks.len();
89
90 // To achieve the padding rules above we calculate the length of the final vector.
91 // This is calculated as the number of field elements. Each peak is 4 field elements.
92 // The length is calculated as follows:
93 // - If there are less than 16 peaks, the data is padded to 16 peaks and as such requires
94 // 64 field elements.
95 // - If there are more than 16 peaks and the number of peaks is odd, the data is padded to
96 // an even number of peaks and as such requires `(num_peaks + 1) * 4` field elements.
97 // - If there are more than 16 peaks and the number of peaks is even, the data is not padded
98 // and as such requires `num_peaks * 4` field elements.
99 let len = if num_peaks < 16 {
100 64
101 } else if num_peaks % 2 == 1 {
102 (num_peaks + 1) * 4
103 } else {
104 num_peaks * 4
105 };
106
107 let mut elements = Vec::with_capacity(len);
108 elements.extend_from_slice(
109 &self
110 .peaks
111 .as_slice()
112 .iter()
113 .map(|digest| digest.into())
114 .collect::<Vec<Word>>()
115 .concat(),
116 );
117 elements.resize(len, ZERO);
118 elements
119 }
120}