11use rand:: Rng ;
2+ use rayon:: prelude:: * ;
23use serde:: { Serialize , de:: DeserializeOwned } ;
34
5+ use crate :: symmetric:: prf:: Pseudorandom ;
6+
47/// Trait to model a tweakable hash function.
58/// Such a function takes a public parameter, a tweak, and a
69/// message to be hashed. The tweak should be understood as an
@@ -14,8 +17,13 @@ use serde::{Serialize, de::DeserializeOwned};
1417/// to obtain distinct tweaks for applications in chains and
1518/// applications in Merkle trees.
1619pub trait TweakableHash {
20+ /// Public parameter type for the hash function
1721 type Parameter : Copy + Sized + Send + Sync + Serialize + DeserializeOwned ;
22+
23+ /// Tweak type for domain separation
1824 type Tweak ;
25+
26+ /// Domain element type (defines output and input types to the hash)
1927 type Domain : Copy + PartialEq + Sized + Send + Sync + Serialize + DeserializeOwned ;
2028
2129 /// Generates a random public parameter.
@@ -39,8 +47,50 @@ pub trait TweakableHash {
3947 message : & [ Self :: Domain ] ,
4048 ) -> Self :: Domain ;
4149
42- /// Function to check internal consistency of any given parameters
43- /// For testing only, and expected to panic if something is wrong.
50+ /// Computes bottom tree leaves by walking hash chains for multiple epochs.
51+ ///
52+ /// This method has a default scalar implementation that processes epochs in parallel.
53+ fn compute_tree_leaves < PRF > (
54+ prf_key : & PRF :: Key ,
55+ parameter : & Self :: Parameter ,
56+ epochs : & [ u32 ] ,
57+ num_chains : usize ,
58+ chain_length : usize ,
59+ ) -> Vec < Self :: Domain >
60+ where
61+ PRF : Pseudorandom ,
62+ PRF :: Domain : Into < Self :: Domain > ,
63+ Self : Sized ,
64+ {
65+ // Default scalar implementation: process each epoch in parallel
66+ epochs
67+ . par_iter ( )
68+ . map ( |& epoch| {
69+ // For each epoch, walk all chains in parallel
70+ let chain_ends: Vec < _ > = ( 0 ..num_chains)
71+ . into_par_iter ( )
72+ . map ( |chain_index| {
73+ let start =
74+ PRF :: get_domain_element ( prf_key, epoch, chain_index as u64 ) . into ( ) ;
75+ chain :: < Self > (
76+ parameter,
77+ epoch,
78+ chain_index as u8 ,
79+ 0 ,
80+ chain_length - 1 ,
81+ & start,
82+ )
83+ } )
84+ . collect ( ) ;
85+ // Hash all chain ends together to get the leaf
86+ Self :: apply ( parameter, & Self :: tree_tweak ( 0 , epoch) , & chain_ends)
87+ } )
88+ . collect ( )
89+ }
90+
91+ /// Function to check internal consistency of any given parameters.
92+ ///
93+ /// This is for testing only and is expected to panic if something is wrong.
4494 #[ cfg( test) ]
4595 fn internal_consistency_check ( ) ;
4696}
@@ -77,7 +127,6 @@ pub mod poseidon;
77127
78128#[ cfg( test) ]
79129mod tests {
80-
81130 use crate :: symmetric:: tweak_hash:: poseidon:: PoseidonTweak44 ;
82131
83132 use super :: * ;
0 commit comments