From cc9c4481de32e8c846a057033d5ae1a0311124dd Mon Sep 17 00:00:00 2001 From: Victor Lopez Date: Fri, 1 Oct 2021 00:44:55 +0200 Subject: [PATCH] Refactor `TurboComposer` for API consistency The current`TurboComposer` API constaints a lot of legacy functions with inconsistent signatures. For the addition gate, we have `big_add`, `big_add_gate`, `add`, `add_gate` with different signatures that internally perform the same operation. This commit aims to create an uniform API for the composer. Resolves #565 , #583 , #584 , #587 , #588 --- .github/workflows/dusk_ci.yml | 1 - .gitignore | 4 +- CHANGELOG.md | 8 +- README.md | 27 +- benches/plonk.rs | 20 +- rust-toolchain | 2 +- src/circuit.rs | 93 ++-- .../mod.rs => commitment_scheme.rs} | 16 +- .../{kzg10/mod.rs => kzg10.rs} | 5 +- src/commitment_scheme/kzg10/key.rs | 2 +- src/commitment_scheme/kzg10/proof.rs | 3 +- .../mod.rs => constraint_system.rs} | 15 +- src/constraint_system/arithmetic.rs | 448 ++++++----------- src/constraint_system/boolean.rs | 23 +- src/constraint_system/composer.rs | 456 ++++++++---------- src/constraint_system/ecc.rs | 195 ++++++++ .../mod.rs => curve_addition.rs} | 0 .../ecc/curve_addition/variable_base_gate.rs | 180 +++++-- src/constraint_system/ecc/mod.rs | 189 -------- .../ecc/{scalar_mul/mod.rs => scalar_mul.rs} | 0 .../ecc/scalar_mul/fixed_base.rs | 70 ++- .../ecc/scalar_mul/variable_base.rs | 43 +- src/constraint_system/helper.rs | 54 ++- src/constraint_system/logic.rs | 58 +-- src/constraint_system/range.rs | 20 +- src/constraint_system/witness.rs | 2 +- src/{fft/mod.rs => fft.rs} | 4 +- src/lib.rs | 25 +- src/{permutation/mod.rs => permutation.rs} | 0 src/permutation/permutation.rs | 17 +- src/{plonkup/mod.rs => plonkup.rs} | 24 +- src/plonkup/plonkup.rs | 72 --- src/plonkup/{table/mod.rs => table.rs} | 0 .../{hash_tables/mod.rs => hash_tables.rs} | 0 src/plonkup/table/preprocess.rs | 2 +- src/prelude.rs | 16 +- src/{proof_system/mod.rs => proof_system.rs} | 19 +- src/proof_system/preprocess.rs | 10 +- src/proof_system/proof.rs | 4 +- src/proof_system/prover.rs | 19 +- src/proof_system/verifier.rs | 14 +- src/proof_system/{widget/mod.rs => widget.rs} | 9 +- .../{arithmetic/mod.rs => arithmetic.rs} | 0 .../widget/arithmetic/verifierkey.rs | 2 +- .../widget/{ecc/mod.rs => ecc.rs} | 0 .../mod.rs => curve_addition.rs} | 0 .../widget/ecc/curve_addition/verifierkey.rs | 2 +- .../ecc/{scalar_mul/mod.rs => scalar_mul.rs} | 0 .../{fixed_base/mod.rs => fixed_base.rs} | 0 .../ecc/scalar_mul/fixed_base/verifierkey.rs | 2 +- .../widget/{logic/mod.rs => logic.rs} | 0 src/proof_system/widget/logic/verifierkey.rs | 2 +- .../widget/{lookup/mod.rs => lookup.rs} | 0 src/proof_system/widget/lookup/verifierkey.rs | 2 +- .../{permutation/mod.rs => permutation.rs} | 0 .../widget/permutation/verifierkey.rs | 2 +- .../widget/{range/mod.rs => range.rs} | 0 src/proof_system/widget/range/verifierkey.rs | 2 +- src/transcript.rs | 2 +- 59 files changed, 1019 insertions(+), 1166 deletions(-) rename src/{commitment_scheme/mod.rs => commitment_scheme.rs} (75%) rename src/commitment_scheme/{kzg10/mod.rs => kzg10.rs} (99%) rename src/{constraint_system/mod.rs => constraint_system.rs} (82%) create mode 100644 src/constraint_system/ecc.rs rename src/constraint_system/ecc/{curve_addition/mod.rs => curve_addition.rs} (100%) delete mode 100644 src/constraint_system/ecc/mod.rs rename src/constraint_system/ecc/{scalar_mul/mod.rs => scalar_mul.rs} (100%) rename src/{fft/mod.rs => fft.rs} (91%) rename src/{permutation/mod.rs => permutation.rs} (100%) rename src/{plonkup/mod.rs => plonkup.rs} (52%) delete mode 100644 src/plonkup/plonkup.rs rename src/plonkup/{table/mod.rs => table.rs} (100%) rename src/plonkup/table/{hash_tables/mod.rs => hash_tables.rs} (100%) rename src/{proof_system/mod.rs => proof_system.rs} (70%) rename src/proof_system/{widget/mod.rs => widget.rs} (99%) rename src/proof_system/widget/{arithmetic/mod.rs => arithmetic.rs} (100%) rename src/proof_system/widget/{ecc/mod.rs => ecc.rs} (100%) rename src/proof_system/widget/ecc/{curve_addition/mod.rs => curve_addition.rs} (100%) rename src/proof_system/widget/ecc/{scalar_mul/mod.rs => scalar_mul.rs} (100%) rename src/proof_system/widget/ecc/scalar_mul/{fixed_base/mod.rs => fixed_base.rs} (100%) rename src/proof_system/widget/{logic/mod.rs => logic.rs} (100%) rename src/proof_system/widget/{lookup/mod.rs => lookup.rs} (100%) rename src/proof_system/widget/{permutation/mod.rs => permutation.rs} (100%) rename src/proof_system/widget/{range/mod.rs => range.rs} (100%) diff --git a/.github/workflows/dusk_ci.yml b/.github/workflows/dusk_ci.yml index 8211f0b8d..d13eaa536 100644 --- a/.github/workflows/dusk_ci.yml +++ b/.github/workflows/dusk_ci.yml @@ -26,7 +26,6 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 with: diff --git a/.gitignore b/.gitignore index e2e5ddadc..58dfc8b67 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ **/*.rs.bk Cargo.lock notes.md -scrap.rs -kzg10.rs design.md refactor_notes -.DS_Store \ No newline at end of file +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index 341165be0..0855b0a89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,12 +10,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add back benchmarks to the crate. [#555](https://github.com/dusk-network/plonk/issue/555) +- Add `Witness` by removing `AllocatedScalar`. [#588](https://github.com/dusk-network/plonk/issue/588) ### Changed - Change `StandardComposer` to `TurboComposer`. [#288](https://github.com/dusk-network/plonk/issue/288) -- Change `Variable` usage in favor of `AllocatedScalar`. [#565]((https://github.com/dusk-network/plonk/issue/565)) -- Add `Witness` by removing `AllocatedScalar`. [#588]((https://github.com/dusk-network/plonk/issue/588)) +- Change `Variable` usage in favor of `AllocatedScalar`. [#565](https://github.com/dusk-network/plonk/issue/565) +- Change `TurboComposer` to consistent API. [#587](https://github.com/dusk-network/plonk/issue/587) +- Change `plonkup_gate` to use public inputs. [#584](https://github.com/dusk-network/plonk/issue/584) ### Fixed @@ -23,7 +25,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix if condition to match [#545](https://github.com/dusk-network/plonk/pull/545) ### Removed + - Remove old perm-computation fns from perm module [#515](https://github.com/dusk-network/plonk/issues/515) +- Remove unused `plonkup` module. [#583](https://github.com/dusk-network/plonk/issue/583) ## [0.8.1] - 07-06-21 diff --git a/README.md b/README.md index 4857c676c..c98198068 100644 --- a/README.md +++ b/README.md @@ -39,41 +39,50 @@ impl Circuit for TestCircuit { let a = composer.append_witness(self.a); let b = composer.append_witness(self.b); // Make first constraint a + b = c - composer.poly_gate( + composer.append_gate( a, b, - composer.zero(), + composer.constant_zero(), + composer.constant_zero(), BlsScalar::zero(), BlsScalar::one(), BlsScalar::one(), BlsScalar::zero(), BlsScalar::zero(), + BlsScalar::zero(), Some(-self.c), ); // Check that a and b are in range - composer.range_gate(a, 1 << 6); - composer.range_gate(b, 1 << 5); + composer.gate_range(a, 1 << 6); + composer.gate_range(b, 1 << 5); // Make second constraint a * b = d - composer.poly_gate( + composer.append_gate( a, b, - composer.zero(), + composer.constant_zero(), + composer.constant_zero(), BlsScalar::one(), BlsScalar::zero(), BlsScalar::zero(), BlsScalar::one(), BlsScalar::zero(), + BlsScalar::zero(), Some(-self.d), ); let e = composer.append_witness(self.e); let scalar_mul_result = composer - .fixed_base_scalar_mul(e, dusk_jubjub::GENERATOR_EXTENDED); + .gate_mul_generator(e, dusk_jubjub::GENERATOR_EXTENDED); // Apply the constrain composer.assert_equal_public_point(scalar_mul_result, self.f); Ok(()) } - fn padded_circuit_size(&self) -> usize { + + fn into_public_inputs(&self) -> Vec { + vec![self.c.into(), self.d.into(), self.f.into()] + } + + fn padded_constraints(&self) -> usize { 1 << 11 } } @@ -97,7 +106,7 @@ let proof = { dusk_jubjub::GENERATOR_EXTENDED * JubJubScalar::from(2u64), ), }; - circuit.gen_proof(&pp, &pk, b"Test").unwrap() + circuit.prove(&pp, &pk, b"Test").unwrap() }; // Verifier POV let public_inputs: Vec = vec![ diff --git a/benches/plonk.rs b/benches/plonk.rs index 0d4355831..67dca0e53 100644 --- a/benches/plonk.rs +++ b/benches/plonk.rs @@ -37,7 +37,9 @@ impl Circuit for BenchCircuit { let mut b = BlsScalar::from(3u64); let mut c; - while composer.circuit_size() < self.padded_circuit_size() { + let zero = composer.constant_zero(); + + while composer.constraints() < self.padded_constraints() { a += BlsScalar::one(); b += BlsScalar::one(); c = a * b + a + b + BlsScalar::one(); @@ -46,14 +48,16 @@ impl Circuit for BenchCircuit { let y = composer.add_input(b); let z = composer.add_input(c); - composer.poly_gate( + composer.append_gate( x, y, z, + zero, BlsScalar::one(), BlsScalar::one(), BlsScalar::one(), -BlsScalar::one(), + BlsScalar::zero(), BlsScalar::one(), None, ); @@ -62,7 +66,11 @@ impl Circuit for BenchCircuit { Ok(()) } - fn padded_circuit_size(&self) -> usize { + fn into_public_inputs(&self) -> Vec { + vec![] + } + + fn padded_constraints(&self) -> usize { self.degree } } @@ -74,7 +82,7 @@ fn constraint_system_prove( label: &'static [u8], ) -> Proof { circuit - .gen_proof(&pp, &pk, label) + .prove(&pp, &pk, label) .expect("Failed to prove bench circuit!") } @@ -113,7 +121,7 @@ fn constraint_system_benchmark(c: &mut Criterion) { data.iter().for_each(|(circuit, pk, _, _)| { let mut circuit = circuit.clone(); - let size = circuit.padded_circuit_size(); + let size = circuit.padded_constraints(); let power = (size as f64).log2() as usize; let description = format!("Prove 2^{} = {} constraints", power, size); @@ -125,7 +133,7 @@ fn constraint_system_benchmark(c: &mut Criterion) { }); data.iter().for_each(|(circuit, _, vd, proof)| { - let size = circuit.padded_circuit_size(); + let size = circuit.padded_constraints(); let power = (size as f64).log2() as usize; let description = format!("Verify 2^{} = {} constraints", power, size); diff --git a/rust-toolchain b/rust-toolchain index 36bb0777e..9d7cd861d 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2021-06-06 +nightly-2021-09-25 diff --git a/src/circuit.rs b/src/circuit.rs index cc192b975..f9cad352b 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -6,7 +6,7 @@ //! Tools & traits for PLONK circuits -use crate::commitment_scheme::kzg10::PublicParameters; +use crate::commitment_scheme::PublicParameters; use crate::constraint_system::TurboComposer; use crate::error::Error; use crate::proof_system::{Proof, Prover, ProverKey, Verifier, VerifierKey}; @@ -15,7 +15,7 @@ use alloc::vec::Vec; use canonical_derive::Canon; use dusk_bls12_381::BlsScalar; use dusk_bytes::{DeserializableSlice, Serializable, Write}; -use dusk_jubjub::{JubJubAffine, JubJubScalar}; +use dusk_jubjub::{JubJubAffine, JubJubExtended, JubJubScalar}; #[derive(Default, Debug, Clone)] #[cfg_attr(feature = "canon", derive(Canon))] @@ -41,6 +41,12 @@ impl From for PublicInputValue { } } +impl From for PublicInputValue { + fn from(point: JubJubExtended) -> Self { + JubJubAffine::from(point).into() + } +} + #[derive(Debug, Clone)] /// Collection of structs/objects that the Verifier will use in order to /// de/serialize data needed for Circuit proof verification. @@ -110,7 +116,6 @@ impl VerifierData { /// /// ``` /// use dusk_plonk::prelude::*; -/// use dusk_plonk::constraint_system::ecc::scalar_mul; /// use rand_core::OsRng; /// /// fn main() -> Result<(), Error> { @@ -137,40 +142,44 @@ impl VerifierData { /// composer: &mut TurboComposer, /// ) -> Result<(), Error> { /// // Add fixed witness zero -/// let zero = composer.zero(); +/// let zero = composer.constant_zero(); /// let a = composer.append_witness(self.a); /// let b = composer.append_witness(self.b); /// // Make first constraint a + b = c -/// composer.poly_gate( +/// composer.append_gate( /// a, /// b, /// zero, +/// zero, /// BlsScalar::zero(), /// BlsScalar::one(), /// BlsScalar::one(), /// BlsScalar::zero(), /// BlsScalar::zero(), +/// BlsScalar::zero(), /// Some(-self.c), /// ); /// // Check that a and b are in range -/// composer.range_gate(a, 1 << 6); -/// composer.range_gate(b, 1 << 5); +/// composer.gate_range(a, 1 << 6); +/// composer.gate_range(b, 1 << 5); /// // Make second constraint a * b = d -/// composer.poly_gate( +/// composer.append_gate( /// a, /// b, /// zero, +/// zero, /// BlsScalar::one(), /// BlsScalar::zero(), /// BlsScalar::zero(), /// BlsScalar::one(), /// BlsScalar::zero(), +/// BlsScalar::zero(), /// Some(-self.d), /// ); /// /// let e = composer.append_witness(self.e); /// let scalar_mul_result = -/// composer.fixed_base_scalar_mul( +/// composer.gate_mul_generator( /// e, dusk_jubjub::GENERATOR_EXTENDED, /// ); /// // Apply the constrain @@ -178,7 +187,12 @@ impl VerifierData { /// .assert_equal_public_point(scalar_mul_result, self.f); /// Ok(()) /// } -/// fn padded_circuit_size(&self) -> usize { +/// +/// fn into_public_inputs(&self) -> Vec { +/// vec![self.c.into(), self.d.into(), self.f.into()] +/// } +/// +/// fn padded_constraints(&self) -> usize { /// 1 << 11 /// } /// } @@ -202,7 +216,7 @@ impl VerifierData { /// ), /// }; /// -/// circuit.gen_proof(&pp, &pk, b"Test") +/// circuit.prove(&pp, &pk, b"Test") /// }?; /// /// // Verifier POV @@ -230,8 +244,10 @@ where { /// Circuit identifier associated constant. const CIRCUIT_ID: [u8; 32]; + /// Gadget implementation used to fill the composer. fn gadget(&mut self, composer: &mut TurboComposer) -> Result<(), Error>; + /// Compiles the circuit by using a function that returns a `Result` /// with the `ProverKey`, `VerifierKey` and the circuit size. fn compile( @@ -239,16 +255,16 @@ where pub_params: &PublicParameters, ) -> Result<(ProverKey, VerifierData), Error> { // Setup PublicParams - let (ck, _) = pub_params.trim(self.padded_circuit_size())?; + let (ck, _) = pub_params.trim(self.padded_constraints())?; // Generate & save `ProverKey` with some random values. let mut prover = Prover::new(b"CircuitCompilation"); - self.gadget(prover.mut_cs())?; - let pi_pos = prover.mut_cs().pi_positions(); + self.gadget(prover.composer_mut())?; + let pi_pos = prover.composer_mut().into_public_input_indexes(); prover.preprocess(&ck)?; // Generate & save `VerifierKey` with some random values. let mut verifier = Verifier::new(b"CircuitCompilation"); - self.gadget(verifier.mut_cs())?; + self.gadget(verifier.composer_mut())?; verifier.preprocess(&ck)?; Ok(( prover @@ -265,24 +281,30 @@ where /// Generates a proof using the provided `CircuitInputs` & `ProverKey` /// instances. - fn gen_proof( + fn prove( &mut self, pub_params: &PublicParameters, prover_key: &ProverKey, transcript_init: &'static [u8], ) -> Result { - let (ck, _) = pub_params.trim(self.padded_circuit_size())?; + let (ck, _) = pub_params.trim(self.padded_constraints())?; + // New Prover instance let mut prover = Prover::new(transcript_init); + // Fill witnesses for Prover - self.gadget(prover.mut_cs())?; + self.gadget(prover.composer_mut())?; + // Add ProverKey to Prover prover.prover_key = Some(prover_key.clone()); prover.prove(&ck) } + /// Return the list of public inputs generated by the gadget + fn into_public_inputs(&self) -> Vec; + /// Returns the Circuit size padded to the next power of two. - fn padded_circuit_size(&self) -> usize; + fn padded_constraints(&self) -> usize; } /// Verifies a proof using the provided `CircuitInputs` & `VerifierKey` @@ -303,7 +325,7 @@ pub fn verify_proof( build_pi( pub_inputs_values, pub_inputs_positions, - verifier_key.padded_circuit_size(), + verifier_key.padded_constraints(), ) .as_slice(), ) @@ -379,41 +401,52 @@ mod tests { let a = composer.append_witness(self.a); let b = composer.append_witness(self.b); // Make first constraint a + b = c - composer.poly_gate( + composer.append_gate( a, b, - composer.zero(), + composer.constant_zero(), + composer.constant_zero(), BlsScalar::zero(), BlsScalar::one(), BlsScalar::one(), BlsScalar::zero(), BlsScalar::zero(), + BlsScalar::zero(), Some(-self.c), ); // Check that a and b are in range - composer.range_gate(a, 1 << 6); - composer.range_gate(b, 1 << 5); + composer.gate_range(a, 1 << 6); + composer.gate_range(b, 1 << 5); // Make second constraint a * b = d - composer.poly_gate( + composer.append_gate( a, b, - composer.zero(), + composer.constant_zero(), + composer.constant_zero(), BlsScalar::one(), BlsScalar::zero(), BlsScalar::zero(), BlsScalar::one(), BlsScalar::zero(), + BlsScalar::zero(), Some(-self.d), ); let e = composer.append_witness(self.e); - let scalar_mul_result = composer - .fixed_base_scalar_mul(e, dusk_jubjub::GENERATOR_EXTENDED); + let scalar_mul_result = + composer.gate_mul_generator(e, dusk_jubjub::GENERATOR_EXTENDED); + // Apply the constrain composer.assert_equal_public_point(scalar_mul_result, self.f); + Ok(()) } - fn padded_circuit_size(&self) -> usize { + + fn into_public_inputs(&self) -> Vec { + vec![self.c.into(), self.d.into(), self.f.into()] + } + + fn padded_constraints(&self) -> usize { 1 << 11 } } @@ -479,7 +512,7 @@ mod tests { ), }; - circuit.gen_proof(&pp, &pk, b"Test") + circuit.prove(&pp, &pk, b"Test") }?; // Verifier POV diff --git a/src/commitment_scheme/mod.rs b/src/commitment_scheme.rs similarity index 75% rename from src/commitment_scheme/mod.rs rename to src/commitment_scheme.rs index 66d11d9d5..f8efcbe35 100644 --- a/src/commitment_scheme/mod.rs +++ b/src/commitment_scheme.rs @@ -13,11 +13,13 @@ //! FRI are not homomorphic and therefore for PLONK to be usable with all //! commitment schemes without modification, one would need to remove the //! lineariser -// XXX: This empty trait is left here so that Rust docs does not complain that -// we are documenting nothing. It is also a reminder that we ideally should find -// a good abstraction. -trait CommitmentScheme { - type Proof; -} -pub mod kzg10; +mod kzg10; + +pub(crate) use kzg10::Commitment; + +#[cfg(feature = "alloc")] +pub(crate) use kzg10::AggregateProof; + +#[cfg(feature = "alloc")] +pub use kzg10::{CommitKey, OpeningKey, PublicParameters}; diff --git a/src/commitment_scheme/kzg10/mod.rs b/src/commitment_scheme/kzg10.rs similarity index 99% rename from src/commitment_scheme/kzg10/mod.rs rename to src/commitment_scheme/kzg10.rs index 249cba9eb..313b66c7d 100644 --- a/src/commitment_scheme/kzg10/mod.rs +++ b/src/commitment_scheme/kzg10.rs @@ -11,11 +11,14 @@ if #[cfg(feature = "alloc")] { pub mod key; pub mod srs; - pub use key::{CommitKey, OpeningKey}; + pub(crate) use proof::alloc::AggregateProof; + + pub use key::{CommitKey, OpeningKey}; pub use srs::PublicParameters; }); pub(crate) mod commitment; pub(crate) mod proof; + pub(crate) use commitment::Commitment; diff --git a/src/commitment_scheme/kzg10/key.rs b/src/commitment_scheme/kzg10/key.rs index 814ad46ac..fb2c1d22c 100644 --- a/src/commitment_scheme/kzg10/key.rs +++ b/src/commitment_scheme/kzg10/key.rs @@ -303,7 +303,7 @@ impl OpeningKey { #[cfg(test)] mod test { use super::*; - use crate::commitment_scheme::kzg10::{AggregateProof, PublicParameters}; + use crate::commitment_scheme::{AggregateProof, PublicParameters}; use crate::fft::Polynomial; use dusk_bls12_381::BlsScalar; use dusk_bytes::Serializable; diff --git a/src/commitment_scheme/kzg10/proof.rs b/src/commitment_scheme/kzg10/proof.rs index ee8ecfe78..008c4777b 100644 --- a/src/commitment_scheme/kzg10/proof.rs +++ b/src/commitment_scheme/kzg10/proof.rs @@ -7,9 +7,10 @@ use super::Commitment; use dusk_bls12_381::BlsScalar; -#[derive(Copy, Clone, Debug)] /// Proof that a polynomial `p` was correctly evaluated at a point `z` /// producing the evaluated point p(z). +#[derive(Copy, Clone, Debug)] +#[allow(dead_code)] pub(crate) struct Proof { /// This is a commitment to the witness polynomial. pub(crate) commitment_to_witness: Commitment, diff --git a/src/constraint_system/mod.rs b/src/constraint_system.rs similarity index 82% rename from src/constraint_system/mod.rs rename to src/constraint_system.rs index e7fa49e51..f8b74d329 100644 --- a/src/constraint_system/mod.rs +++ b/src/constraint_system.rs @@ -8,25 +8,22 @@ //! of the PLONK Standard Composer, as well as the circuit //! tools and abstractions, used by the Composer to generate, //! build, preprocess circuits. + pub(crate) mod composer; +pub(crate) mod ecc; +pub(crate) mod logic; +pub(crate) mod range; pub(crate) mod witness; -/// Simple Arithmetic gates +pub(crate) use witness::WireData; + mod arithmetic; -/// Boolean gate mod boolean; -/// Elliptic Curve Crypto gates -pub mod ecc; #[cfg(feature = "std")] #[cfg(test)] pub(crate) mod helper; -/// XOR and AND gates -pub mod logic; -/// Range gate -pub mod range; pub use composer::TurboComposer; pub use ecc::WitnessPoint; -pub(crate) use witness::WireData; pub use witness::Witness; diff --git a/src/constraint_system/arithmetic.rs b/src/constraint_system/arithmetic.rs index 69ea0aa42..2f65c4548 100644 --- a/src/constraint_system/arithmetic.rs +++ b/src/constraint_system/arithmetic.rs @@ -8,303 +8,84 @@ use crate::constraint_system::{TurboComposer, Witness}; use dusk_bls12_381::BlsScalar; impl TurboComposer { - /// Adds a width-3 add gate to the circuit, linking the addition of the - /// provided inputs, scaled by the selector coefficients with the output - /// provided. - pub fn add_gate( + /// Evaluate and return `o` by appending a new gate into the circuit. + /// + /// `o := q_l · a + q_r · b + q_4 · d + q_c + PI` + pub fn gate_add( &mut self, a: Witness, b: Witness, - c: Witness, + d: Witness, q_l: BlsScalar, q_r: BlsScalar, - q_o: BlsScalar, + q_4: BlsScalar, q_c: BlsScalar, pi: Option, ) -> Witness { - self.big_add_gate( + // Compute the output wire + let o = q_l * self.witnesses[&a] + + q_r * self.witnesses[&b] + + q_4 * self.witnesses[&d] + + q_c + + pi.unwrap_or_default(); + + let o = self.append_witness(o); + let q_o = -BlsScalar::one(); + + self.append_gate( a, b, - c, - None, + o, + d, + BlsScalar::zero(), q_l, q_r, q_o, - BlsScalar::zero(), + q_4, q_c, pi, - ) - } + ); - /// Adds a width-4 add gate to the circuit and it's corresponding - /// constraint. - /// - /// This type of gate is usually used when we need to have - /// the largest amount of performance and the minimum circuit-size - /// possible. Since it allows the end-user to set every selector coefficient - /// as scaling value on the gate eq. - pub fn big_add_gate( - &mut self, - a: Witness, - b: Witness, - c: Witness, - d: Option, - q_l: BlsScalar, - q_r: BlsScalar, - q_o: BlsScalar, - q_4: BlsScalar, - q_c: BlsScalar, - pi: Option, - ) -> Witness { - // Check if advice wire has a value - let d = match d { - Some(alloc_scalar) => alloc_scalar, - None => self.zero(), - }; - - self.w_l.push(a.into()); - self.w_r.push(b.into()); - self.w_o.push(c.into()); - self.w_4.push(d.into()); - - // For an add gate, q_m is zero - self.q_m.push(BlsScalar::zero()); - - // Add selector vectors - self.q_l.push(q_l); - self.q_r.push(q_r); - self.q_o.push(q_o); - self.q_c.push(q_c); - self.q_4.push(q_4); - self.q_arith.push(BlsScalar::one()); - self.q_range.push(BlsScalar::zero()); - self.q_logic.push(BlsScalar::zero()); - self.q_fixed_group_add.push(BlsScalar::zero()); - self.q_variable_group_add.push(BlsScalar::zero()); - self.q_lookup.push(BlsScalar::zero()); - - if let Some(pi) = pi { - assert!(self.public_inputs_sparse_store.insert(self.n, pi).is_none(),"The invariant of already having a PI inserted for this position should never exist"); - } - - self.perm.add_variables_to_map(a, b, c, d, self.n); - - self.n += 1; - - c - } - /// Adds a width-3 mul gate to the circuit linking the product of the - /// provided inputs scaled by the selector coefficient `q_m` with the output - /// provided scaled by `q_o`. - /// - /// Note that this gate requires to provide the actual result of the gate - /// (output wire) since it will just add a `mul constraint` to the circuit. - pub fn mul_gate( - &mut self, - a: Witness, - b: Witness, - c: Witness, - q_m: BlsScalar, - q_o: BlsScalar, - q_c: BlsScalar, - pi: Option, - ) -> Witness { - self.big_mul_gate(a, b, c, None, q_m, q_o, q_c, BlsScalar::zero(), pi) + o } - /// Adds a width-4 `big_mul_gate` with the left, right and fourth inputs - /// and it's scaling factors, computing & returning the output (result) - /// `Witness` and adding the corresponding mul constraint. - /// - /// This type of gate is usually used when we need to have - /// the largest amount of performance and the minimum circuit-size - /// possible. Since it allows the end-user to setup all of the selector - /// coefficients. + /// Evaluate and return `o` by appending a new gate into the circuit. /// - /// Forces `q_m * (w_l * w_r) + w_4 * q_4 + q_c + PI = q_o * w_o`. - /// - /// `{w_l, w_r, w_o, w_4} = {a, b, c, d}` - // XXX: Maybe make these tuples instead of individual field? - pub fn big_mul_gate( + /// `o := q_m · a · b + q_4 · d + q_c + PI` + pub fn gate_mul( &mut self, a: Witness, b: Witness, - c: Witness, - d: Option, + d: Witness, q_m: BlsScalar, - q_o: BlsScalar, - q_c: BlsScalar, q_4: BlsScalar, - pi: Option, - ) -> Witness { - // Check if advice wire has a value - let d = match d { - Some(alloc_scalar) => alloc_scalar, - None => self.zero(), - }; - - self.w_l.push(a.into()); - self.w_r.push(b.into()); - self.w_o.push(c.into()); - self.w_4.push(d.into()); - - // For a mul gate q_L and q_R is zero - self.q_l.push(BlsScalar::zero()); - self.q_r.push(BlsScalar::zero()); - - // Add selector vectors - self.q_m.push(q_m); - self.q_o.push(q_o); - self.q_c.push(q_c); - self.q_4.push(q_4); - self.q_arith.push(BlsScalar::one()); - - self.q_range.push(BlsScalar::zero()); - self.q_logic.push(BlsScalar::zero()); - self.q_fixed_group_add.push(BlsScalar::zero()); - self.q_variable_group_add.push(BlsScalar::zero()); - self.q_lookup.push(BlsScalar::zero()); - - if let Some(pi) = pi { - assert!( - self.public_inputs_sparse_store.insert(self.n, pi).is_none(),"The invariant of already having a PI inserted for this position should never exist" - ); - } - - self.perm.add_variables_to_map(a, b, c, d, self.n); - - self.n += 1; - - c - } - - /// Adds a [`TurboComposer::big_add_gate`] with the left and right - /// inputs and it's scaling factors, computing & returning the output - /// (result) [`Witness`], and adding the corresponding addition - /// constraint. - /// - /// This type of gate is usually used when we don't need to have - /// the largest amount of performance as well as the minimum circuit-size - /// possible. Since it defaults some of the selector coeffs = 0 in order - /// to reduce the verbosity and complexity. - /// - /// Forces `q_l * w_l + q_r * w_r + q_c + PI = w_o(computed by the gate)`. - pub fn add( - &mut self, - q_l_a: (BlsScalar, Witness), - q_r_b: (BlsScalar, Witness), q_c: BlsScalar, pi: Option, ) -> Witness { - self.big_add(q_l_a, q_r_b, None, q_c, pi) - } - - /// Adds a [`TurboComposer::big_add_gate`] with the left, right and - /// fourth inputs and it's scaling factors, computing & returning the - /// output (result) [`Witness`] and adding the corresponding - /// addition constraint. - /// - /// This type of gate is usually used when we don't need to have - /// the largest amount of performance and the minimum circuit-size - /// possible. Since it defaults some of the selector coeffs = 0 in order - /// to reduce the verbosity and complexity. - /// - /// Forces `q_l * w_l + q_r * w_r + q_4 * w_4 + q_c + PI = w_o(computed by - /// the gate)`. - pub fn big_add( - &mut self, - q_l_a: (BlsScalar, Witness), - q_r_b: (BlsScalar, Witness), - q_4_d: Option<(BlsScalar, Witness)>, - q_c: BlsScalar, - pi: Option, - ) -> Witness { - // Check if advice wire is available - let (q_4, d) = match q_4_d { - Some((q_4, alloc_scalar)) => (q_4, alloc_scalar), - None => (BlsScalar::zero(), self.zero()), - }; - - let (q_l, a) = q_l_a; - let (q_r, b) = q_r_b; - - let q_o = -BlsScalar::one(); - // Compute the output wire - let c: BlsScalar = (q_l * self.witnesses[&a]) - + (q_r * self.witnesses[&b]) - + (q_4 * self.witnesses[&d]) + let o = q_m * self.witnesses[&a] * self.witnesses[&b] + + q_4 * self.witnesses[&d] + q_c + pi.unwrap_or_default(); - let c = self.append_witness(c); - - self.big_add_gate(a, b, c, Some(d), q_l, q_r, q_o, q_4, q_c, pi) - } - - /// Adds a [`TurboComposer::big_mul_gate`] with the left, right - /// and fourth inputs and it's scaling factors, computing & returning - /// the output (result) [`Witness`] and adding the corresponding mul - /// constraint. - /// - /// This type of gate is usually used when we don't need to have - /// the largest amount of performance and the minimum circuit-size - /// possible. Since it defaults some of the selector coeffs = 0 in order - /// to reduce the verbosity and complexity. - /// - /// Forces `q_m * (w_l * w_r) + w_4 * q_4 + q_c + PI = w_o(computed by the - /// gate)`. - /// - /// `{w_l, w_r, w_4} = {a, b, d}` - pub fn mul( - &mut self, - q_m: BlsScalar, - a: Witness, - b: Witness, - q_c: BlsScalar, - pi: Option, - ) -> Witness { - self.big_mul(q_m, a, b, None, q_c, pi) - } - /// Adds a width-4 [`TurboComposer::big_mul_gate`] with the left, right - /// and fourth inputs and it's scaling factors, computing & returning - /// the output (result) [`Witness`] and adding the corresponding mul - /// constraint. - /// - /// This type of gate is usually used when we don't need to have - /// the largest amount of performance and the minimum circuit-size - /// possible. Since it defaults some of the selector coeffs = 0 in order - /// to reduce the verbosity and complexity. - /// - /// Forces `q_m * (w_l * w_r) + w_4 * q_4 + q_c + PI = w_o(computed by the - /// gate)`. - /// - /// `{w_l, w_r, w_4} = {a, b, d}` - pub fn big_mul( - &mut self, - q_m: BlsScalar, - a: Witness, - b: Witness, - q_4_d: Option<(BlsScalar, Witness)>, - q_c: BlsScalar, - pi: Option, - ) -> Witness { + let o = self.append_witness(o); let q_o = -BlsScalar::one(); - // Check if advice wire is available - let (q_4, d) = match q_4_d { - Some((q_4, alloc_scalar)) => (q_4, alloc_scalar), - None => (BlsScalar::zero(), self.zero()), - }; - - // Compute output wire - let c = (q_m * self.witnesses[&a] * self.witnesses[&b]) - + (q_4 * self.witnesses[&d]) - + q_c - + pi.unwrap_or_default(); - let c = self.append_witness(c); + self.append_gate( + a, + b, + o, + d, + q_m, + BlsScalar::zero(), + BlsScalar::zero(), + q_o, + q_4, + q_c, + pi, + ); - self.big_mul_gate(a, b, c, Some(d), q_m, q_o, q_c, q_4, pi) + o } } @@ -319,27 +100,37 @@ mod tests { let res = gadget_tester( |composer| { let one = composer.append_witness(BlsScalar::one()); + let zero = composer.constant_zero(); - let should_be_three = composer.big_add( - (BlsScalar::one(), one), - (BlsScalar::one(), one), - None, + let should_be_three = composer.gate_add( + one, + one, + zero, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), Some(BlsScalar::one()), ); - composer.constrain_to_constant( + + composer.assert_equal_constant( should_be_three, BlsScalar::from(3), None, ); - let should_be_four = composer.big_add( - (BlsScalar::one(), one), - (BlsScalar::one(), one), - None, + + let should_be_four = composer.gate_add( + one, + one, + zero, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), Some(BlsScalar::from(2)), ); - composer.constrain_to_constant( + + composer.assert_equal_constant( should_be_four, BlsScalar::from(4), None, @@ -359,19 +150,26 @@ mod tests { let five = composer.append_witness(BlsScalar::from(5)); let six = composer.append_witness(BlsScalar::from(6)); let seven = composer.append_witness(BlsScalar::from(7)); + let zero = composer.constant_zero(); - let fourteen = composer.big_add( - (BlsScalar::one(), four), - (BlsScalar::one(), five), - Some((BlsScalar::one(), five)), + let fourteen = composer.gate_add( + four, + five, + five, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::one(), BlsScalar::zero(), None, ); - let twenty = composer.big_add( - (BlsScalar::one(), six), - (BlsScalar::one(), seven), - Some((BlsScalar::one(), seven)), + let twenty = composer.gate_add( + six, + seven, + seven, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::one(), BlsScalar::zero(), None, ); @@ -383,14 +181,17 @@ mod tests { // can compute it using the `mul` If the output // is public, we can also constrain the output wire of the mul // gate to it. This is what this test does - let output = composer.mul( - BlsScalar::one(), + let output = composer.gate_mul( fourteen, twenty, + zero, + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); - composer.constrain_to_constant( + + composer.assert_equal_constant( output, BlsScalar::from(280), None, @@ -405,16 +206,21 @@ mod tests { fn test_correct_add_gate() { let res = gadget_tester( |composer| { - let zero = composer.zero(); + let zero = composer.constant_zero(); let one = composer.append_witness(BlsScalar::one()); - let c = composer.add( - (BlsScalar::one(), one), - (BlsScalar::zero(), zero), + let c = composer.gate_add( + one, + zero, + zero, + BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), BlsScalar::from(2u64), None, ); - composer.constrain_to_constant(c, BlsScalar::from(3), None); + + composer.assert_equal_constant(c, BlsScalar::from(3), None); }, 32, ); @@ -432,31 +238,39 @@ mod tests { let seven = composer.append_witness(BlsScalar::from(7)); let nine = composer.append_witness(BlsScalar::from(9)); - let fourteen = composer.big_add( - (BlsScalar::one(), four), - (BlsScalar::one(), five), - Some((BlsScalar::one(), five)), + let fourteen = composer.gate_add( + four, + five, + five, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::one(), BlsScalar::zero(), None, ); - let twenty = composer.big_add( - (BlsScalar::one(), six), - (BlsScalar::one(), seven), - Some((BlsScalar::one(), seven)), + let twenty = composer.gate_add( + six, + seven, + seven, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::one(), BlsScalar::zero(), None, ); - let output = composer.big_mul( - BlsScalar::one(), + let output = composer.gate_mul( fourteen, twenty, - Some((BlsScalar::from(8), nine)), + nine, + BlsScalar::one(), + BlsScalar::from(8), BlsScalar::zero(), None, ); - composer.constrain_to_constant( + + composer.assert_equal_constant( output, BlsScalar::from(352), None, @@ -475,31 +289,41 @@ mod tests { let five = composer.append_witness(BlsScalar::from(5)); let six = composer.append_witness(BlsScalar::from(6)); let seven = composer.append_witness(BlsScalar::from(7)); + let zero = composer.constant_zero(); - let five_plus_five = composer.big_add( - (BlsScalar::one(), five), - (BlsScalar::one(), five), - None, + let five_plus_five = composer.gate_add( + five, + five, + zero, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); - let six_plus_seven = composer.big_add( - (BlsScalar::one(), six), - (BlsScalar::one(), seven), - None, + let six_plus_seven = composer.gate_add( + six, + seven, + zero, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); - let output = composer.mul( - BlsScalar::one(), + let output = composer.gate_mul( five_plus_five, six_plus_seven, + zero, + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); - composer.constrain_to_constant( + + composer.assert_equal_constant( output, BlsScalar::from(117), None, diff --git a/src/constraint_system/boolean.rs b/src/constraint_system/boolean.rs index 1ea18c8cf..c367c9322 100644 --- a/src/constraint_system/boolean.rs +++ b/src/constraint_system/boolean.rs @@ -16,11 +16,11 @@ impl TurboComposer { /// Note that using this constraint with whatever [`Witness`] that /// is not representing a value equalling 0 or 1, will always force the /// equation to fail. - pub fn boolean_gate(&mut self, a: Witness) -> Witness { - self.w_l.push(a.into()); - self.w_r.push(a.into()); - self.w_o.push(a.into()); - self.w_4.push(self.zero_var); + pub fn gate_boolean(&mut self, a: Witness) -> Witness { + self.w_l.push(a); + self.w_r.push(a); + self.w_o.push(a); + self.w_4.push(self.constant_zero()); self.q_m.push(BlsScalar::one()); self.q_l.push(BlsScalar::zero()); @@ -36,7 +36,8 @@ impl TurboComposer { self.q_variable_group_add.push(BlsScalar::zero()); self.q_lookup.push(BlsScalar::zero()); - self.perm.add_variables_to_map(a, a, a, self.zero(), self.n); + self.perm + .add_variables_to_map(a, a, a, self.constant_zero(), self.n); self.n += 1; @@ -53,11 +54,11 @@ mod tests { fn test_correct_bool_gate() { let res = gadget_tester( |composer| { - let zero = composer.zero(); + let zero = composer.constant_zero(); let one = composer.append_witness(BlsScalar::one()); - composer.boolean_gate(zero); - composer.boolean_gate(one); + composer.gate_boolean(zero); + composer.gate_boolean(one); }, 32, ); @@ -71,8 +72,8 @@ mod tests { let zero = composer.append_witness(BlsScalar::from(5)); let one = composer.append_witness(BlsScalar::one()); - composer.boolean_gate(zero); - composer.boolean_gate(one); + composer.gate_boolean(zero); + composer.gate_boolean(one); }, 32, ); diff --git a/src/constraint_system/composer.rs b/src/constraint_system/composer.rs index 4eab7d4b3..e52e3a392 100644 --- a/src/constraint_system/composer.rs +++ b/src/constraint_system/composer.rs @@ -44,9 +44,9 @@ use hashbrown::HashMap; /// The TurboComposer also contains as associated functions all the /// neccessary tools to be able to istrument the circuits that the user needs /// through the addition of gates. There are functions that may add a single -/// gate to the circuit as for example [`TurboComposer::add_gate`] and others +/// gate to the circuit as for example [`TurboComposer::gate_add`] and others /// that can add several gates to the circuit description such as -/// [`TurboComposer::conditional_select`]. +/// [`TurboComposer::gate_select`]. /// /// Each gate or group of gates adds an specific functionallity or operation to /// de circuit description, and so, that's why we can understand @@ -97,13 +97,13 @@ pub struct TurboComposer { pub(crate) w_4: Vec, /// Public lookup table - pub lookup_table: PlonkupTable4Arity, + pub(crate) lookup_table: PlonkupTable4Arity, /// A zero Witness that is a part of the circuit description. /// We reserve a variable to be zero in the system /// This is so that when a gate only uses three wires, we set the fourth /// wire to be the variable that references zero - pub(crate) zero_var: Witness, + pub(crate) constant_zero: Witness, /// These are the actual variable values. pub(crate) witnesses: HashMap, @@ -118,12 +118,12 @@ impl TurboComposer { /// Every [`TurboComposer`] is initialized with a circuit description /// containing a representation of zero. This function will return the /// index of that representation. - pub const fn zero(&self) -> Witness { - self.zero_var + pub const fn constant_zero(&self) -> Witness { + self.constant_zero } - /// Returns the number of gates in the circuit - pub fn circuit_size(&self) -> usize { + /// Return the number of constraints in the circuit + pub const fn constraints(&self) -> usize { self.n } @@ -135,7 +135,7 @@ impl TurboComposer { /// Constructs a dense vector of the Public Inputs from the positions and /// the sparse vector that contains the values. - pub fn construct_dense_pi_vec(&self) -> Vec { + pub(crate) fn into_dense_public_inputs(&self) -> Vec { let mut pi = vec![BlsScalar::zero(); self.n]; self.public_inputs_sparse_store .iter() @@ -149,7 +149,7 @@ impl TurboComposer { /// instance. // TODO: Find a more performant solution which can return a ref to a Vec or // Iterator. - pub fn pi_positions(&self) -> Vec { + pub fn into_public_input_indexes(&self) -> Vec { self.public_inputs_sparse_store .keys() .copied() @@ -172,16 +172,16 @@ impl TurboComposer { /// The usage of this may cause lots of re-allocations since the `Composer` /// holds `Vec` for every polynomial, and these will need to be re-allocated /// each time the circuit grows considerably. - pub fn new() -> Self { - TurboComposer::with_expected_size(0) + pub(crate) fn new() -> Self { + TurboComposer::with_size(0) } /// Constrain a scalar into the circuit description and return an allocated /// [`Witness`] with its value - pub fn append_circuit_constant(&mut self, value: BlsScalar) -> Witness { + pub fn append_constant(&mut self, value: BlsScalar) -> Witness { let witness = self.append_witness(value); - self.constrain_to_constant(witness, value, None); + self.assert_equal_constant(witness, value, None); witness } @@ -190,120 +190,93 @@ impl TurboComposer { /// This will allow for less reallocations when building the circuit /// since the `Vec`s will already have an appropriate allocation at the /// beginning of the composing stage. - pub fn with_expected_size(expected_size: usize) -> Self { + pub(crate) fn with_size(size: usize) -> Self { let mut composer = TurboComposer { n: 0, - q_m: Vec::with_capacity(expected_size), - q_l: Vec::with_capacity(expected_size), - q_r: Vec::with_capacity(expected_size), - q_o: Vec::with_capacity(expected_size), - q_c: Vec::with_capacity(expected_size), - q_4: Vec::with_capacity(expected_size), - q_arith: Vec::with_capacity(expected_size), - q_range: Vec::with_capacity(expected_size), - q_logic: Vec::with_capacity(expected_size), - q_fixed_group_add: Vec::with_capacity(expected_size), - q_variable_group_add: Vec::with_capacity(expected_size), - q_lookup: Vec::with_capacity(expected_size), + q_m: Vec::with_capacity(size), + q_l: Vec::with_capacity(size), + q_r: Vec::with_capacity(size), + q_o: Vec::with_capacity(size), + q_c: Vec::with_capacity(size), + q_4: Vec::with_capacity(size), + q_arith: Vec::with_capacity(size), + q_range: Vec::with_capacity(size), + q_logic: Vec::with_capacity(size), + q_fixed_group_add: Vec::with_capacity(size), + q_variable_group_add: Vec::with_capacity(size), + q_lookup: Vec::with_capacity(size), public_inputs_sparse_store: BTreeMap::new(), - w_l: Vec::with_capacity(expected_size), - w_r: Vec::with_capacity(expected_size), - w_o: Vec::with_capacity(expected_size), - w_4: Vec::with_capacity(expected_size), + w_l: Vec::with_capacity(size), + w_r: Vec::with_capacity(size), + w_o: Vec::with_capacity(size), + w_4: Vec::with_capacity(size), lookup_table: PlonkupTable4Arity::new(), - zero_var: Witness::new(0), + constant_zero: Witness::new(0), - witnesses: HashMap::with_capacity(expected_size), + witnesses: HashMap::with_capacity(size), perm: Permutation::new(), }; // Reserve the first variable to be zero - composer.zero_var = composer.append_circuit_constant(BlsScalar::zero()); + composer.constant_zero = composer.append_constant(BlsScalar::zero()); // Add dummy constraints - composer.add_dummy_constraints(); + composer.append_dummy_constraints(); composer } /// Allocate a witness value into the composer and return its index. - pub fn append_witness + Copy>( - &mut self, - s: T, - ) -> Witness { + pub fn append_witness>(&mut self, scalar: T) -> Witness { + let scalar = scalar.into(); + // Get a new Witness from the permutation let var = self.perm.new_variable(); // The composer now links the BlsScalar to the Witness returned from // the Permutation - self.witnesses.insert(var, s.into()); + self.witnesses.insert(var, scalar); var } - /// This pushes the result of a lookup read to a gate - pub fn lookup_gate(&mut self, a: Witness, b: Witness, c: Witness) { - self.w_l.push(a.into()); - self.w_l.push(b.into()); - self.w_l.push(c.into()); - self.w_4.push(self.zero_var); - self.q_l.push(BlsScalar::zero()); - self.q_r.push(BlsScalar::zero()); - - // Add selector vectors - self.q_m.push(BlsScalar::zero()); - self.q_o.push(BlsScalar::zero()); - self.q_c.push(BlsScalar::zero()); - self.q_4.push(BlsScalar::zero()); - self.q_arith.push(BlsScalar::zero()); - - self.q_range.push(BlsScalar::zero()); - self.q_logic.push(BlsScalar::zero()); - self.q_fixed_group_add.push(BlsScalar::zero()); - self.q_variable_group_add.push(BlsScalar::zero()); - self.q_lookup.push(BlsScalar::one()); - } - - /// Adds a width-3 poly gate. - /// This gate gives total freedom to the end user to implement the - /// corresponding circuits in the most optimized way possible because - /// the under has access to the whole set of variables, as well as - /// selector coefficients that take part in the computation of the gate - /// equation. + /// Adds a width-4 poly gate. /// - /// The final constraint added will force the following: - /// `(a * b) * q_m + a * q_l + b * q_r + q_c + PI + q_o * c = 0`. - pub fn poly_gate( + /// The final constraint added will enforce the following: + /// `q_m · a · b + q_l · a + q_r · b + q_o · o + q_4 · d + q_c + PI = 0`. + pub fn append_gate( &mut self, a: Witness, b: Witness, - c: Witness, + o: Witness, + d: Witness, q_m: BlsScalar, q_l: BlsScalar, q_r: BlsScalar, q_o: BlsScalar, + q_4: BlsScalar, q_c: BlsScalar, pi: Option, - ) -> (Witness, Witness, Witness) { - self.w_l.push(a.into()); - self.w_r.push(b.into()); - self.w_o.push(c.into()); - self.w_4.push(self.zero_var); - self.q_l.push(q_l); - self.q_r.push(q_r); + ) { + self.w_l.push(a); + self.w_r.push(b); + self.w_o.push(o); + self.w_4.push(d); // Add selector vectors self.q_m.push(q_m); + self.q_l.push(q_l); + self.q_r.push(q_r); self.q_o.push(q_o); + self.q_4.push(q_4); self.q_c.push(q_c); - self.q_4.push(BlsScalar::zero()); - self.q_arith.push(BlsScalar::one()); + self.q_arith.push(BlsScalar::one()); self.q_range.push(BlsScalar::zero()); self.q_logic.push(BlsScalar::zero()); self.q_fixed_group_add.push(BlsScalar::zero()); @@ -311,159 +284,167 @@ impl TurboComposer { self.q_lookup.push(BlsScalar::zero()); if let Some(pi) = pi { - assert!(self - .public_inputs_sparse_store - .insert(self.n, pi) - .is_none()); + debug_assert!(self.public_inputs_sparse_store.get(&self.n).is_none(), "The invariant of already having a PI inserted for this position should never exist"); + + self.public_inputs_sparse_store.insert(self.n, pi); } - self.perm.add_variables_to_map( - a.into(), - b.into(), - c.into(), - self.zero_var, - self.n, - ); - self.n += 1; + self.perm.add_variables_to_map(a, b, o, d, self.n); - (a, b, c) + self.n += 1; } /// Constrain `a` to be equal to `constant + pi`. /// /// `constant` will be defined as part of the public circuit description. - pub fn constrain_to_constant( + pub fn assert_equal_constant( &mut self, a: Witness, constant: BlsScalar, pi: Option, ) { - self.poly_gate( - a.into(), - a.into(), - a.into(), + let zero = self.constant_zero(); + + self.append_gate( + a, + zero, + zero, + zero, BlsScalar::zero(), BlsScalar::one(), BlsScalar::zero(), BlsScalar::zero(), + BlsScalar::zero(), -constant, pi, ); } - /// Add a constraint into the circuit description that states that two - /// [`Witness`]s are equal. + /// Asserts `a == b` by appending a gate pub fn assert_equal(&mut self, a: Witness, b: Witness) { - self.poly_gate( - a.into(), - b.into(), - self.zero(), + let zero = self.constant_zero(); + + self.append_gate( + a, + b, + zero, + zero, BlsScalar::zero(), BlsScalar::one(), -BlsScalar::one(), BlsScalar::zero(), BlsScalar::zero(), + BlsScalar::zero(), None, ); } /// Conditionally selects a [`Witness`] based on an input bit. /// - /// If: - /// bit == 1 => choice_a, - /// bit == 0 => choice_b, + /// bit == 1 => a, + /// bit == 0 => b, /// - /// # Note - /// The `bit` used as input which is a [`Witness`] should had previously - /// been constrained to be either 1 or 0 using a bool constrain. See: - /// [`TurboComposer::boolean_gate`]. - pub fn conditional_select( + /// `bit` is expected to be constrained by [`TurboComposer::gate_boolean`] + pub fn gate_select( &mut self, bit: Witness, - choice_a: Witness, - choice_b: Witness, + a: Witness, + b: Witness, ) -> Witness { - // bit * choice_a - let bit_times_a = self.mul( + // bit * a + let bit_times_a = self.gate_mul( + bit, + a, + self.constant_zero(), BlsScalar::one(), - bit.into(), - choice_a.into(), + BlsScalar::zero(), BlsScalar::zero(), None, ); // 1 - bit - let one_min_bit = self.add( - (-BlsScalar::one(), bit.into()), - (BlsScalar::zero(), self.zero()), + let one_min_bit = self.gate_add( + bit, + self.constant_zero(), + self.constant_zero(), + -BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), BlsScalar::one(), None, ); // (1 - bit) * b - let one_min_bit_choice_b = self.mul( - BlsScalar::one(), + let one_min_bit_b = self.gate_mul( one_min_bit, - choice_b.into(), + b, + self.constant_zero(), + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); // [ (1 - bit) * b ] + [ bit * a ] - self.add( - (BlsScalar::one(), one_min_bit_choice_b), - (BlsScalar::one(), bit_times_a), + self.gate_add( + one_min_bit_b, + bit_times_a, + self.constant_zero(), + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ) } - /// Adds the polynomial f(x) = x * a to the circuit description where - /// `x = bit`. If: + /// Conditionally selects a [`Witness`] based on an input bit. + /// /// bit == 1 => value, /// bit == 0 => 0, /// - /// # Note - /// The `bit` used as input which is a [`Witness`] should had previously - /// been constrained to be either 1 or 0 using a bool constrain. See: - /// [`TurboComposer::boolean_gate`]. - pub fn conditional_select_zero( + /// `bit` is expected to be constrained by [`TurboComposer::gate_boolean`] + pub fn gate_select_zero( &mut self, bit: Witness, value: Witness, ) -> Witness { // returns bit * value - self.mul(BlsScalar::one(), bit, value, BlsScalar::zero(), None) + self.gate_mul( + bit, + value, + self.constant_zero(), + BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), + None, + ) } - /// Adds the polynomial f(x) = 1 - x + xa to the circuit description where - /// `x = bit`. If: + /// Conditionally selects a [`Witness`] based on an input bit. + /// /// bit == 1 => value, /// bit == 0 => 1, /// - /// # Note - /// The `bit` used as input which is a [`Witness`] should had previously - /// been constrained to be either 1 or 0 using a bool constrain. See: - /// [`TurboComposer::boolean_gate`]. - pub fn conditional_select_one( - &mut self, - bit: Witness, - value: Witness, - ) -> Witness { + /// `bit` is expected to be constrained by [`TurboComposer::gate_boolean`] + pub fn gate_select_one(&mut self, bit: Witness, value: Witness) -> Witness { let b = self.witnesses[&bit]; let v = self.witnesses[&value]; + let zero = self.constant_zero(); let f_x = BlsScalar::one() - b + (b * v); let f_x = self.append_witness(f_x); - self.poly_gate( - bit.into(), - value.into(), - f_x.into(), + self.append_gate( + bit, + value, + f_x, + zero, BlsScalar::one(), -BlsScalar::one(), BlsScalar::zero(), -BlsScalar::one(), + BlsScalar::zero(), BlsScalar::one(), None, ); @@ -471,13 +452,9 @@ impl TurboComposer { f_x } - /// Decomposes an [`Witness`] into an array of 256 bits represented - /// as [`Witness`]s. - pub fn scalar_bit_decomposition( - &mut self, - scalar: Witness, - ) -> [Witness; 256] { - let mut res = [self.zero(); 256]; + /// Decomposes `scalar` into an array of 256 bits. + pub fn gate_decomposition(&mut self, scalar: Witness) -> [Witness; 256] { + let mut res = [self.constant_zero(); 256]; let bytes = self.witnesses[&scalar].to_bytes(); for (byte, bits) in bytes.iter().zip(res.chunks_mut(8)) { @@ -500,7 +477,7 @@ impl TurboComposer { /// This function is used to add a blinding factor to the witness /// polynomials. It essentially adds two dummy gates to the circuit /// description which are guaranteed to always satisfy the gate equation. - pub fn add_dummy_constraints(&mut self) { + pub fn append_dummy_constraints(&mut self) { // Add a dummy constraint so that we do not have zero polynomials self.q_m.push(BlsScalar::from(1)); self.q_l.push(BlsScalar::from(2)); @@ -518,10 +495,10 @@ impl TurboComposer { let var_one = self.append_witness(BlsScalar::from(1)); let var_seven = self.append_witness(BlsScalar::from(7)); let var_min_twenty = self.append_witness(-BlsScalar::from(20)); - self.w_l.push(var_six.into()); - self.w_r.push(var_seven.into()); - self.w_o.push(var_min_twenty.into()); - self.w_4.push(var_one.into()); + self.w_l.push(var_six); + self.w_r.push(var_seven); + self.w_o.push(var_min_twenty); + self.w_4.push(var_one); self.perm.add_variables_to_map( var_six, var_seven, @@ -544,15 +521,15 @@ impl TurboComposer { self.q_fixed_group_add.push(BlsScalar::zero()); self.q_variable_group_add.push(BlsScalar::zero()); self.q_lookup.push(BlsScalar::one()); - self.w_l.push(var_min_twenty.into()); - self.w_r.push(var_six.into()); - self.w_o.push(var_seven.into()); - self.w_4.push(self.zero_var); + self.w_l.push(var_min_twenty); + self.w_r.push(var_six); + self.w_o.push(var_seven); + self.w_4.push(self.constant_zero()); self.perm.add_variables_to_map( - var_min_twenty.into(), - var_six.into(), - var_seven.into(), - self.zero_var, + var_min_twenty, + var_six, + var_seven, + self.constant_zero(), self.n, ); @@ -603,7 +580,8 @@ impl TurboComposer { /// the gates does not satisfy the equation or there are no more gates. If /// the cause is an unsatisfied gate equation, the function will panic. #[cfg(feature = "trace")] - pub fn check_circuit_satisfied(&self) { + #[allow(dead_code)] + pub(crate) fn check_circuit_satisfied(&self) { let w_l: Vec<&BlsScalar> = self .w_l .iter() @@ -633,7 +611,7 @@ impl TurboComposer { f * f_1 * f_2 * f_3 }; - let pi_vec = self.construct_dense_pi_vec(); + let pi_vec = self.into_dense_public_inputs(); let four = BlsScalar::from(4); for i in 0..self.n { @@ -737,20 +715,14 @@ impl TurboComposer { /// the largest amount of performance and the minimum circuit-size /// possible. Since it allows the end-user to set every selector coefficient /// as scaling value on the gate eq. - pub fn plonkup_gate( + pub fn append_plonkup_gate( &mut self, a: Witness, b: Witness, c: Witness, - d: Option, - _pi: BlsScalar, + d: Witness, + pi: Option, ) -> Witness { - // Check if advice wire has a value - let d = match d { - Some(var) => var, - None => self.zero_var, - }; - self.w_l.push(a); self.w_r.push(b); self.w_o.push(c); @@ -773,6 +745,12 @@ impl TurboComposer { // turned on as the output is inputted directly self.q_lookup.push(BlsScalar::one()); + if let Some(pi) = pi { + debug_assert!(self.public_inputs_sparse_store.get(&self.n).is_none(), "The invariant of already having a PI inserted for this position should never exist"); + + self.public_inputs_sparse_store.insert(self.n, pi); + } + self.perm.add_variables_to_map(a, b, c, d, self.n); self.n += 1; @@ -780,10 +758,10 @@ impl TurboComposer { c } - /// When StandardComposer is initialised, it spawns a dummy table + /// When [`TurboComposer`] is initialised, it spawns a dummy table /// with 3 entries that should not be removed. This function appends /// its input table to the composer's dummy table - pub fn append_lookup_table(&mut self, table: &PlonkupTable4Arity) { + pub fn append_plonkup_table(&mut self, table: &PlonkupTable4Arity) { table.0.iter().for_each(|k| self.lookup_table.0.push(*k)) } } @@ -792,7 +770,7 @@ impl TurboComposer { #[cfg(test)] mod tests { use super::*; - use crate::commitment_scheme::kzg10::PublicParameters; + use crate::commitment_scheme::PublicParameters; use crate::constraint_system::helper::*; use crate::error::Error; use crate::proof_system::{Prover, Verifier}; @@ -800,7 +778,7 @@ mod tests { #[test] /// Tests that a circuit initially has 3 gates - fn test_initial_circuit_size() { + fn test_initial_gates() { let composer: TurboComposer = TurboComposer::new(); // Circuit size is n+3 because // - We have an extra gate which forces the first witness to be zero. @@ -809,7 +787,7 @@ mod tests { // not the identity and // - Another gate which ensures that the selector polynomials are not // all zeroes - assert_eq!(3, composer.circuit_size()) + assert_eq!(3, composer.constraints()) } #[allow(unused_variables)] @@ -819,7 +797,7 @@ mod tests { let res = gadget_tester( |composer| { // do nothing except add the dummy constraints - composer.add_dummy_constraints(); + composer.append_dummy_constraints(); }, 200, ); @@ -827,21 +805,19 @@ mod tests { } #[test] - fn test_conditional_select() { + fn test_gate_select() { let res = gadget_tester( |composer| { let bit_1 = composer.append_witness(BlsScalar::one()); - let bit_0 = composer.zero(); + let bit_0 = composer.constant_zero(); let choice_a = composer.append_witness(BlsScalar::from(10u64)); let choice_b = composer.append_witness(BlsScalar::from(20u64)); - let choice = - composer.conditional_select(bit_1, choice_a, choice_b); + let choice = composer.gate_select(bit_1, choice_a, choice_b); composer.assert_equal(choice, choice_a); - let choice = - composer.conditional_select(bit_0, choice_a, choice_b); + let choice = composer.gate_select(bit_0, choice_a, choice_b); composer.assert_equal(choice, choice_b); }, 32, @@ -873,17 +849,15 @@ mod tests { let res = gadget_plonkup_tester( |composer| { let bit_1 = composer.append_witness(BlsScalar::one()); - let bit_0 = composer.zero(); + let bit_0 = composer.constant_zero(); let choice_a = composer.append_witness(BlsScalar::from(10u64)); let choice_b = composer.append_witness(BlsScalar::from(20u64)); - let choice = - composer.conditional_select(bit_1, choice_a, choice_b); + let choice = composer.gate_select(bit_1, choice_a, choice_b); composer.assert_equal(choice, choice_a); - let choice = - composer.conditional_select(bit_0, choice_a, choice_b); + let choice = composer.gate_select(bit_0, choice_a, choice_b); composer.assert_equal(choice, choice_b); }, 65, @@ -904,17 +878,11 @@ mod tests { ); let res = gadget_plonkup_tester( |composer| { - let twelve = - composer.append_circuit_constant(BlsScalar::from(12)); - let three = - composer.append_circuit_constant(BlsScalar::from(3)); - composer.plonkup_gate( - twelve.into(), - twelve.into(), - twelve.into(), - Some(three.into()), - BlsScalar::zero(), - ); + let twelve = composer.append_constant(BlsScalar::from(12)); + let three = composer.append_constant(BlsScalar::from(3)); + + composer + .append_plonkup_gate(twelve, twelve, twelve, three, None); }, 65, t, @@ -932,7 +900,7 @@ mod tests { let mut prover = Prover::new(b"demo"); // Add gadgets - dummy_gadget(10, prover.mut_cs()); + dummy_gadget(10, prover.composer_mut()); // Commit Key let (ck, _) = public_parameters.trim(2 * 20).unwrap(); @@ -940,7 +908,7 @@ mod tests { // Preprocess circuit prover.preprocess(&ck).unwrap(); - let public_inputs = prover.cs.construct_dense_pi_vec(); + let public_inputs = prover.cs.into_dense_public_inputs(); let mut proofs = Vec::new(); @@ -949,7 +917,7 @@ mod tests { proofs.push(prover.prove(&ck).unwrap()); // Add another witness instance - dummy_gadget(10, prover.mut_cs()); + dummy_gadget(10, prover.composer_mut()); } // Verifier @@ -957,7 +925,7 @@ mod tests { let mut verifier = Verifier::new(b"demo"); // Add gadgets - dummy_gadget(10, verifier.mut_cs()); + dummy_gadget(10, verifier.composer_mut()); // Commit and Verifier Key let (ck, vk) = public_parameters.trim(2 * 20).unwrap(); @@ -989,33 +957,31 @@ mod tests { BlsScalar::one(), ); - let two = prover.cs.append_circuit_constant(BlsScalar::from(2)); - let three = prover.cs.append_circuit_constant(BlsScalar::from(3)); - let result = prover.cs.append_circuit_constant(output.unwrap()); - let one = prover.cs.append_circuit_constant(BlsScalar::one()); - - prover - .cs - .plonkup_gate(two, three, result, Some(one), BlsScalar::one()); - prover - .cs - .plonkup_gate(two, three, result, Some(one), BlsScalar::one()); - prover - .cs - .plonkup_gate(two, three, result, Some(one), BlsScalar::one()); - prover - .cs - .plonkup_gate(two, three, result, Some(one), BlsScalar::one()); - prover - .cs - .plonkup_gate(two, three, result, Some(one), BlsScalar::one()); - - prover.cs.big_add( - (BlsScalar::one(), two), - (BlsScalar::one(), three), - None, + let two = prover.cs.append_constant(BlsScalar::from(2)); + let three = prover.cs.append_constant(BlsScalar::from(3)); + let result = prover.cs.append_constant(output.unwrap()); + let one = prover.cs.append_constant(BlsScalar::one()); + let zero = prover.cs.constant_zero(); + + prover.cs.append_plonkup_gate(two, three, result, one, None); + + prover.cs.append_plonkup_gate(two, three, result, one, None); + + prover.cs.append_plonkup_gate(two, three, result, one, None); + + prover.cs.append_plonkup_gate(two, three, result, one, None); + + prover.cs.append_plonkup_gate(two, three, result, one, None); + + prover.cs.gate_add( + two, + three, + zero, + BlsScalar::one(), + BlsScalar::one(), BlsScalar::zero(), - Some(BlsScalar::zero()), + BlsScalar::zero(), + None, ); // Commit Key @@ -1026,7 +992,7 @@ mod tests { // Once the prove method is called, the public inputs are cleared // So pre-fetch these before calling Prove - let public_inputs = prover.cs.construct_dense_pi_vec(); + let public_inputs = prover.cs.into_dense_public_inputs(); (prover.prove(&ck).unwrap(), public_inputs); } @@ -1040,10 +1006,10 @@ mod tests { let mut verifier = Verifier::new(b"test"); // Add gadgets - dummy_gadget_plonkup(4, prover.mut_cs()); + dummy_gadget_plonkup(4, prover.composer_mut()); prover.cs.lookup_table.insert_multi_mul(0, 3); - dummy_gadget_plonkup(4, verifier.mut_cs()); + dummy_gadget_plonkup(4, verifier.composer_mut()); verifier.cs.lookup_table.insert_multi_mul(0, 3); // Commit and verifier key @@ -1053,7 +1019,7 @@ mod tests { prover.preprocess(&ck)?; verifier.preprocess(&ck)?; - let public_inputs = prover.cs.construct_dense_pi_vec(); + let public_inputs = prover.cs.into_dense_public_inputs(); let proof = prover.prove(&ck)?; diff --git a/src/constraint_system/ecc.rs b/src/constraint_system/ecc.rs new file mode 100644 index 000000000..6e77929a3 --- /dev/null +++ b/src/constraint_system/ecc.rs @@ -0,0 +1,195 @@ +// 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. + +/// Curve addition gate +pub mod curve_addition; +/// Gates related to scalar multiplication +pub mod scalar_mul; + +use crate::constraint_system::{TurboComposer, Witness}; +use dusk_bls12_381::BlsScalar; +use dusk_jubjub::JubJubAffine; + +/// Represents a JubJub point in the circuit +#[derive(Debug, Clone, Copy)] +pub struct WitnessPoint { + x: Witness, + y: Witness, +} + +impl WitnessPoint { + /// Return the X coordinate of the point + pub const fn x(&self) -> &Witness { + &self.x + } + + /// Return the Y coordinate of the point + pub const fn y(&self) -> &Witness { + &self.y + } +} + +impl TurboComposer { + /// Appends a point in affine form as [`WitnessPoint`] + pub fn append_point>( + &mut self, + affine: P, + ) -> WitnessPoint { + let affine = affine.into(); + + let x = self.append_witness(affine.get_x()); + let y = self.append_witness(affine.get_y()); + + WitnessPoint { x, y } + } + + /// Appends a point in affine form as [`WitnessPoint`] + /// + /// Creates two public inputs as `(x, y)` + pub fn append_public_point>( + &mut self, + affine: P, + ) -> WitnessPoint { + let affine = affine.into(); + let point = self.append_point(affine); + + self.assert_equal_constant( + point.x, + BlsScalar::zero(), + Some(-affine.get_x()), + ); + + self.assert_equal_constant( + point.y, + BlsScalar::zero(), + Some(-affine.get_y()), + ); + + point + } + + /// Constrain a point into the circuit description and return an allocated + /// [`WitnessPoint`] with its coordinates + pub fn append_constant_point>( + &mut self, + affine: P, + ) -> WitnessPoint { + let affine = affine.into(); + + let x = self.append_constant(affine.get_x()); + let y = self.append_constant(affine.get_y()); + + WitnessPoint { x, y } + } + + /// Create an identity [`WitnessPoint`] constrained by the circuit + /// description + pub fn append_constant_identity(&mut self) -> WitnessPoint { + let x = self.constant_zero(); + let y = self.append_constant(BlsScalar::one()); + + WitnessPoint { x, y } + } + + /// Asserts `point == public`. + /// + /// Will add `public` affine coordinates `(x,y)` as public inputs + pub fn assert_equal_public_point>( + &mut self, + point: WitnessPoint, + public: P, + ) { + let public = public.into(); + + self.assert_equal_constant( + point.x, + BlsScalar::zero(), + Some(-public.get_x()), + ); + + self.assert_equal_constant( + point.y, + BlsScalar::zero(), + Some(-public.get_y()), + ); + } + + /// Asserts `a == b` by appending two gates + pub fn assert_equal_point(&mut self, a: WitnessPoint, b: WitnessPoint) { + self.assert_equal(a.x, b.x); + self.assert_equal(b.y, b.y); + } + + /// Conditionally selects a [`WitnessPoint`] based on an input bit. + /// + /// bit == 1 => a, + /// bit == 0 => b, + /// + /// `bit` is expected to be constrained by [`TurboComposer::gate_boolean`] + pub fn gate_select_point( + &mut self, + a: WitnessPoint, + b: WitnessPoint, + bit: Witness, + ) -> WitnessPoint { + let x = self.gate_select(bit, *a.x(), *b.x()); + let y = self.gate_select(bit, *a.y(), *b.y()); + + WitnessPoint { x, y } + } + + /// Conditionally selects identity as [`WitnessPoint`] based on an input + /// bit. + /// + /// bit == 1 => a, + /// bit == 0 => identity, + /// + /// `bit` is expected to be constrained by [`TurboComposer::gate_boolean`] + pub fn gate_select_identity( + &mut self, + bit: Witness, + a: WitnessPoint, + ) -> WitnessPoint { + let x = self.gate_select_zero(bit, *a.x()); + let y = self.gate_select_one(bit, *a.y()); + + WitnessPoint { x, y } + } +} + +#[cfg(feature = "std")] +#[cfg(test)] +mod tests { + use super::*; + use crate::constraint_system::helper::*; + + #[test] + fn test_gate_select_point() { + let res = gadget_tester( + |composer| { + let bit_1 = composer.append_witness(BlsScalar::one()); + let bit_0 = composer.constant_zero(); + + let point_a = composer.append_constant_identity(); + let point_b = WitnessPoint { + x: composer.append_witness(BlsScalar::from(10u64)), + y: composer.append_witness(BlsScalar::from(20u64)), + }; + + let choice = + composer.gate_select_point(point_a, point_b, bit_1); + + composer.assert_equal_point(point_a, choice); + + let choice = + composer.gate_select_point(point_a, point_b, bit_0); + composer.assert_equal_point(point_b, choice); + }, + 32, + ); + assert!(res.is_ok()); + } +} diff --git a/src/constraint_system/ecc/curve_addition/mod.rs b/src/constraint_system/ecc/curve_addition.rs similarity index 100% rename from src/constraint_system/ecc/curve_addition/mod.rs rename to src/constraint_system/ecc/curve_addition.rs diff --git a/src/constraint_system/ecc/curve_addition/variable_base_gate.rs b/src/constraint_system/ecc/curve_addition/variable_base_gate.rs index a368de5ec..1966ca6b7 100644 --- a/src/constraint_system/ecc/curve_addition/variable_base_gate.rs +++ b/src/constraint_system/ecc/curve_addition/variable_base_gate.rs @@ -14,20 +14,22 @@ impl TurboComposer { /// Note that since the points are not fixed the generator is not a part of /// the circuit description, however it is less efficient for a program /// width of 4. - pub fn point_addition_gate( + /// + /// Adds two curve points + pub fn gate_add_point( &mut self, - point_a: WitnessPoint, - point_b: WitnessPoint, + a: WitnessPoint, + b: WitnessPoint, ) -> WitnessPoint { // In order to verify that two points were correctly added // without going over a degree 4 polynomial, we will need // x_1, y_1, x_2, y_2 - // x_3, y_3, x_1 * y_2 + // x_3, y_3, x_1 * y_2 - let x_1 = point_a.x; - let y_1 = point_a.y; - let x_2 = point_b.x; - let y_2 = point_b.y; + let x_1 = a.x; + let y_1 = a.y; + let x_2 = b.x; + let y_2 = b.y; let p1 = JubJubAffine::from_raw_unchecked( self.witnesses[&x_1], @@ -50,10 +52,10 @@ impl TurboComposer { let x_3 = self.append_witness(x_3); let y_3 = self.append_witness(y_3); - self.w_l.extend(&[x_1.into(), x_3.into()]); - self.w_r.extend(&[y_1.into(), y_3.into()]); - self.w_o.extend(&[x_2.into(), self.zero_var]); - self.w_4.extend(&[y_2.into(), x_1_y_2.into()]); + self.w_l.extend(&[x_1, x_3]); + self.w_r.extend(&[y_1, y_3]); + self.w_o.extend(&[x_2, self.constant_zero()]); + self.w_4.extend(&[y_2, x_1_y_2]); let zeros = [BlsScalar::zero(), BlsScalar::zero()]; self.q_l.extend(&zeros); @@ -74,8 +76,13 @@ impl TurboComposer { self.perm.add_variables_to_map(x_1, y_1, x_2, y_2, self.n); self.n += 1; - self.perm - .add_variables_to_map(x_3, y_3, self.zero(), x_1_y_2, self.n); + self.perm.add_variables_to_map( + x_3, + y_3, + self.constant_zero(), + x_1_y_2, + self.n, + ); self.n += 1; WitnessPoint { x: x_3, y: y_3 } @@ -95,51 +102,105 @@ mod test { /// source of truth to test the WNaf method. pub fn classical_point_addition( composer: &mut TurboComposer, - point_a: WitnessPoint, - point_b: WitnessPoint, + a: WitnessPoint, + b: WitnessPoint, ) -> WitnessPoint { - let x1 = point_a.x; - let y1 = point_a.y; + let zero = composer.constant_zero(); + + let x1 = a.x; + let y1 = a.y; - let x2 = point_b.x; - let y2 = point_b.y; + let x2 = b.x; + let y2 = b.y; // x1 * y2 - let x1_y2 = - composer.mul(BlsScalar::one(), x1, y2, BlsScalar::zero(), None); + let x1_y2 = composer.gate_mul( + x1, + y2, + zero, + BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), + None, + ); + // y1 * x2 - let y1_x2 = - composer.mul(BlsScalar::one(), y1, x2, BlsScalar::zero(), None); + let y1_x2 = composer.gate_mul( + y1, + x2, + zero, + BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), + None, + ); + // y1 * y2 - let y1_y2 = - composer.mul(BlsScalar::one(), y1, y2, BlsScalar::zero(), None); + let y1_y2 = composer.gate_mul( + y1, + y2, + zero, + BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), + None, + ); + // x1 * x2 - let x1_x2 = - composer.mul(BlsScalar::one(), x1, x2, BlsScalar::zero(), None); + let x1_x2 = composer.gate_mul( + x1, + x2, + zero, + BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), + None, + ); + // d x1x2 * y1y2 - let d_x1_x2_y1_y2 = - composer.mul(EDWARDS_D, x1_x2, y1_y2, BlsScalar::zero(), None); + let d_x1_x2_y1_y2 = composer.gate_mul( + x1_x2, + y1_y2, + zero, + EDWARDS_D, + BlsScalar::zero(), + BlsScalar::zero(), + None, + ); // x1y2 + y1x2 - let x_numerator = composer.add( - (BlsScalar::one(), x1_y2), - (BlsScalar::one(), y1_x2), + let zero = composer.constant_zero(); + let x_numerator = composer.gate_add( + x1_y2, + y1_x2, + zero, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); // y1y2 - a * x1x2 (a=-1) => y1y2 + x1x2 - let y_numerator = composer.add( - (BlsScalar::one(), y1_y2), - (BlsScalar::one(), x1_x2), + let y_numerator = composer.gate_add( + y1_y2, + x1_x2, + zero, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); // 1 + dx1x2y1y2 - let x_denominator = composer.add( - (BlsScalar::one(), d_x1_x2_y1_y2), - (BlsScalar::zero(), composer.zero()), + let x_denominator = composer.gate_add( + d_x1_x2_y1_y2, + zero, + zero, + BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), BlsScalar::one(), None, ); @@ -151,20 +212,28 @@ mod test { // Assert that we actually have the inverse // inv_x * x = 1 - composer.mul_gate( + composer.append_gate( x_denominator, inv_x_denom, - composer.zero(), + zero, + zero, BlsScalar::one(), BlsScalar::zero(), + BlsScalar::zero(), + BlsScalar::zero(), + BlsScalar::zero(), -BlsScalar::one(), None, ); // 1 - dx1x2y1y2 - let y_denominator = composer.add( - (-BlsScalar::one(), d_x1_x2_y1_y2), - (BlsScalar::zero(), composer.zero()), + let y_denominator = composer.gate_add( + d_x1_x2_y1_y2, + zero, + zero, + -BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), BlsScalar::one(), None, ); @@ -175,29 +244,38 @@ mod test { // Assert that we actually have the inverse // inv_y * y = 1 - composer.mul_gate( + composer.append_gate( y_denominator, inv_y_denom, - composer.zero(), + zero, + zero, BlsScalar::one(), BlsScalar::zero(), + BlsScalar::zero(), + BlsScalar::zero(), + BlsScalar::zero(), -BlsScalar::one(), None, ); // We can now use the inverses - let x_3 = composer.mul( - BlsScalar::one(), + let x_3 = composer.gate_mul( inv_x_denom, x_numerator, + zero, + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); - let y_3 = composer.mul( - BlsScalar::one(), + + let y_3 = composer.gate_mul( inv_y_denom, y_numerator, + zero, + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); @@ -218,7 +296,7 @@ mod test { let point_a = WitnessPoint { x, y }; let point_b = WitnessPoint { x, y }; - let point = composer.point_addition_gate(point_a, point_b); + let point = composer.gate_add_point(point_a, point_b); let point2 = classical_point_addition(composer, point_a, point_b); diff --git a/src/constraint_system/ecc/mod.rs b/src/constraint_system/ecc/mod.rs deleted file mode 100644 index e9ce54674..000000000 --- a/src/constraint_system/ecc/mod.rs +++ /dev/null @@ -1,189 +0,0 @@ -// 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. - -/// Curve addition gate -pub mod curve_addition; -/// Gates related to scalar multiplication -pub mod scalar_mul; - -use crate::constraint_system::{TurboComposer, Witness}; -use dusk_bls12_381::BlsScalar; -use dusk_jubjub::JubJubAffine; - -/// Represents a JubJub point in the circuit -#[derive(Debug, Clone, Copy)] -pub struct WitnessPoint { - x: Witness, - y: Witness, -} - -impl WitnessPoint { - /// Returns thes identity point. - pub fn identity(composer: &mut TurboComposer) -> WitnessPoint { - let one = composer.append_circuit_constant(BlsScalar::one()); - WitnessPoint { - x: composer.zero(), - y: one, - } - } - /// Return the X coordinate of the point - pub const fn x(&self) -> &Witness { - &self.x - } - - /// Return the Y coordinate of the point - pub const fn y(&self) -> &Witness { - &self.y - } -} - -impl TurboComposer { - /// Converts an JubJubAffine into a constraint system WitnessPoint - /// without constraining the values - pub fn add_affine(&mut self, affine: JubJubAffine) -> WitnessPoint { - let x = self.append_witness(affine.get_x()); - let y = self.append_witness(affine.get_y()); - WitnessPoint { x, y } - } - - /// Converts an JubJubAffine into a constraint system WitnessPoint - /// without constraining the values - pub fn add_public_affine( - &mut self, - affine: dusk_jubjub::JubJubAffine, - ) -> WitnessPoint { - let point = self.add_affine(affine); - self.constrain_to_constant( - point.x, - BlsScalar::zero(), - Some(-affine.get_x()), - ); - self.constrain_to_constant( - point.y, - BlsScalar::zero(), - Some(-affine.get_y()), - ); - - point - } - - /// Add the provided affine point as a circuit description and return its - /// constrained witness value - pub fn add_affine_to_circuit_description( - &mut self, - affine: dusk_jubjub::JubJubAffine, - ) -> WitnessPoint { - // Not using individual gates because one of these may be zero - let x = self.append_circuit_constant(affine.get_x()); - let y = self.append_circuit_constant(affine.get_y()); - - WitnessPoint { x, y } - } - - /// Asserts that a [`WitnessPoint`] in the circuit is equal to a known - /// public point. - pub fn assert_equal_public_point( - &mut self, - point: WitnessPoint, - public_point: dusk_jubjub::JubJubAffine, - ) { - self.constrain_to_constant( - point.x, - BlsScalar::zero(), - Some(-public_point.get_x()), - ); - self.constrain_to_constant( - point.y, - BlsScalar::zero(), - Some(-public_point.get_y()), - ); - } - /// Asserts that a point in the circuit is equal to another point in the - /// circuit - pub fn assert_equal_point( - &mut self, - point_a: WitnessPoint, - point_b: WitnessPoint, - ) { - self.assert_equal(point_a.x, point_b.x); - self.assert_equal(point_b.y, point_b.y); - } - - /// Adds to the circuit description the conditional selection of the - /// a point between two of them. - /// bit == 1 => point_a, - /// bit == 0 => point_b, - /// - /// # Note - /// The `bit` used as input which is a - /// [`Witness`] should had previously been constrained to be either 1 or 0 - /// using a bool constrain. See: [`TurboComposer::boolean_gate`]. - pub fn conditional_point_select( - &mut self, - point_a: WitnessPoint, - point_b: WitnessPoint, - bit: Witness, - ) -> WitnessPoint { - let x = self.conditional_select(bit, *point_a.x(), *point_b.x()); - let y = self.conditional_select(bit, *point_a.y(), *point_b.y()); - - WitnessPoint { x, y } - } - - /// Adds to the circuit description the conditional selection of the - /// identity point: - /// bit == 1 => value, - /// bit == 0 => 1, - /// - /// # Note - /// The `bit` used as input which is a [`Witness`] should had - /// previously been constrained to be either 1 or 0 using a bool - /// constrain. See: [`TurboComposer::boolean_gate`]. - fn conditional_select_identity( - &mut self, - bit: Witness, - point_b: WitnessPoint, - ) -> WitnessPoint { - let x = self.conditional_select_zero(bit, *point_b.x()); - let y = self.conditional_select_one(bit, *point_b.y()); - - WitnessPoint { x, y } - } -} - -#[cfg(feature = "std")] -#[cfg(test)] -mod tests { - use super::*; - use crate::constraint_system::helper::*; - - #[test] - fn test_conditional_select_point() { - let res = gadget_tester( - |composer| { - let bit_1 = composer.append_witness(BlsScalar::one()); - let bit_0 = composer.zero(); - - let point_a = WitnessPoint::identity(composer); - let point_b = WitnessPoint { - x: composer.append_witness(BlsScalar::from(10u64)), - y: composer.append_witness(BlsScalar::from(20u64)), - }; - - let choice = - composer.conditional_point_select(point_a, point_b, bit_1); - - composer.assert_equal_point(point_a, choice); - - let choice = - composer.conditional_point_select(point_a, point_b, bit_0); - composer.assert_equal_point(point_b, choice); - }, - 32, - ); - assert!(res.is_ok()); - } -} diff --git a/src/constraint_system/ecc/scalar_mul/mod.rs b/src/constraint_system/ecc/scalar_mul.rs similarity index 100% rename from src/constraint_system/ecc/scalar_mul/mod.rs rename to src/constraint_system/ecc/scalar_mul.rs diff --git a/src/constraint_system/ecc/scalar_mul/fixed_base.rs b/src/constraint_system/ecc/scalar_mul/fixed_base.rs index 0aed142fe..57461d8f6 100644 --- a/src/constraint_system/ecc/scalar_mul/fixed_base.rs +++ b/src/constraint_system/ecc/scalar_mul/fixed_base.rs @@ -27,19 +27,16 @@ fn compute_wnaf_point_multiples( } impl TurboComposer { - /// Adds an elliptic curve Scalar multiplication gate to the circuit - /// description. + /// Evaluate `jubjub · Generator` as a [`WitnessPoint`] /// - /// # Note - /// This function is optimized for fixed base ops **ONLY** and therefore, - /// the **ONLY** `generator` inputs that should be passed to this - /// function as inputs are [`dusk_jubjub::GENERATOR`] or - /// [`dusk_jubjub::GENERATOR_NUMS`]. - pub fn fixed_base_scalar_mul( + /// `generator` will be appended to the circuit description as constant + pub fn gate_mul_generator>( &mut self, - jubjub_scalar: Witness, - generator: JubJubExtended, + jubjub: Witness, + generator: P, ) -> WitnessPoint { + let generator = generator.into(); + // XXX: we can slice off 3 bits from the top of wnaf, since F_r prime // has 252 bits. XXX :We can also move to base4 and have half // the number of gates since wnaf adjacent entries product is @@ -49,16 +46,16 @@ impl TurboComposer { // compute 2^iG let mut point_multiples = compute_wnaf_point_multiples(generator, num_bits); + point_multiples.reverse(); // Fetch the raw scalar value as bls scalar, then convert to a jubjub // scalar XXX: Not very Tidy, impl From function in JubJub // This will panic if the JubJub scalar is not a jubjub scalar indeed // and was introduced as a BlsScalar. - let raw_jubjub_scalar = JubJubScalar::from_bytes( - &self.witnesses[&jubjub_scalar].to_bytes(), - ) - .unwrap(); + let raw_jubjub_scalar = + JubJubScalar::from_bytes(&self.witnesses[&jubjub].to_bytes()) + .unwrap(); // Convert scalar to wnaf_2(k) let wnaf_entries = raw_jubjub_scalar.compute_windowed_naf(2); @@ -104,9 +101,9 @@ impl TurboComposer { // We constrain the point accumulator to start from the Identity // point and the Scalar accumulator to start from zero if i == 0 { - self.constrain_to_constant(acc_x, BlsScalar::zero(), None); - self.constrain_to_constant(acc_y, BlsScalar::one(), None); - self.constrain_to_constant( + self.assert_equal_constant(acc_x, BlsScalar::zero(), None); + self.assert_equal_constant(acc_y, BlsScalar::one(), None); + self.assert_equal_constant( accumulated_bit, BlsScalar::zero(), None, @@ -139,11 +136,14 @@ impl TurboComposer { let acc_y = self.append_witness(point_acc[num_bits].get_y()); let last_accumulated_bit = self.append_witness(scalar_acc[num_bits]); - self.big_add_gate( + // FIXME this gate isn't verifying anything because all the selectors + // are zeroed. Validate what was the intent + self.append_gate( acc_x, acc_y, - self.zero(), - Some(last_accumulated_bit), + self.constant_zero(), + last_accumulated_bit, + BlsScalar::zero(), BlsScalar::zero(), BlsScalar::zero(), BlsScalar::zero(), @@ -154,7 +154,7 @@ impl TurboComposer { // Constrain the last element in the accumulator to be equal to the // input jubjub scalar - self.assert_equal(last_accumulated_bit, jubjub_scalar); + self.assert_equal(last_accumulated_bit, jubjub); WitnessPoint { x: acc_x, y: acc_y } } @@ -186,7 +186,7 @@ mod tests { (GENERATOR_EXTENDED * scalar).into(); let point_scalar = composer - .fixed_base_scalar_mul(secret_scalar, GENERATOR_EXTENDED); + .gate_mul_generator(secret_scalar, GENERATOR_EXTENDED); composer .assert_equal_public_point(point_scalar, expected_point); @@ -209,7 +209,7 @@ mod tests { (GENERATOR_EXTENDED * scalar).into(); let point_scalar = composer - .fixed_base_scalar_mul(secret_scalar, GENERATOR_EXTENDED); + .gate_mul_generator(secret_scalar, GENERATOR_EXTENDED); composer .assert_equal_public_point(point_scalar, expected_point); @@ -234,7 +234,7 @@ mod tests { let expected_point: JubJubAffine = (double_gen * scalar).into(); let point_scalar = composer - .fixed_base_scalar_mul(secret_scalar, GENERATOR_EXTENDED); + .gate_mul_generator(secret_scalar, GENERATOR_EXTENDED); composer .assert_equal_public_point(point_scalar, expected_point); @@ -272,7 +272,7 @@ mod tests { x: var_point_b_x, y: var_point_b_y, }; - let new_point = composer.point_addition_gate(point_a, point_b); + let new_point = composer.gate_add_point(point_a, point_b); composer.assert_equal_public_point( new_point, @@ -314,10 +314,8 @@ mod tests { // - One curve addition // // Scalar multiplications - let aG = - composer.fixed_base_scalar_mul(secret_scalar_a, point_a); - let bH = - composer.fixed_base_scalar_mul(secret_scalar_b, point_b); + let aG = composer.gate_mul_generator(secret_scalar_a, point_a); + let bH = composer.gate_mul_generator(secret_scalar_b, point_b); // Depending on the context, one can check if the resulting aG // and bH are as expected @@ -326,7 +324,7 @@ mod tests { composer.assert_equal_public_point(bH, c_b); // Curve addition - let commitment = composer.point_addition_gate(aG, bH); + let commitment = composer.gate_add_point(aG, bH); // Add final constraints to ensure that the commitment that we // computed is equal to the public point @@ -368,13 +366,13 @@ mod tests { let expected_rhs: JubJubAffine = (gen * (scalar_c + scalar_d)).into(); - let P1 = composer.fixed_base_scalar_mul(secret_scalar_a, gen); - let P2 = composer.fixed_base_scalar_mul(secret_scalar_b, gen); - let P3 = composer.fixed_base_scalar_mul(secret_scalar_c, gen); - let P4 = composer.fixed_base_scalar_mul(secret_scalar_d, gen); + let P1 = composer.gate_mul_generator(secret_scalar_a, gen); + let P2 = composer.gate_mul_generator(secret_scalar_b, gen); + let P3 = composer.gate_mul_generator(secret_scalar_c, gen); + let P4 = composer.gate_mul_generator(secret_scalar_d, gen); - let commitment_a = composer.point_addition_gate(P1, P2); - let commitment_b = composer.point_addition_gate(P3, P4); + let commitment_a = composer.gate_add_point(P1, P2); + let commitment_b = composer.gate_add_point(P3, P4); composer.assert_equal_point(commitment_a, commitment_b); diff --git a/src/constraint_system/ecc/scalar_mul/variable_base.rs b/src/constraint_system/ecc/scalar_mul/variable_base.rs index 11e73d9e5..e12851d08 100644 --- a/src/constraint_system/ecc/scalar_mul/variable_base.rs +++ b/src/constraint_system/ecc/scalar_mul/variable_base.rs @@ -9,13 +9,8 @@ use alloc::vec::Vec; use dusk_bls12_381::BlsScalar; impl TurboComposer { - /// Adds a variable-base scalar multiplication to the circuit description. - /// - /// # Note - /// If you're planning to multiply always by the generator of the Scalar - /// field, you should use [`TurboComposer::fixed_base_scalar_mul`] - /// which is optimized for fixed_base ops. - pub fn variable_base_scalar_mul( + /// Evaluate `jubjub · point` as a [`WitnessPoint`] + pub fn gate_mul_point( &mut self, jubjub: Witness, point: WitnessPoint, @@ -23,13 +18,14 @@ impl TurboComposer { // Turn scalar into bits let scalar_bits = self.scalar_decomposition(jubjub); - let identity = WitnessPoint::identity(self); + let identity = self.append_constant_identity(); let mut result = identity; for bit in scalar_bits.into_iter().rev() { - result = self.point_addition_gate(result, result); - let point_to_add = self.conditional_select_identity(bit, point); - result = self.point_addition_gate(result, point_to_add); + result = self.gate_add_point(result, result); + + let point_to_add = self.gate_select_identity(bit, point); + result = self.gate_add_point(result, point_to_add); } result @@ -37,25 +33,30 @@ impl TurboComposer { fn scalar_decomposition(&mut self, witness: Witness) -> Vec { // Decompose the bits - let scalar_bits = self.scalar_bit_decomposition(witness); + let scalar_bits = self.gate_decomposition(witness); // Take the first 252 bits let scalar_bits_witness = scalar_bits[..252].to_vec(); // Now ensure that the bits correctly accumulate to the witness given - let mut accumulator_witness = self.zero(); + let mut accumulator_witness = self.constant_zero(); let mut accumulator_scalar = BlsScalar::zero(); for (power, bit) in scalar_bits_witness.iter().enumerate() { - self.boolean_gate(*bit); + self.gate_boolean(*bit); let two_pow = BlsScalar::pow_of_2(power as u64); - let q_l_a = (two_pow, *bit); - let q_r_b = (BlsScalar::one(), accumulator_witness); - let q_c = BlsScalar::zero(); - - accumulator_witness = self.add(q_l_a, q_r_b, q_c, None); + accumulator_witness = self.gate_add( + *bit, + accumulator_witness, + self.constant_zero(), + two_pow, + BlsScalar::one(), + BlsScalar::zero(), + BlsScalar::zero(), + None, + ); accumulator_scalar += two_pow * self.witnesses[&scalar_bits[power]]; } @@ -92,10 +93,10 @@ mod tests { let expected_point: JubJubAffine = (JubJubExtended::from(GENERATOR) * scalar).into(); - let point = composer.add_affine(GENERATOR); + let point = composer.append_point(GENERATOR); let point_scalar = - composer.variable_base_scalar_mul(secret_scalar, point); + composer.gate_mul_point(secret_scalar, point); composer .assert_equal_public_point(point_scalar, expected_point); diff --git a/src/constraint_system/helper.rs b/src/constraint_system/helper.rs index bc22ab4c3..3007f10f4 100644 --- a/src/constraint_system/helper.rs +++ b/src/constraint_system/helper.rs @@ -5,7 +5,7 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use super::TurboComposer; -use crate::commitment_scheme::kzg10::PublicParameters; +use crate::commitment_scheme::PublicParameters; use crate::error::Error; use crate::plonkup::PlonkupTable4Arity; use crate::proof_system::{Prover, Verifier}; @@ -16,12 +16,17 @@ use rand_core::OsRng; pub(crate) fn dummy_gadget(n: usize, composer: &mut TurboComposer) { let one = BlsScalar::one(); let one = composer.append_witness(one); + let zero = composer.constant_zero(); for _ in 0..n { - composer.big_add( - (BlsScalar::one(), one), - (BlsScalar::one(), one), - None, + // FIXME dummy gates with zeroed selectors doesn't make sense + composer.gate_add( + one, + one, + zero, + BlsScalar::one(), + BlsScalar::one(), + BlsScalar::zero(), BlsScalar::zero(), None, ); @@ -30,16 +35,21 @@ pub(crate) fn dummy_gadget(n: usize, composer: &mut TurboComposer) { /// Adds dummy constraints using arithmetic gates pub(crate) fn dummy_gadget_plonkup(n: usize, composer: &mut TurboComposer) { + // FIXME duplicate of `dummy_gadget` for no clear reason let one = BlsScalar::one(); let one = composer.append_witness(one); + let zero = composer.constant_zero(); for _ in 0..n { - composer.big_add( - (BlsScalar::one(), one), - (BlsScalar::one(), one), - None, + composer.gate_add( + one, + one, + zero, + BlsScalar::one(), + BlsScalar::one(), BlsScalar::zero(), - Some(BlsScalar::zero()), + BlsScalar::zero(), + None, ); } } @@ -61,18 +71,18 @@ pub(crate) fn gadget_tester( prover.key_transcript(b"key", b"additional seed information"); // Add gadgets - gadget(&mut prover.mut_cs()); + gadget(&mut prover.composer_mut()); // Commit Key let (ck, _) = public_parameters - .trim(2 * prover.cs.circuit_size().next_power_of_two())?; + .trim(2 * prover.cs.constraints().next_power_of_two())?; // Preprocess circuit prover.preprocess(&ck)?; // Once the prove method is called, the public inputs are cleared // So pre-fetch these before calling Prove - let public_inputs = prover.cs.construct_dense_pi_vec(); + let public_inputs = prover.cs.into_dense_public_inputs(); // Compute Proof (prover.prove(&ck)?, public_inputs) @@ -86,11 +96,11 @@ pub(crate) fn gadget_tester( verifier.key_transcript(b"key", b"additional seed information"); // Add gadgets - gadget(&mut verifier.mut_cs()); + gadget(&mut verifier.composer_mut()); // Compute Commit and Verifier Key let (ck, vk) = public_parameters - .trim(verifier.cs.circuit_size().next_power_of_two())?; + .trim(verifier.cs.constraints().next_power_of_two())?; // Preprocess circuit verifier.preprocess(&ck)?; @@ -115,24 +125,24 @@ pub(crate) fn gadget_plonkup_tester( let mut prover = Prover::new(b"demo"); // Add lookup table to the composer - prover.mut_cs().append_lookup_table(&lookup_table); + prover.composer_mut().append_plonkup_table(&lookup_table); // Additionally key the transcript prover.key_transcript(b"key", b"additional seed information"); // Add gadgets - gadget(&mut prover.mut_cs()); + gadget(&mut prover.composer_mut()); // Commit Key let (ck, _) = public_parameters - .trim(2 * prover.cs.circuit_size().next_power_of_two())?; + .trim(2 * prover.cs.constraints().next_power_of_two())?; // Preprocess circuit prover.preprocess(&ck)?; // Once the prove method is called, the public inputs are cleared // So pre-fetch these before calling Prove - let public_inputs = prover.cs.construct_dense_pi_vec(); + let public_inputs = prover.cs.into_dense_public_inputs(); // Compute Proof (prover.prove(&ck)?, public_inputs) @@ -143,17 +153,17 @@ pub(crate) fn gadget_plonkup_tester( let mut verifier = Verifier::new(b"demo"); // Add lookup table to the composer - verifier.mut_cs().append_lookup_table(&lookup_table); + verifier.composer_mut().append_plonkup_table(&lookup_table); // Additionally key the transcript verifier.key_transcript(b"key", b"additional seed information"); // Add gadgets - gadget(&mut verifier.mut_cs()); + gadget(&mut verifier.composer_mut()); // Compute Commit and Verifier Key let (ck, vk) = public_parameters - .trim(verifier.cs.circuit_size().next_power_of_two())?; + .trim(verifier.cs.constraints().next_power_of_two())?; // Preprocess circuit verifier.preprocess(&ck)?; diff --git a/src/constraint_system/logic.rs b/src/constraint_system/logic.rs index 8573b0c32..195b7e2c8 100644 --- a/src/constraint_system/logic.rs +++ b/src/constraint_system/logic.rs @@ -19,9 +19,9 @@ impl TurboComposer { /// perform the whole operation. /// /// ## Selector - /// - is_xor_gate = 1 -> Performs XOR between the first `num_bits` for `a` + /// - is_gate_xor = 1 -> Performs XOR between the first `num_bits` for `a` /// and `b`. - /// - is_xor_gate = 0 -> Performs AND between the first `num_bits` for `a` + /// - is_gate_xor = 0 -> Performs AND between the first `num_bits` for `a` /// and `b`. /// /// # Panics @@ -32,7 +32,7 @@ impl TurboComposer { a: Witness, b: Witness, num_bits: usize, - is_xor_gate: bool, + is_gate_xor: bool, ) -> Witness { // Since we work on base4, we need to guarantee that we have an even // number of bits representing the greatest input. @@ -74,14 +74,16 @@ impl TurboComposer { // Now we can add the first row as: `| 0 | 0 | -- | 0 |`. // Note that `w_1` will be set on the first loop iteration. self.perm - .add_variable_to_map(self.zero_var, WireData::Left(self.n)); + .add_variable_to_map(self.constant_zero(), WireData::Left(self.n)); self.perm - .add_variable_to_map(self.zero_var, WireData::Right(self.n)); - self.perm - .add_variable_to_map(self.zero_var, WireData::Fourth(self.n)); - self.w_l.push(self.zero_var); - self.w_r.push(self.zero_var); - self.w_4.push(self.zero_var); + .add_variable_to_map(self.constant_zero(), WireData::Right(self.n)); + self.perm.add_variable_to_map( + self.constant_zero(), + WireData::Fourth(self.n), + ); + self.w_l.push(self.constant_zero()); + self.w_r.push(self.constant_zero()); + self.w_4.push(self.constant_zero()); // Increase the gate index so we can add the following rows in the // correct order. self.n += 1; @@ -115,7 +117,7 @@ impl TurboComposer { // The `out_quad` is the result of the bitwise ops `&` or `^` // between the left and right quads. The op is decided // with a boolean flag set as input of the function. - let out_quad_fr = match is_xor_gate { + let out_quad_fr = match is_gate_xor { true => BlsScalar::from((left_quad ^ right_quad) as u64), false => BlsScalar::from((left_quad & right_quad) as u64), }; @@ -218,9 +220,11 @@ impl TurboComposer { // ahead. To fix this, we simply pad with a 0 so the last row of // the program memory will look like this: // | an | bn | --- | cn | - self.perm - .add_variable_to_map(self.zero_var, WireData::Output(self.n - 1)); - self.w_o.push(self.zero_var); + self.perm.add_variable_to_map( + self.constant_zero(), + WireData::Output(self.n - 1), + ); + self.w_o.push(self.constant_zero()); // Now the wire values are set for each gate, indexed and mapped in the // `variable_map` inside of the `Permutation` struct. @@ -237,7 +241,7 @@ impl TurboComposer { self.q_fixed_group_add.push(BlsScalar::zero()); self.q_variable_group_add.push(BlsScalar::zero()); self.q_lookup.push(BlsScalar::zero()); - match is_xor_gate { + match is_gate_xor { true => { self.q_c.push(-BlsScalar::one()); self.q_logic.push(-BlsScalar::one()); @@ -304,7 +308,7 @@ impl TurboComposer { /// # Panics /// /// If the `num_bits` specified in the fn params is odd. - pub fn xor_gate( + pub fn gate_xor( &mut self, a: Witness, b: Witness, @@ -320,7 +324,7 @@ impl TurboComposer { /// # Panics /// /// If the `num_bits` specified in the fn params is odd. - pub fn and_gate( + pub fn gate_and( &mut self, a: Witness, b: Witness, @@ -345,9 +349,9 @@ mod tests { composer.append_witness(BlsScalar::from(500u64)); let witness_b = composer.append_witness(BlsScalar::from(357u64)); - let xor_res = composer.xor_gate(witness_a, witness_b, 10); + let xor_res = composer.gate_xor(witness_a, witness_b, 10); // Check that the XOR result is indeed what we are expecting. - composer.constrain_to_constant( + composer.assert_equal_constant( xor_res, BlsScalar::from(500u64 ^ 357u64), None, @@ -364,9 +368,9 @@ mod tests { composer.append_witness(BlsScalar::from(469u64)); let witness_b = composer.append_witness(BlsScalar::from(321u64)); - let xor_res = composer.and_gate(witness_a, witness_b, 10); + let xor_res = composer.gate_and(witness_a, witness_b, 10); // Check that the AND result is indeed what we are expecting. - composer.constrain_to_constant( + composer.assert_equal_constant( xor_res, BlsScalar::from(469u64 & 321u64), None, @@ -383,9 +387,9 @@ mod tests { let witness_a = composer.append_witness(BlsScalar::from(139u64)); let witness_b = composer.append_witness(BlsScalar::from(33u64)); - let xor_res = composer.xor_gate(witness_a, witness_b, 10); + let xor_res = composer.gate_xor(witness_a, witness_b, 10); // Check that the XOR result is indeed what we are expecting. - composer.constrain_to_constant( + composer.assert_equal_constant( xor_res, BlsScalar::from(139u64 & 33u64), None, @@ -402,9 +406,9 @@ mod tests { composer.append_witness(BlsScalar::from(256u64)); let witness_b = composer.append_witness(BlsScalar::from(235u64)); - let xor_res = composer.xor_gate(witness_a, witness_b, 2); + let xor_res = composer.gate_xor(witness_a, witness_b, 2); // Check that the XOR result is indeed what we are expecting. - composer.constrain_to_constant( + composer.assert_equal_constant( xor_res, BlsScalar::from(256 ^ 235), None, @@ -425,9 +429,9 @@ mod tests { composer.append_witness(BlsScalar::from(500u64)); let witness_b = composer.append_witness(BlsScalar::from(499u64)); - let xor_res = composer.xor_gate(witness_a, witness_b, 9); + let xor_res = composer.gate_xor(witness_a, witness_b, 9); // Check that the XOR result is indeed what we are expecting. - composer.constrain_to_constant( + composer.assert_equal_constant( xor_res, BlsScalar::from(7u64), None, diff --git a/src/constraint_system/range.rs b/src/constraint_system/range.rs index e7240b622..c86566856 100644 --- a/src/constraint_system/range.rs +++ b/src/constraint_system/range.rs @@ -21,14 +21,14 @@ impl TurboComposer { ///# Panics /// This function will panic if the num_bits specified is not even, ie. /// `num_bits % 2 != 0`. - pub fn range_gate(&mut self, witness: Witness, num_bits: usize) { + pub fn gate_range(&mut self, witness: Witness, num_bits: usize) { // Adds `variable` into the appropriate witness position // based on the accumulator number a_i let add_wire = |composer: &mut TurboComposer, i: usize, witness: Witness| { // Since four quads can fit into one gate, the gate index does // not change for every four wires - let gate_index = composer.circuit_size() + (i / 4); + let gate_index = composer.constraints() + (i / 4); let wire_data = match i % 4 { 0 => { @@ -139,7 +139,7 @@ impl TurboComposer { // First we pad our gates by the necessary amount for i in 0..pad { - add_wire(self, i, self.zero()); + add_wire(self, i, self.constant_zero()); } for i in pad..=num_quads { @@ -182,9 +182,9 @@ impl TurboComposer { // wire, which will be used in the gate before it // Furthermore, we set the left, right and output wires to zero *self.q_range.last_mut().unwrap() = BlsScalar::zero(); - self.w_l.push(self.zero_var); - self.w_r.push(self.zero_var); - self.w_o.push(self.zero_var); + self.w_l.push(self.constant_zero()); + self.w_r.push(self.constant_zero()); + self.w_o.push(self.constant_zero()); // Lastly, we must link the last accumulator value to the initial // witness This last constraint will pass as long as @@ -209,7 +209,7 @@ mod tests { let witness = composer.append_witness(BlsScalar::from( (u32::max_value() as u64) + 1, )); - composer.range_gate(witness, 32); + composer.gate_range(witness, 32); }, 200, ); @@ -220,7 +220,7 @@ mod tests { |composer| { let witness = composer.append_witness(BlsScalar::from(u64::max_value())); - composer.range_gate(witness, 32); + composer.gate_range(witness, 32); }, 200, ); @@ -231,7 +231,7 @@ mod tests { |composer| { let witness = composer.append_witness(BlsScalar::from(2u64.pow(34) - 1)); - composer.range_gate(witness, 34); + composer.gate_range(witness, 34); }, 200, ); @@ -246,7 +246,7 @@ mod tests { |composer| { let witness = composer .append_witness(BlsScalar::from(u32::max_value() as u64)); - composer.range_gate(witness, 33); + composer.gate_range(witness, 33); }, 200, ); diff --git a/src/constraint_system/witness.rs b/src/constraint_system/witness.rs index 0346f1b2d..feeb873bd 100644 --- a/src/constraint_system/witness.rs +++ b/src/constraint_system/witness.rs @@ -23,7 +23,7 @@ pub(crate) enum WireData { Fourth(usize), } -/// Witness data indexed in a [`super::TurboComposer`] instance +/// Witness data indexed in a [`TurboComposer`](super::TurboComposer) instance #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct Witness { index: usize, diff --git a/src/fft/mod.rs b/src/fft.rs similarity index 91% rename from src/fft/mod.rs rename to src/fft.rs index f6932e56a..9bbcb6e59 100644 --- a/src/fft/mod.rs +++ b/src/fft.rs @@ -11,14 +11,14 @@ cfg_if::cfg_if!( if #[cfg(feature = "alloc")] { - #[allow(unused_imports)] - pub(crate) use domain::alloc::*; pub(crate) mod evaluations; pub(crate) mod polynomial; + pub(crate) use evaluations::Evaluations; pub(crate) use polynomial::Polynomial; }); pub(crate) mod domain; + #[allow(unused_imports)] pub(crate) use domain::EvaluationDomain; diff --git a/src/lib.rs b/src/lib.rs index 245a4b6d8..36c774694 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,29 +53,29 @@ #![allow(clippy::too_many_arguments)] #![deny(rustdoc::broken_intra_doc_links)] #![deny(missing_docs)] -#![no_std] - -#[cfg(feature = "std")] -extern crate std; +#![cfg_attr(not(feature = "std"), no_std)] cfg_if::cfg_if!( if #[cfg(feature = "alloc")] { - #[macro_use] + #[cfg_attr(not(feature = "std"), macro_use)] extern crate alloc; - pub mod constraint_system; + mod bit_iterator; - pub mod circuit; - mod util; mod permutation; + mod util; + + pub mod circuit; + pub mod constraint_system; + pub mod plonkup; }); +mod fft; +mod transcript; + pub mod commitment_scheme; pub mod error; -mod fft; -pub mod plonkup; pub mod prelude; pub mod proof_system; -mod transcript; #[doc = include_str!("../docs/notes-intro.md")] pub mod notes { @@ -89,8 +89,5 @@ pub mod notes { pub mod kzg10_docs {} } -/// Re-exported dusk-bls12_381 fork. pub use dusk_bls12_381 as bls12_381; - -/// Re-exported dusk-jubjub fork. pub use dusk_jubjub as jubjub; diff --git a/src/permutation/mod.rs b/src/permutation.rs similarity index 100% rename from src/permutation/mod.rs rename to src/permutation.rs diff --git a/src/permutation/permutation.rs b/src/permutation/permutation.rs index fd0a609a8..7dde67d70 100644 --- a/src/permutation/permutation.rs +++ b/src/permutation/permutation.rs @@ -31,9 +31,9 @@ impl Permutation { } /// Creates a Permutation struct with an expected capacity of `n`. - pub(crate) fn with_capacity(expected_size: usize) -> Permutation { + pub(crate) fn with_capacity(size: usize) -> Permutation { Permutation { - variable_map: HashMap::with_capacity(expected_size), + variable_map: HashMap::with_capacity(size), } } @@ -808,7 +808,7 @@ mod test { #[test] fn test_multizip_permutation_poly() { - let mut cs = TurboComposer::with_expected_size(4); + let mut cs = TurboComposer::with_size(4); let x1 = cs.append_witness(BlsScalar::from_raw([4, 0, 0, 0])); let x2 = cs.append_witness(BlsScalar::from_raw([12, 0, 0, 0])); @@ -818,20 +818,21 @@ mod test { let zero = BlsScalar::zero(); let one = BlsScalar::one(); let two = BlsScalar::from_raw([2, 0, 0, 0]); + let z = cs.constant_zero(); // x1 * x4 = x2 - cs.poly_gate(x1, x4, x2, one, zero, zero, -one, zero, None); + cs.append_gate(x1, x4, x2, z, one, zero, zero, -one, zero, zero, None); // x1 + x3 = x2 - cs.poly_gate(x1, x3, x2, zero, one, one, -one, zero, None); + cs.append_gate(x1, x3, x2, z, zero, one, one, -one, zero, zero, None); // x1 + x2 = 2*x3 - cs.poly_gate(x1, x2, x3, zero, one, one, -two, zero, None); + cs.append_gate(x1, x2, x3, z, zero, one, one, -two, zero, zero, None); // x3 * x4 = 2*x2 - cs.poly_gate(x3, x4, x2, one, zero, zero, -two, zero, None); + cs.append_gate(x3, x4, x2, z, one, zero, zero, -two, zero, zero, None); - let domain = EvaluationDomain::new(cs.circuit_size()).unwrap(); + let domain = EvaluationDomain::new(cs.constraints()).unwrap(); let pad = vec![BlsScalar::zero(); domain.size() - cs.w_l.len()]; let mut w_l_scalar: Vec = cs.w_l.iter().map(|v| cs.witnesses[v]).collect(); diff --git a/src/plonkup/mod.rs b/src/plonkup.rs similarity index 52% rename from src/plonkup/mod.rs rename to src/plonkup.rs index 07cd7530a..84173f68a 100644 --- a/src/plonkup/mod.rs +++ b/src/plonkup.rs @@ -11,19 +11,13 @@ //! output of gates within a circuit, without //! computing them. -cfg_if::cfg_if!( - if #[cfg(feature = "alloc")] { - /// Multiset definition - pub mod multiset; +pub(crate) mod multiset; +pub(crate) mod table; - /// Arity-4 table - pub mod table; - - pub use multiset::MultiSet; - pub use table::{ - lookup_table::{PlonkupTable3Arity, PlonkupTable4Arity}, - preprocess::{PreprocessedTable3Arity, PreprocessedTable4Arity}, - witness_table::{WitnessTable3Arity, WitnessTable4Arity}, - }; - } -); +pub use multiset::MultiSet; +pub use table::hash_tables::constants; +pub use table::{ + lookup_table::{PlonkupTable3Arity, PlonkupTable4Arity}, + preprocess::{PreprocessedTable3Arity, PreprocessedTable4Arity}, + witness_table::{WitnessTable3Arity, WitnessTable4Arity}, +}; diff --git a/src/plonkup/plonkup.rs b/src/plonkup/plonkup.rs deleted file mode 100644 index 3ccbe550f..000000000 --- a/src/plonkup/plonkup.rs +++ /dev/null @@ -1,72 +0,0 @@ -// 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. - -//! Contains the functionality of plonkup gates on top of the composer - -#![allow(clippy::too_many_arguments)] - -use crate::constraint_system::TurboComposer; -use crate::constraint_system::Witness; -use dusk_bls12_381::BlsScalar; - -impl TurboComposer { - /// Adds a plonkup gate to the circuit with its corresponding - /// constraints. - /// - /// This type of gate is usually used when we need to have - /// the largest amount of performance and the minimum circuit-size - /// possible. Since it allows the end-user to set every selector coefficient - /// as scaling value on the gate eq. - pub fn plonkup_gate( - &mut self, - a: Witness, - b: Witness, - c: Witness, - d: Option, - q_l: BlsScalar, - q_r: BlsScalar, - q_o: BlsScalar, - q_4: BlsScalar, - q_c: BlsScalar, - pi: BlsScalar, - ) -> Witness { - // Check if advice wire has a value - let d = match d { - Some(witness) => witness, - None => self.zero_var, - }; - - self.w_l.push(a); - self.w_r.push(b); - self.w_o.push(c); - self.w_4.push(d); - - // Add selector vectors - self.q_l.push(q_l); - self.q_r.push(q_r); - self.q_o.push(q_o); - self.q_c.push(q_c); - self.q_4.push(q_4); - self.q_arith.push(BlsScalar::zero()); - self.q_m.push(BlsScalar::zero()); - self.q_range.push(BlsScalar::zero()); - self.q_logic.push(BlsScalar::zero()); - self.q_fixed_group_add.push(BlsScalar::zero()); - self.q_variable_group_add.push(BlsScalar::zero()); - - // For a lookup gate, only one selector poly is - // turned on as the output is inputted directly - self.q_lookup.push(BlsScalar::one()); - - self.public_inputs.push(pi); - - self.perm.add_variables_to_map(a, b, c, d, self.n); - - self.n += 1; - - c - } -} diff --git a/src/plonkup/table/mod.rs b/src/plonkup/table.rs similarity index 100% rename from src/plonkup/table/mod.rs rename to src/plonkup/table.rs diff --git a/src/plonkup/table/hash_tables/mod.rs b/src/plonkup/table/hash_tables.rs similarity index 100% rename from src/plonkup/table/hash_tables/mod.rs rename to src/plonkup/table/hash_tables.rs diff --git a/src/plonkup/table/preprocess.rs b/src/plonkup/table/preprocess.rs index 31b4f0408..180be14d6 100644 --- a/src/plonkup/table/preprocess.rs +++ b/src/plonkup/table/preprocess.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::commitment_scheme::kzg10::{CommitKey, Commitment}; +use crate::commitment_scheme::{CommitKey, Commitment}; use crate::error::Error; use crate::fft::{EvaluationDomain, Polynomial}; use crate::plonkup::{MultiSet, PlonkupTable3Arity, PlonkupTable4Arity}; diff --git a/src/prelude.rs b/src/prelude.rs index 11d858bbf..1ecdaded8 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -12,22 +12,12 @@ #[cfg(feature = "alloc")] pub use crate::{ circuit::{self, Circuit, PublicInputValue, VerifierData}, - commitment_scheme::kzg10::{ - key::{CommitKey, OpeningKey}, - PublicParameters, - }, + commitment_scheme::{CommitKey, OpeningKey, PublicParameters}, constraint_system::{TurboComposer, Witness, WitnessPoint}, proof_system::{Prover, ProverKey, Verifier}, }; +pub use crate::error::Error; pub use crate::proof_system::{Proof, VerifierKey}; - -/// Re-exported [`dusk-bls12_381::BlsScalar`]. pub use dusk_bls12_381::BlsScalar; - -/// Re-exported [`dusk-jubjub::JubJubScalar`] & -/// [`dusk-jubjub::JubJubAffine`]. -pub use dusk_jubjub::{JubJubAffine, JubJubScalar}; - -/// Collection of errors that the library exposes/uses. -pub use crate::error::Error; +pub use dusk_jubjub::{JubJubAffine, JubJubExtended, JubJubScalar}; diff --git a/src/proof_system/mod.rs b/src/proof_system.rs similarity index 70% rename from src/proof_system/mod.rs rename to src/proof_system.rs index c0b557279..ffff10c07 100644 --- a/src/proof_system/mod.rs +++ b/src/proof_system.rs @@ -6,24 +6,23 @@ //! Proving system +pub(crate) mod linearisation_poly; +pub(crate) mod proof; +pub(crate) mod widget; + cfg_if::cfg_if!( if #[cfg(feature = "alloc")] { mod preprocess; - /// Represents a PLONK Prover - pub mod prover; - pub use proof::alloc::*; + pub(crate) mod quotient_poly; - /// Represents a PLONK Verifier - pub mod verifier; + pub(crate) mod prover; + pub(crate) mod verifier; + pub use prover::Prover; pub use verifier::Verifier; - pub use widget::alloc::*; + pub use widget::alloc::ProverKey; } ); -/// Represents a PLONK Proof -pub mod proof; -pub(crate) mod widget; pub use proof::Proof; pub use widget::VerifierKey; -pub(crate) mod linearisation_poly; diff --git a/src/proof_system/preprocess.rs b/src/proof_system/preprocess.rs index 6b2612a37..1b23b3074 100644 --- a/src/proof_system/preprocess.rs +++ b/src/proof_system/preprocess.rs @@ -6,7 +6,7 @@ //! Methods to preprocess the constraint system for use in a proof -use crate::commitment_scheme::kzg10::CommitKey; +use crate::commitment_scheme::CommitKey; use crate::constraint_system::TurboComposer; use crate::plonkup::PreprocessedTable4Arity; @@ -46,7 +46,7 @@ impl TurboComposer { fn pad(&mut self, diff: usize) { // Add a zero variable to circuit let zero_scalar = BlsScalar::zero(); - let zero_var = self.zero_var; + let zero_var = self.constant_zero(); let zeroes_scalar = vec![zero_scalar; diff]; let zeroes_var = vec![zero_var; diff]; @@ -103,7 +103,7 @@ impl TurboComposer { /// Although the prover does not need the verification key, he must compute /// the commitments in order to seed the transcript, allowing both the /// prover and verifier to have the same view - pub fn preprocess_prover( + pub(crate) fn preprocess_prover( &mut self, commit_key: &CommitKey, transcript: &mut Transcript, @@ -296,7 +296,7 @@ impl TurboComposer { /// The verifier only requires the commitments in order to verify a /// [`Proof`](super::Proof) We can therefore speed up preprocessing for the /// verifier by skipping the FFTs needed to compute the 4n evaluations. - pub fn preprocess_verifier( + pub(crate) fn preprocess_verifier( &mut self, commit_key: &CommitKey, transcript: &mut Transcript, @@ -448,7 +448,7 @@ impl TurboComposer { }; let verifier_key = widget::VerifierKey { - n: self.circuit_size(), + n: self.constraints(), arithmetic: arithmetic_verifier_key, logic: logic_verifier_key, range: range_verifier_key, diff --git a/src/proof_system/proof.rs b/src/proof_system/proof.rs index 1a1b280a8..6f9e4eb58 100644 --- a/src/proof_system/proof.rs +++ b/src/proof_system/proof.rs @@ -11,7 +11,7 @@ //! `Proof` structure and it's methods. use super::linearisation_poly::ProofEvaluations; -use crate::commitment_scheme::kzg10::Commitment; +use crate::commitment_scheme::Commitment; use dusk_bytes::{DeserializableSlice, Serializable}; /// A Proof is a composition of `Commitment`s to the Witness, Permutation, @@ -143,7 +143,7 @@ impl Serializable<{ 15 * Commitment::SIZE + ProofEvaluations::SIZE }> pub(crate) mod alloc { use super::*; use crate::{ - commitment_scheme::kzg10::{AggregateProof, OpeningKey}, + commitment_scheme::{AggregateProof, OpeningKey}, error::Error, fft::EvaluationDomain, proof_system::widget::VerifierKey, diff --git a/src/proof_system/prover.rs b/src/proof_system/prover.rs index 370a45f04..f86ec4563 100644 --- a/src/proof_system/prover.rs +++ b/src/proof_system/prover.rs @@ -5,7 +5,7 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use crate::{ - commitment_scheme::kzg10::CommitKey, + commitment_scheme::CommitKey, constraint_system::{TurboComposer, Witness}, error::Error, fft::{EvaluationDomain, Polynomial}, @@ -33,8 +33,8 @@ pub struct Prover { } impl Prover { - /// Returns a mutable copy of the underlying [`TurboComposer`]. - pub fn mut_cs(&mut self) -> &mut TurboComposer { + /// Mutable borrow of [`TurboComposer`]. + pub fn composer_mut(&mut self) -> &mut TurboComposer { &mut self.cs } @@ -68,19 +68,20 @@ impl Prover { } /// Creates a new `Prover` object with some expected size. - pub fn with_expected_size(label: &'static [u8], size: usize) -> Prover { + pub fn with_size(label: &'static [u8], size: usize) -> Prover { Prover { prover_key: None, - cs: TurboComposer::with_expected_size(size), + cs: TurboComposer::with_size(size), preprocessed_transcript: Transcript::new(label), } } /// Returns the number of gates in the circuit thet the `Prover` actually /// stores inside. - pub fn circuit_size(&self) -> usize { - self.cs.circuit_size() + pub const fn constraints(&self) -> usize { + self.cs.constraints() } + /// Split `t(X)` poly into 4 degree `n` polynomials. pub(crate) fn split_tx_poly( &self, @@ -158,7 +159,7 @@ impl Prover { // make sure the domain is big enough to handle the circuit as well as // the lookup table let domain = EvaluationDomain::new(core::cmp::max( - self.cs.circuit_size(), + self.cs.constraints(), self.cs.lookup_table.0.len(), ))?; @@ -306,7 +307,7 @@ impl Prover { // 3. Compute public inputs polynomial let pi_poly = Polynomial::from_coefficients_vec( - domain.ifft(&self.cs.construct_dense_pi_vec()), + domain.ifft(&self.cs.into_dense_public_inputs()), ); // Compute evaluation challenge; `z` diff --git a/src/proof_system/verifier.rs b/src/proof_system/verifier.rs index 8d3eb2870..7ac767907 100644 --- a/src/proof_system/verifier.rs +++ b/src/proof_system/verifier.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::commitment_scheme::kzg10::{CommitKey, OpeningKey}; +use crate::commitment_scheme::{CommitKey, OpeningKey}; use crate::constraint_system::TurboComposer; use crate::error::Error; use crate::proof_system::widget::VerifierKey; @@ -44,21 +44,21 @@ impl Verifier { } /// Creates a new `Verifier` instance with some expected size. - pub fn with_expected_size(label: &'static [u8], size: usize) -> Verifier { + pub fn with_size(label: &'static [u8], size: usize) -> Verifier { Verifier { verifier_key: None, - cs: TurboComposer::with_expected_size(size), + cs: TurboComposer::with_size(size), preprocessed_transcript: Transcript::new(label), } } /// Returns the number of gates in the circuit. - pub fn circuit_size(&self) -> usize { - self.cs.circuit_size() + pub const fn constraints(&self) -> usize { + self.cs.constraints() } - /// Returns a mutable copy of the underlying composer. - pub fn mut_cs(&mut self) -> &mut TurboComposer { + /// Mutable borrow of the [`TurboComposer`]. + pub fn composer_mut(&mut self) -> &mut TurboComposer { &mut self.cs } diff --git a/src/proof_system/widget/mod.rs b/src/proof_system/widget.rs similarity index 99% rename from src/proof_system/widget/mod.rs rename to src/proof_system/widget.rs index 35e96f97d..74a7e408c 100644 --- a/src/proof_system/widget/mod.rs +++ b/src/proof_system/widget.rs @@ -4,14 +4,15 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. +use crate::commitment_scheme::Commitment; +use dusk_bytes::{DeserializableSlice, Serializable}; + pub mod arithmetic; pub mod ecc; pub mod logic; pub mod lookup; pub mod permutation; pub mod range; -use crate::commitment_scheme::kzg10::Commitment; -use dusk_bytes::{DeserializableSlice, Serializable}; /// PLONK circuit Verification Key. /// @@ -102,7 +103,7 @@ impl Serializable<{ 20 * Commitment::SIZE + u64::SIZE }> for VerifierKey { impl VerifierKey { /// Returns the Circuit size padded to the next power of two. - pub const fn padded_circuit_size(&self) -> usize { + pub const fn padded_constraints(&self) -> usize { self.n.next_power_of_two() } @@ -769,7 +770,7 @@ mod test { #[test] fn test_serialise_deserialise_verifier_key() { - use crate::commitment_scheme::kzg10::Commitment; + use crate::commitment_scheme::Commitment; use dusk_bls12_381::G1Affine; let n = 2usize.pow(5); diff --git a/src/proof_system/widget/arithmetic/mod.rs b/src/proof_system/widget/arithmetic.rs similarity index 100% rename from src/proof_system/widget/arithmetic/mod.rs rename to src/proof_system/widget/arithmetic.rs diff --git a/src/proof_system/widget/arithmetic/verifierkey.rs b/src/proof_system/widget/arithmetic/verifierkey.rs index 5863c3124..d2e930984 100644 --- a/src/proof_system/widget/arithmetic/verifierkey.rs +++ b/src/proof_system/widget/arithmetic/verifierkey.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::commitment_scheme::kzg10::Commitment; +use crate::commitment_scheme::Commitment; use dusk_bytes::{DeserializableSlice, Serializable}; #[derive(Debug, PartialEq, Eq, Copy, Clone)] diff --git a/src/proof_system/widget/ecc/mod.rs b/src/proof_system/widget/ecc.rs similarity index 100% rename from src/proof_system/widget/ecc/mod.rs rename to src/proof_system/widget/ecc.rs diff --git a/src/proof_system/widget/ecc/curve_addition/mod.rs b/src/proof_system/widget/ecc/curve_addition.rs similarity index 100% rename from src/proof_system/widget/ecc/curve_addition/mod.rs rename to src/proof_system/widget/ecc/curve_addition.rs diff --git a/src/proof_system/widget/ecc/curve_addition/verifierkey.rs b/src/proof_system/widget/ecc/curve_addition/verifierkey.rs index 20f0185c7..0e69b8103 100644 --- a/src/proof_system/widget/ecc/curve_addition/verifierkey.rs +++ b/src/proof_system/widget/ecc/curve_addition/verifierkey.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::commitment_scheme::kzg10::Commitment; +use crate::commitment_scheme::Commitment; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub(crate) struct VerifierKey { diff --git a/src/proof_system/widget/ecc/scalar_mul/mod.rs b/src/proof_system/widget/ecc/scalar_mul.rs similarity index 100% rename from src/proof_system/widget/ecc/scalar_mul/mod.rs rename to src/proof_system/widget/ecc/scalar_mul.rs diff --git a/src/proof_system/widget/ecc/scalar_mul/fixed_base/mod.rs b/src/proof_system/widget/ecc/scalar_mul/fixed_base.rs similarity index 100% rename from src/proof_system/widget/ecc/scalar_mul/fixed_base/mod.rs rename to src/proof_system/widget/ecc/scalar_mul/fixed_base.rs diff --git a/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs b/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs index 5f11a1666..766afbdae 100644 --- a/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs +++ b/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::commitment_scheme::kzg10::Commitment; +use crate::commitment_scheme::Commitment; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub(crate) struct VerifierKey { diff --git a/src/proof_system/widget/logic/mod.rs b/src/proof_system/widget/logic.rs similarity index 100% rename from src/proof_system/widget/logic/mod.rs rename to src/proof_system/widget/logic.rs diff --git a/src/proof_system/widget/logic/verifierkey.rs b/src/proof_system/widget/logic/verifierkey.rs index 75faeb436..979180e2b 100644 --- a/src/proof_system/widget/logic/verifierkey.rs +++ b/src/proof_system/widget/logic/verifierkey.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::commitment_scheme::kzg10::Commitment; +use crate::commitment_scheme::Commitment; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub(crate) struct VerifierKey { diff --git a/src/proof_system/widget/lookup/mod.rs b/src/proof_system/widget/lookup.rs similarity index 100% rename from src/proof_system/widget/lookup/mod.rs rename to src/proof_system/widget/lookup.rs diff --git a/src/proof_system/widget/lookup/verifierkey.rs b/src/proof_system/widget/lookup/verifierkey.rs index 3b657ff05..ac3238ee3 100644 --- a/src/proof_system/widget/lookup/verifierkey.rs +++ b/src/proof_system/widget/lookup/verifierkey.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::commitment_scheme::kzg10::Commitment; +use crate::commitment_scheme::Commitment; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct VerifierKey { diff --git a/src/proof_system/widget/permutation/mod.rs b/src/proof_system/widget/permutation.rs similarity index 100% rename from src/proof_system/widget/permutation/mod.rs rename to src/proof_system/widget/permutation.rs diff --git a/src/proof_system/widget/permutation/verifierkey.rs b/src/proof_system/widget/permutation/verifierkey.rs index cdb40ddc4..9731dcffa 100644 --- a/src/proof_system/widget/permutation/verifierkey.rs +++ b/src/proof_system/widget/permutation/verifierkey.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::commitment_scheme::kzg10::Commitment; +use crate::commitment_scheme::Commitment; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub(crate) struct VerifierKey { diff --git a/src/proof_system/widget/range/mod.rs b/src/proof_system/widget/range.rs similarity index 100% rename from src/proof_system/widget/range/mod.rs rename to src/proof_system/widget/range.rs diff --git a/src/proof_system/widget/range/verifierkey.rs b/src/proof_system/widget/range/verifierkey.rs index 3f5b093c7..0bc091aaf 100644 --- a/src/proof_system/widget/range/verifierkey.rs +++ b/src/proof_system/widget/range/verifierkey.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::commitment_scheme::kzg10::Commitment; +use crate::commitment_scheme::Commitment; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub(crate) struct VerifierKey { diff --git a/src/transcript.rs b/src/transcript.rs index 7d5d271d6..37a73a3d7 100644 --- a/src/transcript.rs +++ b/src/transcript.rs @@ -6,7 +6,7 @@ //! This is an extension over the [Merlin Transcript](Transcript) //! which adds a few extra functionalities. -use crate::commitment_scheme::kzg10::Commitment; +use crate::commitment_scheme::Commitment; use dusk_bls12_381::BlsScalar; use dusk_bytes::Serializable; use merlin::Transcript;