Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions w3f-plonk-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ rand_core = "0.6"

[dev-dependencies]
ark-ed-on-bls12-381-bandersnatch = { version = "0.5", default-features = false }
criterion = { version = "0.5", features = ["html_reports"] }

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

[features]
default = ["std"]
Expand Down
60 changes: 60 additions & 0 deletions w3f-plonk-common/benches/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# w3f-plonk-common Benchmark Results

Measured with `cargo bench --bench plonk_common -p w3f-plonk-common -- --quick`.

Curve: Bandersnatch (on BLS12-381). Single-threaded, release profile.

Machine: AMD Ryzen Threadripper 3970X (64 logical cores), 62 GiB RAM, Arch Linux 6.18.9, rustc 1.93.0.

## Domain Creation

| Domain Size | Hiding | Non-Hiding |
|-------------|-----------|------------|
| 512 | 884 us | 865 us |
| 1024 | 1.90 ms | 1.89 ms |
| 4096 | 8.79 ms | 8.85 ms |
| 16384 | 44.2 ms | 44.1 ms |

Hiding vs non-hiding makes no measurable difference. Scales roughly linearly with domain size.

## Field Column Construction

| Domain Size | private_column | public_column | shifted_4x |
|-------------|----------------|---------------|------------|
| 512 | 455 us | 445 us | 2.31 us |
| 1024 | 982 us | 981 us | 4.62 us |
| 4096 | 4.76 ms | 4.68 ms | 22.8 us |

Column construction is dominated by FFT (interpolation + 4x evaluation). `shifted_4x` is a cheap rotate+copy.

## Booleanity Gadget

Constraint evaluation in 4x domain.

| Domain Size | constraints |
|-------------|-------------|
| 512 | 45.1 us |
| 1024 | 90.9 us |
| 4096 | 384 us |

Single constraint `b(1-b)`. Linear scaling.

## Inner Product Gadget

| Domain Size | init | constraints | constraints_linearized |
|-------------|---------|-------------|------------------------|
| 512 | 1.65 ms | 100 us | 9.73 us |
| 1024 | 3.20 ms | 210 us | 19.6 us |
| 4096 | 13.8 ms | 942 us | 94.2 us |

Init includes column construction (2 FFTs). Constraints are evaluated pointwise in 4x domain. Linearization is a single polynomial scalar multiplication.

## TE Conditional Addition Gadget

| Domain Size | init | constraints | constraints_linearized |
|-------------|----------|-------------|------------------------|
| 512 | 3.78 ms | 857 us | 75.9 us |
| 1024 | 8.03 ms | 1.72 ms | 162 us |
| 4096 | 35.2 ms | 13.9 ms | 669 us |

Init includes EC conditional additions (sequential scan) plus column construction. Constraint evaluation is the most expensive gadget due to the degree-4 EC addition formulas. Linearization remains cheap.
181 changes: 181 additions & 0 deletions w3f-plonk-common/benches/plonk_common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};

use ark_ec::AffineRepr;
use ark_ed_on_bls12_381_bandersnatch::{EdwardsAffine, Fq};
use ark_std::{test_rng, UniformRand};

use w3f_plonk_common::domain::Domain;
use w3f_plonk_common::gadgets::booleanity::{BitColumn, Booleanity};
use w3f_plonk_common::gadgets::ec::{AffineColumn, CondAdd};
use w3f_plonk_common::gadgets::inner_prod::InnerProd;
use w3f_plonk_common::gadgets::ProverGadget;
use w3f_plonk_common::test_helpers::{random_bitvec, random_vec};

fn bench_domain_creation(c: &mut Criterion) {
let mut group = c.benchmark_group("domain_creation");
for log_n in [9, 10, 12, 14] {
let n = 1usize << log_n;
group.bench_with_input(BenchmarkId::new("hiding", n), &n, |b, &n| {
b.iter(|| Domain::<Fq>::new(n, true));
});
group.bench_with_input(BenchmarkId::new("non_hiding", n), &n, |b, &n| {
b.iter(|| Domain::<Fq>::new(n, false));
});
}
group.finish();
}

fn bench_field_column(c: &mut Criterion) {
let rng = &mut test_rng();
let mut group = c.benchmark_group("field_column");
for log_n in [9, 10, 12] {
let n = 1usize << log_n;
let domain = Domain::<Fq>::new(n, true);
let vals: Vec<Fq> = random_vec(domain.capacity - 1, rng);

group.bench_with_input(
BenchmarkId::new("private_column", n),
&(vals.clone(), &domain),
|b, (vals, domain)| {
b.iter(|| domain.private_column(vals.clone()));
},
);

group.bench_with_input(
BenchmarkId::new("public_column", n),
&(vals.clone(), &domain),
|b, (vals, domain)| {
b.iter(|| domain.public_column(vals.clone()));
},
);

let col = domain.private_column(vals);
group.bench_with_input(BenchmarkId::new("shifted_4x", n), &col, |b, col| {
b.iter(|| col.shifted_4x());
});
}
group.finish();
}

fn bench_booleanity_gadget(c: &mut Criterion) {
let rng = &mut test_rng();
let mut group = c.benchmark_group("booleanity");
for log_n in [9, 10, 12] {
let n = 1usize << log_n;
let domain = Domain::<Fq>::new(n, true);
let bits = random_bitvec(domain.capacity - 1, 0.5, rng);
let bit_col = BitColumn::init(bits, &domain);

group.bench_with_input(
BenchmarkId::new("constraints", n),
&bit_col,
|b, bit_col| {
let gadget = Booleanity::init(bit_col.clone());
b.iter(|| gadget.constraints());
},
);
}
group.finish();
}

