@@ -22,13 +22,11 @@ use zeroize::Zeroizing;
22
22
use crate :: {
23
23
gray:: GrayIterator ,
24
24
statement:: Statement ,
25
- util:: { NullRng , OperationTiming } ,
25
+ transcript:: ProofTranscript ,
26
+ util:: { delta, NullRng , OperationTiming } ,
26
27
witness:: Witness ,
27
28
} ;
28
29
29
- // Proof version flag
30
- const VERSION : u64 = 0 ;
31
-
32
30
// Size of serialized proof elements in bytes
33
31
const SERIALIZED_BYTES : usize = 32 ;
34
32
@@ -66,38 +64,6 @@ pub enum ProofError {
66
64
FailedVerification ,
67
65
}
68
66
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
-
101
67
impl Proof {
102
68
/// Generate a Triptych [`Proof`].
103
69
///
@@ -217,26 +183,15 @@ impl Proof {
217
183
return Err ( ProofError :: InvalidParameter ) ;
218
184
}
219
185
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) ) ;
233
188
234
189
// Compute the `A` matrix commitment
235
- let r_A = Scalar :: random ( & mut transcript_rng ) ;
190
+ let r_A = Scalar :: random ( transcript . as_mut_rng ( ) ) ;
236
191
let mut a = ( 0 ..params. get_m ( ) )
237
192
. map ( |_| {
238
193
( 0 ..params. get_n ( ) )
239
- . map ( |_| Scalar :: random ( & mut transcript_rng ) )
194
+ . map ( |_| Scalar :: random ( transcript . as_mut_rng ( ) ) )
240
195
. collect :: < Vec < Scalar > > ( )
241
196
} )
242
197
. collect :: < Vec < Vec < Scalar > > > ( ) ;
@@ -248,7 +203,7 @@ impl Proof {
248
203
. map_err ( |_| ProofError :: InvalidParameter ) ?;
249
204
250
205
// Compute the `B` matrix commitment
251
- let r_B = Scalar :: random ( & mut transcript_rng ) ;
206
+ let r_B = Scalar :: random ( transcript . as_mut_rng ( ) ) ;
252
207
let l_decomposed = match timing {
253
208
OperationTiming :: Constant => {
254
209
GrayIterator :: decompose ( params. get_n ( ) , params. get_m ( ) , l) . ok_or ( ProofError :: InvalidParameter ) ?
@@ -269,7 +224,7 @@ impl Proof {
269
224
270
225
// Compute the `C` matrix commitment
271
226
let two = Scalar :: from ( 2u32 ) ;
272
- let r_C = Scalar :: random ( & mut transcript_rng ) ;
227
+ let r_C = Scalar :: random ( transcript . as_mut_rng ( ) ) ;
273
228
let a_sigma = ( 0 ..params. get_m ( ) )
274
229
. map ( |j| {
275
230
( 0 ..params. get_n ( ) )
@@ -282,7 +237,7 @@ impl Proof {
282
237
. map_err ( |_| ProofError :: InvalidParameter ) ?;
283
238
284
239
// Compute the `D` matrix commitment
285
- let r_D = Scalar :: random ( & mut transcript_rng ) ;
240
+ let r_D = Scalar :: random ( transcript . as_mut_rng ( ) ) ;
286
241
let a_square = ( 0 ..params. get_m ( ) )
287
242
. map ( |j| {
288
243
( 0 ..params. get_n ( ) )
@@ -297,7 +252,7 @@ impl Proof {
297
252
// Random masks
298
253
let rho = Zeroizing :: new (
299
254
( 0 ..params. get_m ( ) )
300
- . map ( |_| Scalar :: random ( & mut transcript_rng ) )
255
+ . map ( |_| Scalar :: random ( transcript . as_mut_rng ( ) ) )
301
256
. collect :: < Vec < Scalar > > ( ) ,
302
257
) ;
303
258
@@ -365,20 +320,8 @@ impl Proof {
365
320
// Compute `Y` vector
366
321
let Y = rho. iter ( ) . map ( |rho| rho * J ) . collect :: < Vec < RistrettoPoint > > ( ) ;
367
322
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 ) ?;
382
325
383
326
// Compute the `f` matrix
384
327
let f = ( 0 ..params. get_m ( ) )
@@ -543,47 +486,24 @@ impl Proof {
543
486
// Set up a transcript generator for use in weighting
544
487
let mut transcript_weights = Transcript :: new ( "Triptych verifier weights" . as_bytes ( ) ) ;
545
488
489
+ let mut null_rng = NullRng ;
490
+
546
491
// Generate all verifier challenges
547
492
let mut xi_powers_all = Vec :: with_capacity ( proofs. len ( ) ) ;
548
493
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 ) ;
570
496
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 ) ?) ;
581
499
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 ) ;
582
502
transcript_weights. append_u64 ( "proof" . as_bytes ( ) , transcript_rng. as_rngcore ( ) . next_u64 ( ) ) ;
583
503
}
584
504
585
505
// 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 ) ;
587
507
588
508
// Process each proof
589
509
for ( proof, xi_powers) in proofs. iter ( ) . zip ( xi_powers_all. iter ( ) ) {
0 commit comments