acvm/pwg/blackbox/
range.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use crate::{
    OpcodeResolutionError,
    pwg::{ErrorLocation, input_to_value},
};
use acir::{AcirField, circuit::opcodes::FunctionInput, native_types::WitnessMap};

pub(crate) fn solve_range_opcode<F: AcirField>(
    initial_witness: &WitnessMap<F>,
    input: &FunctionInput<F>,
    num_bits: u32,
) -> Result<(), OpcodeResolutionError<F>> {
    let w_value = input_to_value(initial_witness, *input)?;

    if w_value.num_bits() > num_bits {
        return Err(OpcodeResolutionError::UnsatisfiedConstrain {
            opcode_location: ErrorLocation::Unresolved,
            payload: None,
        });
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;

    use acir::{
        AcirField, FieldElement,
        circuit::opcodes::FunctionInput,
        native_types::{Witness, WitnessMap},
    };

    use crate::pwg::blackbox::solve_range_opcode;

    #[test]
    fn rejects_too_large_inputs() {
        let witness_map =
            WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::from(256u32))]));
        let input: FunctionInput<FieldElement> = FunctionInput::Witness(Witness(0));
        assert!(solve_range_opcode(&witness_map, &input, 8).is_err());
    }

    #[test]
    fn accepts_zero_for_zero_bits() {
        let witness_map = WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::zero())]));
        let input: FunctionInput<FieldElement> = FunctionInput::Witness(Witness(0));
        assert!(solve_range_opcode(&witness_map, &input, 0).is_ok());
    }

    #[test]
    fn accepts_valid_inputs() {
        let values: [u32; 4] = [0, 1, 8, 255];

        for value in values {
            let witness_map =
                WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::from(value))]));
            let input: FunctionInput<FieldElement> = FunctionInput::Witness(Witness(0));
            assert!(solve_range_opcode(&witness_map, &input, 8).is_ok());
        }
    }
}