forked from axiom-crypto/snark-verifier
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEAT] implement multi-batch aggregation
- Loading branch information
1 parent
a3d0a5a
commit 654706d
Showing
24 changed files
with
406 additions
and
315 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
snark-verifier-sdk/configs/two_layer_recursion_first_layer.config
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
{"strategy":"Simple","degree":25,"num_advice":[21],"num_lookup_advice":[2],"num_fixed":1,"lookup_bits":20,"limb_bits":88,"num_limbs":3} | ||
{"strategy":"Simple","degree":26,"num_advice":[21],"num_lookup_advice":[2],"num_fixed":1,"lookup_bits":20,"limb_bits":88,"num_limbs":3} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ pub mod evm; | |
pub mod halo2; | ||
|
||
mod evm_circuits; | ||
pub mod multi_batch; | ||
|
||
#[cfg(test)] | ||
mod tests; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
//! APIs to handle multi-batching snarks. | ||
//! | ||
//! In each batch iteration, we are doing two layers of recursions. | ||
//! - use a wide recursive circuit to aggregate the proofs | ||
//! - use a slim recursive circuit to shrink the size of the aggregated proof | ||
//! | ||
mod evm; | ||
mod halo2; | ||
|
||
pub use evm::*; | ||
pub use halo2::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use crate::evm::{gen_evm_proof_shplonk, gen_evm_verifier_shplonk}; | ||
use crate::gen_pk; | ||
use crate::halo2::aggregation::AggregationCircuit; | ||
use crate::halo2::gen_snark_shplonk; | ||
use crate::multi_batch::gen_two_layer_recursive_snark; | ||
use crate::{CircuitExt, Snark}; | ||
#[cfg(feature = "display")] | ||
use ark_std::{end_timer, start_timer}; | ||
use halo2_base::halo2_proofs; | ||
use halo2_proofs::{halo2curves::bn256::Bn256, poly::kzg::commitment::ParamsKZG}; | ||
use itertools::Itertools; | ||
use rand::Rng; | ||
|
||
/// Inputs: | ||
/// - kzg parameters | ||
/// - a public key: all circuit should share a same public key | ||
/// - circuit instances: c1,...ck | ||
/// - rng | ||
/// Output | ||
/// - | ||
/// - the evm byte code to verify the proof | ||
/// - the actual serialized proof | ||
pub fn gen_two_layer_evm_verifier<'params>( | ||
params: &'params ParamsKZG<Bn256>, | ||
input_snarks: Vec<Snark>, | ||
rng: &mut (impl Rng + Send), | ||
) -> (Vec<u8>, Vec<u8>) { | ||
let timer = start_timer!(|| "begin two layer recursions"); | ||
// =============================================== | ||
// first layer | ||
// =============================================== | ||
// use a wide config to aggregate snarks | ||
|
||
std::env::set_var("VERIFY_CONFIG", "./configs/two_layer_recursion_first_layer.config"); | ||
|
||
let layer_1_snark = { | ||
let layer_1_circuit = AggregationCircuit::new(¶ms, input_snarks, rng); | ||
let layer_1_pk = gen_pk(¶ms, &layer_1_circuit, None); | ||
gen_snark_shplonk(¶ms, &layer_1_pk, layer_1_circuit.clone(), rng, None::<String>) | ||
}; | ||
|
||
println!("Finished layer 1 snark generation"); | ||
|
||
// =============================================== | ||
// second layer | ||
// =============================================== | ||
// use a skim config to aggregate snarks | ||
|
||
std::env::set_var("VERIFY_CONFIG", "./configs/two_layer_recursion_second_layer.config"); | ||
|
||
let layer_2_circuit = AggregationCircuit::new(¶ms, [layer_1_snark], rng); | ||
let layer_2_pk = gen_pk(¶ms, &layer_2_circuit, None); | ||
|
||
let snark = gen_evm_proof_shplonk( | ||
¶ms, | ||
&layer_2_pk, | ||
layer_2_circuit.clone(), | ||
layer_2_circuit.instances(), | ||
rng, | ||
); | ||
// =============================================== | ||
// bytecode | ||
// =============================================== | ||
let num_instance = layer_2_circuit.instances().iter().map(|x| x.len()).collect_vec(); | ||
|
||
let bytecode = gen_evm_verifier_shplonk::<AggregationCircuit>( | ||
params, | ||
layer_2_pk.get_vk(), | ||
num_instance, | ||
None, | ||
); | ||
|
||
println!("Finished layer 2 snark generation"); | ||
end_timer!(timer); | ||
(bytecode, snark) | ||
} | ||
|
||
/// Generate the EVM bytecode and the proofs for the 4 layer recursion circuit | ||
/// Output | ||
/// - | ||
/// - the evm byte code to verify the proof | ||
/// - the actual serialized proof | ||
pub fn gen_evm_four_layer_recursive_snark<'params>( | ||
params: &'params ParamsKZG<Bn256>, | ||
input_snark_vecs: Vec<Vec<Snark>>, | ||
rng: &mut (impl Rng + Send), | ||
) -> (Vec<u8>, Vec<u8>) { | ||
let timer = start_timer!(|| "begin two layer recursions"); | ||
|
||
let mut snarks = vec![]; | ||
let len = input_snark_vecs[0].len(); | ||
let inner_timer = start_timer!(|| "inner layers"); | ||
for input_snarks in input_snark_vecs.iter() { | ||
assert_eq!(len, input_snarks.len()); | ||
|
||
let snark = gen_two_layer_recursive_snark(params, input_snarks.clone(), rng); | ||
snarks.push(snark); | ||
} | ||
end_timer!(inner_timer); | ||
|
||
let outer_timer = start_timer!(|| "outer layers"); | ||
let (bytecode, snark) = gen_two_layer_evm_verifier(params, snarks, rng); | ||
end_timer!(outer_timer); | ||
|
||
end_timer!(timer); | ||
(bytecode, snark) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
use crate::gen_pk; | ||
use crate::halo2::aggregation::AggregationCircuit; | ||
use crate::halo2::gen_snark_shplonk; | ||
use crate::Snark; | ||
#[cfg(feature = "display")] | ||
use ark_std::{end_timer, start_timer}; | ||
use halo2_base::halo2_proofs; | ||
use halo2_proofs::{halo2curves::bn256::Bn256, poly::kzg::commitment::ParamsKZG}; | ||
use rand::Rng; | ||
|
||
// use super::MultiBatchConfig; | ||
|
||
// Inputs: | ||
// - kzg parameters | ||
// - a public key: all circuit should share a same public key | ||
// - circuit instances: c1,...ck | ||
// - rng | ||
// Output | ||
// - | ||
// - a SNARK which is a snark **proof** of statement s, where | ||
// - s: I have seen the proofs for all circuits c1,...ck | ||
pub fn gen_two_layer_recursive_snark<'params>( | ||
params: &'params ParamsKZG<Bn256>, | ||
input_snarks: Vec<Snark>, | ||
rng: &mut (impl Rng + Send), | ||
) -> Snark { | ||
let timer = start_timer!(|| "begin two layer recursions"); | ||
// =============================================== | ||
// first layer | ||
// =============================================== | ||
// use a wide config to aggregate snarks | ||
|
||
std::env::set_var("VERIFY_CONFIG", "./configs/two_layer_recursion_first_layer.config"); | ||
|
||
let layer_1_snark = { | ||
let layer_1_circuit = AggregationCircuit::new(¶ms, input_snarks, rng); | ||
let layer_1_pk = gen_pk(¶ms, &layer_1_circuit, None); | ||
gen_snark_shplonk(¶ms, &layer_1_pk, layer_1_circuit.clone(), rng, None::<String>) | ||
}; | ||
|
||
println!("Finished layer 1 snark generation"); | ||
// =============================================== | ||
// second layer | ||
// =============================================== | ||
// use a skim config to aggregate snarks | ||
|
||
std::env::set_var("VERIFY_CONFIG", "./configs/two_layer_recursion_second_layer.config"); | ||
|
||
let layer_2_circuit = AggregationCircuit::new(¶ms, [layer_1_snark], rng); | ||
let layer_2_pk = gen_pk(¶ms, &layer_2_circuit, None); | ||
|
||
let snark = | ||
gen_snark_shplonk(¶ms, &layer_2_pk, layer_2_circuit.clone(), rng, None::<String>); | ||
|
||
println!("Finished layer 2 snark generation"); | ||
end_timer!(timer); | ||
snark | ||
} | ||
|
||
pub fn gen_four_layer_recursive_snark<'params>( | ||
params: &'params ParamsKZG<Bn256>, | ||
input_snark_vecs: Vec<Vec<Snark>>, | ||
rng: &mut (impl Rng + Send), | ||
) -> Snark { | ||
let timer = start_timer!(|| "begin two layer recursions"); | ||
|
||
let mut snarks = vec![]; | ||
let len = input_snark_vecs[0].len(); | ||
let inner_timer = start_timer!(|| "inner layers"); | ||
for input_snarks in input_snark_vecs.iter() { | ||
assert_eq!(len, input_snarks.len()); | ||
|
||
let snark = gen_two_layer_recursive_snark(params, input_snarks.clone(), rng); | ||
snarks.push(snark); | ||
} | ||
end_timer!(inner_timer); | ||
|
||
let outer_timer = start_timer!(|| "outer layers"); | ||
let snark = gen_two_layer_recursive_snark(params, snarks, rng); | ||
end_timer!(outer_timer); | ||
|
||
end_timer!(timer); | ||
snark | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use super::TestCircuit1; | ||
use crate::multi_batch::{gen_four_layer_recursive_snark, gen_two_layer_recursive_snark}; | ||
use crate::Snark; | ||
use crate::{gen_pk, halo2::gen_snark_shplonk}; | ||
use ark_std::test_rng; | ||
use halo2_base::halo2_proofs; | ||
use halo2_proofs::poly::commitment::Params; | ||
use snark_verifier::loader::halo2::halo2_ecc::halo2_base::utils::fs::gen_srs; | ||
|
||
#[test] | ||
fn test_partial_multi_batch_aggregation() { | ||
let k = 8; | ||
|
||
// let config = MultiBatchConfig::new(k, k_layer_1, k_layer_2); | ||
println!("finished configurations"); | ||
let mut rng = test_rng(); | ||
let params = gen_srs(26 as u32); | ||
let mut param_inner = params.clone(); | ||
param_inner.downsize(k as u32); | ||
println!("finished SRS generation"); | ||
|
||
let circuits: Vec<_> = (0..2).map(|_| TestCircuit1::rand(&mut rng)).collect(); | ||
let pk = gen_pk(¶m_inner, &circuits[0], None); | ||
println!("finished pk and circuits generation"); | ||
|
||
// =============================================== | ||
// convert input circuits to snarks | ||
// =============================================== | ||
let input_snarks: Vec<Snark> = { | ||
let k = pk.get_vk().get_domain().k(); | ||
println!("inner circuit k = {}", k); | ||
circuits | ||
.iter() | ||
.map(|circuit| { | ||
gen_snark_shplonk::<TestCircuit1>( | ||
¶m_inner, | ||
&pk, | ||
circuit.clone(), | ||
&mut rng, | ||
None::<String>, | ||
) | ||
}) | ||
.collect() | ||
}; | ||
println!("Finished input snark generation"); | ||
|
||
let _snark = gen_two_layer_recursive_snark(¶ms, input_snarks, &mut rng); | ||
} | ||
|
||
#[test] | ||
fn test_full_multi_batch_aggregation() { | ||
let k = 8; | ||
|
||
// let config = MultiBatchConfig::new(k, k_layer_1, k_layer_2); | ||
println!("finished configurations"); | ||
let mut rng = test_rng(); | ||
let params = gen_srs(26 as u32); | ||
let mut param_inner = params.clone(); | ||
param_inner.downsize(k as u32); | ||
println!("finished SRS generation"); | ||
|
||
let circuit_vecs: Vec<Vec<_>> = | ||
(0..2).map(|_| (0..2).map(|_| TestCircuit1::rand(&mut rng)).collect()).collect(); | ||
let pk = gen_pk(¶m_inner, &circuit_vecs[0][0], None); | ||
println!("finished pk and circuits generation"); | ||
|
||
// =============================================== | ||
// convert input circuits to snarks | ||
// =============================================== | ||
let input_snarks: Vec<Vec<Snark>> = { | ||
let k = pk.get_vk().get_domain().k(); | ||
println!("inner circuit k = {}", k); | ||
circuit_vecs | ||
.iter() | ||
.map(|circuits| { | ||
circuits | ||
.iter() | ||
.map(|circuit| { | ||
gen_snark_shplonk::<TestCircuit1>( | ||
¶m_inner, | ||
&pk, | ||
circuit.clone(), | ||
&mut rng, | ||
None::<String>, | ||
) | ||
}) | ||
.collect() | ||
}) | ||
.collect() | ||
}; | ||
println!("Finished input snark generation"); | ||
|
||
let _snark = gen_four_layer_recursive_snark(¶ms, input_snarks, &mut rng); | ||
} |
Oops, something went wrong.