Skip to content

Commit

Permalink
feat: add snark-verifier-sdk (#38)
Browse files Browse the repository at this point in the history
* feat: add snark-verifier-sdk

* chore: remove config and add example dir

* feat: add "derive_serde" feature to `snark-verifier`

This way `Snark` can be derive `Serialize`d

* fix: remove leftover artifacts

* feat: add back feature `halo2_circuit_params` and fix clippy

* fix: consider  for all targets

---------

Co-authored-by: Jonathan Wang <[email protected]>
Co-authored-by: Han <[email protected]>
  • Loading branch information
3 people authored Jun 1, 2023
1 parent 5a7693b commit 7e5254c
Show file tree
Hide file tree
Showing 15 changed files with 1,750 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
members = [
"snark-verifier",
"snark-verifier-sdk"
]
52 changes: 52 additions & 0 deletions snark-verifier-sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[package]
name = "snark-verifier-sdk"
version = "0.1.1"
edition = "2021"

[dependencies]
itertools = "0.10.3"
lazy_static = "1.4.0"
num-bigint = "0.4.3"
num-integer = "0.1.45"
num-traits = "0.2.15"
rand = "0.8"
rand_chacha = "0.3.1"
hex = "0.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
bincode = "1.3.3"
ark-std = { version = "0.3.0", features = ["print-trace"], optional = true }

snark-verifier = { path = "../snark-verifier", default-features = false }

# system_halo2
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2", tag = "v2023_04_20" } # not optional for now
halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves', tag = "0.3.2" } # must be same version as in halo2_proofs

# loader_halo2
halo2_wrong_ecc = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2023_04_20", package = "ecc", optional = true }
poseidon = { git = "https://github.com/privacy-scaling-explorations/poseidon", tag = "v2023_04_20", optional = true }

# loader_evm
ethereum-types = { version = "0.14", default-features = false, features = ["std"], optional = true }

[dev-dependencies]
ark-std = { version = "0.3.0", features = ["print-trace"] }
paste = "1.0.7"
pprof = { version = "0.11", features = ["criterion", "flamegraph"] }
criterion = "0.4"
criterion-macro = "0.4"

[features]
default = ["loader_halo2", "loader_evm", "derive_serde", "display"]
display = ["dep:ark-std"]
loader_evm = ["snark-verifier/loader_evm", "dep:ethereum-types"]
loader_halo2 = ["snark-verifier/system_halo2", "snark-verifier/loader_halo2", "dep:halo2_wrong_ecc", "dep:poseidon"]
parallel = ["snark-verifier/parallel"]
derive_serde = ["snark-verifier/derive_serde", "halo2curves/derive_serde"]
halo2_circuit_params = ["snark-verifier/halo2_circuit_params"]

[[bench]]
name = "standard_plonk"
required-features = ["loader_halo2"]
harness = false
25 changes: 25 additions & 0 deletions snark-verifier-sdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Snark Verifier SDK

To make file storage go in the correct places,

```bash
cd snark-verifier-sdk
```

To run standard plonk example:

```bash
cargo run --example standard_plonk --release
```

If feature "loader_evm" is on, this will generate yul code for the verifier contract and simulate a transaction call to that contract with generated proof calldata using revm.

This example is essentially the same as [`evm-verifier-with-accumulator`](../snark-verifier/examples/evm-verifier-with-accumulator.rs) except that it uses this SDK and uses SHPLONK as the polynomial multi-open scheme instead of GWC (multi-open scheme from original PLONK paper).

To run standard Plonk benchmark:

```bash
cargo bench --bench standard_plonk
```

These examples/benches will generate unsafe trusted setups in `./params` folder. It will also cache proving keys and certain snarks.
193 changes: 193 additions & 0 deletions snark-verifier-sdk/benches/standard_plonk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
use ark_std::{end_timer, start_timer};
use criterion::{criterion_group, criterion_main};
use criterion::{BenchmarkId, Criterion};
use halo2_proofs::halo2curves as halo2_curves;
use halo2_proofs::{
halo2curves::bn256::Bn256,
poly::{commitment::Params, kzg::commitment::ParamsKZG},
};
use pprof::criterion::{Output, PProfProfiler};
use rand::rngs::OsRng;
use snark_verifier_sdk::halo2::gen_srs;
use snark_verifier_sdk::SHPLONK;
use snark_verifier_sdk::{
gen_pk,
halo2::{aggregation::AggregationCircuit, gen_snark_shplonk},
Snark,
};
use std::path::Path;

mod application {
use super::halo2_curves::bn256::Fr;
use halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner, Value},
plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance},
poly::Rotation,
};
use rand::RngCore;
use snark_verifier_sdk::CircuitExt;

