diff --git a/CHANGELOG.md b/CHANGELOG.md index 980753fd..17812d9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Add back benchmarks to the crate. [#555](https://github.com/dusk-network/plonk/issue/555) ### Changed -- Change `StandardComposer` to `TurboComposer`. [#288](https://github.com/dusk-network/plonk/pull/288) +- Change `StandardComposer` to `TurboComposer`. [#288](https://github.com/dusk-network/plonk/issue/288) ### Fixed diff --git a/Cargo.toml b/Cargo.toml index 37df4f2a..40f3242c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,8 +35,13 @@ canonical = {version = "0.6", optional = true} canonical_derive = {version = "0.6", optional = true} [dev-dependencies] +criterion = "0.3" tempdir = "0.3" +[[bench]] +name = "plonk" +harness = false + [features] default = ["std"] std = [ @@ -52,3 +57,12 @@ alloc = ["dusk-bls12_381/alloc"] trace = [] trace-print = ["trace"] canon = ["dusk-bls12_381/canon", "dusk-jubjub/canon", "canonical", "canonical_derive"] + +[profile.bench] +opt-level = 3 +debug = false +debug-assertions = false +overflow-checks = false +lto = true +incremental = false +codegen-units = 1 diff --git a/README.md b/README.md index 36fb3ff7..0831fc89 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,8 @@ For a circuit-size of `2^16` constraints/gates: - Proving time: `5.46s` - Verification time: `9.34ms`. **(This time will not vary depending on the circuit-size.)** +For more results, please run `cargo bench` to get a full report of benchmarks in respect of constraint numbers. + ## Acknowledgements - Reference implementation AztecProtocol/Barretenberg diff --git a/benches/plonk.rs b/benches/plonk.rs new file mode 100644 index 00000000..0d435583 --- /dev/null +++ b/benches/plonk.rs @@ -0,0 +1,153 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) DUSK NETWORK. All rights reserved. + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dusk_bls12_381::BlsScalar; +use dusk_plonk::circuit::{self, Circuit, VerifierData}; +// Using prelude until PP is available on regular import path +use dusk_plonk::constraint_system::TurboComposer; +use dusk_plonk::error::Error; +use dusk_plonk::prelude::PublicParameters; +use dusk_plonk::proof_system::{Proof, ProverKey}; + +#[derive(Debug, Clone, Copy)] +struct BenchCircuit { + degree: usize, +} + +impl From for BenchCircuit +where + T: Into, +{ + fn from(degree: T) -> Self { + Self { + degree: 1 << degree.into(), + } + } +} + +impl Circuit for BenchCircuit { + const CIRCUIT_ID: [u8; 32] = [0xff; 32]; + + fn gadget(&mut self, composer: &mut TurboComposer) -> Result<(), Error> { + let mut a = BlsScalar::from(2u64); + let mut b = BlsScalar::from(3u64); + let mut c; + + while composer.circuit_size() < self.padded_circuit_size() { + a += BlsScalar::one(); + b += BlsScalar::one(); + c = a * b + a + b + BlsScalar::one(); + + let x = composer.add_input(a); + let y = composer.add_input(b); + let z = composer.add_input(c); + + composer.poly_gate( + x, + y, + z, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::one(), + -BlsScalar::one(), + BlsScalar::one(), + None, + ); + } + + Ok(()) + } + + fn padded_circuit_size(&self) -> usize { + self.degree + } +} + +fn constraint_system_prove( + circuit: &mut BenchCircuit, + pp: &PublicParameters, + pk: &ProverKey, + label: &'static [u8], +) -> Proof { + circuit + .gen_proof(&pp, &pk, label) + .expect("Failed to prove bench circuit!") +} + +fn constraint_system_benchmark(c: &mut Criterion) { + let initial_degree = 5; + let final_degree = 18; + + let rng = &mut rand_core::OsRng; + let label = b"dusk-network"; + let pp = PublicParameters::setup(1 << (final_degree - 1), rng) + .expect("Failed to create PP"); + + let data: Vec<(BenchCircuit, ProverKey, VerifierData, Proof)> = + (initial_degree..final_degree) + .map(|degree| { + let mut circuit = BenchCircuit::from(degree as usize); + let (pk, vd) = + circuit.compile(&pp).expect("Failed to compile circuit!"); + + let proof = + constraint_system_prove(&mut circuit, &pp, &pk, label); + + circuit::verify_proof( + &pp, + vd.key(), + &proof, + &[], + vd.pi_pos(), + label, + ) + .expect("Failed to verify bench circuit!"); + + (circuit, pk, vd, proof) + }) + .collect(); + + data.iter().for_each(|(circuit, pk, _, _)| { + let mut circuit = circuit.clone(); + let size = circuit.padded_circuit_size(); + let power = (size as f64).log2() as usize; + let description = format!("Prove 2^{} = {} constraints", power, size); + + c.bench_function(description.as_str(), |b| { + b.iter(|| { + constraint_system_prove(black_box(&mut circuit), &pp, pk, label) + }) + }); + }); + + data.iter().for_each(|(circuit, _, vd, proof)| { + let size = circuit.padded_circuit_size(); + let power = (size as f64).log2() as usize; + let description = format!("Verify 2^{} = {} constraints", power, size); + + c.bench_function(description.as_str(), |b| { + b.iter(|| { + circuit::verify_proof( + &pp, + vd.key(), + black_box(proof), + &[], + vd.pi_pos(), + label, + ) + .expect("Failed to verify bench circuit!"); + }) + }); + }); +} + +criterion_group! { + name = plonk; + config = Criterion::default().sample_size(10); + targets = constraint_system_benchmark +} +criterion_main!(plonk);