From 70447acf7af97a199ffb23d52958b7ffbb9a68e4 Mon Sep 17 00:00:00 2001 From: moana Date: Tue, 2 Jan 2024 11:47:58 +0100 Subject: [PATCH] Fix `alloc` feature for tests Also add an example for creating a circuit. --- .github/workflows/dusk_ci.yml | 8 +++ Cargo.toml | 64 ++++++++++++++++++++++-- README.md | 79 ++--------------------------- examples/circuit.rs | 93 +++++++++++++++++++++++++++++++++++ src/fft/domain.rs | 4 +- tests/common/mod.rs | 2 + 6 files changed, 167 insertions(+), 83 deletions(-) create mode 100644 examples/circuit.rs diff --git a/.github/workflows/dusk_ci.yml b/.github/workflows/dusk_ci.yml index f36650d9..58464090 100644 --- a/.github/workflows/dusk_ci.yml +++ b/.github/workflows/dusk_ci.yml @@ -25,6 +25,14 @@ jobs: - uses: Swatinem/rust-cache@v2 - run: cargo bench --no-run + run_examples: + name: Run Examples + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + - run: cargo run --release --example circuit + build_docs: name: Build Documentation runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index a63020af..b921589b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,10 +42,6 @@ tempdir = "0.3" rand = "0.8" rkyv = {version = "0.7", default-features = false, features = ["size_32"]} -[[bench]] -name = "plonk" -harness = false - [features] default = ["std"] std = [ @@ -78,9 +74,69 @@ lto = true incremental = false codegen-units = 1 +[[example]] +name = "circuit" +required-features = ["alloc"] + +[[bench]] +name = "plonk" +harness = false + +[[test]] +name = "append_gate" +required-features = ["alloc"] + +[[test]] +name = "assert_point" +required-features = ["alloc"] + +[[test]] +name = "assert_scalar" +required-features = ["alloc"] + +[[test]] +name = "boolean" +required-features = ["alloc"] + +[[test]] +name = "composer" +required-features = ["alloc"] + [[test]] name = "debugger" required-features = ["debug", "std"] +[[test]] +name = "decomposition" +required-features = ["alloc"] + +[[test]] +name = "ecc" +required-features = ["alloc"] + +[[test]] +name = "error_size" +required-features = ["alloc"] + +[[test]] +name = "gate_add_mul" +required-features = ["alloc"] + +[[test]] +name = "logic" +required-features = ["alloc"] + +[[test]] +name = "range" +required-features = ["alloc"] + +[[test]] +name = "select_bls" +required-features = ["alloc"] + +[[test]] +name = "select_point" +required-features = ["alloc"] + [package.metadata.docs.rs] rustdoc-args = [ "--html-in-header", "./docs/katex-header.html" ] diff --git a/README.md b/README.md index 2a9459f0..9b2a13a2 100644 --- a/README.md +++ b/README.md @@ -15,80 +15,9 @@ an exhaustive security analysis. Use at your own risk. ## Usage -```rust -use dusk_plonk::prelude::*; -use rand_core::OsRng; - -// Implement a circuit that checks: -// 1) a + b = c where C is a PI -// 2) a < 2^6 -// 3) b < 2^4 -// 4) a * b = d where D is a PI -// 5) JubJub::GENERATOR * e(JubJubScalar) = f where F is a Public Input -#[derive(Debug, Default)] -pub struct TestCircuit { - a: BlsScalar, - b: BlsScalar, - c: BlsScalar, - d: BlsScalar, - e: JubJubScalar, - f: JubJubAffine, -} - -impl Circuit for TestCircuit { - fn circuit(&self, composer: &mut Composer) -> Result<(), Error> - { - let a = composer.append_witness(self.a); - let b = composer.append_witness(self.b); - - // Make first constraint a + b = c - let constraint = - Constraint::new().left(1).right(1).public(-self.c).a(a).b(b); - - composer.append_gate(constraint); - - // Check that a and b are in range - const HALF_SIX: usize = 3; - composer.component_range::(a); - const HALF_FOUR: usize = 2; - composer.component_range::(b); - - // Make second constraint a * b = d - let constraint = - Constraint::new().mult(1).public(-self.d).a(a).b(b); - - composer.append_gate(constraint); - - let e = composer.append_witness(self.e); - let scalar_mul_result = composer - .component_mul_generator(e, dusk_jubjub::GENERATOR_EXTENDED)?; - - // Apply the constraint - composer.assert_equal_public_point(scalar_mul_result, self.f); - - Ok(()) - } -} - -let label = b"transcript-arguments"; -let pp = PublicParameters::setup(1 << 12, &mut OsRng) - .expect("failed to setup"); - -let (prover, verifier) = Compiler::compile::(&pp, label) - .expect("failed to compile circuit"); - -// Generate the proof and its public inputs -let (proof, public_inputs) = prover - .prove(&mut OsRng, &TestCircuit::default()) - .expect("failed to prove"); - -// Verify the generated proof -verifier - .verify(&proof, &public_inputs) - .expect("failed to verify proof"); -``` - -### Features +Check the 'examples' directory for the usage. + +## Features This crate includes a variety of features which will briefly be explained below: - `alloc`: Enables the usage of an allocator and with it the capability of performing `Proof` constructions and @@ -100,8 +29,6 @@ This crate includes a variety of features which will briefly be explained below: - `debug`: Enables the runtime debugger backend. Will output [CDF](https://crates.io/crates/dusk-cdf) files to the path defined in the `CDF_OUTPUT` environment variable. If used, the binary must be compiled with `debug = true`. For more info, check the [cargo book](https://doc.rust-lang.org/cargo/reference/profiles.html#debug). __The recommended method is to derive the std output, and the std error, and then place them in text file which can be used to efficiently analyse the gates.__ -- `canon`: Enables `canonical` serialization for particular data structures, which is very useful in integrating this library within the rest of the Dusk stack - especially for storage purposes. - ## Documentation diff --git a/examples/circuit.rs b/examples/circuit.rs new file mode 100644 index 00000000..c183653b --- /dev/null +++ b/examples/circuit.rs @@ -0,0 +1,93 @@ +// 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 dusk_plonk::prelude::*; +use rand_core::OsRng; + +// Create a `TestCircuit` struct. +#[derive(Debug, Default)] +pub struct TestCircuit { + pub a: BlsScalar, + pub b: BlsScalar, + pub c: BlsScalar, + pub d: BlsScalar, + pub e: JubJubScalar, + pub f: JubJubAffine, +} + +// Implement the 'Circuit' trait that checks: +// 1) a < 2^6 +// 2) b < 2^4 +// 3) a + b + 42 = c where c is public input +// 4) a * b + d = 42 +// 5) JubJub::GENERATOR * e(JubJubScalar) = f where F is a Public Input +impl Circuit for TestCircuit { + fn circuit(&self, composer: &mut Composer) -> Result<(), Error> { + let a = composer.append_witness(self.a); + let b = composer.append_witness(self.b); + let d = composer.append_witness(self.d); + + // 1) a < 2^6 + composer.component_range::<3>(a); // 3 BIT_PAIRS = 6 bits + + // 2) b < 2^4 + composer.component_range::<2>(b); // 2 BIT_PAIRS = 4 bits + + // 3) a + b + 42 = c where c is public input + let constraint = Constraint::new() + .left(1) + .right(1) + .a(a) + .b(b) + .constant(BlsScalar::from(42)); + let result = composer.gate_add(constraint); + let c = composer.append_public(self.c); + composer.assert_equal(result, c); + + // 4) a * b + d = 42 + let constraint = Constraint::new().mult(1).a(a).b(b).fourth(1).d(d); + let result = composer.gate_mul(constraint); + composer.assert_equal_constant(result, BlsScalar::from(42), None); + + // 5) JubJub::GENERATOR * e(JubJubScalar) = f where F is a Public Input + let e = composer.append_witness(self.e); + let scalar_mul_result = composer + .component_mul_generator(e, dusk_jubjub::GENERATOR_EXTENDED)?; + composer.assert_equal_public_point(scalar_mul_result, self.f); + + Ok(()) + } +} + +fn main() { + let label = b"transcript-arguments"; + let pp = + PublicParameters::setup(1 << 12, &mut OsRng).expect("failed to setup"); + + // Compile the default circuit to generate prover and verifier + let (prover, verifier) = Compiler::compile::(&pp, label) + .expect("failed to compile circuit"); + + // Create the circuit and public inputs to prove + let a = BlsScalar::from(31); + let b = BlsScalar::zero(); + let c = BlsScalar::from(73); + let d = BlsScalar::from(42); + let e = JubJubScalar::one(); + let f: JubJubAffine = dusk_jubjub::GENERATOR_EXTENDED.into(); + let circuit = TestCircuit { a, b, c, d, e, f }; + let public_inputs = vec![c, f.get_u(), f.get_v()]; + + // Generate the proof and its public inputs + let (proof, pi) = + prover.prove(&mut OsRng, &circuit).expect("failed to prove"); + assert_eq!(public_inputs, pi); + + // Verify the generated proof + verifier + .verify(&proof, &public_inputs) + .expect("failed to verify proof"); +} diff --git a/src/fft/domain.rs b/src/fft/domain.rs index 9d9ff777..d49d9e4d 100644 --- a/src/fft/domain.rs +++ b/src/fft/domain.rs @@ -322,12 +322,10 @@ pub(crate) mod alloc { } } - #[cfg(feature = "alloc")] fn best_fft(a: &mut [BlsScalar], omega: BlsScalar, log_n: u32) { serial_fft(a, omega, log_n) } - #[cfg(feature = "alloc")] #[inline] fn bitreverse(mut n: u32, l: u32) -> u32 { let mut r = 0; @@ -338,7 +336,6 @@ pub(crate) mod alloc { r } - #[cfg(feature = "alloc")] pub(crate) fn serial_fft( a: &mut [BlsScalar], omega: BlsScalar, @@ -402,6 +399,7 @@ pub(crate) mod alloc { } #[cfg(test)] +#[cfg(feature = "alloc")] mod tests { use super::*; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 4504dc2b..464f36a7 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -4,6 +4,8 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. +#![cfg(feature = "default")] + use dusk_plonk::prelude::*; use rand::{CryptoRng, RngCore};