Skip to content

Commit

Permalink
Add and refactor tests for decomposition component
Browse files Browse the repository at this point in the history
Resolves: #738
  • Loading branch information
moCello committed Mar 16, 2023
1 parent 1ba3f9d commit 8bb624f
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 62 deletions.
8 changes: 4 additions & 4 deletions src/composer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,15 +745,15 @@ pub trait Composer: Sized + Index<Witness, Output = BlsScalar> {
.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)
Expand Down
161 changes: 103 additions & 58 deletions tests/decomposition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<const N: usize> {
#[test]
fn component_decomposition() {
pub struct TestCircuit<const N: usize> {
a: BlsScalar,
bits: [BlsScalar; N],
decomp_expected: [BlsScalar; N],
}

impl<const N: usize> DummyCircuit<N> {
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<const N: usize> TestCircuit<N> {
pub fn new(a: BlsScalar, decomp_expected: [BlsScalar; N]) -> Self {
Self { a, decomp_expected }
}
}

impl<const N: usize> Default for DummyCircuit<N> {
impl<const N: usize> Default for TestCircuit<N> {
fn default() -> Self {
Self::new(BlsScalar::from(23u64))
Self::new(BlsScalar::zero(), [BlsScalar::zero(); N])
}
}

impl<const N: usize> Circuit for DummyCircuit<N> {
impl<const N: usize> Circuit for TestCircuit<N> {
fn circuit<C>(&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::<DummyCircuit<256>>(&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::<N64>::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::<N256>::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);
}

0 comments on commit 8bb624f

Please sign in to comment.