Skip to content

Commit

Permalink
Add benchmark templates and sample benches for IPA (#133)
Browse files Browse the repository at this point in the history
* Add benchmark templates and sample benches for IPA

Co-authored-by: Antonio Mejías Gil <[email protected]>

* adapt max poly degree to 20

* Move all PC Schemes to one module; bench-templates as a separate module

* inline one of the type aliases

* remove commented out comment

* Add benchmark instructions to the README

* make bench-templates non publishable

* fix yaml file: remove newline

* rename the inner dir to `poly-commit`

* rename usages of `pcs` to `poly-commit`

---------

Co-authored-by: Antonio Mejías Gil <[email protected]>
  • Loading branch information
mmagician and Antonio95 authored Oct 29, 2023
1 parent dac4f46 commit c724fa6
Show file tree
Hide file tree
Showing 34 changed files with 443 additions and 36 deletions.
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

0 comments on commit c724fa6

Please sign in to comment.