From 8bb624f286daa24db2fcf6c7d8429541dc58edc8 Mon Sep 17 00:00:00 2001 From: moana Date: Thu, 16 Mar 2023 17:27:12 +0100 Subject: [PATCH] Add and refactor tests for decomposition component Resolves: #738 --- src/composer.rs | 8 +- tests/decomposition.rs | 161 ++++++++++++++++++++++++++--------------- 2 files changed, 107 insertions(+), 62 deletions(-) diff --git a/src/composer.rs b/src/composer.rs index d64dad57..f57ed1bb 100644 --- a/src/composer.rs +++ b/src/composer.rs @@ -745,15 +745,15 @@ pub trait Composer: Sized + Index { .iter() .enumerate() .zip(decomposition.iter_mut()) - .fold(acc, |acc, ((i, w), d)| { - *d = self.append_witness(BlsScalar::from(*w as u64)); + .fold(acc, |acc, ((i, bit), w_bit)| { + *w_bit = self.append_witness(BlsScalar::from(*bit as u64)); - self.component_boolean(*d); + self.component_boolean(*w_bit); let constraint = Constraint::new() .left(BlsScalar::pow_of_2(i as u64)) .right(1) - .a(*d) + .a(*w_bit) .b(acc); self.gate_add(constraint) diff --git a/tests/decomposition.rs b/tests/decomposition.rs index 25d03e15..889b5479 100644 --- a/tests/decomposition.rs +++ b/tests/decomposition.rs @@ -8,84 +8,129 @@ use dusk_plonk::prelude::*; use rand::rngs::StdRng; use rand::SeedableRng; -#[test] -fn decomposition_works() { - let rng = &mut StdRng::seed_from_u64(8349u64); - - let n = 1 << 10; - let label = b"demo"; - let pp = PublicParameters::setup(n, rng).expect("failed to create pp"); +mod common; +use common::{check_satisfied_circuit, check_unsatisfied_circuit, setup}; - pub struct DummyCircuit { +#[test] +fn component_decomposition() { + pub struct TestCircuit { a: BlsScalar, - bits: [BlsScalar; N], + decomp_expected: [BlsScalar; N], } - impl DummyCircuit { - pub fn new(a: BlsScalar) -> Self { - let mut bits = [BlsScalar::zero(); N]; - - bits.iter_mut() - .zip(a.to_bits().iter()) - .for_each(|(b, v)| *b = BlsScalar::from(*v as u64)); - - Self { a, bits } + impl TestCircuit { + pub fn new(a: BlsScalar, decomp_expected: [BlsScalar; N]) -> Self { + Self { a, decomp_expected } } } - impl Default for DummyCircuit { + impl Default for TestCircuit { fn default() -> Self { - Self::new(BlsScalar::from(23u64)) + Self::new(BlsScalar::zero(), [BlsScalar::zero(); N]) } } - impl Circuit for DummyCircuit { + impl Circuit for TestCircuit { fn circuit(&self, composer: &mut C) -> Result<(), Error> where C: Composer, { let w_a = composer.append_witness(self.a); - let mut w_bits: [Witness; N] = [C::ZERO; N]; - - w_bits - .iter_mut() - .zip(self.bits.iter()) - .for_each(|(w, b)| *w = composer.append_witness(*b)); + let decomp_circuit: [Witness; N] = + composer.component_decomposition(w_a); - let w_x: [Witness; N] = composer.component_decomposition(w_a); - - w_bits.iter().zip(w_x.iter()).for_each(|(w, b)| { - composer.assert_equal(*w, *b); - }); + decomp_circuit.iter().zip(self.decomp_expected).for_each( + |(bit_circuit, bit_expected)| { + let w_bit_expected = composer.append_witness(bit_expected); + composer.assert_equal(*bit_circuit, w_bit_expected); + }, + ); Ok(()) } } - let (prover, verifier) = Compiler::compile::>(&pp, label) - .expect("failed to compile circuit"); - - // default works - { - let a = BlsScalar::random(rng); - - let (proof, public_inputs) = prover - .prove(rng, &DummyCircuit::<256>::new(a)) - .expect("failed to prove"); - - verifier - .verify(&proof, &public_inputs) - .expect("failed to verify proof"); - } - - // negative works - { - let a = BlsScalar::random(rng); - - let mut circuit = DummyCircuit::<256>::new(a); - - circuit.bits[10] = circuit.bits[10] ^ BlsScalar::one(); - - prover.prove(rng, &circuit).expect_err("invalid proof"); - } + // Compile common circuit descriptions for the prover and verifier to be + // used by all tests + let label = b"component_decomposition"; + let rng = &mut StdRng::seed_from_u64(0x1ea); + let capacity = 1 << 10; + let (prover, verifier) = + setup(capacity, rng, label, &TestCircuit::default()); + + // Test N = 1 + // + // Test default works: + let msg = "Default circuit verification should pass"; + let circuit = TestCircuit::<1>::default(); + let pi = vec![]; + check_satisfied_circuit(&prover, &verifier, &pi, &circuit, rng, &msg); + + // Test N = 64 + // + // Compile new circuit descriptions for the prover and verifier + const N64: usize = 64; + let circuit = TestCircuit::::default(); + let (prover, verifier) = setup(capacity, rng, label, &circuit); + + // Test bls two + let msg = "Verification of satisfied circuit should pass"; + let a = BlsScalar::from(2); + let mut decomp_expected = [BlsScalar::zero(); N64]; + decomp_expected[1] = BlsScalar::one(); + let circuit = TestCircuit::new(a, decomp_expected); + check_satisfied_circuit(&prover, &verifier, &pi, &circuit, rng, &msg); + + // Test bls forty two + let msg = "Verification of satisfied circuit should pass"; + let a = BlsScalar::from(42); + let mut decomp_expected = [BlsScalar::zero(); N64]; + decomp_expected[5] = BlsScalar::one(); + decomp_expected[3] = BlsScalar::one(); + decomp_expected[1] = BlsScalar::one(); + let circuit = TestCircuit::new(a, decomp_expected); + check_satisfied_circuit(&prover, &verifier, &pi, &circuit, rng, &msg); + + // Test u64::MAX + let msg = "Verification of satisfied circuit should pass"; + let a = BlsScalar::from(u64::MAX); + let decomp_expected = [BlsScalar::one(); N64]; + let circuit = TestCircuit::new(a, decomp_expected); + check_satisfied_circuit(&prover, &verifier, &pi, &circuit, rng, &msg); + + // Test u64::MAX + 1 fails + let msg = "Proof creation of unsatisfied circuit should fail"; + let a = BlsScalar::from(u64::MAX) + BlsScalar::one(); + let decomp_expected = [BlsScalar::one(); N64]; + let circuit = TestCircuit::new(a, decomp_expected); + check_unsatisfied_circuit(&prover, &circuit, rng, &msg); + + // Test N = 64 + // + // Compile new circuit descriptions for the prover and verifier + const N256: usize = 256; + let circuit = TestCircuit::::default(); + let (prover, verifier) = setup(capacity, rng, label, &circuit); + + // Test random works: + let msg = "Verification of satisfied circuit should pass"; + let a = BlsScalar::random(rng); + let mut decomp_expected = [BlsScalar::zero(); N256]; + a.to_bits().iter().enumerate().for_each(|(i, bit)| { + decomp_expected[i] = BlsScalar::from(*bit as u64); + }); + let circuit = TestCircuit::new(a, decomp_expected); + check_satisfied_circuit(&prover, &verifier, &pi, &circuit, rng, &msg); + + // Test flipping one bit fails + let msg = "Proof creation of unsatisfied circuit should fail"; + let a = BlsScalar::random(rng); + let mut decomp_expected = [BlsScalar::zero(); N256]; + a.to_bits().iter().enumerate().for_each(|(i, bit)| { + decomp_expected[i] = BlsScalar::from(*bit as u64); + }); + decomp_expected[123] *= -BlsScalar::one(); + decomp_expected[123] += BlsScalar::one(); + let circuit = TestCircuit::new(a, decomp_expected); + check_unsatisfied_circuit(&prover, &circuit, rng, &msg); }