@@ -22,13 +22,11 @@ use zeroize::Zeroizing;
2222use crate :: {
2323 gray:: GrayIterator ,
2424 statement:: Statement ,
25- util:: { NullRng , OperationTiming } ,
25+ transcript:: ProofTranscript ,
26+ util:: { delta, NullRng , OperationTiming } ,
2627 witness:: Witness ,
2728} ;
2829
29- // Proof version flag
30- const VERSION : u64 = 0 ;
31-
3230// Size of serialized proof elements in bytes
3331const SERIALIZED_BYTES : usize = 32 ;
3432
@@ -66,38 +64,6 @@ pub enum ProofError {
6664 FailedVerification ,
6765}
6866
69- /// Constant-time Kronecker delta function with scalar output.
70- fn delta ( x : u32 , y : u32 ) -> Scalar {
71- let mut result = Scalar :: ZERO ;
72- result. conditional_assign ( & Scalar :: ONE , x. ct_eq ( & y) ) ;
73- result
74- }
75-
76- /// Get nonzero powers of a challenge value from a transcript.
77- ///
78- /// If successful, returns powers of the challenge with exponents `[0, m]`.
79- /// If any power is zero, returns an error.
80- fn xi_powers ( transcript : & mut Transcript , m : u32 ) -> Result < Vec < Scalar > , ProofError > {
81- // Get the verifier challenge using wide reduction
82- let mut xi_bytes = [ 0u8 ; 64 ] ;
83- transcript. challenge_bytes ( "xi" . as_bytes ( ) , & mut xi_bytes) ;
84- let xi = Scalar :: from_bytes_mod_order_wide ( & xi_bytes) ;
85-
86- // Get powers of the challenge and confirm they are nonzero
87- let mut xi_powers = Vec :: with_capacity ( ( m as usize ) . checked_add ( 1 ) . ok_or ( ProofError :: InvalidParameter ) ?) ;
88- let mut xi_power = Scalar :: ONE ;
89- for _ in 0 ..=m {
90- if xi_power == Scalar :: ZERO {
91- return Err ( ProofError :: InvalidChallenge ) ;
92- }
93-
94- xi_powers. push ( xi_power) ;
95- xi_power *= xi;
96- }
97-
98- Ok ( xi_powers)
99- }
100-
10167impl Proof {
10268 /// Generate a Triptych [`Proof`].
10369 ///
@@ -217,26 +183,15 @@ impl Proof {
217183 return Err ( ProofError :: InvalidParameter ) ;
218184 }
219185
220- // Continue the transcript with domain separation
221- transcript. append_message ( "dom-sep" . as_bytes ( ) , "Triptych proof" . as_bytes ( ) ) ;
222- transcript. append_u64 ( "version" . as_bytes ( ) , VERSION ) ;
223- transcript. append_message ( "params" . as_bytes ( ) , params. get_hash ( ) ) ;
224- transcript. append_message ( "M" . as_bytes ( ) , statement. get_input_set ( ) . get_hash ( ) ) ;
225- transcript. append_message ( "J" . as_bytes ( ) , J . compress ( ) . as_bytes ( ) ) ;
226-
227- // Construct a random number generator at the current transcript state
228- let mut transcript_rng = transcript
229- . build_rng ( )
230- . rekey_with_witness_bytes ( "l" . as_bytes ( ) , & l. to_le_bytes ( ) )
231- . rekey_with_witness_bytes ( "r" . as_bytes ( ) , r. as_bytes ( ) )
232- . finalize ( rng) ;
186+ // Set up the transcript
187+ let mut transcript = ProofTranscript :: new ( transcript, statement, rng, Some ( witness) ) ;
233188
234189 // Compute the `A` matrix commitment
235- let r_A = Scalar :: random ( & mut transcript_rng ) ;
190+ let r_A = Scalar :: random ( transcript . as_mut_rng ( ) ) ;
236191 let mut a = ( 0 ..params. get_m ( ) )
237192 . map ( |_| {
238193 ( 0 ..params. get_n ( ) )
239- . map ( |_| Scalar :: random ( & mut transcript_rng ) )
194+ . map ( |_| Scalar :: random ( transcript . as_mut_rng ( ) ) )
240195 . collect :: < Vec < Scalar > > ( )
241196 } )
242197 . collect :: < Vec < Vec < Scalar > > > ( ) ;
@@ -248,7 +203,7 @@ impl Proof {
248203 . map_err ( |_| ProofError :: InvalidParameter ) ?;
249204
250205 // Compute the `B` matrix commitment
251- let r_B = Scalar :: random ( & mut transcript_rng ) ;
206+ let r_B = Scalar :: random ( transcript . as_mut_rng ( ) ) ;
252207 let l_decomposed = match timing {
253208 OperationTiming :: Constant => {
254209 GrayIterator :: decompose ( params. get_n ( ) , params. get_m ( ) , l) . ok_or ( ProofError :: InvalidParameter ) ?
@@ -269,7 +224,7 @@ impl Proof {
269224
270225 // Compute the `C` matrix commitment
271226 let two = Scalar :: from ( 2u32 ) ;
272- let r_C = Scalar :: random ( & mut transcript_rng ) ;
227+ let r_C = Scalar :: random ( transcript . as_mut_rng ( ) ) ;
273228 let a_sigma = ( 0 ..params. get_m ( ) )
274229 . map ( |j| {
275230 ( 0 ..params. get_n ( ) )
@@ -282,7 +237,7 @@ impl Proof {
282237 . map_err ( |_| ProofError :: InvalidParameter ) ?;
283238
284239 // Compute the `D` matrix commitment
285- let r_D = Scalar :: random ( & mut transcript_rng ) ;
240+ let r_D = Scalar :: random ( transcript . as_mut_rng ( ) ) ;
286241 let a_square = ( 0 ..params. get_m ( ) )
287242 . map ( |j| {
288243 ( 0 ..params. get_n ( ) )
@@ -297,7 +252,7 @@ impl Proof {
297252 // Random masks
298253 let rho = Zeroizing :: new (
299254 ( 0 ..params. get_m ( ) )
300- . map ( |_| Scalar :: random ( & mut transcript_rng ) )
255+ . map ( |_| Scalar :: random ( transcript . as_mut_rng ( ) ) )
301256 . collect :: < Vec < Scalar > > ( ) ,
302257 ) ;
303258
@@ -365,20 +320,8 @@ impl Proof {
365320 // Compute `Y` vector
366321 let Y = rho. iter ( ) . map ( |rho| rho * J ) . collect :: < Vec < RistrettoPoint > > ( ) ;
367322
368- // Update the transcript
369- transcript. append_message ( "A" . as_bytes ( ) , A . compress ( ) . as_bytes ( ) ) ;
370- transcript. append_message ( "B" . as_bytes ( ) , B . compress ( ) . as_bytes ( ) ) ;
371- transcript. append_message ( "C" . as_bytes ( ) , C . compress ( ) . as_bytes ( ) ) ;
372- transcript. append_message ( "D" . as_bytes ( ) , D . compress ( ) . as_bytes ( ) ) ;
373- for item in & X {
374- transcript. append_message ( "X" . as_bytes ( ) , item. compress ( ) . as_bytes ( ) ) ;
375- }
376- for item in & Y {
377- transcript. append_message ( "Y" . as_bytes ( ) , item. compress ( ) . as_bytes ( ) ) ;
378- }
379-
380- // Get challenge powers
381- let xi_powers = xi_powers ( transcript, params. get_m ( ) ) ?;
323+ // Run the Fiat-Shamir commitment phase to get the challenge powers
324+ let xi_powers = transcript. commit ( params, & A , & B , & C , & D , & X , & Y ) ?;
382325
383326 // Compute the `f` matrix
384327 let f = ( 0 ..params. get_m ( ) )
@@ -543,47 +486,24 @@ impl Proof {
543486 // Set up a transcript generator for use in weighting
544487 let mut transcript_weights = Transcript :: new ( "Triptych verifier weights" . as_bytes ( ) ) ;
545488
489+ let mut null_rng = NullRng ;
490+
546491 // Generate all verifier challenges
547492 let mut xi_powers_all = Vec :: with_capacity ( proofs. len ( ) ) ;
548493 for ( statement, proof, transcript) in izip ! ( statements. iter( ) , proofs. iter( ) , transcripts. iter_mut( ) ) {
549- // Generate the verifier challenge
550- transcript. append_message ( "dom-sep" . as_bytes ( ) , "Triptych proof" . as_bytes ( ) ) ;
551- transcript. append_u64 ( "version" . as_bytes ( ) , VERSION ) ;
552- transcript. append_message ( "params" . as_bytes ( ) , params. get_hash ( ) ) ;
553- transcript. append_message ( "M" . as_bytes ( ) , statement. get_input_set ( ) . get_hash ( ) ) ;
554- transcript. append_message ( "J" . as_bytes ( ) , statement. get_J ( ) . compress ( ) . as_bytes ( ) ) ;
555-
556- transcript. append_message ( "A" . as_bytes ( ) , proof. A . compress ( ) . as_bytes ( ) ) ;
557- transcript. append_message ( "B" . as_bytes ( ) , proof. B . compress ( ) . as_bytes ( ) ) ;
558- transcript. append_message ( "C" . as_bytes ( ) , proof. C . compress ( ) . as_bytes ( ) ) ;
559- transcript. append_message ( "D" . as_bytes ( ) , proof. D . compress ( ) . as_bytes ( ) ) ;
560- for item in & proof. X {
561- transcript. append_message ( "X" . as_bytes ( ) , item. compress ( ) . as_bytes ( ) ) ;
562- }
563- for item in & proof. Y {
564- transcript. append_message ( "Y" . as_bytes ( ) , item. compress ( ) . as_bytes ( ) ) ;
565- }
566-
567- // Get challenge powers
568- let xi_powers = xi_powers ( transcript, params. get_m ( ) ) ?;
569- xi_powers_all. push ( xi_powers) ;
494+ // Set up the transcript
495+ let mut transcript = ProofTranscript :: new ( transcript, statement, & mut null_rng, None ) ;
570496
571- // Finish the transcript for pseudorandom number generation
572- for f_row in & proof. f {
573- for f in f_row {
574- transcript. append_message ( "f" . as_bytes ( ) , f. as_bytes ( ) ) ;
575- }
576- }
577- transcript. append_message ( "z_A" . as_bytes ( ) , proof. z_A . as_bytes ( ) ) ;
578- transcript. append_message ( "z_C" . as_bytes ( ) , proof. z_C . as_bytes ( ) ) ;
579- transcript. append_message ( "z" . as_bytes ( ) , proof. z . as_bytes ( ) ) ;
580- let mut transcript_rng = transcript. build_rng ( ) . finalize ( & mut NullRng ) ;
497+ // Run the Fiat-Shamir commitment phase to get the challenge powers
498+ xi_powers_all. push ( transcript. commit ( params, & proof. A , & proof. B , & proof. C , & proof. D , & proof. X , & proof. Y ) ?) ;
581499
500+ // Run the Fiat-Shamir response phase to get the transcript generator and weight
501+ let mut transcript_rng = transcript. response ( & proof. f , & proof. z_A , & proof. z_C , & proof. z ) ;
582502 transcript_weights. append_u64 ( "proof" . as_bytes ( ) , transcript_rng. as_rngcore ( ) . next_u64 ( ) ) ;
583503 }
584504
585505 // Finalize the weighting transcript into a pseudorandom number generator
586- let mut transcript_weights_rng = transcript_weights. build_rng ( ) . finalize ( & mut NullRng ) ;
506+ let mut transcript_weights_rng = transcript_weights. build_rng ( ) . finalize ( & mut null_rng ) ;
587507
588508 // Process each proof
589509 for ( proof, xi_powers) in proofs. iter ( ) . zip ( xi_powers_all. iter ( ) ) {
0 commit comments