11use ark_std:: { end_timer, start_timer} ;
22use halo2_proofs:: {
3+ arithmetic:: Field ,
34 circuit:: { Layouter , SimpleFloorPlanner , Value } ,
45 halo2curves:: bn256:: { Bn256 , Fr , G1Affine } ,
56 plonk:: { Circuit , ConstraintSystem , Error , Selector } ,
@@ -11,14 +12,20 @@ use snark_verifier::{
1112 loader:: halo2:: {
1213 halo2_ecc:: {
1314 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+ } ,
1621 } ,
17- Halo2Loader ,
22+ Halo2Loader , IntegerInstructions ,
1823 } ,
1924 pcs:: kzg:: { Bdfg21 , Kzg , KzgSuccinctVerifyingKey } ,
2025} ;
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+ } ;
2229use std:: { env, fs:: File , rc:: Rc } ;
2330use zkevm_circuits:: util:: Challenges ;
2431
@@ -30,8 +37,8 @@ use crate::{
3037 core:: { assign_batch_hashes, extract_proof_and_instances_with_pairing_check} ,
3138 util:: parse_hash_digest_cells,
3239 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 ,
3542} ;
3643
3744/// Batch circuit, the chunk aggregation routine below recursion circuit
@@ -55,14 +62,21 @@ pub struct BatchCircuit<const N_SNARKS: usize> {
5562 // batch hash circuit for which the snarks are generated
5663 // the chunks in this batch are also padded already
5764 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 ,
5870}
5971
6072impl < const N_SNARKS : usize > BatchCircuit < N_SNARKS > {
61- pub fn new (
73+ pub fn new < P : Into < FixedProtocol > > (
6274 params : & ParamsKZG < Bn256 > ,
6375 snarks_with_padding : & [ Snark ] ,
6476 rng : impl Rng + Send ,
6577 batch_hash : BatchHash < N_SNARKS > ,
78+ halo2_protocol : P ,
79+ sp1_protocol : P ,
6680 ) -> Result < Self , snark_verifier:: Error > {
6781 let timer = start_timer ! ( || "generate aggregation circuit" ) ;
6882
@@ -120,6 +134,8 @@ impl<const N_SNARKS: usize> BatchCircuit<N_SNARKS> {
120134 flattened_instances,
121135 as_proof : Value :: known ( as_proof) ,
122136 batch_hash,
137+ halo2_protocol : halo2_protocol. into ( ) ,
138+ sp1_protocol : sp1_protocol. into ( ) ,
123139 } )
124140 }
125141
@@ -209,22 +225,21 @@ impl<const N_SNARKS: usize> Circuit<Fr> for BatchCircuit<N_SNARKS> {
209225 let loader: Rc < Halo2Loader < G1Affine , EccChip < Fr , FpConfig < Fr , Fq > > > > =
210226 Halo2Loader :: new ( ecc_chip, ctx) ;
211227
212- //
213228 // extract the assigned values for
214229 // - instances which are the public inputs of each chunk (prefixed with 12
215230 // instances from previous accumulators)
216231 // - 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 > > (
220238 & self . svk ,
221239 & loader,
222240 & self . snarks_with_padding ,
223241 self . as_proof ( ) ,
224242 ) ;
225- for ( i, e) in assigned_aggregation_instances[ 0 ] . iter ( ) . enumerate ( ) {
226- log:: trace!( "{}-th instance: {:?}" , i, e. value)
227- }
228243
229244 // extract the following cells for later constraints
230245 // - the accumulators
@@ -238,13 +253,113 @@ impl<const N_SNARKS: usize> Circuit<Fr> for BatchCircuit<N_SNARKS> {
238253 . iter ( )
239254 . flat_map ( |instance_column| instance_column. iter ( ) . skip ( ACC_LEN ) ) ,
240255 ) ;
256+ for ( i, e) in assigned_aggregation_instances[ 0 ] . iter ( ) . enumerate ( ) {
257+ log:: trace!( "{}-th instance: {:?}" , i, e. value)
258+ }
241259
242- loader
243- . ctx_mut ( )
244- . print_stats ( & [ "snark aggregation [chunks -> batch]" ] ) ;
260+ loader. ctx_mut ( ) . print_stats ( & [ "snark aggregation" ] ) ;
245261
246262 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+
248363 let barycentric = config. blob_consistency_config . assign_barycentric (
249364 & mut ctx,
250365 & self . batch_hash . blob_bytes ,
0 commit comments