1
1
use crate :: {
2
- Error , Evaluation , PolynomialCommitmentScheme ,
2
+ Error , Evaluation , Point , PolynomialCommitmentScheme ,
3
3
util:: {
4
4
arithmetic:: inner_product,
5
5
ext_to_usize,
@@ -19,7 +19,7 @@ use sumcheck::macros::{entered_span, exit_span};
19
19
use transcript:: Transcript ;
20
20
use witness:: RowMajorMatrix ;
21
21
22
- use itertools:: Itertools ;
22
+ use itertools:: { Itertools , izip } ;
23
23
use serde:: { Serialize , de:: DeserializeOwned } ;
24
24
25
25
use multilinear_extensions:: { mle:: FieldType , virtual_poly:: build_eq_x_r_vec} ;
@@ -35,14 +35,15 @@ pub use structure::{
35
35
BasefoldProverParams , BasefoldRSParams , BasefoldVerifierParams ,
36
36
} ;
37
37
mod commit_phase;
38
- use commit_phase:: simple_batch_commit_phase;
38
+ use commit_phase:: { batch_commit_phase , simple_batch_commit_phase} ;
39
39
mod encoding;
40
40
use multilinear_extensions:: virtual_poly:: ArcMultilinearExtension ;
41
41
42
42
mod query_phase;
43
43
// This sumcheck module is different from the mpcs::sumcheck module, in that
44
44
// it deals only with the special case of the form \sum eq(r_i)f_i().
45
45
46
+ // make it pure error
46
47
pub enum PolyEvalsCodeword < E : ExtensionField > {
47
48
Normal ( Box < DenseMatrix < E :: BaseField > > ) ,
48
49
TooSmall ( Box < DenseMatrix < E :: BaseField > > ) , // The polynomial is too small to apply FRI
@@ -213,84 +214,50 @@ where
213
214
214
215
fn batch_commit (
215
216
pp : & Self :: ProverParam ,
216
- rmm : witness:: RowMajorMatrix < <E as ff_ext:: ExtensionField >:: BaseField > ,
217
+ rmm : Vec < witness:: RowMajorMatrix < <E as ff_ext:: ExtensionField >:: BaseField > > ,
217
218
) -> Result < Self :: CommitmentWithWitness , Error > {
218
- let span = entered_span ! ( "to_mles" , profiling_3 = true ) ;
219
- let polys = rmm. to_mles ( ) ;
220
- exit_span ! ( span) ;
221
219
// assumptions
222
220
// 1. there must be at least one polynomial
223
221
// 2. all polynomials must exist in the same field type
224
222
// (TODO: eliminate this assumption by supporting commiting
225
223
// and opening mixed-type polys)
226
224
// 3. all polynomials must have the same number of variables
227
225
228
- if polys . is_empty ( ) {
226
+ if rmm . is_empty ( ) {
229
227
return Err ( Error :: InvalidPcsParam (
230
228
"cannot batch commit to zero polynomials" . to_string ( ) ,
231
229
) ) ;
232
230
}
233
231
234
- let num_vars = polys[ 0 ] . num_vars ( ) ;
235
- let num_polys = polys. len ( ) ;
236
-
237
- let is_base = match polys[ 0 ] . evaluations ( ) {
238
- FieldType :: Ext ( _) => false ,
239
- FieldType :: Base ( _) => true ,
240
- _ => unreachable ! ( ) ,
241
- } ;
232
+ let span = entered_span ! ( "to_mles" , profiling_3 = true ) ;
233
+ let polys: Vec < Vec < ArcMultilinearExtension < E > > > = rmm
234
+ . iter ( )
235
+ . map ( |rmm| rmm. to_mles ( ) . into_iter ( ) . map ( |p| p. into ( ) ) . collect_vec ( ) )
236
+ . collect_vec ( ) ;
237
+ exit_span ! ( span) ;
242
238
243
- if !polys. iter ( ) . map ( |poly| poly. num_vars ( ) ) . all_equal ( ) {
244
- return Err ( Error :: InvalidPcsParam (
245
- "cannot batch commit to polynomials with different number of variables" . to_string ( ) ,
246
- ) ) ;
247
- }
248
239
let timer = start_timer ! ( || "Basefold::batch commit" ) ;
249
- let encode_timer = start_timer ! ( || "Basefold::batch commit::encoding and interpolations" ) ;
250
240
let span = entered_span ! ( "encode_codeword_and_mle" , profiling_3 = true ) ;
251
-
252
- let evals_codewords = Spec :: EncodingScheme :: encode ( & pp. encoding_params , rmm) ;
253
-
241
+ let evals_codewords = rmm
242
+ . into_iter ( )
243
+ . map ( |rmm| Spec :: EncodingScheme :: encode ( & pp. encoding_params , rmm) )
244
+ . collect :: < Result < Vec < DenseMatrix < E :: BaseField > > , _ > > ( ) ?;
254
245
exit_span ! ( span) ;
255
- end_timer ! ( encode_timer) ;
256
246
257
247
let span = entered_span ! ( "build mt" , profiling_3 = true ) ;
258
- // build merkle tree
259
- let ret = match evals_codewords {
260
- PolyEvalsCodeword :: Normal ( codewords) => {
261
- let mmcs = poseidon2_merkle_tree :: < E > ( ) ;
262
- let ( comm, codeword) = mmcs. commit_matrix ( * codewords) ;
263
- let polys: Vec < ArcMultilinearExtension < E > > =
264
- polys. into_iter ( ) . map ( |poly| poly. into ( ) ) . collect_vec ( ) ;
265
- Self :: CommitmentWithWitness {
266
- pi_d_digest : comm,
267
- codeword,
268
- polynomials_bh_evals : polys,
269
- num_vars,
270
- is_base,
271
- num_polys,
272
- }
273
- }
274
- PolyEvalsCodeword :: TooSmall ( rmm_padded) => {
275
- let mmcs = poseidon2_merkle_tree :: < E > ( ) ;
276
- let ( comm, codeword) = mmcs. commit_matrix ( * rmm_padded) ;
277
- let polys: Vec < ArcMultilinearExtension < E > > =
278
- polys. into_iter ( ) . map ( |poly| poly. into ( ) ) . collect_vec ( ) ;
279
- Self :: CommitmentWithWitness {
280
- pi_d_digest : comm,
281
- codeword,
282
- polynomials_bh_evals : polys,
283
- num_vars,
284
- is_base,
285
- num_polys,
286
- }
287
- }
288
- PolyEvalsCodeword :: TooBig ( _) => return Err ( Error :: PolynomialTooLarge ( num_vars) ) ,
289
- } ;
248
+ let mmcs = poseidon2_merkle_tree :: < E > ( ) ;
249
+ let ( comm, codeword) = mmcs. commit ( evals_codewords) ;
290
250
exit_span ! ( span) ;
291
- end_timer ! ( timer) ;
292
-
293
- Ok ( ret)
251
+ let meta_info = polys
252
+ . iter ( )
253
+ . map ( |polys| ( polys[ 0 ] . num_vars ( ) , polys. len ( ) ) )
254
+ . collect_vec ( ) ;
255
+ Ok ( Self :: CommitmentWithWitness {
256
+ pi_d_digest : comm,
257
+ codeword,
258
+ polynomials_bh_evals : polys,
259
+ meta_info,
260
+ } )
294
261
}
295
262
296
263
fn write_commitment (
@@ -320,75 +287,72 @@ where
320
287
}
321
288
322
289
/// Open a batch of polynomial commitments at several points.
323
- /// The current version only supports one polynomial per commitment.
324
- /// Because otherwise it is complex to match the polynomials and
325
- /// the commitments, and because currently this high flexibility is
326
- /// not very useful in ceno.
327
290
fn batch_open (
328
- _pp : & Self :: ProverParam ,
329
- _polys : & [ ArcMultilinearExtension < E > ] ,
330
- _comms : & [ Self :: CommitmentWithWitness ] ,
331
- _points : & [ Vec < E > ] ,
332
- _evals : & [ Evaluation < E > ] ,
333
- _transcript : & mut impl Transcript < E > ,
334
- ) -> Result < Self :: Proof , Error > {
335
- unimplemented ! ( )
336
- }
337
-
338
- /// This is a simple version of batch open:
339
- /// 1. Open at one point
340
- /// 2. All the polynomials share the same commitment and have the same
341
- /// number of variables.
342
- /// 3. The point is already a random point generated by a sum-check.
343
- fn simple_batch_open (
344
291
pp : & Self :: ProverParam ,
345
- polys : & [ ArcMultilinearExtension < E > ] ,
346
- comm : & Self :: CommitmentWithWitness ,
347
- point : & [ E ] ,
348
- evals : & [ E ] ,
292
+ comms : & Self :: CommitmentWithWitness ,
293
+ points : & [ Point < E > ] ,
294
+ evals : & [ Vec < E > ] ,
349
295
transcript : & mut impl Transcript < E > ,
350
296
) -> Result < Self :: Proof , Error > {
351
- let timer = start_timer ! ( || "Basefold::batch_open" ) ;
352
- let num_vars = polys[ 0 ] . num_vars ( ) ;
353
-
354
- if comm. is_trivial :: < Spec > ( ) {
355
- let mmcs = poseidon2_merkle_tree :: < E > ( ) ;
356
- return Ok ( Self :: Proof :: trivial (
357
- mmcs. get_matrices ( & comm. codeword ) [ 0 ] . clone ( ) ,
358
- ) ) ;
359
- }
360
-
361
- polys
362
- . iter ( )
363
- . for_each ( |poly| assert_eq ! ( poly. num_vars( ) , num_vars) ) ;
364
- assert ! ( num_vars >= Spec :: get_basecode_msg_size_log( ) ) ;
365
- assert_eq ! ( comm. num_polys, polys. len( ) ) ;
366
- assert_eq ! ( comm. num_polys, evals. len( ) ) ;
297
+ let span = entered_span ! ( "Basefold::batch_open" ) ;
298
+
299
+ // sanity check
300
+ // number of point match with commitment length, assuming each commitment are opening under same point
301
+ assert_eq ! ( points. len( ) , comms. polynomials_bh_evals. len( ) ) ;
302
+
303
+ assert ! ( izip!( & comms. polynomials_bh_evals, & comms. meta_info) . all(
304
+ |( polynomials_bh_evals, meta_info) | {
305
+ let ( num_var, num_polys) = meta_info;
306
+ // check num_vars & num_poly match
307
+ polynomials_bh_evals
308
+ . iter( )
309
+ . all( |p| p. num_vars( ) == * num_var)
310
+ && polynomials_bh_evals. len( ) == * num_polys
311
+ } ,
312
+ ) ) ;
313
+
314
+ let ( min_num_vars, max_num_vars) = (
315
+ * comms
316
+ . meta_info
317
+ . iter ( )
318
+ . map ( |( num_var, _) | num_var)
319
+ . min ( )
320
+ . unwrap ( ) ,
321
+ * comms
322
+ . meta_info
323
+ . iter ( )
324
+ . map ( |( num_var, _) | num_var)
325
+ . max ( )
326
+ . unwrap ( ) ,
327
+ ) ;
328
+ assert ! ( min_num_vars >= Spec :: get_basecode_msg_size_log( ) ) ;
367
329
368
330
if cfg ! ( feature = "sanity-check" ) {
369
- evals
370
- . iter ( )
371
- . zip ( polys)
372
- . for_each ( |( eval, poly) | assert_eq ! ( & poly. evaluate( point) , eval) )
331
+ assert ! ( izip!( comms. polynomials_bh_evals, points, evals) . all(
332
+ |( polys, point, evals) | {
333
+ izip!( polys, evals) . all( |( poly, eval) | poly. evaluate( point) == * eval)
334
+ }
335
+ ) ) ;
373
336
}
374
- // evals.len() is the batch size, i.e., how many polynomials are being opened together
375
- let batch_coeffs = & transcript
376
- . sample_and_append_challenge_pows ( evals. len ( ) , b"batch coeffs" ) [ 0 ..evals. len ( ) ] ;
377
- let _target_sum = inner_product ( evals, batch_coeffs) ;
337
+ let total_num_polys = evals. iter ( ) . map ( |evals| evals. len ( ) ) . sum ( ) ;
338
+ // evals.len() is the number of polynomials
339
+ let batch_coeffs =
340
+ & transcript. sample_and_append_challenge_pows ( total_num_polys, b"batch coeffs" ) ;
341
+ // let _target_sum = inner_product(evals, batch_coeffs);
378
342
379
343
// Now the verifier has obtained the new target sum, and is able to compute the random
380
344
// linear coefficients.
381
345
// The remaining tasks for the prover is to prove that
382
346
// sum_i coeffs[i] poly_evals[i] is equal to
383
347
// the new target sum, where coeffs is computed as follows
384
- let ( trees, commit_phase_proof) = simple_batch_commit_phase :: < E , Spec > (
348
+ let ( trees, commit_phase_proof) = batch_commit_phase :: < E , Spec > (
385
349
& pp. encoding_params ,
386
- point ,
350
+ points ,
387
351
batch_coeffs,
388
- comm ,
352
+ comms ,
389
353
transcript,
390
- num_vars ,
391
- num_vars - Spec :: get_basecode_msg_size_log ( ) ,
354
+ ( min_num_vars , max_num_vars ) ,
355
+ max_num_vars - Spec :: get_basecode_msg_size_log ( ) ,
392
356
) ;
393
357
394
358
let query_timer = start_timer ! ( || "Basefold::open::query_phase" ) ;
@@ -398,7 +362,7 @@ where
398
362
simple_batch_prover_query_phase ( transcript, comm, & trees, Spec :: get_number_queries ( ) ) ;
399
363
end_timer ! ( query_timer) ;
400
364
401
- end_timer ! ( timer ) ;
365
+ end_timer ! ( span ) ;
402
366
Ok ( Self :: Proof {
403
367
sumcheck_messages : commit_phase_proof. sumcheck_messages ,
404
368
roots : commit_phase_proof. roots ,
@@ -409,6 +373,22 @@ where
409
373
} )
410
374
}
411
375
376
+ /// This is a simple version of batch open:
377
+ /// 1. Open at one point
378
+ /// 2. All the polynomials share the same commitment and have the same
379
+ /// number of variables.
380
+ /// 3. The point is already a random point generated by a sum-check.
381
+ fn simple_batch_open (
382
+ pp : & Self :: ProverParam ,
383
+ polys : & [ ArcMultilinearExtension < E > ] ,
384
+ comm : & Self :: CommitmentWithWitness ,
385
+ point : & [ E ] ,
386
+ evals : & [ E ] ,
387
+ transcript : & mut impl Transcript < E > ,
388
+ ) -> Result < Self :: Proof , Error > {
389
+ unimplemented ! ( )
390
+ }
391
+
412
392
fn verify (
413
393
_vp : & Self :: VerifierParam ,
414
394
_comm : & Self :: Commitment ,
0 commit comments