#[derive(Clone, Copy)]
pub struct StandardPlonkConfig {
a: Column<Advice>,
b: Column<Advice>,
c: Column<Advice>,
q_a: Column<Fixed>,
q_b: Column<Fixed>,
q_c: Column<Fixed>,
q_ab: Column<Fixed>,
constant: Column<Fixed>,
#[allow(dead_code)]
instance: Column<Instance>,
}

impl StandardPlonkConfig {
fn configure(meta: &mut ConstraintSystem<Fr>) -> Self {
let [a, b, c] = [(); 3].map(|_| meta.advice_column());
let [q_a, q_b, q_c, q_ab, constant] = [(); 5].map(|_| meta.fixed_column());
let instance = meta.instance_column();

[a, b, c].map(|column| meta.enable_equality(column));

meta.create_gate(
"q_a·a + q_b·b + q_c·c + q_ab·a·b + constant + instance = 0",
|meta| {
let [a, b, c] =
[a, b, c].map(|column| meta.query_advice(column, Rotation::cur()));
let [q_a, q_b, q_c, q_ab, constant] = [q_a, q_b, q_c, q_ab, constant]
.map(|column| meta.query_fixed(column, Rotation::cur()));
let instance = meta.query_instance(instance, Rotation::cur());
Some(
q_a * a.clone()
+ q_b * b.clone()
+ q_c * c
+ q_ab * a * b
+ constant
+ instance,
)
},
);

StandardPlonkConfig {
a,
b,
c,
q_a,
q_b,
q_c,
q_ab,
constant,
instance,
}
}
}

#[derive(Clone, Default)]
pub struct StandardPlonk(Fr);

impl StandardPlonk {
pub fn rand<R: RngCore>(mut rng: R) -> Self {
Self(Fr::from(rng.next_u32() as u64))
}
}

impl CircuitExt<Fr> for StandardPlonk {
fn num_instance(&self) -> Vec<usize> {
vec![1]
}

fn instances(&self) -> Vec<Vec<Fr>> {
vec![vec![self.0]]
}
}

impl Circuit<Fr> for StandardPlonk {
type Config = StandardPlonkConfig;
type FloorPlanner = SimpleFloorPlanner;
#[cfg(feature = "halo2_circuit_params")]
type Params = ();

fn without_witnesses(&self) -> Self {
Self::default()
}

fn configure(meta: &mut ConstraintSystem<Fr>) -> Self::Config {
meta.set_minimum_degree(4);
StandardPlonkConfig::configure(meta)
}

fn synthesize(
&self,
config: Self::Config,
mut layouter: impl Layouter<Fr>,
) -> Result<(), Error> {
layouter.assign_region(
|| "",
|mut region| {
region.assign_advice(|| "", config.a, 0, || Value::known(self.0))?;
region.assign_fixed(|| "", config.q_a, 0, || Value::known(-Fr::one()))?;
region.assign_advice(|| "", config.a, 1, || Value::known(-Fr::from(5u64)))?;
for (idx, column) in (1..).zip([
config.q_a,
config.q_b,
config.q_c,
config.q_ab,
config.constant,
]) {
region.assign_fixed(
|| "",
column,
1,
|| Value::known(Fr::from(idx as u64)),
)?;
}
let a = region.assign_advice(|| "", config.a, 2, || Value::known(Fr::one()))?;
a.copy_advice(|| "", &mut region, config.b, 3)?;
a.copy_advice(|| "", &mut region, config.c, 4)?;

Ok(())
},
)
}
}
}

fn gen_application_snark(params: &ParamsKZG<Bn256>) -> Snark {
let circuit = application::StandardPlonk::rand(OsRng);

let pk = gen_pk(params, &circuit, Some(Path::new("./benches/app.pk")));
gen_snark_shplonk(params, &pk, circuit, None::<&str>)
}

fn bench(c: &mut Criterion) {
let params_app = gen_srs(8);
let snarks = [(); 3].map(|_| gen_application_snark(&params_app));

let params = gen_srs(22);
let agg_circuit = AggregationCircuit::<SHPLONK>::new(&params, snarks.clone());

let start0 = start_timer!(|| "gen vk & pk");
let pk = gen_pk(&params, &agg_circuit, Some(Path::new("./benches/agg.pk")));
end_timer!(start0);

let mut group = c.benchmark_group("plonk-prover");
group.sample_size(10);
group.bench_with_input(
BenchmarkId::new("standard-plonk-agg", params.k()),
&(&params, &pk, &snarks),
|b, &(params, pk, snarks)| {
b.iter(|| {
let agg_circuit = AggregationCircuit::<SHPLONK>::new(params, snarks.clone());
gen_snark_shplonk(params, pk, agg_circuit, None::<&str>)
})
},
);
group.finish();
}

criterion_group! {
name = benches;
config = Criterion::default().with_profiler(PProfProfiler::new(10, Output::Flamegraph(None)));
targets = bench
}
criterion_main!(benches);
Loading

0 comments on commit 7e5254c

Please sign in to comment.