Skip to content

Commit

Permalink
Test vectors & benchmark for PCS (argumentcomputer#222)
Browse files Browse the repository at this point in the history
* test(ipa): proof verified random seed

test(ipa): proof verified

test(ipa): switch from keccak to grumpkin transcript

test(ipa): wip test IPA prove & verify

chore: added Jetbrain config to gitignore

* test(ipa): using generic fn over mlkzg, ipa & zm

- Implemented test_fail_bad_proof that generates a test case from a seed to try and verify a non valid proof.
- Implement both test_fail_bad_proof & test_from_seed for IPA over Grumpkin, MLKZG over Bn256 and ZM over Bn256

* ci(ipa): fixed xclippy

* feat(ipa): wip bench pcs

* feat(ipa): bench proof generation and verification

- Created a benchmark for proof generation and verification for IPA over Grumpkin, MLKZG over Bn and ZM over Bn
- multilinear.rs to public for benchmark purposes
- Refactored generic test methods per @adr1anh comment

* feat(ipa): proper polynomial sizes for test & sample size to 10

* feat(ipa): benchmark groups

* ci(ipa): fix xclippy

* test(ipa): added more polynomial sizes

* test(ipa): renamed test method

* refactor(ipa): revamp based on review

* refactor(ipa): Flat -> Auto bench

* refactor(ipa): random_with_eval inline

* ci(ipa): fix xclippy
  • Loading branch information
tchataigner authored Jan 5, 2024
1 parent ad94e92 commit ba29a22
Show file tree
Hide file tree
Showing 12 changed files with 381 additions and 75 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ Cargo.lock
**/*.rs.bk

# Configurations for VSCode
.vscode/
.vscode/

# Configuration for Jetbrains
.idea/
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ harness = false
name = "compressed-snark-supernova"
harness = false

[[bench]]
name = "pcs"
harness = false

[features]
default = []
abomonate = []
Expand Down
2 changes: 1 addition & 1 deletion benches/compressed-snark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type SS2 = arecibo::spartan::ppsnark::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
198 changes: 198 additions & 0 deletions benches/pcs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
use arecibo::provider::{
ipa_pc::EvaluationEngine as IPAEvaluationEngine, mlkzg::EvaluationEngine as MLEvaluationEngine,
non_hiding_zeromorph::ZMPCS, Bn256EngineKZG, Bn256EngineZM, GrumpkinEngine,
};
use arecibo::spartan::polys::multilinear::MultilinearPolynomial;
use arecibo::traits::{
commitment::CommitmentEngineTrait, evaluation::EvaluationEngineTrait, Engine,
TranscriptEngineTrait,
};
use criterion::{criterion_group, criterion_main, Bencher, BenchmarkId, Criterion, SamplingMode};
use ff::Field;
use halo2curves::bn256::Bn256;
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<GrumpkinEngine>),
(mlkzg_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();
});
}
2 changes: 1 addition & 1 deletion benches/recursive-snark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type E2 = VestaEngine;
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
14 changes: 14 additions & 0 deletions src/provider/ipa_pc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,17 @@ where
}
}
}

#[cfg(test)]
mod test {
use crate::provider::ipa_pc::EvaluationEngine;
use crate::provider::util::test_utils::prove_verify_from_num_vars;
use crate::provider::GrumpkinEngine;

#[test]
fn test_multiple_polynomial_size() {
for num_vars in [4, 5, 6] {
prove_verify_from_num_vars::<_, EvaluationEngine<GrumpkinEngine>>(num_vars);
}
}
}
55 changes: 4 additions & 51 deletions src/provider/mlkzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,12 +429,11 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::provider::util::test_utils::prove_verify_from_num_vars;
use crate::{
provider::keccak::Keccak256Transcript, spartan::polys::multilinear::MultilinearPolynomial,
traits::commitment::CommitmentTrait, CommitmentKey,
provider::keccak::Keccak256Transcript, traits::commitment::CommitmentTrait, CommitmentKey,
};
use bincode::Options;
use rand::SeedableRng;

type E = halo2curves::bn256::Bn256;
type NE = crate::provider::Bn256EngineKZG;
Expand Down Expand Up @@ -558,54 +557,8 @@ mod tests {
#[test]
fn test_mlkzg_more() {
// test the mlkzg prover and verifier with random instances (derived from a seed)
for ell in [4, 5, 6] {
let mut rng = rand::rngs::StdRng::seed_from_u64(ell as u64);

let n = 1 << ell; // n = 2^ell

let poly = (0..n).map(|_| Fr::random(&mut rng)).collect::<Vec<_>>();
let point = (0..ell).map(|_| Fr::random(&mut rng)).collect::<Vec<_>>();
let eval = MultilinearPolynomial::evaluate_with(&poly, &point);

let ck: CommitmentKey<NE> =
<KZGCommitmentEngine<E> as CommitmentEngineTrait<NE>>::setup(b"test", n);
let (pk, vk): (KZGProverKey<E>, KZGVerifierKey<E>) = EvaluationEngine::<E, NE>::setup(&ck);

// make a commitment
let C = <KZGCommitmentEngine<E> as CommitmentEngineTrait<NE>>::commit(&ck, &poly);

// prove an evaluation
let mut prover_transcript = Keccak256Transcript::<NE>::new(b"TestEval");
let proof: EvaluationArgument<E> = EvaluationEngine::<E, NE>::prove(
&ck,
&pk,
&mut prover_transcript,
&C,
&poly,
&point,
&eval,
)
.unwrap();

// verify the evaluation
let mut verifier_tr = Keccak256Transcript::<NE>::new(b"TestEval");
assert!(
EvaluationEngine::<E, NE>::verify(&vk, &mut verifier_tr, &C, &point, &eval, &proof).is_ok()
);

// Change the proof and expect verification to fail
let mut bad_proof = proof.clone();
bad_proof.comms[0] = (bad_proof.comms[0] + bad_proof.comms[1]).to_affine();
let mut verifier_tr2 = Keccak256Transcript::<NE>::new(b"TestEval");
assert!(EvaluationEngine::<E, NE>::verify(
&vk,
&mut verifier_tr2,
&C,
&point,
&eval,
&bad_proof
)
.is_err());
for num_vars in [4, 5, 6] {
prove_verify_from_num_vars::<_, EvaluationEngine<E, NE>>(num_vars);
}
}
}
2 changes: 1 addition & 1 deletion src/provider/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) mod traits;
// a non-hiding variant of {kzg, zeromorph}
pub(crate) mod kzg_commitment;
pub(crate) mod non_hiding_kzg;
mod util;
pub(crate) mod util;

// crate-private modules
mod keccak;
Expand Down
Loading

0 comments on commit ba29a22

Please sign in to comment.