fn bench_inner_prod_gadget(c: &mut Criterion) {
let rng = &mut test_rng();
let mut group = c.benchmark_group("inner_prod");
for log_n in [9, 10, 12] {
let n = 1usize << log_n;
let domain = Domain::<Fq>::new(n, true);
let a: Vec<Fq> = random_vec(domain.capacity - 1, rng);
let b_vals: Vec<Fq> = random_vec(domain.capacity - 1, rng);

group.bench_with_input(
BenchmarkId::new("init", n),
&(a.clone(), b_vals.clone(), &domain),
|bench, (a, b_vals, domain)| {
bench.iter(|| {
let a_col = domain.private_column(a.clone());
let b_col = domain.private_column(b_vals.clone());
InnerProd::<Fq>::init(a_col, b_col, domain);
});
},
);

let a_col = domain.private_column(a);
let b_col = domain.private_column(b_vals);
let gadget = InnerProd::<Fq>::init(a_col, b_col, &domain);

group.bench_with_input(
BenchmarkId::new("constraints", n),
&gadget,
|bench, gadget| {
bench.iter(|| gadget.constraints());
},
);

let zeta = Fq::rand(rng);
group.bench_with_input(
BenchmarkId::new("constraints_linearized", n),
&(gadget, zeta),
|bench, (gadget, zeta)| {
bench.iter(|| gadget.constraints_linearized(zeta));
},
);
}
group.finish();
}

fn bench_te_cond_add_gadget(c: &mut Criterion) {
let rng = &mut test_rng();
let mut group = c.benchmark_group("te_cond_add");
for log_n in [9, 10, 12] {
let n = 1usize << log_n;
let domain = Domain::<Fq>::new(n, true);
let seed = EdwardsAffine::generator();

let bitmask = random_bitvec(domain.capacity - 1, 0.5, rng);
let points = random_vec::<EdwardsAffine, _>(domain.capacity - 1, rng);

group.bench_with_input(
BenchmarkId::new("init", n),
&(bitmask.clone(), points.clone(), &domain),
|bench, (bitmask, points, domain)| {
bench.iter(|| {
let bitmask_col = BitColumn::init(bitmask.clone(), domain);
let points_col = AffineColumn::private_column(points.clone(), domain);
CondAdd::init(bitmask_col, points_col, seed, domain);
});
},
);

let bitmask_col = BitColumn::init(bitmask, &domain);
let points_col = AffineColumn::private_column(points, &domain);
let gadget = CondAdd::init(bitmask_col, points_col, seed, &domain);

group.bench_with_input(
BenchmarkId::new("constraints", n),
&gadget,
|bench, gadget| {
bench.iter(|| gadget.constraints());
},
);

let zeta = Fq::rand(rng);
group.bench_with_input(
BenchmarkId::new("constraints_linearized", n),
&(gadget, zeta),
|bench, (gadget, zeta)| {
bench.iter(|| gadget.constraints_linearized(zeta));
},
);
}
group.finish();
}

criterion_group!(
benches,
bench_domain_creation,
bench_field_column,
bench_booleanity_gadget,
bench_inner_prod_gadget,
bench_te_cond_add_gadget,
);
criterion_main!(benches);
5 changes: 5 additions & 0 deletions w3f-ring-proof/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ ark-transcript = { version = "0.0.3", default-features = false }
[dev-dependencies]
ark-bls12-381 = { version = "0.5", default-features = false, features = ["curve"] }
ark-ed-on-bls12-381-bandersnatch = { version = "0.5", default-features = false }
criterion = { version = "0.5", features = ["html_reports"] }

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

[features]
default = [ "std" ]
Expand Down
62 changes: 62 additions & 0 deletions w3f-ring-proof/benches/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# w3f-ring-proof Benchmark Results

Measured with `cargo bench --bench ring_proof -p w3f-ring-proof -- --quick`.

Curve: Bandersnatch on BLS12-381 with KZG. Single-threaded, release profile.

Machine: AMD Ryzen Threadripper 3970X (64 logical cores), 62 GiB RAM, Arch Linux 6.18.9, rustc 1.93.0.

## Setup (PCS + PIOP Parameters)

| Domain Size | Time |
|-------------|----------|
| 512 | 61.9 ms |
| 1024 | 86.1 ms |

Includes KZG trusted setup (`3 * domain_size` degree) and domain/PIOP parameter construction.

## Indexing (Fixed Column Commitments)

| Domain Size | Time |
|-------------|----------|
| 512 | 48.0 ms |
| 1024 | 92.0 ms |

Commits the ring key columns and selector polynomial using KZG. Full keyset (max capacity).

## Proving

| Domain Size | Time |
|-------------|-----------|
| 512 | 159 ms |
| 1024 | 289 ms |

Single proof generation. Includes witness generation (conditional additions, inner product accumulation) and PLONK prover (constraint evaluation, quotient polynomial, KZG commitments and openings).

## Single Verification

| Domain Size | Time |
|-------------|----------|
| 512 | 3.63 ms |
| 1024 | 3.36 ms |

Single proof verification. Dominated by pairing checks. Near-constant with domain size as the verifier works with evaluations, not full polynomials.

## Batch Verification (domain_size = 1024)

| Batch Size | Sequential | KZG Accumulator | Speedup |
|------------|------------|-----------------|---------|
| 1 | 3.10 ms | 3.10 ms | 1.0x |
| 4 | 14.0 ms | 5.29 ms | 2.6x |
| 16 | 49.8 ms | 11.3 ms | 4.4x |
| 32 | 99.6 ms | 19.8 ms | 5.0x |

Sequential verification scales linearly (one pairing check per proof). KZG accumulator batches all pairing equations into a single check via MSM, giving sub-linear scaling.

## Proof Size

| Format | Size |
|------------|---------|
| Compressed | 592 bytes |

Serialization time: ~771 ns.
Loading
Loading