miden-crypto/src/merkle/mmr/accumulator.rs
src/merkle/mmr/accumulator.rsRaw
1use super::{
2 super::Vec,
3 super::{WORD_SIZE, ZERO},
4 MmrProof, Rpo256, Word,
5};
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct MmrPeaks {
9 /// The number of leaves is used to differentiate accumulators that have the same number of
10 /// peaks. This happens because the number of peaks goes up-and-down as the structure is used
11 /// causing existing trees to be merged and new ones to be created. As an example, every time
12 /// the MMR has a power-of-two number of leaves there is a single peak.
13 ///
14 /// Every tree in the MMR forest has a distinct power-of-two size, this means only the right
15 /// most tree can have an odd number of elements (e.g. `1`). Additionally this means that the bits in
16 /// `num_leaves` conveniently encode the size of each individual tree.
17 ///
18 /// Examples:
19 ///
20 /// - With 5 leaves, the binary `0b101`. The number of set bits is equal the number
21 /// of peaks, in this case there are 2 peaks. The 0-indexed least-significant position of
22 /// the bit determines the number of elements of a tree, so the rightmost tree has `2**0`
23 /// elements and the left most has `2**2`.
24 /// - With 12 leaves, the binary is `0b1100`, this case also has 2 peaks, the
25 /// leftmost tree has `2**3=8` elements, and the right most has `2**2=4` elements.
26 pub num_leaves: usize,
27
28 /// All the peaks of every tree in the MMR forest. The peaks are always ordered by number of
29 /// leaves, starting from the peak with most children, to the one with least.
30 ///
31 /// Invariant: The length of `peaks` must be equal to the number of true bits in `num_leaves`.
32 pub peaks: Vec<Word>,
33}
34
35impl MmrPeaks {
36 /// Hashes the peaks.
37 ///
38 /// The hashing is optimized to work with the Miden VM, the procedure will:
39 ///
40 /// - Pad the peaks with ZERO to an even number of words, this removes the need to handle RPO padding.
41 /// - Pad the peaks to a minimum length of 16 words, which reduces the constant cost of
42 /// hashing.
43 pub fn hash_peaks(&self) -> Word {
44 let mut copy = self.peaks.clone();
45
46 if copy.len() < 16 {
47 copy.resize(16, [ZERO; WORD_SIZE])
48 } else if copy.len() % 2 == 1 {
49 copy.push([ZERO; WORD_SIZE])
50 }
51
52 Rpo256::hash_elements(©.as_slice().concat()).into()
53 }
54
55 pub fn verify(&self, value: Word, opening: MmrProof) -> bool {
56 let root = &self.peaks[opening.peak_index()];
57 opening.merkle_path.verify(opening.relative_pos() as u64, value, root)
58 }
59}