@@ -3,7 +3,7 @@ use core::{
33 ops:: { BitAnd , BitOr , BitXor , BitXorAssign } ,
44} ;
55
6- use super :: InOrderIndex ;
6+ use super :: { InOrderIndex , MmrError } ;
77use crate :: {
88 Felt ,
99 utils:: { ByteReader , ByteWriter , Deserializable , DeserializationError , Serializable } ,
@@ -29,31 +29,61 @@ use crate::{
2929/// - `Forest(0b1010)` is a forest with two trees: one with 8 leaves (15 nodes), one with 2 leaves
3030/// (3 nodes).
3131/// - `Forest(0b1000)` is a forest with one tree, which has 8 leaves (15 nodes).
32+ ///
33+ /// Forest sizes are capped at [`Forest::MAX_LEAVES`]. Use [`Forest::new`] or
34+ /// [`Forest::append_leaf`] to enforce the limit.
3235#[ derive( Debug , Copy , Clone , Default , PartialEq , Eq , PartialOrd , Ord ) ]
33- #[ cfg_attr( feature = "serde" , derive( serde:: Deserialize , serde :: Serialize ) ) ]
36+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize ) ) ]
3437pub struct Forest ( usize ) ;
3538
3639impl Forest {
40+ /// Maximum number of leaves supported by the forest.
41+ ///
42+ /// Rationale:
43+ /// - We require `MAX_LEAVES <= usize::MAX / 2 + 1` so `num_nodes()` stays indexable via
44+ /// `usize`.
45+ /// - We choose `usize::MAX / 2` (hard cutoff) rather than `usize::MAX / 2 + 1` so the cap is
46+ /// always of the form `2^k - 1` on all targets.
47+ /// - With that shape, bitwise OR/XOR of valid forest values remains within bounds, so OR/XOR
48+ /// does not need additional overflow protection.
49+ pub const MAX_LEAVES : usize = if ( u32:: MAX as usize ) < ( usize:: MAX / 2 ) {
50+ u32:: MAX as usize
51+ } else {
52+ usize:: MAX / 2
53+ } ;
54+
3755 /// Creates an empty forest (no trees).
3856 pub const fn empty ( ) -> Self {
3957 Self ( 0 )
4058 }
4159
42- /// Creates a forest with `num_leaves` leaves.
43- pub const fn new ( num_leaves : usize ) -> Self {
44- Self ( num_leaves)
60+ /// Creates a forest with `num_leaves` leaves, returning an error if the value is too large.
61+ pub fn new ( num_leaves : usize ) -> Result < Self , DeserializationError > {
62+ if !Self :: is_valid_size ( num_leaves) {
63+ return Err ( DeserializationError :: InvalidValue ( format ! (
64+ "forest size {} exceeds maximum {}" ,
65+ num_leaves,
66+ Self :: MAX_LEAVES
67+ ) ) ) ;
68+ }
69+ Ok ( Self ( num_leaves) )
4570 }
4671
4772 /// Creates a forest with a given height.
4873 ///
49- /// This is equivalent to `Forest::new( 1 << height)` .
74+ /// This is equivalent to creating a forest with ` 1 << height` leaves .
5075 ///
5176 /// # Panics
5277 ///
5378 /// This will panic if `height` is greater than `usize::BITS - 1`.
54- pub const fn with_height ( height : usize ) -> Self {
79+ pub fn with_height ( height : usize ) -> Self {
5580 assert ! ( height < usize :: BITS as usize ) ;
56- Self :: new ( 1 << height)
81+ Self :: new ( 1 << height) . expect ( "forest height exceeds maximum" )
82+ }
83+
84+ /// Returns true if `num_leaves` is within the supported bounds.
85+ pub const fn is_valid_size ( num_leaves : usize ) -> bool {
86+ num_leaves <= Self :: MAX_LEAVES
5787 }
5888
5989 /// Returns true if there are no trees in the forest.
@@ -64,8 +94,15 @@ impl Forest {
6494 /// Adds exactly one more leaf to the capacity of this forest.
6595 ///
6696 /// Some smaller trees might be merged together.
67- pub fn append_leaf ( & mut self ) {
97+ pub fn append_leaf ( & mut self ) -> Result < ( ) , MmrError > {
98+ if self . 0 >= Self :: MAX_LEAVES {
99+ return Err ( MmrError :: ForestSizeExceeded {
100+ requested : self . 0 . saturating_add ( 1 ) ,
101+ max : Self :: MAX_LEAVES ,
102+ } ) ;
103+ }
68104 self . 0 += 1 ;
105+ Ok ( ( ) )
69106 }
70107
71108 /// Returns a count of leaves in the entire underlying forest (MMR).
@@ -75,11 +112,11 @@ impl Forest {
75112
76113 /// Return the total number of nodes of a given forest.
77114 ///
78- /// # Panics
79- ///
80- /// This will panic if the forest has size greater than `usize::MAX / 2 + 1` .
115+ /// This relies on the `Forest` invariant that `num_leaves() <= Forest::MAX_LEAVES`.
116+ /// The internal assertion is a defensive check and should be unreachable for values created
117+ /// through validated constructors/deserializers .
81118 pub const fn num_nodes ( self ) -> usize {
82- assert ! ( self . 0 <= usize :: MAX / 2 + 1 ) ;
119+ assert ! ( self . 0 <= Self :: MAX_LEAVES ) ;
83120 if self . 0 <= usize:: MAX / 2 {
84121 self . 0 * 2 - self . num_trees ( )
85122 } else {
@@ -197,11 +234,12 @@ impl Forest {
197234 ///
198235 /// ```
199236 /// # use miden_crypto::merkle::mmr::Forest;
200- /// let range = Forest::new(0b0101_0110);
201- /// assert_eq!(range.trees_larger_than(1), Forest::new(0b0101_0100));
237+ /// let range = Forest::new(0b0101_0110).unwrap() ;
238+ /// assert_eq!(range.trees_larger_than(1), Forest::new(0b0101_0100).unwrap() );
202239 /// ```
203240 pub fn trees_larger_than ( self , tree_idx : u32 ) -> Self {
204- self & high_bitmask ( tree_idx + 1 )
241+ let mask = high_bitmask ( tree_idx + 1 ) ;
242+ Self :: new ( self . 0 & mask) . expect ( "forest size exceeds maximum" )
205243 }
206244
207245 /// Creates a new forest with all possible trees smaller than the smallest tree in this
@@ -216,7 +254,7 @@ impl Forest {
216254 /// For a non-panicking version of this function, see [`Forest::all_smaller_trees()`].
217255 pub fn all_smaller_trees_unchecked ( self ) -> Self {
218256 debug_assert_eq ! ( self . num_trees( ) , 1 ) ;
219- Self :: new ( self . 0 - 1 )
257+ Self :: new ( self . 0 - 1 ) . expect ( "forest size exceeds maximum" )
220258 }
221259
222260 /// Creates a new forest with all possible trees smaller than the smallest tree in this
@@ -232,9 +270,16 @@ impl Forest {
232270 }
233271
234272 /// Returns a forest with exactly one tree, one size (depth) larger than the current one.
235- pub fn next_larger_tree ( self ) -> Self {
273+ ///
274+ /// # Errors
275+ /// Returns an error if the resulting forest would exceed [`Forest::MAX_LEAVES`].
276+ pub ( crate ) fn next_larger_tree ( self ) -> Result < Self , MmrError > {
236277 debug_assert_eq ! ( self . num_trees( ) , 1 ) ;
237- Forest ( self . 0 << 1 )
278+ let value = self . 0 . saturating_mul ( 2 ) ;
279+ if value > Self :: MAX_LEAVES {
280+ return Err ( MmrError :: ForestSizeExceeded { requested : value, max : Self :: MAX_LEAVES } ) ;
281+ }
282+ Ok ( Forest ( value) )
238283 }
239284
240285 /// Returns true if the forest contains a single-node tree.
@@ -244,25 +289,29 @@ impl Forest {
244289
245290 /// Add a single-node tree if not already present in the forest.
246291 pub fn with_single_leaf ( self ) -> Self {
247- Self :: new ( self . 0 | 1 )
292+ // Setting the lowest bit cannot exceed MAX_LEAVES when MAX_LEAVES is 2^k - 1.
293+ Self ( self . 0 | 1 )
248294 }
249295
250296 /// Remove the single-node tree if present in the forest.
251297 pub fn without_single_leaf ( self ) -> Self {
252- Self :: new ( self . 0 & ( usize:: MAX - 1 ) )
298+ // Clearing the lowest bit does not add leaves.
299+ Self ( self . 0 & ( usize:: MAX - 1 ) )
253300 }
254301
255302 /// Returns a new forest that does not have the trees that `other` has.
256303 pub fn without_trees ( self , other : Forest ) -> Self {
257- self ^ other
304+ // Clearing bits does not add leaves.
305+ Self ( self . 0 & !other. 0 )
258306 }
259307
260308 /// Returns index of the forest tree for a specified leaf index.
261309 pub fn tree_index ( & self , leaf_idx : usize ) -> usize {
262310 let root = self
263311 . leaf_to_corresponding_tree ( leaf_idx)
264312 . expect ( "position must be part of the forest" ) ;
265- let smaller_tree_mask = Self :: new ( 2_usize . pow ( root) - 1 ) ;
313+ let smaller_tree_mask =
314+ Self :: new ( 2_usize . pow ( root) - 1 ) . expect ( "forest size exceeds maximum" ) ;
266315 let num_smaller_trees = ( * self & smaller_tree_mask) . num_trees ( ) ;
267316 self . num_trees ( ) - num_smaller_trees - 1
268317 }
@@ -350,8 +399,7 @@ impl Forest {
350399 /// Given a leaf index in the current forest, return the tree number responsible for the
351400 /// leaf.
352401 ///
353- /// Note:
354- /// The result is a tree position `p`, it has the following interpretations:
402+ /// The result is a tree position `p`:
355403 /// - `p+1` is the depth of the tree.
356404 /// - Because the root element is not part of the proof, `p` is the length of the authentication
357405 /// path.
@@ -396,8 +444,8 @@ impl Forest {
396444 /// the leaf belongs.
397445 pub ( super ) fn leaf_relative_position ( self , leaf_idx : usize ) -> Option < usize > {
398446 let tree_idx = self . leaf_to_corresponding_tree ( leaf_idx) ?;
399- let forest_before = self & high_bitmask ( tree_idx + 1 ) ;
400- Some ( leaf_idx - forest_before . 0 )
447+ let mask = high_bitmask ( tree_idx + 1 ) ;
448+ Some ( leaf_idx - ( self . 0 & mask ) )
401449 }
402450}
403451
@@ -417,23 +465,27 @@ impl BitAnd<Forest> for Forest {
417465 type Output = Self ;
418466
419467 fn bitand ( self , rhs : Self ) -> Self :: Output {
420- Self :: new ( self . 0 & rhs. 0 )
468+ Self :: new ( self . 0 & rhs. 0 ) . expect ( "forest size exceeds maximum" )
421469 }
422470}
423471
472+ // Compile-time invariant: MAX_LEAVES must be exactly 2^k - 1.
473+ const _: ( ) =
474+ assert ! ( Forest :: MAX_LEAVES != 0 && ( Forest :: MAX_LEAVES & ( Forest :: MAX_LEAVES + 1 ) ) == 0 ) ;
475+
424476impl BitOr < Forest > for Forest {
425477 type Output = Self ;
426478
427479 fn bitor ( self , rhs : Self ) -> Self :: Output {
428- Self :: new ( self . 0 | rhs. 0 )
480+ Self ( self . 0 | rhs. 0 )
429481 }
430482}
431483
432484impl BitXor < Forest > for Forest {
433485 type Output = Self ;
434486
435487 fn bitxor ( self , rhs : Self ) -> Self :: Output {
436- Self :: new ( self . 0 ^ rhs. 0 )
488+ Self ( self . 0 ^ rhs. 0 )
437489 }
438490}
439491
@@ -443,9 +495,29 @@ impl BitXorAssign<Forest> for Forest {
443495 }
444496}
445497
446- impl From < Felt > for Forest {
447- fn from ( value : Felt ) -> Self {
448- Self :: new ( value. as_canonical_u64 ( ) as usize )
498+ impl TryFrom < Felt > for Forest {
499+ type Error = MmrError ;
500+
501+ fn try_from ( value : Felt ) -> Result < Self , Self :: Error > {
502+ let value = usize:: try_from ( value. as_canonical_u64 ( ) ) . map_err ( |_| {
503+ MmrError :: ForestSizeExceeded {
504+ requested : usize:: MAX ,
505+ max : Self :: MAX_LEAVES ,
506+ }
507+ } ) ?;
508+ if value > Self :: MAX_LEAVES {
509+ return Err ( MmrError :: ForestSizeExceeded { requested : value, max : Self :: MAX_LEAVES } ) ;
510+ }
511+ Ok ( Self ( value) )
512+ }
513+ }
514+
515+ pub ( crate ) fn largest_tree_from_mask ( mask : usize ) -> Forest {
516+ if mask == 0 {
517+ Forest :: empty ( )
518+ } else {
519+ let bit = mask. ilog2 ( ) ;
520+ Forest :: new ( 1usize << bit) . expect ( "forest size exceeds maximum" )
449521 }
450522}
451523
@@ -456,12 +528,8 @@ impl From<Forest> for Felt {
456528}
457529
458530/// Return a bitmask for the bits including and above the given position.
459- pub ( crate ) const fn high_bitmask ( bit : u32 ) -> Forest {
460- if bit > usize:: BITS - 1 {
461- Forest :: empty ( )
462- } else {
463- Forest :: new ( usize:: MAX << bit)
464- }
531+ pub ( crate ) fn high_bitmask ( bit : u32 ) -> usize {
532+ if bit > usize:: BITS - 1 { 0 } else { usize:: MAX << bit }
465533}
466534
467535// SERIALIZATION
@@ -476,7 +544,18 @@ impl Serializable for Forest {
476544impl Deserializable for Forest {
477545 fn read_from < R : ByteReader > ( source : & mut R ) -> Result < Self , DeserializationError > {
478546 let value = source. read_usize ( ) ?;
479- Ok ( Self :: new ( value) )
547+ Self :: new ( value)
548+ }
549+ }
550+
551+ #[ cfg( feature = "serde" ) ]
552+ impl < ' de > serde:: Deserialize < ' de > for Forest {
553+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
554+ where
555+ D : serde:: Deserializer < ' de > ,
556+ {
557+ let value = usize:: deserialize ( deserializer) ?;
558+ Self :: new ( value) . map_err ( serde:: de:: Error :: custom)
480559 }
481560}
482561
0 commit comments