mirror of
https://github.com/vacp2p/zk-explorations.git
synced 2026-01-09 20:17:59 -05:00
@@ -10,20 +10,19 @@ ark-std = { version = "0.3", features = ["print-trace"] }
|
||||
ff = { version = "0.12.0", features = ["derive"]}
|
||||
num-bigint = { version = "0.4", features = ["serde", "rand"] }
|
||||
num-traits = "0.2.15"
|
||||
|
||||
#nova-scotia = {git = "https://github.com/oskarth/Nova-Scotia", branch="benchmark-logging"}
|
||||
#nova-scotia = {path = "../../Nova-Scotia/"}
|
||||
nova-scotia = { git = "https://github.com/privacy-scaling-explorations/Nova-Scotia", branch = "parallel_nova" }
|
||||
#nova-scotia = {git = "https://github.com/oskarth/Nova-Scotia.git", branch="feat/r1cs-dual"}
|
||||
|
||||
nova-snark = {git = "https://github.com/privacy-scaling-explorations/Nova", branch="parallel_prover_bench"}
|
||||
#nova-snark = { path = "../../Nova" }
|
||||
#nova-snark = { version = "0.19.0" }
|
||||
|
||||
serde = "1.0"
|
||||
serde_json = "1.0.85"
|
||||
sha2 = "0.10.6"
|
||||
wee_alloc = "0.4.5"
|
||||
light-poseidon = { version = "*", git = "https://github.com/tyshkor/light-poseidon.git", branch = "hash_vec"}
|
||||
ark-bn254 = "*"
|
||||
ark-ff = "*"
|
||||
ark-ff = "*"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.5", features = ["html_reports"] }
|
||||
|
||||
[[bench]]
|
||||
name = "poseidon"
|
||||
harness = false
|
||||
|
||||
@@ -13,4 +13,10 @@ One time:
|
||||
|
||||
Then:
|
||||
|
||||
`cargo run --example poseidon`
|
||||
`cargo run --example poseidon`
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
cargo bench
|
||||
```
|
||||
148
nova-bench/benches/poseidon.rs
Normal file
148
nova-bench/benches/poseidon.rs
Normal file
@@ -0,0 +1,148 @@
|
||||
use core::time::Duration;
|
||||
use criterion::*;
|
||||
use nova_scotia::{
|
||||
circom::reader::load_r1cs, create_public_params, create_recursive_circuit, FileLocation, F1, G2,
|
||||
};
|
||||
use nova_snark::traits::Group;
|
||||
use std::{collections::HashMap, env::current_dir};
|
||||
|
||||
criterion_group! {
|
||||
name = recursive_snark;
|
||||
config = Criterion::default().warm_up_time(Duration::from_millis(3000));
|
||||
targets = bench_recursive_snark_proove, bench_recursive_snark_verify
|
||||
}
|
||||
|
||||
criterion_main!(recursive_snark);
|
||||
|
||||
fn bench_recursive_snark_proove(c: &mut Criterion) {
|
||||
let cases = vec![3, 10, 100];
|
||||
|
||||
let root = current_dir().unwrap();
|
||||
|
||||
// has to be generated by circom before running the code
|
||||
let circuit_file = root.join("./examples/poseidon/circom/poseidon_test_nova.r1cs");
|
||||
let r1cs = load_r1cs(&FileLocation::PathBuf(circuit_file));
|
||||
// has to be generated by circom before running the code
|
||||
let witness_generator_wasm =
|
||||
root.join("./examples/poseidon/circom/poseidon_test_nova_js/poseidon_test_nova.wasm");
|
||||
|
||||
// Creating public parameters
|
||||
let pp = create_public_params(r1cs.clone());
|
||||
|
||||
for k in cases {
|
||||
let iteration_count = k;
|
||||
|
||||
let step_in_vector = vec![0, 1, 2, 3];
|
||||
|
||||
// We don't have any private inputs, so corresponding `HashMap`s are empty, thoough we still need to create and pass them
|
||||
let mut private_inputs = Vec::new();
|
||||
for _ in 0..iteration_count {
|
||||
let private_input = HashMap::new();
|
||||
private_inputs.push(private_input);
|
||||
}
|
||||
|
||||
let start_public_input = step_in_vector
|
||||
.into_iter()
|
||||
.map(|x| F1::from(x))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut group = c.benchmark_group(format!("Nova-Circom-Poseidon-num-steps-{}", k));
|
||||
group.sample_size(10);
|
||||
|
||||
group.bench_function("Prove", |b| {
|
||||
b.iter(|| {
|
||||
// create a recursive SNARK
|
||||
create_recursive_circuit(
|
||||
FileLocation::PathBuf(witness_generator_wasm.clone()),
|
||||
r1cs.clone(),
|
||||
private_inputs.clone(),
|
||||
start_public_input.clone(),
|
||||
&pp,
|
||||
)
|
||||
.unwrap();
|
||||
})
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
}
|
||||
|
||||
fn bench_recursive_snark_verify(c: &mut Criterion) {
|
||||
let cases = vec![3, 10, 100];
|
||||
|
||||
let root = current_dir().unwrap();
|
||||
|
||||
// has to be generated by circom before running the code
|
||||
let circuit_file = root.join("./examples/poseidon/circom/poseidon_test_nova.r1cs");
|
||||
let r1cs = load_r1cs(&FileLocation::PathBuf(circuit_file));
|
||||
// has to be generated by circom before running the code
|
||||
let witness_generator_wasm =
|
||||
root.join("./examples/poseidon/circom/poseidon_test_nova_js/poseidon_test_nova.wasm");
|
||||
|
||||
let step_in_vector = vec![0, 1, 2, 3];
|
||||
|
||||
// Creating public parameters
|
||||
let pp = create_public_params(r1cs.clone());
|
||||
|
||||
println!(
|
||||
"Number of constraints per step (primary circuit): {}",
|
||||
pp.num_constraints().0
|
||||
);
|
||||
println!(
|
||||
"Number of constraints per step (secondary circuit): {}",
|
||||
pp.num_constraints().1
|
||||
);
|
||||
|
||||
println!(
|
||||
"Number of variables per step (primary circuit): {}",
|
||||
pp.num_variables().0
|
||||
);
|
||||
println!(
|
||||
"Number of variables per step (secondary circuit): {}",
|
||||
pp.num_variables().1
|
||||
);
|
||||
|
||||
for k in cases {
|
||||
let iteration_count = k;
|
||||
|
||||
// We don't have any private inputs, so corresponding `HashMap`s are empty, thoough we still need to create and pass them
|
||||
let mut private_inputs = Vec::new();
|
||||
for _ in 0..iteration_count {
|
||||
let private_input = HashMap::new();
|
||||
private_inputs.push(private_input);
|
||||
}
|
||||
|
||||
let start_public_input = step_in_vector
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|x| F1::from(x))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// create a recursive SNARK
|
||||
let recursive_snark = create_recursive_circuit(
|
||||
FileLocation::PathBuf(witness_generator_wasm.clone()),
|
||||
r1cs.clone(),
|
||||
private_inputs.clone(),
|
||||
start_public_input.clone(),
|
||||
&pp,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let z0_secondary = vec![<G2 as Group>::Scalar::zero()];
|
||||
|
||||
let mut group = c.benchmark_group(format!("Nova-Circom-Poseidon-num-steps-{}", k));
|
||||
group.sample_size(10);
|
||||
|
||||
group.bench_function("Verify", |b| {
|
||||
b.iter(|| {
|
||||
let res = recursive_snark.verify(
|
||||
&pp,
|
||||
iteration_count,
|
||||
start_public_input.clone(),
|
||||
z0_secondary.clone(),
|
||||
);
|
||||
assert!(res.is_ok());
|
||||
})
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
}
|
||||
@@ -21,10 +21,10 @@ extern crate wee_alloc;
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
/// Creates a recursive SNARK, that proves the recursive (cyclic) calculation, of 4 values using Poseidon hashing function
|
||||
///
|
||||
///
|
||||
/// Panic
|
||||
///
|
||||
/// Code panics in case needed `poseidon_test_nova.r1cs` and/or `poseidon_test_nova.wasm` do no exist at specified paths
|
||||
///
|
||||
/// Code panics in case needed `poseidon_test_nova.r1cs` and/or `poseidon_test_nova.wasm` do no exist at specified paths
|
||||
fn recursive_hashing(depth: usize) {
|
||||
println! {"Using recursive depth: {:?} times depth_per_fold in circuit (default 10 or 100, check yourself! :D)", depth};
|
||||
|
||||
|
||||
@@ -1,14 +1,93 @@
|
||||
pub fn add(left: usize, right: usize) -> usize {
|
||||
left + right
|
||||
}
|
||||
use ark_std::{end_timer, start_timer};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::{collections::HashMap, env, env::current_dir, time::Instant};
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
use nova_scotia::{
|
||||
circom::{circuit::CircomCircuit, reader::load_r1cs},
|
||||
create_public_params, create_recursive_circuit, FileLocation, F1, G1, G2, S1, S2,
|
||||
};
|
||||
// Ignore create_recursive_circuit
|
||||
|
||||
use nova_snark::{
|
||||
traits::{circuit::TrivialTestCircuit, Group},
|
||||
CompressedSNARK, RecursiveSNARK,
|
||||
};
|
||||
|
||||
extern crate wee_alloc;
|
||||
|
||||
// NOTE: Supposedly this helps against segfaults, but seems intermittent
|
||||
// Consider trying jemallocator (?)
|
||||
// Alternatively, just run larger benchmarks on a server (with C++ version)
|
||||
//
|
||||
// Use `wee_alloc` as the global allocator.
|
||||
#[global_allocator]
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
type C1 = CircomCircuit<<G1 as Group>::Scalar>;
|
||||
type C2 = TrivialTestCircuit<<G2 as Group>::Scalar>;
|
||||
|
||||
/// Creates a recursive SNARK, that proves the recursive (cyclic) calculation, of 4 values using Poseidon hashing function
|
||||
///
|
||||
/// Panic
|
||||
///
|
||||
/// Code panics in case needed `poseidon_test_nova.r1cs` and/or `poseidon_test_nova.wasm` do no exist at specified paths
|
||||
pub fn recursive_hashing_proove(depth: usize) -> RecursiveSNARK<G1, G2, C1, C2> {
|
||||
println! {"Using recursive depth: {:?} times depth_per_fold in circuit (default 10 or 100, check yourself! :D)", depth};
|
||||
|
||||
let iteration_count = depth;
|
||||
let root = current_dir().unwrap();
|
||||
|
||||
// has to be generated by circom before running the code
|
||||
let circuit_file = root.join("./examples/poseidon/circom/poseidon_test_nova.r1cs");
|
||||
let r1cs = load_r1cs(&FileLocation::PathBuf(circuit_file));
|
||||
// has to be generated by circom before running the code
|
||||
let witness_generator_wasm =
|
||||
root.join("./examples/poseidon/circom/poseidon_test_nova_js/poseidon_test_nova.wasm");
|
||||
|
||||
let step_in_vector = vec![0, 1, 2, 3];
|
||||
|
||||
// We don't have any private inputs, so corresponding `HashMap`s are empty, thoough we still need to create and pass them
|
||||
let mut private_inputs = Vec::new();
|
||||
for _ in 0..iteration_count {
|
||||
let private_input = HashMap::new();
|
||||
private_inputs.push(private_input);
|
||||
}
|
||||
|
||||
let start_public_input = step_in_vector
|
||||
.into_iter()
|
||||
.map(|x| F1::from(x))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Creating public parameters
|
||||
let pp = create_public_params(r1cs.clone());
|
||||
|
||||
println!(
|
||||
"Number of constraints per step (primary circuit): {}",
|
||||
pp.num_constraints().0
|
||||
);
|
||||
println!(
|
||||
"Number of constraints per step (secondary circuit): {}",
|
||||
pp.num_constraints().1
|
||||
);
|
||||
|
||||
println!(
|
||||
"Number of variables per step (primary circuit): {}",
|
||||
pp.num_variables().0
|
||||
);
|
||||
println!(
|
||||
"Number of variables per step (secondary circuit): {}",
|
||||
pp.num_variables().1
|
||||
);
|
||||
|
||||
// create a recursive SNARK
|
||||
let recursive_snark = create_recursive_circuit(
|
||||
FileLocation::PathBuf(witness_generator_wasm),
|
||||
r1cs,
|
||||
private_inputs,
|
||||
start_public_input.clone(),
|
||||
&pp,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
recursive_snark
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user