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

Add benchmark templates and sample benches for IPA #133

Merged
merged 11 commits into from
Oct 29, 2023
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ jobs:
with:
use-cross: true
command: build
args: --no-default-features --target aarch64-unknown-none
args: --workspace --no-default-features --target aarch64-unknown-none --exclude ark-pcs-bench-templates

- name: Check
uses: actions-rs/cargo@v1
with:
use-cross: true
command: check
args: --examples --no-default-features --target aarch64-unknown-none
args: --workspace --examples --no-default-features --target aarch64-unknown-none --exclude ark-pcs-bench-templates
43 changes: 9 additions & 34 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,38 +1,20 @@
[package]
name = "ark-poly-commit"
[workspace]
members = ["poly-commit", "bench-templates"]
resolver = "2"


[workspace.package]
version = "0.4.0"
authors = ["arkworks contributors"]
description = "A library for constructing polynomial commitment schemes for use in zkSNARKs"
repository = "https://github.com/arkworks-rs/poly-commit"
documentation = "https://docs.rs/ark-poly-commit/"
keywords = ["cryptography", "commitments", "elliptic-curves", "pairing"]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
categories = ["cryptography"]
license = "MIT/Apache-2.0"
edition = "2018"

[dependencies]
ark-serialize = { version = "^0.4.0", default-features = false, features = [ "derive" ] }
ark-ff = { version = "^0.4.0", default-features = false }
ark-ec = { version = "^0.4.0", default-features = false }
ark-poly = {version = "^0.4.0", default-features = false }
ark-crypto-primitives = {version = "^0.4.0", default-features = false, features = ["sponge"] }
ark-std = { version = "^0.4.0", default-features = false }

ark-relations = { version = "^0.4.0", default-features = false, optional = true }
ark-r1cs-std = { version = "^0.4.0", default-features = false, optional = true }
hashbrown = { version = "0.13", default-features = false, optional = true }

digest = "0.10"
derivative = { version = "2", features = [ "use_core" ] }
rayon = { version = "1", optional = true }

[dev-dependencies]
ark-ed-on-bls12-381 = { version = "^0.4.0", default-features = false }
ark-bls12-381 = { version = "^0.4.0", default-features = false, features = [ "curve" ] }
ark-bls12-377 = { version = "^0.4.0", default-features = false, features = [ "curve" ] }
blake2 = { version = "0.10", default-features = false }
rand_chacha = { version = "0.3.0", default-features = false }

[profile.release]
opt-level = 3
lto = "thin"
Expand All @@ -45,13 +27,6 @@ debug-assertions = true
incremental = true
debug = true

[features]
default = [ "std", "parallel" ]
std = [ "ark-ff/std", "ark-ec/std", "ark-poly/std", "ark-std/std", "ark-relations/std", "ark-serialize/std", "ark-crypto-primitives/std"]
r1cs = [ "ark-relations", "ark-r1cs-std", "hashbrown", "ark-crypto-primitives/r1cs"]
print-trace = [ "ark-std/print-trace" ]
parallel = [ "std", "ark-ff/parallel", "ark-ec/parallel", "ark-poly/parallel", "ark-std/parallel", "rayon" ]

