1use crate::hash_pair;
2use crate::unbalanced::UnbalancedMerkleTree;
3use ab_blake3::OUT_LEN;
4#[cfg(feature = "alloc")]
5use alloc::boxed::Box;
6#[cfg(feature = "alloc")]
7use alloc::vec::Vec;
8use core::mem;
9use core::mem::MaybeUninit;
10use core::ops::{Deref, DerefMut};
11
12pub const NUM_PEAKS<const MAX_N: u64>: usize = MAX_N.next_power_of_two().ilog2() as usize;
14pub const MAX_PROOF_ELEMENTS<const MAX_N: u64>: usize = MAX_N.next_power_of_two().ilog2() as usize;
16const STACK_SIZE<const MAX_N: u64>: usize = {
17 assert!(
20 MAX_N > 1,
21 "This Merkle Mountain Range must have MAX_N > 1 leaves"
22 );
23
24 MAX_N.next_power_of_two().ilog2() as usize + 1
25};
26
27const MERKLE_MOUNTAIN_RANGE_BYTES_SIZE<const MAX_N: u64>: usize =
29 size_of::<u64>() + OUT_LEN * (MAX_N.next_power_of_two().ilog2() as usize + 1);
30
31const {
32 assert!(size_of::<MerkleMountainRangeBytes<2>>() == MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<2>);
33 assert!(size_of::<MerkleMountainRange<2>>() == MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<2>);
34 assert!(align_of::<MerkleMountainRangeBytes<2>>() == align_of::<MerkleMountainRange<2>>());
35
36 assert!(size_of::<MerkleMountainRangeBytes<100>>() == MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<100>);
39 assert!(size_of::<MerkleMountainRange<100>>() == MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<100>);
40 assert!(align_of::<MerkleMountainRangeBytes<100>>() == align_of::<MerkleMountainRange<100>>());
41
42 assert!(
43 size_of::<MerkleMountainRangeBytes<65536>>() == MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<65536>
44 );
45 assert!(size_of::<MerkleMountainRange<65536>>() == MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<65536>);
46 assert!(
47 align_of::<MerkleMountainRangeBytes<65536>>() == align_of::<MerkleMountainRange<65536>>()
48 );
49}
50
51#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
56pub struct MmrPeaks<const MAX_N: u64> {
57 pub num_leaves: u64,
59 pub peaks: [[u8; OUT_LEN]; NUM_PEAKS::<MAX_N>],
62}
63
64impl<const MAX_N: u64> MmrPeaks<MAX_N> {
65 #[inline(always)]
67 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
68 pub fn num_peaks(&self) -> u8 {
69 self.num_leaves.count_ones() as u8
70 }
71}
72
73#[derive(Debug, Copy, Clone)]
77#[repr(C, align(8))]
78pub struct MerkleMountainRangeBytes<const MAX_N: u64>(
79 [u8; MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<MAX_N>],
80);
81
82impl<const MAX_N: u64> Default for MerkleMountainRangeBytes<MAX_N> {
83 #[inline(always)]
84 fn default() -> Self {
85 Self([0; _])
86 }
87}
88
89impl<const MAX_N: u64> From<[u8; MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<MAX_N>]>
90 for MerkleMountainRangeBytes<MAX_N>
91{
92 fn from(value: [u8; MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<MAX_N>]) -> Self {
93 Self(value)
94 }
95}
96
97impl<const MAX_N: u64> From<MerkleMountainRangeBytes<MAX_N>>
98 for [u8; MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<MAX_N>]
99{
100 fn from(value: MerkleMountainRangeBytes<MAX_N>) -> Self {
101 value.0
102 }
103}
104
105impl<const MAX_N: u64> Deref for MerkleMountainRangeBytes<MAX_N> {
106 type Target = [u8; MERKLE_MOUNTAIN_RANGE_BYTES_SIZE::<MAX_N>];
107
108 #[inline(always)]
109 fn deref(&self) -> &Self::Target {
110 &self.0
111 }
112}
113
114impl<const MAX_N: u64> DerefMut for MerkleMountainRangeBytes<MAX_N> {
115 #[inline(always)]
116 fn deref_mut(&mut self) -> &mut Self::Target {
117 &mut self.0
118 }
119}
120
121#[derive(Debug, Copy, Clone)]
131#[repr(C)]
132pub struct MerkleMountainRange<const MAX_N: u64> {
133 num_leaves: u64,
134 stack: [[u8; OUT_LEN]; STACK_SIZE::<MAX_N>],
136}
137
138impl<const MAX_N: u64> Default for MerkleMountainRange<MAX_N>
139where
140 [(); STACK_SIZE::<MAX_N>]:,
141{
142 #[inline(always)]
143 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
144 fn default() -> Self {
145 Self::new()
146 }
147}
148
149impl<const MAX_N: u64> MerkleMountainRange<MAX_N>
151where
152 [(); STACK_SIZE::<MAX_N>]:,
153{
154 #[inline(always)]
156 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
157 pub fn new() -> Self {
158 const { STACK_SIZE::<MAX_N> };
161
162 Self {
163 num_leaves: 0,
164 stack: [[0u8; OUT_LEN]; _],
165 }
166 }
167
168 #[inline]
172 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
173 pub fn from_peaks(peaks: &MmrPeaks<MAX_N>) -> Option<Self> {
174 const { STACK_SIZE::<MAX_N> };
177
178 if peaks.num_leaves > MAX_N {
180 return None;
181 }
182
183 let mut result = Self {
184 num_leaves: peaks.num_leaves,
185 stack: [[0u8; OUT_LEN]; _],
186 };
187
188 let mut stack_bits = peaks.num_leaves;
191 let mut peaks_offset = 0;
192
193 while stack_bits != 0 {
194 let stack_offset = stack_bits.trailing_zeros();
195
196 *result.stack.get_mut(stack_offset as usize)? = *peaks.peaks.get(peaks_offset)?;
197
198 peaks_offset += 1;
199 stack_bits &= !(1 << stack_offset);
201 }
202
203 Some(result)
204 }
205
206 #[inline(always)]
208 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
209 pub fn as_bytes(&self) -> &MerkleMountainRangeBytes<MAX_N> {
210 unsafe { mem::transmute(self) }
213 }
214
215 #[inline(always)]
220 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
221 pub unsafe fn from_bytes(bytes: &MerkleMountainRangeBytes<MAX_N>) -> &Self {
222 unsafe { mem::transmute(bytes) }
226 }
227
228 #[inline(always)]
230 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
231 pub fn num_leaves(&self) -> u64 {
232 self.num_leaves
233 }
234
235 #[inline]
240 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
241 pub fn root(&self) -> Option<[u8; OUT_LEN]> {
242 if self.num_leaves == 0 {
243 return None;
245 }
246
247 let mut root;
248 let mut stack_bits = self.num_leaves;
249 {
250 let lowest_active_level = stack_bits.trailing_zeros() as usize;
251 root = *unsafe { self.stack.get_unchecked(lowest_active_level) };
253 stack_bits &= !(1 << lowest_active_level);
255 }
256
257 loop {
259 let lowest_active_level = stack_bits.trailing_zeros() as usize;
260
261 if lowest_active_level == u64::BITS as usize {
262 break;
263 }
264
265 stack_bits &= !(1 << lowest_active_level);
267
268 let lowest_active_level_item = unsafe { self.stack.get_unchecked(lowest_active_level) };
270
271 root = hash_pair(lowest_active_level_item, &root);
272 }
273
274 Some(root)
275 }
276
277 #[inline]
279 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
280 pub fn peaks(&self) -> MmrPeaks<MAX_N> {
281 let mut result = MmrPeaks {
282 num_leaves: self.num_leaves,
283 peaks: [[0u8; OUT_LEN]; _],
284 };
285
286 let mut stack_bits = self.num_leaves;
289 let mut peaks_offset = 0;
290 while stack_bits != 0 {
291 let stack_offset = stack_bits.trailing_zeros();
292
293 *unsafe { result.peaks.get_unchecked_mut(peaks_offset) } =
296 *unsafe { self.stack.get_unchecked(stack_offset as usize) };
297
298 peaks_offset += 1;
299 stack_bits &= !(1 << stack_offset);
301 }
302
303 result
304 }
305
306 #[inline]
313 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
314 pub fn add_leaf(&mut self, leaf: &[u8; OUT_LEN]) -> bool {
315 if self.num_leaves >= MAX_N {
318 return false;
319 }
320
321 let mut current = *leaf;
322
323 let lowest_active_levels = self.num_leaves.trailing_ones() as usize;
325 for item in self.stack.iter().take(lowest_active_levels) {
326 current = hash_pair(item, ¤t);
327 }
328
329 *self
331 .stack
332 .get_mut(lowest_active_levels)
333 .expect("Stack has enough levels for `num_leaves < MAX_N`; qed") = current;
334 self.num_leaves += 1;
335
336 true
337 }
338
339 #[inline]
346 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
347 pub fn add_leaves<'a, Item, Iter>(&mut self, leaves: Iter) -> bool
348 where
349 Item: Into<[u8; OUT_LEN]>,
350 Iter: IntoIterator<Item = Item> + 'a,
351 {
352 for leaf in leaves {
354 if self.num_leaves >= MAX_N {
357 return false;
358 }
359
360 let mut current = leaf.into();
361
362 let lowest_active_levels = self.num_leaves.trailing_ones() as usize;
364 for item in self.stack.iter().take(lowest_active_levels) {
365 current = hash_pair(item, ¤t);
366 }
367
368 self.stack[lowest_active_levels] = current;
370 self.num_leaves += 1;
371 }
372
373 true
374 }
375
376 #[inline]
380 #[cfg(feature = "alloc")]
381 pub fn add_leaf_and_compute_proof(
382 &mut self,
383 leaf: &[u8; OUT_LEN],
384 ) -> Option<([u8; OUT_LEN], Vec<[u8; OUT_LEN]>)> {
385 let mut proof =
387 unsafe { Box::<[MaybeUninit<[u8; OUT_LEN]>; _]>::new_uninit().assume_init() };
388
389 let (root, proof_length) = self.add_leaf_and_compute_proof_inner(leaf, &mut proof)?;
390
391 let proof_capacity = proof.len();
392 let proof = Box::into_raw(proof);
393 let proof = unsafe {
396 Vec::from_raw_parts(proof.cast::<[u8; OUT_LEN]>(), proof_length, proof_capacity)
397 };
398
399 Some((root, proof))
400 }
401
402 #[inline]
406 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
407 pub fn add_leaf_and_compute_proof_in<'proof>(
408 &mut self,
409 leaf: &[u8; OUT_LEN],
410 proof: &'proof mut [MaybeUninit<[u8; OUT_LEN]>; MAX_PROOF_ELEMENTS::<MAX_N>],
411 ) -> Option<([u8; OUT_LEN], &'proof mut [[u8; OUT_LEN]])> {
412 let (root, proof_length) = self.add_leaf_and_compute_proof_inner(leaf, proof)?;
413
414 let proof = unsafe { proof.get_unchecked_mut(..proof_length).assume_init_mut() };
416
417 Some((root, proof))
418 }
419
420 #[inline]
421 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
422 fn add_leaf_and_compute_proof_inner(
423 &mut self,
424 leaf: &[u8; OUT_LEN],
425 proof: &mut [MaybeUninit<[u8; OUT_LEN]>; MAX_PROOF_ELEMENTS::<MAX_N>],
426 ) -> Option<([u8; OUT_LEN], usize)> {
427 let mut proof_length = 0;
428
429 let current_target_level;
430 let mut position = self.num_leaves;
431
432 {
433 if self.num_leaves >= MAX_N {
436 return None;
437 }
438
439 let mut current = *leaf;
440
441 let lowest_active_levels = self.num_leaves.trailing_ones() as usize;
443
444 for item in self.stack.iter().take(lowest_active_levels) {
445 proof
447 .get_mut(proof_length)
448 .expect("Proof has enough capacity for `num_leaves < MAX_N` checked above; qed")
449 .write(*item);
450 proof_length += 1;
451
452 current = hash_pair(item, ¤t);
453
454 position /= 2;
456 }
457
458 current_target_level = lowest_active_levels;
459
460 self.stack[lowest_active_levels] = current;
462 self.num_leaves += 1;
463 }
464
465 let mut root;
466 let mut stack_bits = self.num_leaves;
467
468 {
469 let lowest_active_level = stack_bits.trailing_zeros() as usize;
470 root = *unsafe { self.stack.get_unchecked(lowest_active_level) };
472 stack_bits &= !(1 << lowest_active_level);
474 }
475
476 let mut merged_peaks = false;
479 loop {
480 let lowest_active_level = stack_bits.trailing_zeros() as usize;
481
482 if lowest_active_level == u64::BITS as usize {
483 break;
484 }
485
486 stack_bits &= !(1 << lowest_active_level);
488
489 let lowest_active_level_item = unsafe { self.stack.get_unchecked(lowest_active_level) };
491
492 if lowest_active_level > current_target_level
493 || (lowest_active_level == current_target_level
494 && !position.is_multiple_of(2)
495 && !merged_peaks)
496 {
497 unsafe { proof.get_unchecked_mut(proof_length) }.write(*lowest_active_level_item);
499 proof_length += 1;
500 merged_peaks = false;
501 } else if lowest_active_level == current_target_level {
502 unsafe { proof.get_unchecked_mut(proof_length) }.write(root);
504 proof_length += 1;
505 merged_peaks = false;
506 } else {
507 merged_peaks = true;
509 }
510
511 root = hash_pair(lowest_active_level_item, &root);
513
514 position /= 2;
515 }
516
517 Some((root, proof_length))
518 }
519
520 #[inline]
524 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
525 pub fn verify(
526 root: &[u8; OUT_LEN],
527 proof: &[[u8; OUT_LEN]],
528 leaf_index: u64,
529 leaf: [u8; OUT_LEN],
530 num_leaves: u64,
531 ) -> bool {
532 const { STACK_SIZE::<MAX_N> };
535
536 UnbalancedMerkleTree::verify(root, proof, leaf_index, leaf, num_leaves)
537 }
538}