diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml
index 6fd804592..1959fb5b5 100644
--- a/primitives/Cargo.toml
+++ b/primitives/Cargo.toml
@@ -74,6 +74,11 @@ harness = false
name = "pcs"
harness = false
+[[bench]]
+name = "pcs-size"
+path = "benches/pcs_size.rs"
+harness = false
+
[[bench]]
name = "reed-solomon"
path = "benches/reed_solomon.rs"
diff --git a/primitives/benches/pcs.rs b/primitives/benches/pcs.rs
index ad5f1d484..74416d465 100644
--- a/primitives/benches/pcs.rs
+++ b/primitives/benches/pcs.rs
@@ -4,100 +4,160 @@
// You should have received a copy of the MIT License
// along with the Jellyfish library. If not, see .
-#[cfg(not(feature = "test-srs"))]
-fn main() {
- panic!("We need features=['bench'] to run this benchmark.");
+#![cfg(feature = "test-srs")]
+
+use std::time::{Duration, Instant};
+
+use ark_bls12_381::Bls12_381;
+use ark_bn254::Bn254;
+use ark_ec::pairing::Pairing;
+use ark_ff::UniformRand;
+use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
+use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
+use jf_primitives::pcs::{
+ prelude::{MultilinearKzgPCS, PolynomialCommitmentScheme, MLE},
+ StructuredReferenceString,
+};
+use jf_utils::test_rng;
+
+const MIN_NUM_VARS: usize = 10;
+const MAX_NUM_VARS: usize = 20;
+
+/// Measure the time cost of {commit/open/verify} across a range of num_vars
+pub fn bench_pcs_method(
+ c: &mut Criterion,
+ range: impl Iterator- ,
+ msg: &str,
+ method: impl Fn(& as PolynomialCommitmentScheme>::SRS, usize) -> Duration,
+) {
+ let mut group = c.benchmark_group(msg);
+
+ let mut rng = &mut test_rng();
+
+ for num_vars in range {
+ let pp = MultilinearKzgPCS::::gen_srs_for_testing(&mut rng, num_vars).unwrap();
+
+ group.bench_with_input(
+ BenchmarkId::from_parameter(num_vars),
+ &num_vars,
+ |b, num_vars| {
+ b.iter(|| method(&pp, *num_vars));
+ },
+ );
+ }
+
+ group.finish();
}
-#[cfg(feature = "test-srs")]
-fn main() -> Result<(), jf_primitives::pcs::prelude::PCSError> {
- bench::bench_pcs()
+/// Report the time cost of a commitment
+pub fn commit(
+ pp: & as PolynomialCommitmentScheme>::SRS,
+ num_vars: usize,
+) -> Duration {
+ let rng = &mut test_rng();
+
+ let (ml_ck, _ml_vk) = pp.0.trim(num_vars).unwrap();
+ let (uni_ck, _uni_vk) = pp.1.trim(num_vars).unwrap();
+ let ck = (ml_ck, uni_ck);
+
+ let poly = MLE::from(DenseMultilinearExtension::rand(num_vars, rng));
+
+ let start = Instant::now();
+ let _ = MultilinearKzgPCS::commit(&ck, &poly).unwrap();
+ start.elapsed()
}
-#[cfg(feature = "test-srs")]
-mod bench {
- use ark_bls12_381::{Bls12_381, Fr};
- use ark_ff::UniformRand;
- use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
- use jf_primitives::pcs::{
- prelude::{MultilinearKzgPCS, PCSError, PolynomialCommitmentScheme, MLE},
- StructuredReferenceString,
- };
- use jf_utils::test_rng;
- use std::time::Instant;
-
- pub(crate) fn bench_pcs() -> Result<(), PCSError> {
- let mut rng = test_rng();
-
- // normal polynomials
- let uni_params = MultilinearKzgPCS::::gen_srs_for_testing(&mut rng, 18)?;
-
- for nv in 4..19 {
- let repetition = if nv < 10 {
- 100
- } else if nv < 20 {
- 50
- } else {
- 10
- };
-
- let poly = MLE::from(DenseMultilinearExtension::rand(nv, &mut rng));
- let (ml_ck, ml_vk) = uni_params.0.trim(nv)?;
- let (uni_ck, uni_vk) = uni_params.1.trim(nv)?;
- let ck = (ml_ck, uni_ck);
- let vk = (ml_vk, uni_vk);
-
- let point: Vec<_> = (0..nv).map(|_| Fr::rand(&mut rng)).collect();
-
- // commit
- let com = {
- let start = Instant::now();
- for _ in 0..repetition {
- let _commit = MultilinearKzgPCS::commit(&ck, &poly)?;
- }
-
- println!(
- "KZG commit for {} variables: {} ns",
- nv,
- start.elapsed().as_nanos() / repetition as u128
- );
-
- MultilinearKzgPCS::commit(&ck, &poly)?
- };
-
- // open
- let (proof, value) = {
- let start = Instant::now();
- for _ in 0..repetition {
- let _open = MultilinearKzgPCS::open(&ck, &poly, &point)?;
- }
-
- println!(
- "KZG open for {} variables: {} ns",
- nv,
- start.elapsed().as_nanos() / repetition as u128
- );
- MultilinearKzgPCS::open(&ck, &poly, &point)?
- };
-
- // verify
- {
- let start = Instant::now();
- for _ in 0..repetition {
- assert!(MultilinearKzgPCS::verify(
- &vk, &com, &point, &value, &proof
- )?);
- }
- println!(
- "KZG verify for {} variables: {} ns",
- nv,
- start.elapsed().as_nanos() / repetition as u128
- );
- }
-
- println!("====================================");
- }
-
- Ok(())
- }
+/// Report the time cost of an opening
+pub fn open(
+ pp: & as PolynomialCommitmentScheme>::SRS,
+ num_vars: usize,
+) -> Duration {
+ let rng = &mut test_rng();
+
+ let (ml_ck, _ml_vk) = pp.0.trim(num_vars).unwrap();
+ let (uni_ck, _uni_vk) = pp.1.trim(num_vars).unwrap();
+ let ck = (ml_ck, uni_ck);
+
+ let poly = MLE::from(DenseMultilinearExtension::rand(num_vars, rng));
+ let point: Vec<_> = (0..num_vars).map(|_| E::ScalarField::rand(rng)).collect();
+
+ let start = Instant::now();
+ let _ = MultilinearKzgPCS::open(&ck, &poly, &point).unwrap();
+ start.elapsed()
}
+
+/// Report the time cost of a verification
+pub fn verify(
+ pp: & as PolynomialCommitmentScheme>::SRS,
+ num_vars: usize,
+) -> Duration {
+ let rng = &mut test_rng();
+
+ let (ml_ck, ml_vk) = pp.0.trim(num_vars).unwrap();
+ let (uni_ck, uni_vk) = pp.1.trim(num_vars).unwrap();
+ let ck = (ml_ck, uni_ck);
+ let vk = (ml_vk, uni_vk);
+
+ let poly = MLE::from(DenseMultilinearExtension::rand(num_vars, rng));
+ let point: Vec<_> = (0..num_vars).map(|_| E::ScalarField::rand(rng)).collect();
+
+ let commitment = MultilinearKzgPCS::commit(&ck, &poly).unwrap();
+
+ let (proof, value) = MultilinearKzgPCS::open(&ck, &poly, &point).unwrap();
+
+ let start = Instant::now();
+ assert!(MultilinearKzgPCS::verify(&vk, &commitment, &point, &value, &proof).unwrap());
+ start.elapsed()
+}
+
+fn kzg_254(c: &mut Criterion) {
+ bench_pcs_method::(
+ c,
+ (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2),
+ "commit_kzg_range_BN_254",
+ commit::,
+ );
+ bench_pcs_method::(
+ c,
+ (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2),
+ "open_kzg_range_BN_254",
+ open::,
+ );
+ bench_pcs_method::(
+ c,
+ (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2),
+ "verify_kzg_range_BN_254",
+ verify::,
+ );
+}
+
+fn kzg_381(c: &mut Criterion) {
+ bench_pcs_method::(
+ c,
+ (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2),
+ "commit_kzg_range_BLS_381",
+ commit::,
+ );
+ bench_pcs_method::(
+ c,
+ (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2),
+ "open_kzg_range_BLS_381",
+ open::,
+ );
+ bench_pcs_method::(
+ c,
+ (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2),
+ "verify_kzg_range_BLS_381",
+ verify::,
+ );
+}
+
+criterion_group! {
+ name = pcs_benches;
+ config = Criterion::default();
+ targets =
+ kzg_254,
+ kzg_381
+}
+
+criterion_main!(pcs_benches);
diff --git a/primitives/benches/pcs_size.rs b/primitives/benches/pcs_size.rs
new file mode 100644
index 000000000..873192658
--- /dev/null
+++ b/primitives/benches/pcs_size.rs
@@ -0,0 +1,86 @@
+#![cfg(feature = "test-srs")]
+
+use ark_bls12_381::Bls12_381;
+use ark_bn254::Bn254;
+use ark_ec::pairing::Pairing;
+use ark_ff::UniformRand;
+use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
+use ark_serialize::CanonicalSerialize;
+use jf_primitives::pcs::{
+ prelude::{MultilinearKzgPCS, PolynomialCommitmentScheme, MLE},
+ StructuredReferenceString,
+};
+use jf_utils::test_rng;
+
+const MIN_NUM_VARS: usize = 10;
+const MAX_NUM_VARS: usize = 20;
+
+/// Report the size of a commitment
+pub fn commitment_size(num_vars: usize) -> usize {
+ let rng = &mut test_rng();
+ let pp = MultilinearKzgPCS::::gen_srs_for_testing(rng, num_vars).unwrap();
+
+ let (ml_ck, _ml_vk) = pp.0.trim(num_vars).unwrap();
+ let (uni_ck, _uni_vk) = pp.1.trim(num_vars).unwrap();
+ let ck = (ml_ck, uni_ck);
+
+ let poly = MLE::from(DenseMultilinearExtension::rand(num_vars, rng));
+
+ let commitment = MultilinearKzgPCS::commit(&ck, &poly).unwrap();
+ commitment.serialized_size(ark_serialize::Compress::No)
+}
+
+/// Report the size of a proof
+pub fn proof_size(num_vars: usize) -> usize {
+ let rng = &mut test_rng();
+ let pp = MultilinearKzgPCS::::gen_srs_for_testing(rng, num_vars).unwrap();
+
+ let (ml_ck, _ml_vk) = pp.0.trim(num_vars).unwrap();
+ let (uni_ck, _uni_vk) = pp.1.trim(num_vars).unwrap();
+ let ck = (ml_ck, uni_ck);
+
+ let poly = MLE::from(DenseMultilinearExtension::rand(num_vars, rng));
+ let point: Vec<_> = (0..num_vars).map(|_| E::ScalarField::rand(rng)).collect();
+
+ let (proof, _) = MultilinearKzgPCS::open(&ck, &poly, &point).unwrap();
+
+ proof.serialized_size(ark_serialize::Compress::No)
+}
+
+fn main() {
+ println!("\nKZG on BN-254: Commitment size");
+ for num_vars in (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2) {
+ println!(
+ "\tnum_vars: {}, size: {} B",
+ num_vars,
+ commitment_size::(num_vars)
+ );
+ }
+
+ println!("\nKZG on BN-254: Proof size");
+ for num_vars in (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2) {
+ println!(
+ "\tnum_vars: {}, size: {} B",
+ num_vars,
+ proof_size::(num_vars)
+ );
+ }
+
+ println!("\nKZG on BLS-381: Commitment size");
+ for num_vars in (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2) {
+ println!(
+ "\tnum_vars: {}, size: {} B",
+ num_vars,
+ commitment_size::(num_vars)
+ );
+ }
+
+ println!("\nKZG on BLS-381: Proof size");
+ for num_vars in (MIN_NUM_VARS..MAX_NUM_VARS).step_by(2) {
+ println!(
+ "\tnum_vars: {}, size: {} B",
+ num_vars,
+ proof_size::(num_vars)
+ );
+ }
+}