dusk-network/plonk

No range check when `num_bits = 0`

moCello opened this issue · 0 comments

Describe the bug
When adding a range gate with zero bits, any witness always satisfies the circuit.

To Reproduce
In 'tests'

use dusk_plonk::prelude::*;
use rand::rngs::StdRng;
use rand::SeedableRng;

mod common;
use common::{check_satisfied_circuit, check_unsatisfied_circuit, setup};

#[test]
fn range() {
    #[derive(Default)]
    pub struct TestCircuit {
        a: BlsScalar,
        bits: usize,
    }

    impl TestCircuit {
        pub fn new(a: BlsScalar, bits: usize) -> Self {
            Self { a, bits }
        }
    }

    impl Circuit for TestCircuit {
        fn circuit<C>(&self, composer: &mut C) -> Result<(), Error>
        where
            C: Composer,
        {
            let w_a = composer.append_witness(self.a);

            composer.component_range(w_a, self.bits);

            Ok(())
        }
    }

    // Compile common circuit descriptions for the prover and verifier to be
    // used by all tests
    let label = b"component_range";
    let rng = &mut StdRng::seed_from_u64(0xb1eeb);
    let capacity = 1 << 6;
    let (prover, verifier) =
        setup(capacity, rng, label, &TestCircuit::default());

    // public input to be used by all tests
    let pi = vec![];

    // Test bits = zero
    //
    // Test default works:
    // 0 < 2^0
    // This is an edge case but one can argue that this case can pass
    let msg = "Default circuit verification should pass";
    let circuit = TestCircuit::default();
    check_satisfied_circuit(&prover, &verifier, &pi, &circuit, rng, &msg);

    // Test:
    // 1 !< 2^0
    // In this case it shouldn't be possible to generate a circuit that is satisfied
    let msg = "Verification of satisfied circuit should pass";
    let bits = 0;
    let a = BlsScalar::one();
    let circuit = TestCircuit::new(a, bits);
    check_unsatisfied_circuit(&prover, &circuit, rng, &msg);

    // Test:
    // random !< 2^0
    // In this case it shouldn't be possible to generate a circuit that is satisfied
    let msg = "Unsatisfied circuit should fail";
    let a = BlsScalar::random(rng);
    assert!(a != BlsScalar::zero());
    let circuit = TestCircuit::new(a, bits);
    check_unsatisfied_circuit(&prover, &circuit, rng, &msg);
}

Expected behaviour
No witness should satisfy a range gate with 0 bits (since no number can be encoded in 0 bits). An edge case would be BlsScalar::zero() itself as one can argue that zero is encodable in 0 bits.

Additional context
This bug came up in issue #735 and the above test is in 'tests/range.rs'