From a1c07a57cf965377718f148b08bcbf24966ac497 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Mon, 16 Jan 2023 15:15:59 -0800 Subject: [PATCH] Minor compatibility updates (#5) * feat: add bench for zkEVM EVM + State circuit aggregation * chore: minor update with new `print_stats` * chore: update Cargo * chore: change `AggregationConfigParams` to allow multi-phase advice columns * chore: update Cargo * sdk: remove `ExtraCircuitParams` from `CircuitExt` and just allow `num_instance` to depend on circuit itself * feat: change `EvmSingleVerifierCircuit` to `PublicAggregationCircuit` * aggregation circuit that passes through instances from multiple snarks * assumes snarks are either all aggregation circuits or all non-aggregation circuits when determining passthrough logic * chore: update pk serialization to new halo2_proofs API --- Cargo.toml | 4 - snark-verifier-sdk/Cargo.toml | 7 +- snark-verifier-sdk/benches/standard_plonk.rs | 4 +- snark-verifier-sdk/benches/zkevm.rs | 48 ++++- .../benches/zkevm_plus_state.rs | 187 ++++++++++++++++++ snark-verifier-sdk/configs/bench_zkevm.config | 2 +- .../configs/example_evm_accumulator.config | 2 +- .../configs/verify_circuit.config | 2 +- snark-verifier-sdk/src/evm.rs | 14 +- snark-verifier-sdk/src/halo2.rs | 17 +- snark-verifier-sdk/src/halo2/aggregation.rs | 112 +++++++---- snark-verifier-sdk/src/lib.rs | 28 +-- snark-verifier/Cargo.toml | 11 +- snark-verifier/src/lib.rs | 10 +- snark-verifier/src/pcs/kzg/accumulation.rs | 13 +- snark-verifier/src/system/halo2/test.rs | 2 + .../src/system/halo2/test/kzg/halo2.rs | 3 +- 17 files changed, 356 insertions(+), 110 deletions(-) create mode 100644 snark-verifier-sdk/benches/zkevm_plus_state.rs diff --git a/Cargo.toml b/Cargo.toml index 5f6be49e..7b3ec409 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,10 +34,6 @@ incremental = false inherits = "release" debug = true -# patch until PR https://github.com/privacy-scaling-explorations/halo2curves/pull/10 is merged -[patch."https://github.com/privacy-scaling-explorations/halo2curves.git"] -halo2curves = { git = "https://github.com/jonathanpwang/halo2curves.git", branch = "feat/serde-field" } - # patch until PR https://github.com/privacy-scaling-explorations/halo2/pull/111 is merged [patch."https://github.com/privacy-scaling-explorations/halo2.git"] halo2_proofs = { git = "https://github.com/axiom-crypto/halo2.git", branch = "feat/serde-raw" } \ No newline at end of file diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index 5cd03a9c..5ab1b92f 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -17,7 +17,7 @@ serde_json = "1.0" bincode = "1.3.3" ark-std = { version = "0.3.0", features = ["print-trace"], optional = true } -halo2-base = { git = "ssh://git@github.com/axiom-crypto/axiom-core-working.git", branch = "experiment/optimizations", default-features = false } +halo2-base = { git = "ssh://git@github.com/axiom-crypto/axiom-core-working.git", default-features = false } snark-verifier = { path = "../snark-verifier", default-features = false } # loader_evm @@ -63,4 +63,9 @@ harness = false [[bench]] name = "zkevm" required-features = ["loader_halo2", "zkevm", "halo2-pse", "halo2-base/jemallocator"] +harness = false + +[[bench]] +name = "zkevm_plus_state" +required-features = ["loader_halo2", "zkevm", "halo2-pse", "halo2-base/jemallocator"] harness = false \ No newline at end of file diff --git a/snark-verifier-sdk/benches/standard_plonk.rs b/snark-verifier-sdk/benches/standard_plonk.rs index 2d242dad..2a831e45 100644 --- a/snark-verifier-sdk/benches/standard_plonk.rs +++ b/snark-verifier-sdk/benches/standard_plonk.rs @@ -88,9 +88,7 @@ mod application { } impl CircuitExt for StandardPlonk { - fn extra_params(&self) -> Self::ExtraCircuitParams {} - - fn num_instance(_: &Self::ExtraCircuitParams) -> Vec { + fn num_instance(&self) -> Vec { vec![1] } diff --git a/snark-verifier-sdk/benches/zkevm.rs b/snark-verifier-sdk/benches/zkevm.rs index 03749cc2..f4c3f3fc 100644 --- a/snark-verifier-sdk/benches/zkevm.rs +++ b/snark-verifier-sdk/benches/zkevm.rs @@ -14,7 +14,7 @@ use snark_verifier_sdk::{ gen_pk, halo2::{ aggregation::load_verify_circuit_degree, aggregation::AggregationCircuit, gen_proof_gwc, - gen_proof_shplonk, gen_snark_shplonk, PoseidonTranscript, POSEIDON_SPEC, + gen_proof_shplonk, gen_snark_gwc, gen_snark_shplonk, PoseidonTranscript, POSEIDON_SPEC, }, CircuitExt, }; @@ -66,13 +66,13 @@ fn bench(c: &mut Criterion) { let circuit = zkevm::test_circuit(); let params_app = gen_srs(k); let pk = gen_pk(¶ms_app, &circuit, Some(Path::new("data/zkevm_evm.pkey"))); - let snark = gen_snark_shplonk( + let snark = gen_snark_gwc( ¶ms_app, &pk, circuit, &mut transcript, &mut rng, - None, // Some((Path::new("data/zkevm_evm.in"), Path::new("data/zkevm_evm.pf"))), + Some(Path::new("data/zkevm_evm.snark")), ); let snarks = [snark]; // === finished zkevm evm circuit === @@ -88,7 +88,7 @@ fn bench(c: &mut Criterion) { let pk = gen_pk(¶ms, &agg_circuit, None); - let mut group = c.benchmark_group("plonk-prover"); + let mut group = c.benchmark_group("shplonk-proof"); group.sample_size(10); group.bench_with_input( BenchmarkId::new("zkevm-evm-agg", k), @@ -110,12 +110,34 @@ fn bench(c: &mut Criterion) { ); group.finish(); + let mut group = c.benchmark_group("gwc-proof"); + group.sample_size(10); + group.bench_with_input( + BenchmarkId::new("zkevm-evm-agg", k), + &(¶ms, &pk, &agg_circuit), + |b, &(params, pk, agg_circuit)| { + b.iter(|| { + let instances = agg_circuit.instances(); + gen_proof_gwc( + params, + pk, + agg_circuit.clone(), + instances, + &mut transcript, + &mut rng, + None, + ); + }) + }, + ); + group.finish(); + #[cfg(feature = "loader_evm")] { let deployment_code = gen_evm_verifier_shplonk::(¶ms, pk.get_vk(), &(), None::<&str>); - let start2 = start_timer!(|| "Create EVM proof"); + let start2 = start_timer!(|| "Create EVM SHPLONK proof"); let proof = gen_evm_proof_shplonk( ¶ms, &pk, @@ -126,12 +148,18 @@ fn bench(c: &mut Criterion) { end_timer!(start2); evm_verify(deployment_code, agg_circuit.instances(), proof); + + let deployment_code = + gen_evm_verifier_shplonk::(¶ms, pk.get_vk(), &(), None::<&str>); + + let start2 = start_timer!(|| "Create EVM GWC proof"); + let proof = + gen_evm_proof_gwc(¶ms, &pk, agg_circuit.clone(), agg_circuit.instances(), &mut rng); + end_timer!(start2); + + evm_verify(deployment_code, agg_circuit.instances(), proof); } } -criterion_group! { - name = benches; - config = Criterion::default().with_profiler(PProfProfiler::new(10, Output::Flamegraph(None))); - targets = bench -} +criterion_group!(benches, bench); criterion_main!(benches); diff --git a/snark-verifier-sdk/benches/zkevm_plus_state.rs b/snark-verifier-sdk/benches/zkevm_plus_state.rs new file mode 100644 index 00000000..840f8581 --- /dev/null +++ b/snark-verifier-sdk/benches/zkevm_plus_state.rs @@ -0,0 +1,187 @@ +use ark_std::{end_timer, start_timer}; +use halo2_base::halo2_proofs; +use halo2_base::utils::fs::gen_srs; +use halo2_proofs::halo2curves::bn256::Fr; +use rand::SeedableRng; +use rand_chacha::ChaCha20Rng; +use snark_verifier::loader::native::NativeLoader; +use snark_verifier_sdk::{ + self, + evm::{ + evm_verify, gen_evm_proof_gwc, gen_evm_proof_shplonk, gen_evm_verifier_gwc, + gen_evm_verifier_shplonk, + }, + gen_pk, + halo2::{ + aggregation::load_verify_circuit_degree, aggregation::AggregationCircuit, gen_proof_gwc, + gen_proof_shplonk, gen_snark_gwc, gen_snark_shplonk, PoseidonTranscript, POSEIDON_SPEC, + }, + CircuitExt, +}; +use std::env::{set_var, var}; +use std::path::Path; + +use criterion::{criterion_group, criterion_main}; +use criterion::{BenchmarkId, Criterion}; +use pprof::criterion::{Output, PProfProfiler}; + +pub mod zkevm { + use super::Fr; + use bus_mapping::{circuit_input_builder::CircuitsParams, mock::BlockData}; + use eth_types::geth_types::GethData; + use mock::TestContext; + use zkevm_circuits::{ + evm_circuit::{witness::block_convert, EvmCircuit}, + state_circuit::StateCircuit, + witness::RwMap, + }; + + pub fn test_evm_circuit() -> EvmCircuit { + let empty_data: GethData = + TestContext::<0, 0>::new(None, |_| {}, |_, _| {}, |b, _| b).unwrap().into(); + + let mut builder = BlockData::new_from_geth_data_with_params( + empty_data.clone(), + CircuitsParams::default(), + ) + .new_circuit_input_builder(); + + builder.handle_block(&empty_data.eth_block, &empty_data.geth_traces).unwrap(); + + let block = block_convert(&builder.block, &builder.code_db).unwrap(); + + EvmCircuit::::new(block) + } + + pub fn test_state_circuit() -> StateCircuit { + StateCircuit::new(RwMap::default(), 1 << 16) + } +} + +fn bench(c: &mut Criterion) { + let mut rng = ChaCha20Rng::from_entropy(); + let mut transcript = + PoseidonTranscript::::from_spec(vec![], POSEIDON_SPEC.clone()); + + // === create zkevm evm circuit snark === + let k: u32 = var("DEGREE") + .unwrap_or_else(|_| { + set_var("DEGREE", "18"); + "18".to_owned() + }) + .parse() + .unwrap(); + let evm_circuit = zkevm::test_evm_circuit(); + let state_circuit = zkevm::test_state_circuit(); + let params_app = gen_srs(k); + let evm_snark = { + let pk = gen_pk(¶ms_app, &evm_circuit, Some(Path::new("data/zkevm_evm.pkey"))); + gen_snark_gwc( + ¶ms_app, + &pk, + evm_circuit, + &mut transcript, + &mut rng, + Some(Path::new("data/zkevm_evm.snark")), + ) + }; + let state_snark = { + let pk = gen_pk(¶ms_app, &state_circuit, Some(Path::new("data/zkevm_state.pkey"))); + gen_snark_shplonk( + ¶ms_app, + &pk, + state_circuit, + &mut transcript, + &mut rng, + Some(Path::new("data/zkevm_state.snark")), + ) + }; + let snarks = [evm_snark, state_snark]; + // === finished zkevm evm circuit === + + // === now to do aggregation === + set_var("VERIFY_CONFIG", "./configs/bench_zkevm_plus_state.config"); + let k = load_verify_circuit_degree(); + let params = gen_srs(k); + + let start1 = start_timer!(|| "Create aggregation circuit"); + let agg_circuit = AggregationCircuit::new(¶ms, snarks, &mut transcript, &mut rng); + end_timer!(start1); + + let pk = gen_pk(¶ms, &agg_circuit, None); + + let mut group = c.benchmark_group("shplonk-proof"); + group.sample_size(10); + group.bench_with_input( + BenchmarkId::new("zkevm-evm-state-agg", k), + &(¶ms, &pk, &agg_circuit), + |b, &(params, pk, agg_circuit)| { + b.iter(|| { + let instances = agg_circuit.instances(); + gen_proof_shplonk( + params, + pk, + agg_circuit.clone(), + instances, + &mut transcript, + &mut rng, + None, + ); + }) + }, + ); + group.finish(); + + let mut group = c.benchmark_group("gwc-proof"); + group.sample_size(10); + group.bench_with_input( + BenchmarkId::new("zkevm-evm-state-agg", k), + &(¶ms, &pk, &agg_circuit), + |b, &(params, pk, agg_circuit)| { + b.iter(|| { + let instances = agg_circuit.instances(); + gen_proof_gwc( + params, + pk, + agg_circuit.clone(), + instances, + &mut transcript, + &mut rng, + None, + ); + }) + }, + ); + group.finish(); + + #[cfg(feature = "loader_evm")] + { + let deployment_code = + gen_evm_verifier_shplonk::(¶ms, pk.get_vk(), &(), None::<&str>); + + let start2 = start_timer!(|| "Create EVM SHPLONK proof"); + let proof = gen_evm_proof_shplonk( + ¶ms, + &pk, + agg_circuit.clone(), + agg_circuit.instances(), + &mut rng, + ); + end_timer!(start2); + + evm_verify(deployment_code, agg_circuit.instances(), proof); + + let deployment_code = + gen_evm_verifier_shplonk::(¶ms, pk.get_vk(), &(), None::<&str>); + + let start2 = start_timer!(|| "Create EVM GWC proof"); + let proof = + gen_evm_proof_gwc(¶ms, &pk, agg_circuit.clone(), agg_circuit.instances(), &mut rng); + end_timer!(start2); + + evm_verify(deployment_code, agg_circuit.instances(), proof); + } +} + +criterion_group!(benches, bench); +criterion_main!(benches); diff --git a/snark-verifier-sdk/configs/bench_zkevm.config b/snark-verifier-sdk/configs/bench_zkevm.config index 1cda14ab..5156de4f 100644 --- a/snark-verifier-sdk/configs/bench_zkevm.config +++ b/snark-verifier-sdk/configs/bench_zkevm.config @@ -1 +1 @@ -{"strategy":"Simple","degree":23,"num_advice":5,"num_lookup_advice":1,"num_fixed":1,"lookup_bits":22,"limb_bits":88,"num_limbs":3} \ No newline at end of file +{"strategy":"Simple","degree":23,"num_advice":[5],"num_lookup_advice":[1],"num_fixed":1,"lookup_bits":22,"limb_bits":88,"num_limbs":3} diff --git a/snark-verifier-sdk/configs/example_evm_accumulator.config b/snark-verifier-sdk/configs/example_evm_accumulator.config index fcda49a0..156c402a 100644 --- a/snark-verifier-sdk/configs/example_evm_accumulator.config +++ b/snark-verifier-sdk/configs/example_evm_accumulator.config @@ -1 +1 @@ -{"strategy":"Simple","degree":21,"num_advice":5,"num_lookup_advice":1,"num_fixed":1,"lookup_bits":20,"limb_bits":88,"num_limbs":3} \ No newline at end of file +{"strategy":"Simple","degree":21,"num_advice":[5],"num_lookup_advice":[1],"num_fixed":1,"lookup_bits":20,"limb_bits":88,"num_limbs":3} diff --git a/snark-verifier-sdk/configs/verify_circuit.config b/snark-verifier-sdk/configs/verify_circuit.config index e65b2b52..90aff847 100644 --- a/snark-verifier-sdk/configs/verify_circuit.config +++ b/snark-verifier-sdk/configs/verify_circuit.config @@ -1 +1 @@ -{"strategy":"Simple","degree":21,"num_advice":4,"num_lookup_advice":1,"num_fixed":1,"lookup_bits":20,"limb_bits":88,"num_limbs":3} \ No newline at end of file +{"strategy":"Simple","degree":21,"num_advice":[4],"num_lookup_advice":[1],"num_fixed":1,"lookup_bits":20,"limb_bits":88,"num_limbs":3} diff --git a/snark-verifier-sdk/src/evm.rs b/snark-verifier-sdk/src/evm.rs index ecb5567c..d5ca209c 100644 --- a/snark-verifier-sdk/src/evm.rs +++ b/snark-verifier-sdk/src/evm.rs @@ -115,7 +115,7 @@ pub fn gen_evm_proof_shplonk<'params, C: Circuit>( pub fn gen_evm_verifier( params: &ParamsKZG, vk: &VerifyingKey, - extra_circuit_params: &C::ExtraCircuitParams, + num_instance: Vec, path: Option<&Path>, ) -> Vec where @@ -136,7 +136,7 @@ where params, vk, Config::kzg() - .with_num_instance(C::num_instance(extra_circuit_params)) + .with_num_instance(num_instance.clone()) .with_accumulator_indices(C::accumulator_indices()), ); @@ -144,7 +144,7 @@ where let protocol = protocol.loaded(&loader); let mut transcript = EvmTranscript::<_, Rc, _, _>::new(&loader); - let instances = transcript.load_instances(C::num_instance(extra_circuit_params)); + let instances = transcript.load_instances(num_instance); let proof = Plonk::::read_proof(&svk, &protocol, &instances, &mut transcript); Plonk::::verify(&svk, &dk, &protocol, &instances, &proof); @@ -160,19 +160,19 @@ where pub fn gen_evm_verifier_gwc>( params: &ParamsKZG, vk: &VerifyingKey, - extra_circuit_params: &C::ExtraCircuitParams, + num_instance: Vec, path: Option<&Path>, ) -> Vec { - gen_evm_verifier::>(params, vk, extra_circuit_params, path) + gen_evm_verifier::>(params, vk, num_instance, path) } pub fn gen_evm_verifier_shplonk>( params: &ParamsKZG, vk: &VerifyingKey, - extra_circuit_params: &C::ExtraCircuitParams, + num_instance: Vec, path: Option<&Path>, ) -> Vec { - gen_evm_verifier::>(params, vk, extra_circuit_params, path) + gen_evm_verifier::>(params, vk, num_instance, path) } pub fn evm_verify(deployment_code: Vec, instances: Vec>, proof: Vec) { diff --git a/snark-verifier-sdk/src/halo2.rs b/snark-verifier-sdk/src/halo2.rs index 7d3ecc60..226a81e8 100644 --- a/snark-verifier-sdk/src/halo2.rs +++ b/snark-verifier-sdk/src/halo2.rs @@ -1,7 +1,7 @@ use super::{read_instances, write_instances, CircuitExt, Snark, SnarkWitness}; #[cfg(feature = "display")] use ark_std::{end_timer, start_timer}; -use halo2_base::{halo2_proofs, poseidon::Spec}; +use halo2_base::halo2_proofs; use halo2_proofs::{ circuit::Layouter, dev::MockProver, @@ -34,10 +34,10 @@ use snark_verifier::{ system::halo2::{compile, Config}, util::transcript::TranscriptWrite, verifier::PlonkProof, + PoseidonSpec, }; use std::{ fs::{self, File}, - iter, marker::PhantomData, path::Path, }; @@ -62,7 +62,7 @@ pub type PoseidonTranscript = >; lazy_static! { - pub static ref POSEIDON_SPEC: Spec = Spec::new(R_F, R_P); + pub static ref POSEIDON_SPEC: PoseidonSpec = PoseidonSpec::new(R_F, R_P); } /// Generates a native proof using either SHPLONK or GWC proving method. Uses Poseidon for Fiat-Shamir. @@ -207,7 +207,7 @@ where params, pk.get_vk(), Config::kzg() - .with_num_instance(ConcreteCircuit::num_instance(&circuit.extra_params())) + .with_num_instance(circuit.num_instance()) .with_accumulator_indices(ConcreteCircuit::accumulator_indices()), ); @@ -279,7 +279,7 @@ pub fn read_snark(path: impl AsRef) -> Result { pub fn gen_dummy_snark( params: &ParamsKZG, vk: Option<&VerifyingKey>, - extra_params: &ConcreteCircuit::ExtraCircuitParams, + num_instance: Vec, ) -> Snark where ConcreteCircuit: CircuitExt, @@ -327,13 +327,10 @@ where params, vk.or(dummy_vk.as_ref()).unwrap(), Config::kzg() - .with_num_instance(ConcreteCircuit::num_instance(extra_params)) + .with_num_instance(num_instance.clone()) .with_accumulator_indices(ConcreteCircuit::accumulator_indices()), ); - let instances = ConcreteCircuit::num_instance(extra_params) - .into_iter() - .map(|n| iter::repeat(Fr::default()).take(n).collect()) - .collect(); + let instances = num_instance.into_iter().map(|n| vec![Fr::default(); n]).collect(); let proof = { let mut transcript = PoseidonTranscript::::new(Vec::new()); for _ in 0..protocol diff --git a/snark-verifier-sdk/src/halo2/aggregation.rs b/snark-verifier-sdk/src/halo2/aggregation.rs index da25225a..e29bf145 100644 --- a/snark-verifier-sdk/src/halo2/aggregation.rs +++ b/snark-verifier-sdk/src/halo2/aggregation.rs @@ -1,3 +1,4 @@ +#![allow(clippy::clone_on_copy)] use crate::{Plonk, BITS, LIMBS}; #[cfg(feature = "display")] use ark_std::{end_timer, start_timer}; @@ -121,8 +122,8 @@ where pub struct AggregationConfigParams { pub strategy: halo2_ecc::fields::fp::FpStrategy, pub degree: u32, - pub num_advice: usize, - pub num_lookup_advice: usize, + pub num_advice: Vec, + pub num_lookup_advice: Vec, pub num_fixed: usize, pub lookup_bits: usize, pub limb_bits: usize, @@ -145,8 +146,8 @@ impl AggregationConfig { let base_field_config = halo2_ecc::fields::fp::FpConfig::configure( meta, params.strategy, - &[params.num_advice], - &[params.num_lookup_advice], + ¶ms.num_advice, + ¶ms.num_lookup_advice, params.num_fixed, params.lookup_bits, BITS, @@ -256,8 +257,7 @@ impl AggregationCircuit { } impl CircuitExt for AggregationCircuit { - fn extra_params(&self) -> Self::ExtraCircuitParams {} - fn num_instance(_: &()) -> Vec { + fn num_instance(&self) -> Vec { // [..lhs, ..rhs] vec![4 * LIMBS] } @@ -346,12 +346,11 @@ impl Circuit for AggregationCircuit { .chain(lhs.y.truncation.limbs.iter()) .chain(rhs.x.truncation.limbs.iter()) .chain(rhs.y.truncation.limbs.iter()) - .map(|assigned| assigned.cell()) - .cloned(), + .map(|assigned| assigned.cell().clone()), ); - let _num_lookup_advice = config.range().finalize(&mut loader.ctx_mut()); + config.range().finalize(&mut loader.ctx_mut()); #[cfg(feature = "display")] - loader.ctx_mut().print_stats(&["Range"], _num_lookup_advice); + loader.ctx_mut().print_stats(&["Range"]); Ok(()) }, ) @@ -367,47 +366,58 @@ impl Circuit for AggregationCircuit { } } -/// This circuit takes a single SNARK, assumed to be an aggregation circuit of some kind, -/// and passes through all of its instances except the old accumulators. +/// This circuit takes multiple SNARKs and passes through all of their instances except the old accumulators. /// -/// We assume the previous SNARK circuit only has one instance column. +/// * If `has_prev_accumulator = true`, we assume all SNARKs are of aggregation circuits with old accumulators +/// only in the first instance column. +/// * Otherwise if `has_prev_accumulator = false`, then all previous instances are passed through. #[derive(Clone)] -pub struct EvmVerifierAfterAggregationCircuit(pub AggregationCircuit); +pub struct PublicAggregationCircuit { + pub aggregation: AggregationCircuit, + pub has_prev_accumulator: bool, +} -impl EvmVerifierAfterAggregationCircuit { +impl PublicAggregationCircuit { pub fn new( params: &ParamsKZG, - snark: Snark, + snarks: Vec, + has_prev_accumulator: bool, transcript_write: &mut PoseidonTranscript>, rng: &mut (impl Rng + Send), ) -> Self { - Self(AggregationCircuit::new(params, vec![snark], transcript_write, rng)) + Self { + aggregation: AggregationCircuit::new(params, snarks, transcript_write, rng), + has_prev_accumulator, + } } } -impl CircuitExt for EvmVerifierAfterAggregationCircuit { - type ExtraCircuitParams = usize; - - fn extra_params(&self) -> usize { - assert_eq!(self.0.snarks[0].instances.len(), 1); - self.0.snarks[0].instances[0].len() - } - - fn num_instance(num_instance: &usize) -> Vec { - vec![*num_instance] +impl CircuitExt for PublicAggregationCircuit { + fn num_instance(&self) -> Vec { + let prev_num = self + .aggregation + .snarks + .iter() + .map(|snark| snark.instances.iter().map(|instance| instance.len()).sum::()) + .sum::() + - self.aggregation.snarks.len() * 4 * LIMBS * usize::from(self.has_prev_accumulator); + vec![4 * LIMBS + prev_num] } fn instances(&self) -> Vec> { + let start_idx = 4 * LIMBS * usize::from(self.has_prev_accumulator); let instance = self - .0 + .aggregation .instances .iter() .cloned() - .chain( - self.0.snarks[0].instances[0][4 * LIMBS..] - .iter() - .map(|v| value_to_option(*v).unwrap()), - ) + .chain(self.aggregation.snarks.iter().flat_map(|snark| { + snark.instances.iter().enumerate().flat_map(|(i, instance)| { + instance[usize::from(i == 0) * start_idx..] + .iter() + .map(|v| value_to_option(*v).unwrap()) + }) + })) .collect_vec(); vec![instance] } @@ -421,12 +431,15 @@ impl CircuitExt for EvmVerifierAfterAggregationCircuit { } } -impl Circuit for EvmVerifierAfterAggregationCircuit { +impl Circuit for PublicAggregationCircuit { type Config = AggregationConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - Self(self.0.without_witnesses()) + Self { + aggregation: self.aggregation.without_witnesses(), + has_prev_accumulator: self.has_prev_accumulator, + } } fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { @@ -464,14 +477,15 @@ impl Circuit for EvmVerifierAfterAggregationCircuit { let loader = Halo2Loader::new(ecc_chip, ctx); let (prev_instances, KzgAccumulator { lhs, rhs }) = aggregate::>( - &self.0.svk, + &self.aggregation.svk, &loader, - &self.0.snarks, - self.0.as_proof(), + &self.aggregation.snarks, + self.aggregation.as_proof(), ); let lhs = lhs.assigned(); let rhs = rhs.assigned(); + // accumulator instances.extend( lhs.x .truncation @@ -480,14 +494,26 @@ impl Circuit for EvmVerifierAfterAggregationCircuit { .chain(lhs.y.truncation.limbs.iter()) .chain(rhs.x.truncation.limbs.iter()) .chain(rhs.y.truncation.limbs.iter()) - .chain(prev_instances[4 * LIMBS..].iter()) - .map(|assigned| assigned.cell()) - .cloned(), + .map(|a| a.cell().clone()), ); + // prev instances except accumulators + let mut idx = 0; + let start_idx = 4 * LIMBS * usize::from(self.has_prev_accumulator); + for snark in self.aggregation.snarks.iter() { + for (i, instance) in snark.instances.iter().enumerate() { + let start_idx = usize::from(i == 0) * start_idx; + instances.extend( + prev_instances[idx + start_idx..idx + instance.len()] + .iter() + .map(|a| a.cell().clone()), + ); + idx += instance.len(); + } + } - let _num_lookup_advice = config.range().finalize(&mut loader.ctx_mut()); + config.range().finalize(&mut loader.ctx_mut()); #[cfg(feature = "display")] - loader.ctx_mut().print_stats(&["Range"], _num_lookup_advice); + loader.ctx_mut().print_stats(&["Range"]); Ok(()) }, ) diff --git a/snark-verifier-sdk/src/lib.rs b/snark-verifier-sdk/src/lib.rs index c20a7359..38b5da5c 100644 --- a/snark-verifier-sdk/src/lib.rs +++ b/snark-verifier-sdk/src/lib.rs @@ -10,6 +10,7 @@ use halo2_proofs::{ }, plonk::{keygen_pk, keygen_vk, Circuit, ProvingKey, Selector}, poly::kzg::commitment::ParamsKZG, + SerdeFormat, }; use itertools::Itertools; use serde::{Deserialize, Serialize}; @@ -85,14 +86,9 @@ impl SnarkWitness { } pub trait CircuitExt: Circuit { - /// Due to limitations of Rust generics, we provide a helper type to hold extra parameters that may determine a circuit - type ExtraCircuitParams = (); - - /// The extra parameters should be derivable from any circuit instance - fn extra_params(&self) -> Self::ExtraCircuitParams; - - /// Return the number of instances of the circuit. This may depend on extra circuit parameters but NOT on private witnesses. - fn num_instance(params: &Self::ExtraCircuitParams) -> Vec; + /// Return the number of instances of the circuit. + /// This may depend on extra circuit parameters but NOT on private witnesses. + fn num_instance(&self) -> Vec; fn instances(&self) -> Vec>; @@ -117,7 +113,8 @@ pub fn read_pk>(path: &Path) -> io::Result> let initial_buffer_size = f.metadata().map(|m| m.len() as usize + 1).unwrap_or(0); let mut bufreader = Vec::with_capacity(initial_buffer_size); f.read_to_end(&mut bufreader)?; - let pk = ProvingKey::read::<_, C>(&mut bufreader.as_slice())?; + let pk = ProvingKey::read::<_, C>(&mut bufreader.as_slice(), SerdeFormat::RawBytesUnchecked) + .unwrap(); #[cfg(feature = "display")] end_timer!(read_time); @@ -151,7 +148,7 @@ pub fn gen_pk>( path.parent().and_then(|dir| fs::create_dir_all(dir).ok()).unwrap(); let mut f = BufWriter::new(File::create(path).unwrap()); - pk.write(&mut f).unwrap(); + pk.write(&mut f, SerdeFormat::RawBytesUnchecked).unwrap(); #[cfg(feature = "display")] end_timer!(write_time); @@ -191,7 +188,7 @@ pub fn write_instances(instances: &[&[Fr]], path: impl AsRef) { mod zkevm { use super::CircuitExt; use eth_types::Field; - use zkevm_circuits::evm_circuit::EvmCircuit; + use zkevm_circuits::{evm_circuit::EvmCircuit, state_circuit::StateCircuit}; impl CircuitExt for EvmCircuit { fn instances(&self) -> Vec> { @@ -201,4 +198,13 @@ mod zkevm { vec![] } } + + impl CircuitExt for StateCircuit { + fn instances(&self) -> Vec> { + vec![] + } + fn num_instance() -> Vec { + vec![] + } + } } diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index 745840c5..b356b4ce 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -15,7 +15,10 @@ rustc-hash = "1.1.0" serde = { version = "1.0", features = ["derive"] } # Use halo2-base as non-optional dependency because it re-exports halo2_proofs, halo2curves, and poseidon, using different repos based on feature flag "halo2-axiom" or "halo2-pse" -halo2-base = { git = "ssh://git@github.com/axiom-crypto/axiom-core-working.git", branch = "experiment/optimizations", default-features = false } +halo2-base = { git = "ssh://git@github.com/axiom-crypto/axiom-core-working.git", default-features = false } +# This poseidon is identical to PSE (for now) but uses axiom's halo2curves; otherwise would require patching +poseidon-axiom = { git = "https://github.com/axiom-crypto/halo2.git", branch = "axiom/faster-witness-generation", package = "poseidon", optional = true } +poseidon= { git = "https://github.com/privacy-scaling-explorations/poseidon", optional = true } # parallel rayon = { version = "1.5.3", optional = true } @@ -28,7 +31,7 @@ bytes = { version = "1.2", optional = true } rlp = { version = "0.5", default-features = false, features = ["std"], optional = true } # loader_halo2 -halo2-ecc = { git = "ssh://git@github.com/axiom-crypto/axiom-core-working.git", branch = "experiment/optimizations", default-features = false, optional = true } +halo2-ecc = { git = "ssh://git@github.com/axiom-crypto/axiom-core-working.git", default-features = false, optional = true } [dev-dependencies] ark-std = { version = "0.3.0", features = ["print-trace"] } @@ -47,8 +50,8 @@ loader_evm = ["dep:ethereum-types", "dep:sha3", "dep:revm", "dep:bytes", "dep:rl loader_halo2 = ["halo2-ecc"] parallel = ["dep:rayon"] # EXACTLY one of halo2-pse / halo2-axiom should always be turned on; not sure how to enforce this with Cargo -halo2-pse = ["halo2-base/halo2-pse", "halo2-ecc?/halo2-pse"] -halo2-axiom = ["halo2-base/halo2-axiom", "halo2-ecc?/halo2-axiom"] +halo2-pse = ["halo2-base/halo2-pse", "halo2-ecc?/halo2-pse", "poseidon"] +halo2-axiom = ["halo2-base/halo2-axiom", "halo2-ecc?/halo2-axiom", "poseidon-axiom"] [[example]] name = "evm-verifier" diff --git a/snark-verifier/src/lib.rs b/snark-verifier/src/lib.rs index f89f2272..1976def7 100644 --- a/snark-verifier/src/lib.rs +++ b/snark-verifier/src/lib.rs @@ -10,10 +10,14 @@ pub mod util; pub mod verifier; pub(crate) use halo2_base::halo2_proofs; -pub(crate) use halo2_base::poseidon; pub(crate) use halo2_proofs::halo2curves as halo2_curves; -use serde::Deserialize; -use serde::Serialize; +#[cfg(feature = "halo2-pse")] +pub(crate) use poseidon; +#[cfg(feature = "halo2-axiom")] +pub(crate) use poseidon_axiom as poseidon; + +pub use poseidon::Spec as PoseidonSpec; +use serde::{Deserialize, Serialize}; #[derive(Clone, Debug)] pub enum Error { diff --git a/snark-verifier/src/pcs/kzg/accumulation.rs b/snark-verifier/src/pcs/kzg/accumulation.rs index 4273ce9a..f4bd9783 100644 --- a/snark-verifier/src/pcs/kzg/accumulation.rs +++ b/snark-verifier/src/pcs/kzg/accumulation.rs @@ -117,22 +117,17 @@ where assert!(!instances.is_empty()); for accumulator in instances { - transcript.common_ec_point(&accumulator.lhs)?; - transcript.common_ec_point(&accumulator.rhs)?; + transcript.common_ec_point(&accumulator.lhs).unwrap(); + transcript.common_ec_point(&accumulator.rhs).unwrap(); } let blind = vk .zk() - .then(|| Ok((transcript.read_ec_point()?, transcript.read_ec_point()?))) - .transpose()?; + .then(|| (transcript.read_ec_point().unwrap(), transcript.read_ec_point().unwrap())); let r = transcript.squeeze_challenge(); - Ok(Self { - blind, - r, - _marker: PhantomData, - }) + Ok(Self { blind, r, _marker: PhantomData }) } } diff --git a/snark-verifier/src/system/halo2/test.rs b/snark-verifier/src/system/halo2/test.rs index 230824fc..88a2ff26 100644 --- a/snark-verifier/src/system/halo2/test.rs +++ b/snark-verifier/src/system/halo2/test.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] +#![allow(clippy::all)] use crate::halo2_proofs::{ dev::MockProver, plonk::{create_proof, verify_proof, Circuit, ProvingKey}, diff --git a/snark-verifier/src/system/halo2/test/kzg/halo2.rs b/snark-verifier/src/system/halo2/test/kzg/halo2.rs index db3092ae..9090a0a1 100644 --- a/snark-verifier/src/system/halo2/test/kzg/halo2.rs +++ b/snark-verifier/src/system/halo2/test/kzg/halo2.rs @@ -11,8 +11,7 @@ use crate::halo2_proofs::{ }, }, transcript::{ - Blake2bRead, Blake2bWrite, Challenge255, EncodedChallenge, TranscriptReadBuffer, - TranscriptWriterBuffer, + Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }, }; use crate::{