Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Batch Circuit PI for Recursion #1349

Merged
merged 26 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d0703f7
Rename aggregation circuit to batch circuit
darth-cy Jun 24, 2024
b6f6391
Revert unintended root circuit changes
darth-cy Jun 24, 2024
e7bbd0d
Revert unintended root circuit changes
darth-cy Jun 24, 2024
375b986
Add parent state and hash to batch hash
darth-cy Jun 25, 2024
238d1b2
Add additional context fields to batch hash
darth-cy Jun 26, 2024
476a31a
Merge branch 'feat/agg_recursion' into feat/batch_circuit_pi
darth-cy Jun 26, 2024
aa88660
Remove skipped_l1_message_bitmap
darth-cy Jun 26, 2024
7314bb3
Merge branch 'feat/agg_recursion' into feat/batch_circuit_pi
darth-cy Jun 26, 2024
f819827
Add back additional fields in batch header
darth-cy Jun 26, 2024
aa649f9
Add checks for chunk-derived values against context batch header
darth-cy Jun 26, 2024
e94dc62
Adjust schema for batch hash
darth-cy Jun 26, 2024
ced4805
Adjust hash components and constraints for batch hash
darth-cy Jun 27, 2024
d08214f
Adjust batch circuit pi order
darth-cy Jun 27, 2024
a3aa4a5
Adjust CircuitExt impl
darth-cy Jun 27, 2024
6090b8a
Comment definition
darth-cy Jun 27, 2024
06ce41a
Add copy constraints for chunk-level preimage against public input
darth-cy Jun 28, 2024
a0cd5c1
adjust comment
darth-cy Jun 28, 2024
7ab2e45
Add instance constraints for batch hash and its preimage
darth-cy Jun 28, 2024
1fc65b7
Merge branch 'feat/agg_recursion' into feat/batch_circuit_pi
darth-cy Jul 1, 2024
8491477
Resolve compilation issues
darth-cy Jul 1, 2024
625769b
Resolve compilation issue
darth-cy Jul 1, 2024
15094e7
Resolve compilation issues
darth-cy Jul 1, 2024
ea4c602
Resolve compilation issue
darth-cy Jul 1, 2024
b268283
Correct h256 spliting
darth-cy Jul 2, 2024
2585348
Merge branch 'feat/agg_recursion' into feat/batch_circuit_pi
roynalnaruto Jul 2, 2024
4d48233
compilation fix and batch header's hash (test)
roynalnaruto Jul 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aggregator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ csv = "1.1"
[features]
default = ["revm-precompile/c-kzg"]
print-trace = ["ark-std/print-trace"]
# This feature is useful for unit tests where we check the SAT of pi aggregation circuit
# This feature is useful for unit tests where we check the SAT of pi batch circuit
disable_proof_aggregation = []
4 changes: 2 additions & 2 deletions aggregator/src/aggregation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ pub(crate) use blob_data::BlobDataConfig;
pub(crate) use decoder::{witgen, DecoderConfig, DecoderConfigArgs};
pub(crate) use rlc::RlcConfig;

