@@ -53,8 +53,11 @@ pub struct TriptychProof {
53
53
#[ derive( Debug , Snafu ) ]
54
54
pub enum ProofError {
55
55
/// An invalid parameter was provided.
56
- #[ snafu( display( "An invalid parameter was provided" ) ) ]
57
- InvalidParameter ,
56
+ #[ snafu( display( "An invalid parameter was provided: {reason}" ) ) ]
57
+ InvalidParameter {
58
+ /// The reason for the parameter error.
59
+ reason : & ' static str ,
60
+ } ,
58
61
/// A transcript challenge was invalid.
59
62
#[ snafu( display( "A transcript challenge was invalid" ) ) ]
60
63
InvalidChallenge ,
@@ -174,7 +177,9 @@ impl TriptychProof {
174
177
) -> Result < Self , ProofError > {
175
178
// Check that the witness and statement have identical parameters
176
179
if witness. get_params ( ) != statement. get_params ( ) {
177
- return Err ( ProofError :: InvalidParameter ) ;
180
+ return Err ( ProofError :: InvalidParameter {
181
+ reason : "witness and statement parameters did not match" ,
182
+ } ) ;
178
183
}
179
184
180
185
// Extract values for convenience
@@ -205,13 +210,17 @@ impl TriptychProof {
205
210
}
206
211
207
212
if M_l != r * params. get_G ( ) {
208
- return Err ( ProofError :: InvalidParameter ) ;
213
+ return Err ( ProofError :: InvalidParameter {
214
+ reason : "`M[l] != r * G`" ,
215
+ } ) ;
209
216
}
210
217
if M1_l - offset != r1 * params. get_G1 ( ) {
211
- return Err ( ProofError :: InvalidParameter ) ;
218
+ return Err ( ProofError :: InvalidParameter {
219
+ reason : "`M1[l] - offset != r1 * G1`" ,
220
+ } ) ;
212
221
}
213
222
if & ( r * J ) != params. get_U ( ) {
214
- return Err ( ProofError :: InvalidParameter ) ;
223
+ return Err ( ProofError :: InvalidParameter { reason : "`r * J != U`" } ) ;
215
224
}
216
225
217
226
// Set up the transcript
@@ -231,16 +240,23 @@ impl TriptychProof {
231
240
}
232
241
let A = params
233
242
. commit_matrix ( & a, & r_A, timing)
234
- . map_err ( |_| ProofError :: InvalidParameter ) ?;
243
+ . map_err ( |_| ProofError :: InvalidParameter {
244
+ reason : "unable to compute `A`" ,
245
+ } ) ?;
235
246
236
247
// Compute the `B` matrix commitment
237
248
let r_B = Scalar :: random ( transcript. as_mut_rng ( ) ) ;
238
249
let l_decomposed = match timing {
239
250
OperationTiming :: Constant => {
240
- GrayIterator :: decompose ( params. get_n ( ) , params. get_m ( ) , l) . ok_or ( ProofError :: InvalidParameter ) ?
251
+ GrayIterator :: decompose ( params. get_n ( ) , params. get_m ( ) , l) . ok_or ( ProofError :: InvalidParameter {
252
+ reason : "`l` decomposition failed" ,
253
+ } ) ?
241
254
} ,
242
- OperationTiming :: Variable => GrayIterator :: decompose_vartime ( params. get_n ( ) , params. get_m ( ) , l)
243
- . ok_or ( ProofError :: InvalidParameter ) ?,
255
+ OperationTiming :: Variable => GrayIterator :: decompose_vartime ( params. get_n ( ) , params. get_m ( ) , l) . ok_or (
256
+ ProofError :: InvalidParameter {
257
+ reason : "`l` decomposition failed" ,
258
+ } ,
259
+ ) ?,
244
260
} ;
245
261
let sigma = ( 0 ..params. get_m ( ) )
246
262
. map ( |j| {
@@ -251,7 +267,9 @@ impl TriptychProof {
251
267
. collect :: < Vec < Vec < Scalar > > > ( ) ;
252
268
let B = params
253
269
. commit_matrix ( & sigma, & r_B, timing)
254
- . map_err ( |_| ProofError :: InvalidParameter ) ?;
270
+ . map_err ( |_| ProofError :: InvalidParameter {
271
+ reason : "unable to compute `B`" ,
272
+ } ) ?;
255
273
256
274
// Compute the `C` matrix commitment
257
275
let two = Scalar :: from ( 2u32 ) ;
@@ -265,7 +283,9 @@ impl TriptychProof {
265
283
. collect :: < Vec < Vec < Scalar > > > ( ) ;
266
284
let C = params
267
285
. commit_matrix ( & a_sigma, & r_C, timing)
268
- . map_err ( |_| ProofError :: InvalidParameter ) ?;
286
+ . map_err ( |_| ProofError :: InvalidParameter {
287
+ reason : "unable to compute `C`" ,
288
+ } ) ?;
269
289
270
290
// Compute the `D` matrix commitment
271
291
let r_D = Scalar :: random ( transcript. as_mut_rng ( ) ) ;
@@ -278,7 +298,9 @@ impl TriptychProof {
278
298
. collect :: < Vec < Vec < Scalar > > > ( ) ;
279
299
let D = params
280
300
. commit_matrix ( & a_square, & r_D, timing)
281
- . map_err ( |_| ProofError :: InvalidParameter ) ?;
301
+ . map_err ( |_| ProofError :: InvalidParameter {
302
+ reason : "unable to compute `D`" ,
303
+ } ) ?;
282
304
283
305
// Random masks
284
306
let rho = Zeroizing :: new (
@@ -296,7 +318,9 @@ impl TriptychProof {
296
318
let mut p = Vec :: < Vec < Scalar > > :: with_capacity ( params. get_N ( ) as usize ) ;
297
319
let mut k_decomposed = vec ! [ 0 ; params. get_m( ) as usize ] ;
298
320
for ( gray_index, _, gray_new) in
299
- GrayIterator :: new ( params. get_n ( ) , params. get_m ( ) ) . ok_or ( ProofError :: InvalidParameter ) ?
321
+ GrayIterator :: new ( params. get_n ( ) , params. get_m ( ) ) . ok_or ( ProofError :: InvalidParameter {
322
+ reason : "coefficient decomposition failed" ,
323
+ } ) ?
300
324
{
301
325
k_decomposed[ gray_index] = gray_new;
302
326
@@ -305,7 +329,9 @@ impl TriptychProof {
305
329
coefficients. resize (
306
330
( params. get_m ( ) as usize )
307
331
. checked_add ( 1 )
308
- . ok_or ( ProofError :: InvalidParameter ) ?,
332
+ . ok_or ( ProofError :: InvalidParameter {
333
+ reason : "polynomial degree overflowed" ,
334
+ } ) ?,
309
335
Scalar :: ZERO ,
310
336
) ;
311
337
coefficients[ 0 ] = a[ 0 ] [ k_decomposed[ 0 ] as usize ] ;
@@ -564,10 +590,14 @@ impl TriptychProof {
564
590
) -> Result < ( ) , ProofError > {
565
591
// Check that we have the same number of statements, proofs, and transcripts
566
592
if statements. len ( ) != proofs. len ( ) {
567
- return Err ( ProofError :: InvalidParameter ) ;
593
+ return Err ( ProofError :: InvalidParameter {
594
+ reason : "number of statements and proofs does not match" ,
595
+ } ) ;
568
596
}
569
597
if statements. len ( ) != transcripts. len ( ) {
570
- return Err ( ProofError :: InvalidParameter ) ;
598
+ return Err ( ProofError :: InvalidParameter {
599
+ reason : "number of statements and transcripts does not match" ,
600
+ } ) ;
571
601
}
572
602
573
603
// An empty batch is considered trivially valid
@@ -578,12 +608,16 @@ impl TriptychProof {
578
608
579
609
// Each statement must use the same input set (checked using the hash for efficiency)
580
610
if !statements. iter ( ) . map ( |s| s. get_input_set ( ) . get_hash ( ) ) . all_equal ( ) {
581
- return Err ( ProofError :: InvalidParameter ) ;
611
+ return Err ( ProofError :: InvalidParameter {
612
+ reason : "statement input sets do not match" ,
613
+ } ) ;
582
614
}
583
615
584
616
// Each statement must use the same parameters (checked using the hash for efficiency)
585
617
if !statements. iter ( ) . map ( |s| s. get_params ( ) . get_hash ( ) ) . all_equal ( ) {
586
- return Err ( ProofError :: InvalidParameter ) ;
618
+ return Err ( ProofError :: InvalidParameter {
619
+ reason : "statement parameters do not match" ,
620
+ } ) ;
587
621
}
588
622
589
623
// Extract common values for convenience
@@ -594,26 +628,42 @@ impl TriptychProof {
594
628
// Check that all proof semantics are valid for the statement
595
629
for proof in proofs {
596
630
if proof. X . len ( ) != params. get_m ( ) as usize {
597
- return Err ( ProofError :: InvalidParameter ) ;
631
+ return Err ( ProofError :: InvalidParameter {
632
+ reason : "proof `X` vector length was not `m`" ,
633
+ } ) ;
598
634
}
599
635
if proof. X1 . len ( ) != params. get_m ( ) as usize {
600
- return Err ( ProofError :: InvalidParameter ) ;
636
+ return Err ( ProofError :: InvalidParameter {
637
+ reason : "proof `X1` vector length was not `m`" ,
638
+ } ) ;
601
639
}
602
640
if proof. Y . len ( ) != params. get_m ( ) as usize {
603
- return Err ( ProofError :: InvalidParameter ) ;
641
+ return Err ( ProofError :: InvalidParameter {
642
+ reason : "proof `Y` vector length was not `m`" ,
643
+ } ) ;
604
644
}
605
645
if proof. f . len ( ) != params. get_m ( ) as usize {
606
- return Err ( ProofError :: InvalidParameter ) ;
646
+ return Err ( ProofError :: InvalidParameter {
647
+ reason : "proof `f` matrix did not have `m` rows" ,
648
+ } ) ;
607
649
}
608
650
for f_row in & proof. f {
609
- if f_row. len ( ) != params. get_n ( ) . checked_sub ( 1 ) . ok_or ( ProofError :: InvalidParameter ) ? as usize {
610
- return Err ( ProofError :: InvalidParameter ) ;
651
+ if f_row. len ( ) !=
652
+ params. get_n ( ) . checked_sub ( 1 ) . ok_or ( ProofError :: InvalidParameter {
653
+ reason : "proof `f` matrix column count overflowed" ,
654
+ } ) ? as usize
655
+ {
656
+ return Err ( ProofError :: InvalidParameter {
657
+ reason : "proof `f` matrix did not have `n - 1` columns" ,
658
+ } ) ;
611
659
}
612
660
}
613
661
}
614
662
615
663
// Determine the size of the final check vector, which must not overflow `usize`
616
- let batch_size = u32:: try_from ( proofs. len ( ) ) . map_err ( |_| ProofError :: InvalidParameter ) ?;
664
+ let batch_size = u32:: try_from ( proofs. len ( ) ) . map_err ( |_| ProofError :: InvalidParameter {
665
+ reason : "batch size overflowed `u32`" ,
666
+ } ) ?;
617
667
618
668
// This is unlikely to overflow; even if it does, the only effect is unnecessary reallocation
619
669
#[ allow( clippy:: arithmetic_side_effects) ]
@@ -631,7 +681,9 @@ impl TriptychProof {
631
681
+ 3 * params. get_m ( ) // X, X1, Y
632
682
) ,
633
683
)
634
- . map_err ( |_| ProofError :: InvalidParameter ) ?;
684
+ . map_err ( |_| ProofError :: InvalidParameter {
685
+ reason : "multiscalar multiplication size overflowed `usize`" ,
686
+ } ) ?;
635
687
636
688
// Set up the point vector for the final check
637
689
let points = proofs
@@ -708,7 +760,9 @@ impl TriptychProof {
708
760
// Check that `f` does not contain zero, which breaks batch inversion
709
761
for f_row in & f {
710
762
if f_row. contains ( & Scalar :: ZERO ) {
711
- return Err ( ProofError :: InvalidParameter ) ;
763
+ return Err ( ProofError :: InvalidParameter {
764
+ reason : "proof `f` matrix contained 0" ,
765
+ } ) ;
712
766
}
713
767
}
714
768
@@ -779,7 +833,9 @@ impl TriptychProof {
779
833
// Set up the initial `f` product and Gray iterator
780
834
let mut f_product = f. iter ( ) . map ( |f_row| f_row[ 0 ] ) . product :: < Scalar > ( ) ;
781
835
let gray_iterator =
782
- GrayIterator :: new ( params. get_n ( ) , params. get_m ( ) ) . ok_or ( ProofError :: InvalidParameter ) ?;
836
+ GrayIterator :: new ( params. get_n ( ) , params. get_m ( ) ) . ok_or ( ProofError :: InvalidParameter {
837
+ reason : "coefficient decomposition failed" ,
838
+ } ) ?;
783
839
784
840
// Invert each element of `f` for efficiency
785
841
let mut f_inverse_flat = f. iter ( ) . flatten ( ) . copied ( ) . collect :: < Vec < Scalar > > ( ) ;
0 commit comments