1
1
use ark_std:: { end_timer, start_timer} ;
2
2
use halo2_proofs:: {
3
+ arithmetic:: Field ,
3
4
circuit:: { Layouter , SimpleFloorPlanner , Value } ,
4
5
halo2curves:: bn256:: { Bn256 , Fr , G1Affine } ,
5
6
plonk:: { Circuit , ConstraintSystem , Error , Selector } ,
@@ -11,14 +12,20 @@ use snark_verifier::{
11
12
loader:: halo2:: {
12
13
halo2_ecc:: {
13
14
ecc:: EccChip ,
14
- fields:: fp:: FpConfig ,
15
- halo2_base:: { AssignedValue , Context , ContextParams } ,
15
+ fields:: { fp:: FpConfig , FieldChip } ,
16
+ halo2_base:: {
17
+ gates:: { GateInstructions , RangeInstructions } ,
18
+ AssignedValue , Context , ContextParams ,
19
+ QuantumCell :: Existing ,
20
+ } ,
16
21
} ,
17
- Halo2Loader ,
22
+ Halo2Loader , IntegerInstructions ,
18
23
} ,
19
24
pcs:: kzg:: { Bdfg21 , Kzg , KzgSuccinctVerifyingKey } ,
20
25
} ;
21
- use snark_verifier_sdk:: { aggregate, flatten_accumulator, CircuitExt , Snark , SnarkWitness } ;
26
+ use snark_verifier_sdk:: {
27
+ aggregate_as_witness, flatten_accumulator, CircuitExt , Snark , SnarkWitness ,
28
+ } ;
22
29
use std:: { env, fs:: File , rc:: Rc } ;
23
30
use zkevm_circuits:: util:: Challenges ;
24
31
@@ -30,8 +37,8 @@ use crate::{
30
37
core:: { assign_batch_hashes, extract_proof_and_instances_with_pairing_check} ,
31
38
util:: parse_hash_digest_cells,
32
39
witgen:: { zstd_encode, MultiBlockProcessResult } ,
33
- ConfigParams , LOG_DEGREE , PI_CHAIN_ID , PI_CURRENT_BATCH_HASH , PI_CURRENT_STATE_ROOT ,
34
- PI_CURRENT_WITHDRAW_ROOT , PI_PARENT_BATCH_HASH , PI_PARENT_STATE_ROOT ,
40
+ ConfigParams , FixedProtocol , LOG_DEGREE , PI_CHAIN_ID , PI_CURRENT_BATCH_HASH ,
41
+ PI_CURRENT_STATE_ROOT , PI_CURRENT_WITHDRAW_ROOT , PI_PARENT_BATCH_HASH , PI_PARENT_STATE_ROOT ,
35
42
} ;
36
43
37
44
/// Batch circuit, the chunk aggregation routine below recursion circuit
@@ -55,14 +62,21 @@ pub struct BatchCircuit<const N_SNARKS: usize> {
55
62
// batch hash circuit for which the snarks are generated
56
63
// the chunks in this batch are also padded already
57
64
pub batch_hash : BatchHash < N_SNARKS > ,
65
+
66
+ /// The SNARK protocol from the halo2-based inner circuit route.
67
+ pub halo2_protocol : FixedProtocol ,
68
+ /// The SNARK protocol from the sp1-based inner circuit route.
69
+ pub sp1_protocol : FixedProtocol ,
58
70
}
59
71
60
72
impl < const N_SNARKS : usize > BatchCircuit < N_SNARKS > {
61
- pub fn new (
73
+ pub fn new < P : Into < FixedProtocol > > (
62
74
params : & ParamsKZG < Bn256 > ,
63
75
snarks_with_padding : & [ Snark ] ,
64
76
rng : impl Rng + Send ,
65
77
batch_hash : BatchHash < N_SNARKS > ,
78
+ halo2_protocol : P ,
79
+ sp1_protocol : P ,
66
80
) -> Result < Self , snark_verifier:: Error > {
67
81
let timer = start_timer ! ( || "generate aggregation circuit" ) ;
68
82
@@ -120,6 +134,8 @@ impl<const N_SNARKS: usize> BatchCircuit<N_SNARKS> {
120
134
flattened_instances,
121
135
as_proof : Value :: known ( as_proof) ,
122
136
batch_hash,
137
+ halo2_protocol : halo2_protocol. into ( ) ,
138
+ sp1_protocol : sp1_protocol. into ( ) ,
123
139
} )
124
140
}
125
141
@@ -209,22 +225,21 @@ impl<const N_SNARKS: usize> Circuit<Fr> for BatchCircuit<N_SNARKS> {
209
225
let loader: Rc < Halo2Loader < G1Affine , EccChip < Fr , FpConfig < Fr , Fq > > > > =
210
226
Halo2Loader :: new ( ecc_chip, ctx) ;
211
227
212
- //
213
228
// extract the assigned values for
214
229
// - instances which are the public inputs of each chunk (prefixed with 12
215
230
// instances from previous accumulators)
216
231
// - new accumulator
217
- //
218
- log:: debug!( "aggregation: chunk aggregation" ) ;
219
- let ( assigned_aggregation_instances, acc) = aggregate :: < Kzg < Bn256 , Bdfg21 > > (
232
+ let (
233
+ assigned_aggregation_instances,
234
+ acc,
235
+ preprocessed_poly_sets,
236
+ transcript_init_states,
237
+ ) = aggregate_as_witness :: < Kzg < Bn256 , Bdfg21 > > (
220
238
& self . svk ,
221
239
& loader,
222
240
& self . snarks_with_padding ,
223
241
self . as_proof ( ) ,
224
242
) ;
225
- for ( i, e) in assigned_aggregation_instances[ 0 ] . iter ( ) . enumerate ( ) {
226
- log:: trace!( "{}-th instance: {:?}" , i, e. value)
227
- }
228
243
229
244
// extract the following cells for later constraints
230
245
// - the accumulators
@@ -238,13 +253,113 @@ impl<const N_SNARKS: usize> Circuit<Fr> for BatchCircuit<N_SNARKS> {
238
253
. iter ( )
239
254
. flat_map ( |instance_column| instance_column. iter ( ) . skip ( ACC_LEN ) ) ,
240
255
) ;
256
+ for ( i, e) in assigned_aggregation_instances[ 0 ] . iter ( ) . enumerate ( ) {
257
+ log:: trace!( "{}-th instance: {:?}" , i, e. value)
258
+ }
241
259
242
- loader
243
- . ctx_mut ( )
244
- . print_stats ( & [ "snark aggregation [chunks -> batch]" ] ) ;
260
+ loader. ctx_mut ( ) . print_stats ( & [ "snark aggregation" ] ) ;
245
261
246
262
let mut ctx = Rc :: into_inner ( loader) . unwrap ( ) . into_ctx ( ) ;
247
- log:: debug!( "batching: assigning barycentric" ) ;
263
+
264
+ // We must ensure that the commitments to preprocessed polynomial and initial
265
+ // state of transcripts for every SNARK that is being aggregated belongs to the
266
+ // fixed set of values expected.
267
+ //
268
+ // First we load the constants.
269
+ log:: info!( "populating constants" ) ;
270
+ let mut preprocessed_polys_halo2 = Vec :: with_capacity ( 7 ) ;
271
+ let mut preprocessed_polys_sp1 = Vec :: with_capacity ( 7 ) ;
272
+ for & preprocessed_poly in self . halo2_protocol . preprocessed . iter ( ) {
273
+ preprocessed_polys_halo2. push (
274
+ config
275
+ . ecc_chip ( )
276
+ . assign_constant_point ( & mut ctx, preprocessed_poly) ,
277
+ ) ;
278
+ }
279
+ for & preprocessed_poly in self . sp1_protocol . preprocessed . iter ( ) {
280
+ preprocessed_polys_sp1. push (
281
+ config
282
+ . ecc_chip ( )
283
+ . assign_constant_point ( & mut ctx, preprocessed_poly) ,
284
+ ) ;
285
+ }
286
+ let transcript_init_state_halo2 = config
287
+ . ecc_chip ( )
288
+ . field_chip ( )
289
+ . range ( )
290
+ . gate ( )
291
+ . assign_constant ( & mut ctx, self . halo2_protocol . init_state )
292
+ . expect ( "IntegerInstructions::assign_constant infallible" ) ;
293
+ let transcript_init_state_sp1 = config
294
+ . ecc_chip ( )
295
+ . field_chip ( )
296
+ . range ( )
297
+ . gate ( )
298
+ . assign_constant ( & mut ctx, self . sp1_protocol . init_state )
299
+ . expect ( "IntegerInstructions::assign_constant infallible" ) ;
300
+
301
+ // Commitments to the preprocessed polynomials.
302
+ for preprocessed_polys in preprocessed_poly_sets. iter ( ) {
303
+ let mut preprocessed_check_1 =
304
+ config. flex_gate ( ) . load_constant ( & mut ctx, Fr :: ONE ) ;
305
+ let mut preprocessed_check_2 =
306
+ config. flex_gate ( ) . load_constant ( & mut ctx, Fr :: ONE ) ;
307
+ for ( ( commitment, comm_halo2) , comm_sp1) in preprocessed_polys
308
+ . iter ( )
309
+ . zip_eq ( preprocessed_polys_halo2. iter ( ) )
310
+ . zip_eq ( preprocessed_polys_sp1. iter ( ) )
311
+ {
312
+ let check_1 =
313
+ config. ecc_chip ( ) . is_equal ( & mut ctx, commitment, comm_halo2) ;
314
+ let check_2 =
315
+ config. ecc_chip ( ) . is_equal ( & mut ctx, commitment, comm_sp1) ;
316
+ preprocessed_check_1 = config. flex_gate ( ) . and (
317
+ & mut ctx,
318
+ Existing ( preprocessed_check_1) ,
319
+ Existing ( check_1) ,
320
+ ) ;
321
+ preprocessed_check_2 = config. flex_gate ( ) . and (
322
+ & mut ctx,
323
+ Existing ( preprocessed_check_2) ,
324
+ Existing ( check_2) ,
325
+ ) ;
326
+ }
327
+ let preprocessed_check = config. flex_gate ( ) . or (
328
+ & mut ctx,
329
+ Existing ( preprocessed_check_1) ,
330
+ Existing ( preprocessed_check_2) ,
331
+ ) ;
332
+ config
333
+ . flex_gate ( )
334
+ . assert_is_const ( & mut ctx, & preprocessed_check, Fr :: ONE ) ;
335
+ }
336
+
337
+ // Transcript initial state.
338
+ for transcript_init_state in transcript_init_states {
339
+ let transcript_init_state = transcript_init_state
340
+ . expect ( "SNARK should have an initial state for transcript" ) ;
341
+ let transcript_check_1 = config. flex_gate ( ) . is_equal (
342
+ & mut ctx,
343
+ Existing ( transcript_init_state) ,
344
+ Existing ( transcript_init_state_halo2) ,
345
+ ) ;
346
+ let transcript_check_2 = config. flex_gate ( ) . is_equal (
347
+ & mut ctx,
348
+ Existing ( transcript_init_state) ,
349
+ Existing ( transcript_init_state_sp1) ,
350
+ ) ;
351
+ let transcript_check = config. flex_gate ( ) . or (
352
+ & mut ctx,
353
+ Existing ( transcript_check_1) ,
354
+ Existing ( transcript_check_2) ,
355
+ ) ;
356
+ config
357
+ . flex_gate ( )
358
+ . assert_is_const ( & mut ctx, & transcript_check, Fr :: ONE ) ;
359
+ }
360
+
361
+ ctx. print_stats ( & [ "protocol check" ] ) ;
362
+
248
363
let barycentric = config. blob_consistency_config . assign_barycentric (
249
364
& mut ctx,
250
365
& self . batch_hash . blob_bytes ,
0 commit comments