@@ -48,54 +48,6 @@ pub struct MerkleTree {
4848 nodes : Vec < Digest > ,
4949}
5050
51- /// A trait for creating a [`MerkleTree`] from a list of [`Digest`]s.
52- ///
53- /// This trait defines the method required to construct a `MerkleTree` given an
54- /// array of `Digest` values. Implementations of this trait can define different
55- /// strategies for building the tree, for example parallel or sequential
56- /// construction, using the CPU or a GPU, et cetera.
57- ///
58- /// It might be more intuitive to use [`MerkleTree::new`] over directly calling
59- /// implementors of this trait. For example:
60- ///
61- /// ```
62- /// # use twenty_first::error::MerkleTreeError;
63- /// # use twenty_first::prelude::*;
64- ///
65- /// # fn wrapper_fn() -> Result<(), MerkleTreeError> {
66- /// let leafs = [bfe_vec![42, 43, 44], bfe_vec![1337, 1338]];
67- /// let leaf_digests = leafs.map(|leaf| Tip5::hash_varlen(&leaf));
68- ///
69- /// let tree = MerkleTree::new::<CpuParallel>(&leaf_digests)?;
70- ///
71- /// // also works:
72- /// let tree = CpuParallel::from_digests(&leaf_digests)?;
73- /// # Ok(())
74- /// # }
75- /// # wrapper_fn().unwrap();
76- /// ```
77- ///
78- /// # Implementing
79- ///
80- /// Implementing this trait requires intimate knowledge of the internal
81- /// representation of a [`MerkleTree`], in particular, the indexing of its
82- /// nodes. For a starting point, see [`MerkleTree::authentication_structure`].
83- ///
84- /// ## Errors
85- ///
86- /// Implementations of this trait should return an error if:
87- /// - The number of digests is zero.
88- /// - The number of digests is not a power of two.
89- pub trait MerkleTreeMaker {
90- /// Build a MerkleTree. The passed-in digests are copied as the leafs of the tree.
91- ///
92- /// # Errors
93- ///
94- /// - If the number of digests is zero.
95- /// - If the number of digests is not a power of two.
96- fn from_digests ( digests : & [ Digest ] ) -> Result < MerkleTree > ;
97- }
98-
9951/// A full inclusion proof for the leafs at the supplied indices, including the
10052/// leafs themselves. The proof is relative to some [Merkle tree](MerkleTree),
10153/// which is not necessarily (and generally cannot be) known in its entirety by
@@ -152,8 +104,79 @@ impl MerkleTree {
152104 /// If you need to read the root, try [`root()`](Self::root) instead.
153105 pub ( crate ) const ROOT_INDEX : usize = 1 ;
154106
155- pub fn new < Maker : MerkleTreeMaker > ( leafs : & [ Digest ] ) -> Result < Self > {
156- Maker :: from_digests ( leafs)
107+ /// Build a MerkleTree with the given leafs.
108+ ///
109+ /// [`MerkleTree::par_new`] is equivalent and usually faster.
110+ ///
111+ /// # Errors
112+ ///
113+ /// - If the number of leafs is zero.
114+ /// - If the number of leafs is not a power of two.
115+ pub fn sequential_new ( leafs : & [ Digest ] ) -> Result < Self > {
116+ let mut nodes = Self :: initialize_merkle_tree_nodes ( leafs) ?;
117+
118+ for i in ( MerkleTree :: ROOT_INDEX ..leafs. len ( ) ) . rev ( ) {
119+ nodes[ i] = Tip5 :: hash_pair ( nodes[ i * 2 ] , nodes[ i * 2 + 1 ] ) ;
120+ }
121+
122+ Ok ( MerkleTree { nodes } )
123+ }
124+
125+ /// Build a MerkleTree with the given leafs.
126+ ///
127+ /// Uses [`rayon`] to parallelize Merkle tree construction. If the use of
128+ /// [`rayon`] is not an option in your context, use
129+ /// [`MerkleTree::sequential_new`], which is equivalent but usually slower.
130+ ///
131+ /// # Errors
132+ ///
133+ /// - If the number of leafs is zero.
134+ /// - If the number of leafs is not a power of two.
135+ pub fn par_new ( leafs : & [ Digest ] ) -> Result < Self > {
136+ let mut nodes = Self :: initialize_merkle_tree_nodes ( leafs) ?;
137+
138+ // parallel
139+ let mut num_nodes_on_this_level = leafs. len ( ) ;
140+ while num_nodes_on_this_level >= * PARALLELIZATION_CUTOFF {
141+ num_nodes_on_this_level /= 2 ;
142+ let node_indices_on_this_level = num_nodes_on_this_level..2 * num_nodes_on_this_level;
143+ let nodes_on_this_level = node_indices_on_this_level
144+ . clone ( )
145+ . into_par_iter ( )
146+ . map ( |i| Tip5 :: hash_pair ( nodes[ i * 2 ] , nodes[ i * 2 + 1 ] ) )
147+ . collect :: < Vec < _ > > ( ) ;
148+ nodes[ node_indices_on_this_level] . copy_from_slice ( & nodes_on_this_level) ;
149+ }
150+
151+ // sequential
152+ let num_remaining_nodes = num_nodes_on_this_level;
153+ for i in ( MerkleTree :: ROOT_INDEX ..num_remaining_nodes) . rev ( ) {
154+ nodes[ i] = Tip5 :: hash_pair ( nodes[ i * 2 ] , nodes[ i * 2 + 1 ] ) ;
155+ }
156+
157+ Ok ( MerkleTree { nodes } )
158+ }
159+
160+ /// Helps to kick off Merkle tree construction. Sets up the Merkle tree's
161+ /// internal nodes if (and only if) it is possible to construct a Merkle
162+ /// tree with the given leafs.
163+ fn initialize_merkle_tree_nodes ( leafs : & [ Digest ] ) -> Result < Vec < Digest > > {
164+ if leafs. is_empty ( ) {
165+ return Err ( MerkleTreeError :: TooFewLeafs ) ;
166+ }
167+
168+ let num_leafs = leafs. len ( ) ;
169+ if !num_leafs. is_power_of_two ( ) {
170+ return Err ( MerkleTreeError :: IncorrectNumberOfLeafs ) ;
171+ }
172+ if num_leafs > MAX_NUM_LEAFS {
173+ return Err ( MerkleTreeError :: TreeTooHigh ) ;
174+ }
175+
176+ let mut nodes = vec ! [ Digest :: default ( ) ; 2 * num_leafs] ;
177+ nodes[ num_leafs..] . copy_from_slice ( leafs) ;
178+
179+ Ok ( nodes)
157180 }
158181
159182 /// Given a list of leaf indices, return the indices of exactly those nodes that
@@ -307,7 +330,7 @@ impl<'a> Arbitrary<'a> for MerkleTree {
307330 let leaf_digests: arbitrary:: Result < Vec < _ > > =
308331 ( 0 ..num_leafs) . map ( |_| u. arbitrary ( ) ) . collect ( ) ;
309332
310- let tree = Self :: new :: < CpuParallel > ( & leaf_digests?) . unwrap ( ) ;
333+ let tree = Self :: par_new ( & leaf_digests?) . unwrap ( ) ;
311334 Ok ( tree)
312335 }
313336}
@@ -518,76 +541,6 @@ impl TryFrom<MerkleTreeInclusionProof> for PartialMerkleTree {
518541 }
519542}
520543
521- /// [Build a Merkle tree](MerkleTreeMaker) using parallelism.
522- #[ derive( Debug , Copy , Clone , Eq , PartialEq , Default ) ]
523- pub struct CpuParallel ;
524-
525- impl MerkleTreeMaker for CpuParallel {
526- fn from_digests ( digests : & [ Digest ] ) -> Result < MerkleTree > {
527- let mut nodes = initialize_merkle_tree_nodes ( digests) ?;
528-
529- // parallel
530- let mut num_nodes_on_this_level = digests. len ( ) ;
531- while num_nodes_on_this_level >= * PARALLELIZATION_CUTOFF {
532- num_nodes_on_this_level /= 2 ;
533- let node_indices_on_this_level = num_nodes_on_this_level..2 * num_nodes_on_this_level;
534- let nodes_on_this_level = node_indices_on_this_level
535- . clone ( )
536- . into_par_iter ( )
537- . map ( |i| Tip5 :: hash_pair ( nodes[ i * 2 ] , nodes[ i * 2 + 1 ] ) )
538- . collect :: < Vec < _ > > ( ) ;
539- nodes[ node_indices_on_this_level] . copy_from_slice ( & nodes_on_this_level) ;
540- }
541-
542- // sequential
543- let num_remaining_nodes = num_nodes_on_this_level;
544- for i in ( MerkleTree :: ROOT_INDEX ..num_remaining_nodes) . rev ( ) {
545- nodes[ i] = Tip5 :: hash_pair ( nodes[ i * 2 ] , nodes[ i * 2 + 1 ] ) ;
546- }
547-
548- Ok ( MerkleTree { nodes } )
549- }
550- }
551-
552- /// [Build a Merkle tree](MerkleTreeMaker) without any parallelism.
553- #[ derive( Debug , Copy , Clone , Eq , PartialEq , Default ) ]
554- pub struct CpuSequential ;
555-
556- impl MerkleTreeMaker for CpuSequential {
557- fn from_digests ( digests : & [ Digest ] ) -> Result < MerkleTree > {
558- let mut nodes = initialize_merkle_tree_nodes ( digests) ?;
559-
560- let num_leafs = digests. len ( ) ;
561- for i in ( MerkleTree :: ROOT_INDEX ..num_leafs) . rev ( ) {
562- nodes[ i] = Tip5 :: hash_pair ( nodes[ i * 2 ] , nodes[ i * 2 + 1 ] ) ;
563- }
564-
565- Ok ( MerkleTree { nodes } )
566- }
567- }
568-
569- /// Helps to kick off Merkle tree construction. Sets up the Merkle tree's
570- /// internal nodes if (and only if) it is possible to construct a Merkle
571- /// tree with the given leafs.
572- fn initialize_merkle_tree_nodes ( digests : & [ Digest ] ) -> Result < Vec < Digest > > {
573- if digests. is_empty ( ) {
574- return Err ( MerkleTreeError :: TooFewLeafs ) ;
575- }
576-
577- let num_leafs = digests. len ( ) ;
578- if !num_leafs. is_power_of_two ( ) {
579- return Err ( MerkleTreeError :: IncorrectNumberOfLeafs ) ;
580- }
581- if num_leafs > MAX_NUM_LEAFS {
582- return Err ( MerkleTreeError :: TreeTooHigh ) ;
583- }
584-
585- let mut nodes = vec ! [ Digest :: default ( ) ; 2 * num_leafs] ;
586- nodes[ num_leafs..] . copy_from_slice ( digests) ;
587-
588- Ok ( nodes)
589- }
590-
591544#[ derive( Debug , Clone , Copy , PartialEq , Eq , Error ) ]
592545pub enum MerkleTreeError {
593546 #[ error( "All leaf indices must be valid, i.e., less than {num_leafs}." ) ]
@@ -633,7 +586,7 @@ pub mod merkle_tree_test {
633586 let num_leafs = 1 << tree_height;
634587 let leafs = ( 0 ..num_leafs) . map ( BFieldElement :: new) ;
635588 let leaf_digests = leafs. map ( |bfe| Tip5 :: hash_varlen ( & [ bfe] ) ) . collect_vec ( ) ;
636- let tree = Self :: new :: < CpuParallel > ( & leaf_digests) . unwrap ( ) ;
589+ let tree = Self :: par_new ( & leaf_digests) . unwrap ( ) ;
637590 assert ! ( leaf_digests. iter( ) . all_unique( ) ) ;
638591 tree
639592 }
@@ -674,22 +627,22 @@ pub mod merkle_tree_test {
674627
675628 #[ test]
676629 fn building_merkle_tree_from_empty_list_of_digests_fails_with_expected_error ( ) {
677- let maybe_tree = MerkleTree :: new :: < CpuParallel > ( & [ ] ) ;
630+ let maybe_tree = MerkleTree :: par_new ( & [ ] ) ;
678631 let err = maybe_tree. unwrap_err ( ) ;
679632 assert_eq ! ( MerkleTreeError :: TooFewLeafs , err) ;
680633 }
681634
682635 #[ test]
683636 fn merkle_tree_with_one_leaf_has_expected_height_and_number_of_leafs ( ) {
684637 let digest = Digest :: default ( ) ;
685- let tree = MerkleTree :: new :: < CpuParallel > ( & [ digest] ) . unwrap ( ) ;
638+ let tree = MerkleTree :: par_new ( & [ digest] ) . unwrap ( ) ;
686639 assert_eq ! ( 1 , tree. num_leafs( ) ) ;
687640 assert_eq ! ( 0 , tree. height( ) ) ;
688641 }
689642
690643 #[ proptest]
691644 fn building_merkle_tree_from_one_digest_makes_that_digest_the_root ( digest : Digest ) {
692- let tree = MerkleTree :: new :: < CpuParallel > ( & [ digest] ) . unwrap ( ) ;
645+ let tree = MerkleTree :: par_new ( & [ digest] ) . unwrap ( ) ;
693646 assert_eq ! ( digest, tree. root( ) ) ;
694647 }
695648
@@ -701,26 +654,26 @@ pub mod merkle_tree_test {
701654 ) {
702655 let digest = Digest :: default ( ) ;
703656 let digests = vec ! [ digest; num_leafs] ;
704- let maybe_tree = MerkleTree :: new :: < CpuParallel > ( & digests) ;
657+ let maybe_tree = MerkleTree :: par_new ( & digests) ;
705658 let err = maybe_tree. unwrap_err ( ) ;
706659 assert_eq ! ( MerkleTreeError :: IncorrectNumberOfLeafs , err) ;
707660 }
708661
709662 #[ proptest]
710- fn merkle_tree_makers_behave_identically_on_random_input ( leafs : Vec < Digest > ) {
711- let parallel = MerkleTree :: new :: < CpuParallel > ( & leafs) ;
712- let sequential = MerkleTree :: new :: < CpuSequential > ( & leafs) ;
713- prop_assert_eq ! ( parallel , sequential ) ;
663+ fn merkle_tree_construction_strategies_behave_identically_on_random_input ( leafs : Vec < Digest > ) {
664+ let sequential = MerkleTree :: sequential_new ( & leafs) ;
665+ let parallel = MerkleTree :: par_new ( & leafs) ;
666+ prop_assert_eq ! ( sequential , parallel ) ;
714667 }
715668
716669 #[ proptest]
717- fn merkle_tree_makers_produce_identical_trees (
670+ fn merkle_tree_construction_strategies_produce_identical_trees (
718671 #[ strategy( 0_usize ..10 ) ] _tree_height : usize ,
719672 #[ strategy( vec( arb( ) , 1 << #_tree_height) ) ] leafs : Vec < Digest > ,
720673 ) {
721- let parallel = MerkleTree :: new :: < CpuParallel > ( & leafs) ?;
722- let sequential = MerkleTree :: new :: < CpuSequential > ( & leafs) ?;
723- prop_assert_eq ! ( parallel , sequential ) ;
674+ let sequential = MerkleTree :: sequential_new ( & leafs) ?;
675+ let parallel = MerkleTree :: par_new ( & leafs) ?;
676+ prop_assert_eq ! ( sequential , parallel ) ;
724677 }
725678
726679 #[ proptest( cases = 100 ) ]
0 commit comments