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> {
139 #[inline(always)]
140 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
141 fn default() -> Self {
142 Self::new()
143 }
144}
145
146impl<const MAX_N: u64> MerkleMountainRange<MAX_N> {
148 #[inline(always)]
150 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
151 pub fn new() -> Self {
152 Self {
153 num_leaves: 0,
154 stack: [[0u8; OUT_LEN]; _],
155 }
156 }
157
158 #[inline]
162 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
163 pub fn from_peaks(peaks: &MmrPeaks<MAX_N>) -> Option<Self> {
164 let mut result = Self {
165 num_leaves: peaks.num_leaves,
166 stack: [[0u8; OUT_LEN]; _],
167 };
168
169 let mut stack_bits = peaks.num_leaves;
172 let mut peaks_offset = 0;
173
174 while stack_bits != 0 {
175 let stack_offset = stack_bits.trailing_zeros();
176
177 *result.stack.get_mut(stack_offset as usize)? = *peaks.peaks.get(peaks_offset)?;
178
179 peaks_offset += 1;
180 stack_bits &= !(1 << stack_offset);
182 }
183
184 Some(result)
185 }
186
187 #[inline(always)]
189 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
190 pub fn as_bytes(&self) -> &MerkleMountainRangeBytes<MAX_N> {
191 unsafe { mem::transmute(self) }
194 }
195
196 #[inline(always)]
201 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
202 pub unsafe fn from_bytes(bytes: &MerkleMountainRangeBytes<MAX_N>) -> &Self {
203 unsafe { mem::transmute(bytes) }
207 }
208
209 #[inline(always)]
211 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
212 pub fn num_leaves(&self) -> u64 {
213 self.num_leaves
214 }
215
216 #[inline]
221 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
222 pub fn root(&self) -> Option<[u8; OUT_LEN]> {
223 if self.num_leaves == 0 {
224 return None;
226 }
227
228 let mut root;
229 let mut stack_bits = self.num_leaves;
230 {
231 let lowest_active_level = stack_bits.trailing_zeros() as usize;
232 root = *unsafe { self.stack.get_unchecked(lowest_active_level) };
234 stack_bits &= !(1 << lowest_active_level);
236 }
237
238 loop {
240 let lowest_active_level = stack_bits.trailing_zeros() as usize;
241
242 if lowest_active_level == u64::BITS as usize {
243 break;
244 }
245
246 stack_bits &= !(1 << lowest_active_level);
248
249 let lowest_active_level_item = unsafe { self.stack.get_unchecked(lowest_active_level) };
251
252 root = hash_pair(lowest_active_level_item, &root);
253 }
254
255 Some(root)
256 }
257
258 #[inline]
260 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
261 pub fn peaks(&self) -> MmrPeaks<MAX_N> {
262 let mut result = MmrPeaks {
263 num_leaves: self.num_leaves,
264 peaks: [[0u8; OUT_LEN]; _],
265 };
266
267 let mut stack_bits = self.num_leaves;
270 let mut peaks_offset = 0;
271 while stack_bits != 0 {
272 let stack_offset = stack_bits.trailing_zeros();
273
274 *unsafe { result.peaks.get_unchecked_mut(peaks_offset) } =
277 *unsafe { self.stack.get_unchecked(stack_offset as usize) };
278
279 peaks_offset += 1;
280 stack_bits &= !(1 << stack_offset);
282 }
283
284 result
285 }
286
287 #[inline]
294 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
295 pub fn add_leaf(&mut self, leaf: &[u8; OUT_LEN]) -> bool {
296 if self.num_leaves >= MAX_N {
299 return false;
300 }
301
302 let mut current = *leaf;
303
304 let lowest_active_levels = self.num_leaves.trailing_ones() as usize;
306 for item in self.stack.iter().take(lowest_active_levels) {
307 current = hash_pair(item, ¤t);
308 }
309
310 *unsafe { self.stack.get_unchecked_mut(lowest_active_levels) } = current;
316 self.num_leaves += 1;
317
318 true
319 }
320
321 #[inline]
328 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
329 pub fn add_leaves<'a, Item, Iter>(&mut self, leaves: Iter) -> bool
330 where
331 Item: Into<[u8; OUT_LEN]>,
332 Iter: IntoIterator<Item = Item> + 'a,
333 {
334 for leaf in leaves {
336 if self.num_leaves >= MAX_N {
339 return false;
340 }
341
342 let mut current = leaf.into();
343
344 let lowest_active_levels = self.num_leaves.trailing_ones() as usize;
346 for item in self.stack.iter().take(lowest_active_levels) {
347 current = hash_pair(item, ¤t);
348 }
349
350 self.stack[lowest_active_levels] = current;
352 self.num_leaves += 1;
353 }
354
355 true
356 }
357
358 #[inline]
362 #[cfg(feature = "alloc")]
363 pub fn add_leaf_and_compute_proof(
364 &mut self,
365 leaf: &[u8; OUT_LEN],
366 ) -> Option<([u8; OUT_LEN], Vec<[u8; OUT_LEN]>)> {
367 let mut proof =
369 unsafe { Box::<[MaybeUninit<[u8; OUT_LEN]>; _]>::new_uninit().assume_init() };
370
371 let (root, proof_length) = self.add_leaf_and_compute_proof_inner(leaf, &mut proof)?;
372
373 let proof_capacity = proof.len();
374 let proof = Box::into_raw(proof);
375 let proof = unsafe {
378 Vec::from_raw_parts(proof.cast::<[u8; OUT_LEN]>(), proof_length, proof_capacity)
379 };
380
381 Some((root, proof))
382 }
383
384 #[inline]
388 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
389 pub fn add_leaf_and_compute_proof_in<'proof>(
390 &mut self,
391 leaf: &[u8; OUT_LEN],
392 proof: &'proof mut [MaybeUninit<[u8; OUT_LEN]>; MAX_PROOF_ELEMENTS::<MAX_N>],
393 ) -> Option<([u8; OUT_LEN], &'proof mut [[u8; OUT_LEN]])> {
394 let (root, proof_length) = self.add_leaf_and_compute_proof_inner(leaf, proof)?;
395
396 let proof = unsafe { proof.get_unchecked_mut(..proof_length).assume_init_mut() };
398
399 Some((root, proof))
400 }
401
402 #[inline]
403 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
404 pub fn add_leaf_and_compute_proof_inner(
405 &mut self,
406 leaf: &[u8; OUT_LEN],
407 proof: &mut [MaybeUninit<[u8; OUT_LEN]>; MAX_PROOF_ELEMENTS::<MAX_N>],
408 ) -> Option<([u8; OUT_LEN], usize)> {
409 let mut proof_length = 0;
410
411 let current_target_level;
412 let mut position = self.num_leaves;
413
414 {
415 if self.num_leaves >= MAX_N {
418 return None;
419 }
420
421 let mut current = *leaf;
422
423 let lowest_active_levels = self.num_leaves.trailing_ones() as usize;
425
426 for item in self.stack.iter().take(lowest_active_levels) {
427 unsafe { proof.get_unchecked_mut(proof_length) }.write(*item);
430 proof_length += 1;
431
432 current = hash_pair(item, ¤t);
433
434 position /= 2;
436 }
437
438 current_target_level = lowest_active_levels;
439
440 self.stack[lowest_active_levels] = current;
442 self.num_leaves += 1;
443 }
444
445 let mut root;
446 let mut stack_bits = self.num_leaves;
447
448 {
449 let lowest_active_level = stack_bits.trailing_zeros() as usize;
450 root = *unsafe { self.stack.get_unchecked(lowest_active_level) };
452 stack_bits &= !(1 << lowest_active_level);
454 }
455
456 let mut merged_peaks = false;
459 loop {
460 let lowest_active_level = stack_bits.trailing_zeros() as usize;
461
462 if lowest_active_level == u64::BITS as usize {
463 break;
464 }
465
466 stack_bits &= !(1 << lowest_active_level);
468
469 let lowest_active_level_item = unsafe { self.stack.get_unchecked(lowest_active_level) };
471
472 if lowest_active_level > current_target_level
473 || (lowest_active_level == current_target_level
474 && !position.is_multiple_of(2)
475 && !merged_peaks)
476 {
477 unsafe { proof.get_unchecked_mut(proof_length) }.write(*lowest_active_level_item);
479 proof_length += 1;
480 merged_peaks = false;
481 } else if lowest_active_level == current_target_level {
482 unsafe { proof.get_unchecked_mut(proof_length) }.write(root);
484 proof_length += 1;
485 merged_peaks = false;
486 } else {
487 merged_peaks = true;
489 }
490
491 root = hash_pair(lowest_active_level_item, &root);
493
494 position /= 2;
495 }
496
497 Some((root, proof_length))
498 }
499
500 #[inline]
504 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
505 pub fn verify(
506 root: &[u8; OUT_LEN],
507 proof: &[[u8; OUT_LEN]],
508 leaf_index: u64,
509 leaf: [u8; OUT_LEN],
510 num_leaves: u64,
511 ) -> bool {
512 UnbalancedMerkleTree::verify(root, proof, leaf_index, leaf, num_leaves)
513 }
514}