[patch.crates-io]
ark-ff = { git = "https://github.com/arkworks-rs/algebra/" }
ark-ec = { git = "https://github.com/arkworks-rs/algebra/" }
Expand All @@ -60,4 +35,4 @@ ark-crypto-primitives = { git = "https://github.com/arkworks-rs/crypto-primitive
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/" }

ark-bls12-377 = { git = "https://github.com/arkworks-rs/curves/" }
ark-bls12-381 = { git = "https://github.com/arkworks-rs/curves/" }
ark-bls12-381 = { git = "https://github.com/arkworks-rs/curves/" }
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ This library comes with some unit and integration tests. Run these tests with:
cargo test
```

A benchmarking module is also provided for the `commit`, `open` and `verify` methods, as well as for computing the commitment and proof size. You can add a new benchmark for your scheme following the examples in the `pcs/benches` directory, or run the existing benchmarks with:
```bash
cargo bench
```

Lastly, this library is instrumented with profiling infrastructure that prints detailed traces of execution time. To enable this, compile with `cargo build --features print-trace`.

## Usage
Expand Down
24 changes: 24 additions & 0 deletions bench-templates/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "ark-pcs-bench-templates"
version.workspace = true
authors.workspace = true
repository.workspace = true
categories.workspace = true
include.workspace = true
license.workspace = true
edition.workspace = true
publish = false

[dependencies]
ark-poly-commit = { path = "../poly-commit", default-features = false }
ark-serialize = { version = "^0.4.0", default-features = false, features = [ "derive" ] }
ark-ff = { version = "^0.4.0", default-features = false }
ark-ec = { version = "^0.4.0", default-features = false }
ark-poly = {version = "^0.4.0", default-features = false }
ark-crypto-primitives = {version = "^0.4.0", default-features = false, features = ["sponge", "merkle_tree"] }
ark-std = { version = "^0.4.0", default-features = false }

rand_chacha = { version = "0.3.0", default-features = false }
criterion = { version = "0.5", default-features = false }

paste = "1.0"
278 changes: 278 additions & 0 deletions bench-templates/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
use ark_crypto_primitives::sponge::{
poseidon::{PoseidonConfig, PoseidonSponge},
CryptographicSponge,
};
use ark_ff::PrimeField;
use ark_poly::Polynomial;
use ark_serialize::{CanonicalSerialize, Compress};
use ark_std::{test_rng, UniformRand};
use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng};

use core::time::Duration;
use std::time::Instant;

use ark_poly_commit::{challenge::ChallengeGenerator, LabeledPolynomial, PolynomialCommitment};

pub use criterion::*;
pub use paste::paste;

/// Measure the time cost of {commit/open/verify} across a range of num_vars
pub fn bench_pcs_method<
F: PrimeField,
P: Polynomial<F>,
PCS: PolynomialCommitment<F, P, PoseidonSponge<F>>,
>(
c: &mut Criterion,
range: Vec<usize>,
msg: &str,
method: impl Fn(
&PCS::CommitterKey,
&PCS::VerifierKey,
usize,
fn(usize, &mut ChaCha20Rng) -> P,
) -> Duration,
rand_poly: fn(usize, &mut ChaCha20Rng) -> P,
) {
let mut group = c.benchmark_group(msg);
let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap();

for num_vars in range {
let pp = PCS::setup(num_vars, Some(num_vars), rng).unwrap();
let (ck, vk) = PCS::trim(&pp, num_vars, num_vars, None).unwrap();

group.bench_with_input(
BenchmarkId::from_parameter(num_vars),
&num_vars,
|b, num_vars| {
b.iter(|| method(&ck, &vk, *num_vars, rand_poly));
},
);
}

group.finish();
}

/// Report the time cost of a commitment
pub fn commit<
F: PrimeField,
P: Polynomial<F>,
PCS: PolynomialCommitment<F, P, PoseidonSponge<F>>,
>(
ck: &PCS::CommitterKey,
_vk: &PCS::VerifierKey,
num_vars: usize,
rand_poly: fn(usize, &mut ChaCha20Rng) -> P,
) -> Duration {
let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap();

let labeled_poly =
LabeledPolynomial::new("test".to_string(), rand_poly(num_vars, rng), None, None);

let start = Instant::now();
let (_, _) = PCS::commit(&ck, [&labeled_poly], Some(rng)).unwrap();
start.elapsed()
}

/// Report the size of a commitment
pub fn commitment_size<
F: PrimeField,
P: Polynomial<F>,
PCS: PolynomialCommitment<F, P, PoseidonSponge<F>>,
>(
num_vars: usize,
rand_poly: fn(usize, &mut ChaCha20Rng) -> P,
) -> usize {
let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap();

let pp = PCS::setup(num_vars, Some(num_vars), rng).unwrap();

let (ck, _) = PCS::trim(&pp, num_vars, num_vars, None).unwrap();

let labeled_poly =
LabeledPolynomial::new("test".to_string(), rand_poly(num_vars, rng), None, None);

let (coms, _) = PCS::commit(&ck, [&labeled_poly], Some(rng)).unwrap();

coms[0].commitment().serialized_size(Compress::No)
}

/// Report the time cost of an opening
pub fn open<F, P, PCS>(
ck: &PCS::CommitterKey,
_vk: &PCS::VerifierKey,
num_vars: usize,
rand_poly: fn(usize, &mut ChaCha20Rng) -> P,
) -> Duration
where
F: PrimeField,
P: Polynomial<F>,
PCS: PolynomialCommitment<F, P, PoseidonSponge<F>>,
P::Point: UniformRand,
{
let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap();

let labeled_poly =
LabeledPolynomial::new("test".to_string(), rand_poly(num_vars, rng), None, None);

let (coms, randomness) = PCS::commit(&ck, [&labeled_poly], Some(rng)).unwrap();
let point = P::Point::rand(rng);

let start = Instant::now();
let _ = PCS::open(
&ck,
[&labeled_poly],
&coms,
&point,
&mut ChallengeGenerator::new_univariate(&mut test_sponge()),
&randomness,
Some(rng),
)
.unwrap();
start.elapsed()
}

/// Report the size of a proof
pub fn proof_size<F, P, PCS>(num_vars: usize, rand_poly: fn(usize, &mut ChaCha20Rng) -> P) -> usize
where
F: PrimeField,
P: Polynomial<F>,
PCS: PolynomialCommitment<F, P, PoseidonSponge<F>>,

P::Point: UniformRand,
{
let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap();

let pp = PCS::setup(num_vars, Some(num_vars), rng).unwrap();

let (ck, _) = PCS::trim(&pp, num_vars, num_vars, None).unwrap();
let labeled_poly =
LabeledPolynomial::new("test".to_string(), rand_poly(num_vars, rng), None, None);

let (coms, randomness) = PCS::commit(&ck, [&labeled_poly], Some(rng)).unwrap();
let point = P::Point::rand(rng);

let proofs = PCS::open(
&ck,
[&labeled_poly],
&coms,
&point,
&mut ChallengeGenerator::new_univariate(&mut test_sponge()),
&randomness,
Some(rng),
)
.unwrap();

let bproof: PCS::BatchProof = vec![proofs].into();

bproof.serialized_size(Compress::No)
}

/// Report the time cost of a verification
pub fn verify<F, P, PCS>(
ck: &PCS::CommitterKey,
vk: &PCS::VerifierKey,
num_vars: usize,
rand_poly: fn(usize, &mut ChaCha20Rng) -> P,
) -> Duration
where
F: PrimeField,
P: Polynomial<F>,
PCS: PolynomialCommitment<F, P, PoseidonSponge<F>>,
P::Point: UniformRand,
{
let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap();

let labeled_poly =
LabeledPolynomial::new("test".to_string(), rand_poly(num_vars, rng), None, None);

let (coms, randomness) = PCS::commit(&ck, [&labeled_poly], Some(rng)).unwrap();
let point = P::Point::rand(rng);
let claimed_eval = labeled_poly.evaluate(&point);
let proof = PCS::open(
&ck,
[&labeled_poly],
&coms,
&point,
&mut ChallengeGenerator::new_univariate(&mut test_sponge()),
&randomness,
Some(rng),
)
.unwrap();

let start = Instant::now();
PCS::check(
&vk,
&coms,
&point,
[claimed_eval],
&proof,
&mut ChallengeGenerator::new_univariate(&mut test_sponge()),
None,
)
.unwrap();
start.elapsed()
}

/*************** Auxiliary functions ***************/

fn test_sponge<F: PrimeField>() -> PoseidonSponge<F> {
let full_rounds = 8;
let partial_rounds = 31;
let alpha = 17;

let mds = vec![
vec![F::one(), F::zero(), F::one()],
vec![F::one(), F::one(), F::zero()],
vec![F::zero(), F::one(), F::one()],
];

let mut v = Vec::new();
let mut ark_rng = test_rng();

for _ in 0..(full_rounds + partial_rounds) {
let mut res = Vec::new();

for _ in 0..3 {
res.push(F::rand(&mut ark_rng));
}
v.push(res);
}
let config = PoseidonConfig::new(full_rounds, partial_rounds, alpha, mds, v, 2, 1);
PoseidonSponge::new(&config)
}

#[macro_export]
macro_rules! bench_method {
($c:expr, $method:ident, $scheme_type:ty, $rand_poly:ident) => {
let scheme_type_str = stringify!($scheme_type);
let bench_name = format!("{} {}", stringify!($method), scheme_type_str);
bench_pcs_method::<_, _, $scheme_type>(
$c,
(MIN_NUM_VARS..MAX_NUM_VARS).step_by(2).collect(),
&bench_name,
$method::<_, _, $scheme_type>,
$rand_poly::<_>,
);
};
}

#[macro_export]
macro_rules! bench {
(
$scheme_type:ty, $rand_poly:ident
) => {
fn bench_pcs(c: &mut Criterion) {
bench_method!(c, commit, $scheme_type, $rand_poly);
bench_method!(c, open, $scheme_type, $rand_poly);
bench_method!(c, verify, $scheme_type, $rand_poly);
}

criterion_group!(benches, bench_pcs);

paste! {
criterion_main!(
benches
);
}
};
}
Loading
Loading