Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ thiserror = "1.0"
group = "0.13.0"
once_cell = "1.18.0"
itertools = "0.12.0"
rand = "0.8.5"
ref-cast = "1.0.20"

[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
pasta-msm = { version = "0.1.4" }
Expand Down Expand Up @@ -74,8 +76,15 @@ harness = false
name = "ppsnark"
harness = false


[[bench]]
name = "pcs"
harness = false
required-features = ["bench"]

[features]
default = ["halo2curves/asm"]
bench = []
# Compiles in portable mode, w/o ISA extensions => binary can be executed on all systems.
portable = ["pasta-msm/portable"]
cuda = ["neptune/cuda", "neptune/pasta", "neptune/arity24"]
Expand Down
7 changes: 4 additions & 3 deletions benches/compressed-snark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use bellpepper_core::{num::AllocatedNum, ConstraintSystem, SynthesisError};
use core::marker::PhantomData;
use criterion::{measurement::WallTime, *};
use ff::PrimeField;
use halo2curves::bn256::Bn256;
use nova_snark::{
provider::{Bn256EngineKZG, GrumpkinEngine},
traits::{
Expand All @@ -17,7 +18,7 @@ use std::time::Duration;

type E1 = Bn256EngineKZG;
type E2 = GrumpkinEngine;
type EE1 = nova_snark::provider::hyperkzg::EvaluationEngine<E1>;
type EE1 = nova_snark::provider::hyperkzg::EvaluationEngine<Bn256, E1>;
type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine<E2>;
// SNARKs without computational commitments
type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E1, EE1>;
Expand All @@ -28,7 +29,7 @@ type SS2 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E2, EE2>;
type C1 = NonTrivialCircuit<<E1 as Engine>::Scalar>;
type C2 = TrivialCircuit<<E2 as Engine>::Scalar>;

// To run these benchmarks, first download `criterion` with `cargo install cargo install cargo-criterion`.
// To run these benchmarks, first download `criterion` with `cargo install cargo-criterion`.
// Then `cargo criterion --bench compressed-snark`. The results are located in `target/criterion/data/<name-of-benchmark>`.
// For flamegraphs, run `cargo criterion --bench compressed-snark --features flamegraph -- --profile-time <secs>`.
// The results are located in `target/criterion/profile/<name-of-benchmark>`.
Expand Down Expand Up @@ -216,7 +217,7 @@ impl<F: PrimeField> StepCircuit<F> for NonTrivialCircuit<F> {
let mut y = x.clone();
for i in 0..self.num_cons {
y = x.square(cs.namespace(|| format!("x_sq_{i}")))?;
x = y.clone();
x.clone_from(&y);
}
Ok(vec![y])
}
Expand Down
2 changes: 1 addition & 1 deletion benches/compute-digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<F: PrimeField> StepCircuit<F> for NonTrivialCircuit<F> {
let mut y = x.clone();
for i in 0..self.num_cons {
y = x.square(cs.namespace(|| format!("x_sq_{i}")))?;
x = y.clone();
x.clone_from(&y);
}
Ok(vec![y])
}
Expand Down
199 changes: 199 additions & 0 deletions benches/pcs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
use criterion::{criterion_group, criterion_main, Bencher, BenchmarkId, Criterion, SamplingMode};
use ff::Field;
use halo2curves::bn256::Bn256;
use nova_snark::provider::{
hyperkzg::EvaluationEngine as MLEvaluationEngine,
ipa_pc::EvaluationEngine as IPAEvaluationEngine, non_hiding_zeromorph::ZMPCS, Bn256Engine,
Bn256EngineKZG, Bn256EngineZM,
};
use nova_snark::spartan::polys::multilinear::MultilinearPolynomial;
use nova_snark::traits::{
commitment::CommitmentEngineTrait, evaluation::EvaluationEngineTrait, Engine,
TranscriptEngineTrait,
};
use rand::rngs::StdRng;
use rand_core::{CryptoRng, RngCore, SeedableRng};
use std::any::type_name;
use std::time::Duration;

// To run these benchmarks, first download `criterion` with `cargo install cargo-criterion`.
// Then `cargo criterion --bench pcs`.
// For flamegraphs, run `cargo criterion --bench pcs --features flamegraph -- --profile-time <secs>`.
// The results are located in `target/criterion/profile/<name-of-benchmark>`.
cfg_if::cfg_if! {
if #[cfg(feature = "flamegraph")] {
criterion_group! {
name = pcs;
config = Criterion::default().warm_up_time(Duration::from_millis(3000)).with_profiler(pprof::criterion::PProfProfiler::new(100, pprof::criterion::Output::Flamegraph(None)));
targets = bench_pcs
}
} else {
criterion_group! {
name = pcs;
config = Criterion::default().warm_up_time(Duration::from_millis(3000));
targets = bench_pcs
}
}
}

criterion_main!(pcs);

const NUM_VARS_TEST_VECTOR: [usize; 6] = [10, 12, 14, 16, 18, 20];

struct BenchAssests<E: Engine, EE: EvaluationEngineTrait<E>> {
poly: MultilinearPolynomial<<E as Engine>::Scalar>,
point: Vec<<E as Engine>::Scalar>,
eval: <E as Engine>::Scalar,
ck: <<E as Engine>::CE as CommitmentEngineTrait<E>>::CommitmentKey,
commitment: <<E as Engine>::CE as CommitmentEngineTrait<E>>::Commitment,
prover_key: <EE as EvaluationEngineTrait<E>>::ProverKey,
verifier_key: <EE as EvaluationEngineTrait<E>>::VerifierKey,
proof: Option<<EE as EvaluationEngineTrait<E>>::EvaluationArgument>,
}

/// Returns a random polynomial, a point and calculate its evaluation.
pub fn random_poly_with_eval<E: Engine, R: RngCore + CryptoRng>(
num_vars: usize,
mut rng: &mut R,
) -> (
MultilinearPolynomial<<E as Engine>::Scalar>,
Vec<<E as Engine>::Scalar>,
<E as Engine>::Scalar,
) {
// Generate random polynomial and point.
let poly = MultilinearPolynomial::random(num_vars, &mut rng);
let point = (0..num_vars)
.map(|_| <E as Engine>::Scalar::random(&mut rng))
.collect::<Vec<_>>();

// Calculation evaluation of point over polynomial.
let eval = MultilinearPolynomial::evaluate_with(poly.evaluations(), &point);

(poly, point, eval)
}

impl<E: Engine, EE: EvaluationEngineTrait<E>> BenchAssests<E, EE> {
pub(crate) fn from_num_vars<R: CryptoRng + RngCore>(num_vars: usize, rng: &mut R) -> Self {
let (poly, point, eval) = random_poly_with_eval::<E, R>(num_vars, rng);

// Mock commitment key.
let ck = E::CE::setup(b"test", 1 << num_vars);
// Commits to the provided vector using the provided generators.
let commitment = E::CE::commit(&ck, poly.evaluations());

let (prover_key, verifier_key) = EE::setup(&ck);

// Generate proof so that we can bench verification.
let proof = EE::prove(
&ck,
&prover_key,
&mut E::TE::new(b"TestEval"),
&commitment,
poly.evaluations(),
&point,
&eval,
)
.unwrap();

Self {
poly,
point,
eval,
ck,
commitment,
prover_key,
verifier_key,
proof: Some(proof),
}
}
}

// Macro to generate benchmark code for multiple evaluation engine types
macro_rules! benchmark_all_engines {
($criterion:expr, $test_vector:expr, $proving_fn:expr, $verifying_fn:expr, $( ($assets:ident, $eval_engine:ty) ),*) => {
for num_vars in $test_vector.iter() {
let mut rng = rand::rngs::StdRng::seed_from_u64(*num_vars as u64);

$(
let $assets: BenchAssests<_, $eval_engine> = BenchAssests::from_num_vars::<StdRng>(*num_vars, &mut rng);
)*

// Proving group
let mut proving_group = $criterion.benchmark_group(format!("PCS-Proving {}", num_vars));
proving_group
.sampling_mode(SamplingMode::Auto)
.sample_size(10);

$(
proving_group.bench_with_input(BenchmarkId::new(type_name::<$eval_engine>(), num_vars), &num_vars, |b, _| {
$proving_fn(b, &$assets);
});
)*

proving_group.finish();

// Verifying group
let mut verifying_group = $criterion.benchmark_group(format!("PCS-Verifying {}", num_vars));
verifying_group
.sampling_mode(SamplingMode::Auto)
.sample_size(10);

$(
verifying_group.bench_with_input(BenchmarkId::new(type_name::<$eval_engine>(), num_vars), &num_vars, |b, _| {
$verifying_fn(b, &$assets);
});
)*

verifying_group.finish();
}
};
}

fn bench_pcs(c: &mut Criterion) {
benchmark_all_engines!(
c,
NUM_VARS_TEST_VECTOR,
bench_pcs_proving_internal,
bench_pcs_verifying_internal,
(ipa_assets, IPAEvaluationEngine<Bn256Engine>),
(hyperkzg_assets, MLEvaluationEngine<Bn256, Bn256EngineKZG>),
(zm_assets, ZMPCS<Bn256, Bn256EngineZM>)
);
}

fn bench_pcs_proving_internal<E: Engine, EE: EvaluationEngineTrait<E>>(
b: &mut Bencher<'_>,
bench_assets: &BenchAssests<E, EE>,
) {
// Bench generate proof.
b.iter(|| {
EE::prove(
&bench_assets.ck,
&bench_assets.prover_key,
&mut E::TE::new(b"TestEval"),
&bench_assets.commitment,
bench_assets.poly.evaluations(),
&bench_assets.point,
&bench_assets.eval,
)
.unwrap();
});
}

fn bench_pcs_verifying_internal<E: Engine, EE: EvaluationEngineTrait<E>>(
b: &mut Bencher<'_>,
bench_assets: &BenchAssests<E, EE>,
) {
// Bench verify proof.
b.iter(|| {
EE::verify(
&bench_assets.verifier_key,
&mut E::TE::new(b"TestEval"),
&bench_assets.commitment,
&bench_assets.point,
&bench_assets.eval,
bench_assets.proof.as_ref().unwrap(),
)
.unwrap();
});
}
5 changes: 3 additions & 2 deletions benches/ppsnark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use bellpepper_core::{num::AllocatedNum, ConstraintSystem, SynthesisError};
use core::marker::PhantomData;
use criterion::*;
use ff::PrimeField;
use halo2curves::bn256::Bn256;
use nova_snark::{
provider::Bn256EngineKZG,
spartan::direct::DirectSNARK,
Expand All @@ -12,7 +13,7 @@ use nova_snark::{
use std::time::Duration;

type E = Bn256EngineKZG;
type EE = nova_snark::provider::hyperkzg::EvaluationEngine<E>;
type EE = nova_snark::provider::hyperkzg::EvaluationEngine<Bn256, E>;
type S = nova_snark::spartan::ppsnark::RelaxedR1CSSNARK<E, EE>;

// To run these benchmarks, first download `criterion` with `cargo install cargo install cargo-criterion`.
Expand Down Expand Up @@ -124,7 +125,7 @@ impl<F: PrimeField> StepCircuit<F> for NonTrivialCircuit<F> {
let mut y = z[0].clone();
for i in 0..self.num_cons {
y = x.square(cs.namespace(|| format!("x_sq_{i}")))?;
x = y.clone();
x.clone_from(&y);
}
Ok(vec![y])
}
Expand Down
4 changes: 2 additions & 2 deletions benches/recursive-snark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type E2 = GrumpkinEngine;
type C1 = NonTrivialCircuit<<E1 as Engine>::Scalar>;
type C2 = TrivialCircuit<<E2 as Engine>::Scalar>;

// To run these benchmarks, first download `criterion` with `cargo install cargo install cargo-criterion`.
// To run these benchmarks, first download `criterion` with `cargo install cargo-criterion`.
// Then `cargo criterion --bench recursive-snark`. The results are located in `target/criterion/data/<name-of-benchmark>`.
// For flamegraphs, run `cargo criterion --bench recursive-snark --features flamegraph -- --profile-time <secs>`.
// The results are located in `target/criterion/profile/<name-of-benchmark>`.
Expand Down Expand Up @@ -165,7 +165,7 @@ impl<F: PrimeField> StepCircuit<F> for NonTrivialCircuit<F> {
let mut y = x.clone();
for i in 0..self.num_cons {
y = x.square(cs.namespace(|| format!("x_sq_{i}")))?;
x = y.clone();
x.clone_from(&y);
}
Ok(vec![y])
}
Expand Down
3 changes: 2 additions & 1 deletion examples/and.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use core::marker::PhantomData;
use ff::Field;
use ff::{PrimeField, PrimeFieldBits};
use flate2::{write::ZlibEncoder, Compression};
use halo2curves::bn256::Bn256;
use nova_snark::{
provider::{Bn256EngineKZG, GrumpkinEngine},
traits::{
Expand All @@ -22,7 +23,7 @@ use std::time::Instant;

type E1 = Bn256EngineKZG;
type E2 = GrumpkinEngine;
type EE1 = nova_snark::provider::hyperkzg::EvaluationEngine<E1>;
type EE1 = nova_snark::provider::hyperkzg::EvaluationEngine<Bn256, E1>;
type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine<E2>;
type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E1, EE1>; // non-preprocessing SNARK
type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E2, EE2>; // non-preprocessing SNARK
Expand Down
3 changes: 2 additions & 1 deletion examples/hashchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use bellpepper_core::{num::AllocatedNum, ConstraintSystem, SynthesisError};
use ff::Field;
use flate2::{write::ZlibEncoder, Compression};
use generic_array::typenum::U24;
use halo2curves::bn256::Bn256;
use neptune::{
circuit2::Elt,
sponge::{
Expand All @@ -26,7 +27,7 @@ use std::time::Instant;

type E1 = Bn256EngineKZG;
type E2 = GrumpkinEngine;
type EE1 = nova_snark::provider::hyperkzg::EvaluationEngine<E1>;
type EE1 = nova_snark::provider::hyperkzg::EvaluationEngine<Bn256, E1>;
type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine<E2>;
type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E1, EE1>; // non-preprocessing SNARK
type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E2, EE2>; // non-preprocessing SNARK
Expand Down
3 changes: 2 additions & 1 deletion examples/minroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use bellpepper_core::{num::AllocatedNum, ConstraintSystem, SynthesisError};
use ff::Field;
use flate2::{write::ZlibEncoder, Compression};
use halo2curves::bn256::Bn256;
use nova_snark::{
provider::{Bn256EngineKZG, GrumpkinEngine},
traits::{
Expand All @@ -18,7 +19,7 @@ use std::time::Instant;

type E1 = Bn256EngineKZG;
type E2 = GrumpkinEngine;
type EE1 = nova_snark::provider::hyperkzg::EvaluationEngine<E1>;
type EE1 = nova_snark::provider::hyperkzg::EvaluationEngine<Bn256, E1>;
type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine<E2>;
type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E1, EE1>; // non-preprocessing SNARK
type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E2, EE2>; // non-preprocessing SNARK
Expand Down
20 changes: 17 additions & 3 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ pub enum NovaError {
/// returned if the provided number of steps is zero
#[error("InvalidNumSteps")]
InvalidNumSteps,
/// returned when an invalid PCS evaluation argument is provided
#[error("InvalidPCS")]
InvalidPCS,
/// returned if there is an error in the proof/verification of a PCS
#[error("PCSError")]
PCSError(#[from] PCSError),
/// returned when an invalid sum-check proof is provided
#[error("InvalidSumcheckProof")]
InvalidSumcheckProof,
Expand Down Expand Up @@ -79,3 +79,17 @@ impl From<bellpepper_core::SynthesisError> for NovaError {
}
}
}

/// Errors specific to the Polynomial commitment scheme
#[derive(Clone, Debug, Eq, PartialEq, Error)]
pub enum PCSError {
/// returned when an invalid inner product argument is provided
#[error("InvalidIPA")]
InvalidIPA,
/// returned when there is a Zeromorph error
#[error("ZMError")]
ZMError,
/// returned when a length check fails in a PCS
#[error("LengthError")]
LengthError,
}
Loading