pub use circuit::AggregationCircuit;
pub use config::AggregationConfig;
pub use circuit::BatchCircuit;
pub use config::BatchCircuitConfig;
94 changes: 63 additions & 31 deletions aggregator/src/aggregation/circuit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{blob::BatchData, witgen::MultiBlockProcessResult, LOG_DEGREE};
use crate::{blob::BatchData, witgen::MultiBlockProcessResult, BATCH_PARENT_BATCH_HASH, LOG_DEGREE, PI_CHAIN_ID, PI_CURRENT_BATCH_HASH, PI_CURRENT_STATE_ROOT, PI_CURRENT_WITHDRAW_ROOT, PI_PARENT_BATCH_HASH, PI_PARENT_STATE_ROOT};
use ark_std::{end_timer, start_timer};
use halo2_base::{Context, ContextParams};
use halo2_proofs::{
Expand Down Expand Up @@ -35,18 +35,23 @@ use crate::{
AssignedBarycentricEvaluationConfig, ConfigParams,
};

use super::AggregationConfig;
use super::BatchCircuitConfig;

/// Aggregation circuit that does not re-expose any public inputs from aggregated snarks
/// Batch circuit, the chunk aggregation routine below recursion circuit
#[derive(Clone)]
pub struct AggregationCircuit<const N_SNARKS: usize> {
pub struct BatchCircuit<const N_SNARKS: usize> {
pub svk: KzgSuccinctVerifyingKey<G1Affine>,
// the input snarks for the aggregation circuit
// it is padded already so it will have a fixed length of N_SNARKS
pub snarks_with_padding: Vec<SnarkWitness>,
// batch_circuit_debug:
// the public instance for this circuit consists of
// - an accumulator (12 elements)
// - the batch's public_input_hash (32 elements)
// - parent_state_root (2 elements, split hi_lo)
// - parent_batch_hash (2 elements)
// - current_state_root (2 elements)
// - current_batch_hash (2 elements)
// - chain id (1 element)
// - current_withdraw_root (2 elements)
pub flattened_instances: Vec<Fr>,
// accumulation scheme proof, private input
pub as_proof: Value<Vec<u8>>,
Expand All @@ -55,7 +60,7 @@ pub struct AggregationCircuit<const N_SNARKS: usize> {
pub batch_hash: BatchHash<N_SNARKS>,
}

impl<const N_SNARKS: usize> AggregationCircuit<N_SNARKS> {
impl<const N_SNARKS: usize> BatchCircuit<N_SNARKS> {
pub fn new(
params: &ParamsKZG<Bn256>,
snarks_with_padding: &[Snark],
Expand Down Expand Up @@ -92,17 +97,17 @@ impl<const N_SNARKS: usize> AggregationCircuit<N_SNARKS> {

// this aggregates MULTIPLE snarks
// (instead of ONE as in proof compression)
let (as_proof, acc_instances) =
let (as_proof, _acc_instances) =
extract_proof_and_instances_with_pairing_check(params, snarks_with_padding, rng)?;

// extract batch's public input hash
let public_input_hash = &batch_hash.instances_exclude_acc()[0];

// the public instance for this circuit consists of
// - an accumulator (12 elements)
// - the batch's public_input_hash (32 elements)
let flattened_instances: Vec<Fr> =
[acc_instances.as_slice(), public_input_hash.as_slice()].concat();
// - parent_state_root (2 elements, split hi_lo)
// - parent_batch_hash (2 elements)
// - current_state_root (2 elements)
// - current_batch_hash (2 elements)
// - chain id (1 element)
// - current_withdraw_root (2 elements)
let flattened_instances: Vec<Fr> = batch_hash.instances_exclude_acc::<Fr>()[0].clone();

end_timer!(timer);
Ok(Self {
Expand All @@ -119,8 +124,8 @@ impl<const N_SNARKS: usize> AggregationCircuit<N_SNARKS> {
}
}

impl<const N_SNARKS: usize> Circuit<Fr> for AggregationCircuit<N_SNARKS> {
type Config = (AggregationConfig<N_SNARKS>, Challenges);
impl<const N_SNARKS: usize> Circuit<Fr> for BatchCircuit<N_SNARKS> {
type Config = (BatchCircuitConfig<N_SNARKS>, Challenges);
type FloorPlanner = SimpleFloorPlanner;
fn without_witnesses(&self) -> Self {
unimplemented!()
Expand All @@ -138,7 +143,7 @@ impl<const N_SNARKS: usize> Circuit<Fr> for AggregationCircuit<N_SNARKS> {
);

let challenges = Challenges::construct_p1(meta);
let config = AggregationConfig::configure(meta, &params, challenges);
let config = BatchCircuitConfig::configure(meta, &params, challenges);
log::info!(
"aggregation circuit configured with k = {} and {:?} advice columns",
params.degree,
Expand Down Expand Up @@ -266,10 +271,10 @@ impl<const N_SNARKS: usize> Circuit<Fr> for AggregationCircuit<N_SNARKS> {
.flat_map(|instance_column| instance_column.iter().skip(ACC_LEN)),
);

loader.ctx_mut().print_stats(&["snark aggregation"]);
loader.ctx_mut().print_stats(&["snark aggregation [chunks -> batch]"]);

let mut ctx = Rc::into_inner(loader).unwrap().into_ctx();
log::debug!("aggregation: assigning barycentric");
log::debug!("batching: assigning barycentric");
let barycentric = config.barycentric.assign(
&mut ctx,
&self.batch_hash.point_evaluation_assignments.coefficients,
Expand All @@ -292,7 +297,7 @@ impl<const N_SNARKS: usize> Circuit<Fr> for AggregationCircuit<N_SNARKS> {
};
end_timer!(timer);
// ==============================================
// step 2: public input aggregation circuit
// step 2: public input batch circuit
// ==============================================
// extract all the hashes and load them to the hash table
let challenges = challenge.values(&layouter);
Expand All @@ -307,7 +312,7 @@ impl<const N_SNARKS: usize> Circuit<Fr> for AggregationCircuit<N_SNARKS> {

let timer = start_timer!(|| "extract hash");
// orders:
// - batch_public_input_hash
// - batch_hash
// - chunk\[i\].piHash for i in \[0, N_SNARKS)
// - batch_data_hash_preimage
// - preimage for blob metadata
Expand Down Expand Up @@ -336,6 +341,7 @@ impl<const N_SNARKS: usize> Circuit<Fr> for AggregationCircuit<N_SNARKS> {
&chunks_are_valid,
self.batch_hash.number_of_valid_chunks,
&preimages,
config.instance,
)
.map_err(|e| {
log::error!("assign_batch_hashes err {:#?}", e);
Expand All @@ -350,6 +356,31 @@ impl<const N_SNARKS: usize> Circuit<Fr> for AggregationCircuit<N_SNARKS> {
let (batch_pi_hash_digest, chunk_pi_hash_digests, _potential_batch_data_hash_digest) =
parse_hash_digest_cells::<N_SNARKS>(&assigned_batch_hash.hash_output);

// ========================================================================
// step 2.a: constrain extracted public input cells against actual instance
// ========================================================================
let hash_derived_public_input_cells = assigned_batch_hash.hash_derived_public_input_cells;
let instance_offsets: Vec<usize> = vec![
PI_PARENT_BATCH_HASH,
PI_PARENT_BATCH_HASH + 1,
PI_CURRENT_BATCH_HASH,
PI_CURRENT_BATCH_HASH + 1,
PI_PARENT_STATE_ROOT,
PI_PARENT_STATE_ROOT + 1,
PI_CURRENT_STATE_ROOT,
PI_CURRENT_STATE_ROOT + 1,
PI_CURRENT_WITHDRAW_ROOT,
PI_CURRENT_WITHDRAW_ROOT + 1,
PI_CHAIN_ID,
];
for (c, inst_offset) in hash_derived_public_input_cells.into_iter().zip(instance_offsets.into_iter()) {
layouter.constrain_instance(
c.cell(),
config.instance,
inst_offset
)?;
}

// ==============================================
// step 3: assert public inputs to the snarks are correct
// ==============================================
Expand Down Expand Up @@ -489,7 +520,7 @@ impl<const N_SNARKS: usize> Circuit<Fr> for AggregationCircuit<N_SNARKS> {
address_table_arr,
sequence_exec_info_arr,
&challenges,
LOG_DEGREE, // TODO: configure k for aggregation circuit instead of hard-coded here.
LOG_DEGREE, // TODO: configure k for batch circuit instead of hard-coded here.
)?;

layouter.assign_region(
Expand Down Expand Up @@ -571,22 +602,23 @@ impl<const N_SNARKS: usize> Circuit<Fr> for AggregationCircuit<N_SNARKS> {
}
}

impl<const N_SNARKS: usize> CircuitExt<Fr> for AggregationCircuit<N_SNARKS> {
impl<const N_SNARKS: usize> CircuitExt<Fr> for BatchCircuit<N_SNARKS> {
fn num_instance(&self) -> Vec<usize> {
// 12 elements from accumulator
// 32 elements from batch's public_input_hash
vec![ACC_LEN + DIGEST_LEN]
// - parent_state_root (2 elements, split hi_lo)
// - parent_batch_hash (2 elements)
// - current_state_root (2 elements)
// - current_batch_hash (2 elements)
// - chain id (1 element)
// - current_withdraw_root (2 elements)
vec![11]
}

// 12 elements from accumulator
// 32 elements from batch's public_input_hash
fn instances(&self) -> Vec<Vec<Fr>> {
vec![self.flattened_instances.clone()]
}

fn accumulator_indices() -> Option<Vec<(usize, usize)>> {
// the accumulator are the first 12 cells in the instance
Some((0..ACC_LEN).map(|idx| (0, idx)).collect())
None
}

fn selectors(config: &Self::Config) -> Vec<Selector> {
Expand Down
37 changes: 21 additions & 16 deletions aggregator/src/aggregation/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,14 @@ use zkevm_circuits::{
};

use crate::{
constants::{BITS, LIMBS},
param::ConfigParams,
BarycentricEvaluationConfig, BatchDataConfig, BlobDataConfig, DecoderConfig, DecoderConfigArgs,
RlcConfig,
constants::{BITS, LIMBS}, param::ConfigParams, BarycentricEvaluationConfig, BatchDataConfig, BlobDataConfig, DecoderConfig, DecoderConfigArgs, RlcConfig
};

#[derive(Debug, Clone)]
#[rustfmt::skip]
/// Configurations for aggregation circuit.
/// Configurations for batch circuit.
/// This config is hard coded for BN256 curve.
pub struct AggregationConfig<const N_SNARKS: usize> {
pub struct BatchCircuitConfig<const N_SNARKS: usize> {
/// Non-native field chip configurations
pub base_field_config: FpConfig<Fr, Fq>,
/// Keccak circuit configurations
Expand All @@ -43,13 +40,17 @@ pub struct AggregationConfig<const N_SNARKS: usize> {
/// Config to do the barycentric evaluation on blob polynomial.
pub barycentric: BarycentricEvaluationConfig,
/// Instance for public input; stores
/// - accumulator from aggregation (12 elements)
/// - batch_public_input_hash (32 elements)
/// - chain id (1 element)
/// - parent_state_root (2 elements, split hi_lo)
/// - parent_batch_hash (2 elements)
/// - current_state_root (2 elements)
/// - current_batch_hash (2 elements)
/// - current_withdraw_root (2 elements)
/// - the number of valid SNARKs (1 element)
pub instance: Column<Instance>,
}

impl<const N_SNARKS: usize> AggregationConfig<N_SNARKS> {
impl<const N_SNARKS: usize> BatchCircuitConfig<N_SNARKS> {
/// Build a configuration from parameters.
pub fn configure(
meta: &mut ConstraintSystem<Fr>,
Expand All @@ -61,7 +62,7 @@ impl<const N_SNARKS: usize> AggregationConfig<N_SNARKS> {
"For now we fix limb_bits = {BITS}, otherwise change code",
);

// hash configuration for aggregation circuit
// hash configuration for batch circuit
let (keccak_table, keccak_circuit_config) = {
let keccak_table = KeccakTable::construct(meta);

Expand All @@ -80,7 +81,7 @@ impl<const N_SNARKS: usize> AggregationConfig<N_SNARKS> {
// RLC configuration
let rlc_config = RlcConfig::configure(meta, &keccak_table, challenges);

// base field configuration for aggregation circuit
// base field configuration for batch circuit
let base_field_config = FpConfig::configure(
meta,
params.strategy.clone(),
Expand Down Expand Up @@ -149,9 +150,13 @@ impl<const N_SNARKS: usize> AggregationConfig<N_SNARKS> {
);

// Instance column stores public input column
// - the accumulator
// - the batch public input hash
// - the number of valid SNARKs
// the public instance for this circuit consists of
// - chain id (1 element)
// - parent_state_root (2 elements, split hi_lo)
// - parent_batch_hash (2 elements)
// - current_state_root (2 elements)
// - current_batch_hash (2 elements)
// - current_withdraw_root (2 elements)
let instance = meta.instance_column();
meta.enable_equality(instance);

Expand Down Expand Up @@ -192,7 +197,7 @@ impl<const N_SNARKS: usize> AggregationConfig<N_SNARKS> {
}

#[test]
fn aggregation_circuit_degree() {
fn batch_circuit_degree() {
use halo2_ecc::fields::fp::FpStrategy;
let mut cs = ConstraintSystem::<Fr>::default();
let param = ConfigParams {
Expand All @@ -206,7 +211,7 @@ fn aggregation_circuit_degree() {
num_limbs: 3,
};
let challenges = Challenges::construct_p1(&mut cs);
AggregationConfig::<{ crate::constants::MAX_AGG_SNARKS }>::configure(
BatchCircuitConfig::<{ crate::constants::MAX_AGG_SNARKS }>::configure(
&mut cs, &param, challenges,
);
cs = cs.chunk_lookups();
Expand Down
Loading
Loading