@@ -29,9 +29,9 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
29
29
deserialize = "E::G1Affine: Deserialize<'de>, E::Fr: Deserialize<'de>"
30
30
) ) ]
31
31
pub struct EvaluationArgument < E : Engine > {
32
- com : Vec < E :: G1Affine > ,
33
- w : Vec < E :: G1Affine > ,
34
- v : Vec < Vec < E :: Fr > > ,
32
+ evals_r : Vec < E :: G1Affine > ,
33
+ evals_neg_r : Vec < E :: G1Affine > ,
34
+ evals_r_squared : Vec < Vec < E :: Fr > > ,
35
35
}
36
36
37
37
/// Provides an implementation of a polynomial evaluation engine using KZG
@@ -40,6 +40,8 @@ pub struct EvaluationEngine<E, NE> {
40
40
_p : PhantomData < ( E , NE ) > ,
41
41
}
42
42
43
+ // This impl block defines helper functions that are not a part of
44
+ // EvaluationEngineTrait, but that we will use to implement the trait methods.
43
45
impl < E , NE > EvaluationEngine < E , NE >
44
46
where
45
47
E : Engine ,
48
50
E :: Fr : TranscriptReprTrait < E :: G1 > ,
49
51
E :: G1Affine : TranscriptReprTrait < E :: G1 > , // TODO: this bound on DlogGroup is really unusable!
50
52
{
51
- // This impl block defines helper functions that are not a part of
52
- // EvaluationEngineTrait, but that we will use to implement the trait methods.
53
53
fn compute_challenge (
54
54
C : & E :: G1Affine ,
55
55
y : & E :: Fr ,
87
87
88
88
fn batch_challenge_powers ( q : E :: Fr , k : usize ) -> Vec < E :: Fr > {
89
89
// Compute powers of q : (1, q, q^2, ..., q^(k-1))
90
- let mut q_powers = vec ! [ E :: Fr :: ONE ; k] ;
91
- for i in 1 ..k {
92
- q_powers[ i] = q_powers[ i - 1 ] * q;
93
- }
94
- q_powers
90
+ std:: iter:: successors ( Some ( E :: Fr :: ONE ) , |& x| Some ( x * q) )
91
+ . take ( k)
92
+ . collect ( )
95
93
}
96
94
97
95
fn verifier_second_challenge (
@@ -179,22 +177,21 @@ where
179
177
transcript : & mut <NE as NovaEngine >:: TE |
180
178
-> ( Vec < E :: G1Affine > , Vec < Vec < E :: Fr > > ) {
181
179
let poly_eval = |f : & [ E :: Fr ] , u : E :: Fr | -> E :: Fr {
182
- let mut v = f[ 0 ] ;
183
- let mut u_power = E :: Fr :: ONE ;
184
-
185
- for fi in f. iter ( ) . skip ( 1 ) {
186
- u_power *= u;
187
- v += u_power * fi;
188
- }
189
-
190
- v
180
+ // Horner's scheme
181
+ f. iter ( )
182
+ . rev ( )
183
+ . skip ( 1 )
184
+ . fold ( f. last ( ) . cloned ( ) . unwrap_or_default ( ) , |acc, & fi| {
185
+ acc * u + fi
186
+ } )
191
187
} ;
192
188
193
189
let scalar_vector_muladd = |a : & mut Vec < E :: Fr > , v : & Vec < E :: Fr > , s : E :: Fr | {
194
190
assert ! ( a. len( ) >= v. len( ) ) ;
195
- for i in 0 ..v. len ( ) {
196
- a[ i] += s * v[ i] ;
197
- }
191
+ #[ allow( clippy:: disallowed_methods) ]
192
+ a. par_iter_mut ( )
193
+ . zip ( v. par_iter ( ) )
194
+ . for_each ( |( c, v) | * c += s * v) ;
198
195
} ;
199
196
200
197
let kzg_compute_batch_polynomial = |f : & [ Vec < E :: Fr > ] , q : E :: Fr | -> Vec < E :: Fr > {
@@ -219,23 +216,19 @@ where
219
216
// The verifier needs f_i(u_j), so we compute them here
220
217
// (V will compute B(u_j) itself)
221
218
let mut v = vec ! [ vec!( E :: Fr :: ZERO ; k) ; t] ;
222
- for i in 0 ..t {
219
+ v . par_iter_mut ( ) . enumerate ( ) . for_each ( | ( i , v_i ) | {
223
220
// for each point u
224
- for ( j , f_j ) in f . iter ( ) . enumerate ( ) . take ( k ) {
221
+ v_i . par_iter_mut ( ) . zip_eq ( f ) . for_each ( | ( v_ij , f ) | {
225
222
// for each poly f
226
- v [ i ] [ j ] = poly_eval ( f_j , u[ i] ) ; // = f_j(u_i)
227
- }
228
- }
223
+ * v_ij = poly_eval ( & f , u[ i] ) ;
224
+ } ) ;
225
+ } ) ;
229
226
230
227
let q = Self :: get_batch_challenge ( C , u, & v, transcript) ;
231
228
let B = kzg_compute_batch_polynomial ( f, q) ;
232
229
233
230
// Now open B at u0, ..., u_{t-1}
234
- let mut w = Vec :: with_capacity ( t) ;
235
- for ui in u {
236
- let wi = kzg_open ( & B , * ui) ;
237
- w. push ( wi) ;
238
- }
231
+ let w = u. par_iter ( ) . map ( |ui| kzg_open ( & B , * ui) ) . collect :: < Vec < _ > > ( ) ;
239
232
240
233
// Compute the commitment to the batched polynomial B(X)
241
234
let q_powers = Self :: batch_challenge_powers ( q, k) ;
@@ -297,7 +290,11 @@ where
297
290
com_all. insert ( 0 , C . comm . preprocessed ( ) ) ;
298
291
let ( w, v) = kzg_open_batch ( & com_all, & polys, & u, transcript) ;
299
292
300
- Ok ( EvaluationArgument { com, w, v } )
293
+ Ok ( EvaluationArgument {
294
+ evals_r : com,
295
+ evals_neg_r : w,
296
+ evals_r_squared : v,
297
+ } )
301
298
}
302
299
303
300
/// A method to verify purported evaluations of a batch of polynomials
@@ -385,7 +382,7 @@ where
385
382
386
383
let ell = x. len ( ) ;
387
384
388
- let mut com = pi. com . clone ( ) ;
385
+ let mut com = pi. evals_r . clone ( ) ;
389
386
390
387
// we do not need to add x to the transcript, because in our context x was
391
388
// obtained from the transcript
@@ -399,7 +396,7 @@ where
399
396
let u = vec ! [ r, -r, r * r] ;
400
397
401
398
// Setup vectors (Y, ypos, yneg) from pi.v
402
- let v = & pi. v ;
399
+ let v = & pi. evals_r_squared ;
403
400
if v. len ( ) != 3 {
404
401
return Err ( NovaError :: ProofVerifyError ) ;
405
402
}
@@ -428,7 +425,14 @@ where
428
425
}
429
426
430
427
// Check commitments to (Y, ypos, yneg) are valid
431
- if !kzg_verify_batch ( vk, & com, & pi. w , & u, & pi. v , transcript) {
428
+ if !kzg_verify_batch (
429
+ vk,
430
+ & com,
431
+ & pi. evals_neg_r ,
432
+ & u,
433
+ & pi. evals_r_squared ,
434
+ transcript,
435
+ ) {
432
436
return Err ( NovaError :: ProofVerifyError ) ;
433
437
}
434
438
@@ -552,7 +556,7 @@ mod tests {
552
556
553
557
// Change the proof and expect verification to fail
554
558
let mut bad_proof = proof. clone ( ) ;
555
- bad_proof. com [ 0 ] = ( bad_proof. com [ 0 ] + bad_proof. com [ 1 ] ) . to_affine ( ) ;
559
+ bad_proof. evals_r [ 0 ] = ( bad_proof. evals_r [ 0 ] + bad_proof. evals_r [ 1 ] ) . to_affine ( ) ;
556
560
let mut verifier_transcript2 = Keccak256Transcript :: < NE > :: new ( b"TestEval" ) ;
557
561
assert ! ( EvaluationEngine :: <E , NE >:: verify(
558
562
& vk,
@@ -605,7 +609,7 @@ mod tests {
605
609
606
610
// Change the proof and expect verification to fail
607
611
let mut bad_proof = proof. clone ( ) ;
608
- bad_proof. com [ 0 ] = ( bad_proof. com [ 0 ] + bad_proof. com [ 1 ] ) . to_affine ( ) ;
612
+ bad_proof. evals_r [ 0 ] = ( bad_proof. evals_r [ 0 ] + bad_proof. evals_r [ 1 ] ) . to_affine ( ) ;
609
613
let mut verifier_tr2 = Keccak256Transcript :: < NE > :: new ( b"TestEval" ) ;
610
614
assert ! ( EvaluationEngine :: <E , NE >:: verify(
611
615
& vk,
0 commit comments