Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zeromorph and HyperKZG improvement (Arecibo backports) #301

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
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
Loading