acvm/pwg/blackbox/
range.rs

1use crate::{
2    OpcodeResolutionError,
3    pwg::{ErrorLocation, input_to_value},
4};
5use acir::{AcirField, circuit::opcodes::FunctionInput, native_types::WitnessMap};
6
7pub(crate) fn solve_range_opcode<F: AcirField>(
8    initial_witness: &WitnessMap<F>,
9    input: &FunctionInput<F>,
10    num_bits: u32,
11) -> Result<(), OpcodeResolutionError<F>> {
12    let w_value = input_to_value(initial_witness, *input)?;
13
14    if w_value.num_bits() > num_bits {
15        return Err(OpcodeResolutionError::UnsatisfiedConstrain {
16            opcode_location: ErrorLocation::Unresolved,
17            payload: None,
18        });
19    }
20    Ok(())
21}
22
23#[cfg(test)]
24mod tests {
25    use std::collections::BTreeMap;
26
27    use acir::{
28        AcirField, FieldElement,
29        circuit::opcodes::FunctionInput,
30        native_types::{Witness, WitnessMap},
31    };
32
33    use crate::pwg::blackbox::solve_range_opcode;
34
35    #[test]
36    fn rejects_too_large_inputs() {
37        let witness_map =
38            WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::from(256u32))]));
39        let input: FunctionInput<FieldElement> = FunctionInput::Witness(Witness(0));
40        assert!(solve_range_opcode(&witness_map, &input, 8).is_err());
41    }
42
43    #[test]
44    fn accepts_zero_for_zero_bits() {
45        let witness_map = WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::zero())]));
46        let input: FunctionInput<FieldElement> = FunctionInput::Witness(Witness(0));
47        assert!(solve_range_opcode(&witness_map, &input, 0).is_ok());
48    }
49
50    #[test]
51    fn accepts_valid_inputs() {
52        let values: [u32; 4] = [0, 1, 8, 255];
53
54        for value in values {
55            let witness_map =
56                WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::from(value))]));
57            let input: FunctionInput<FieldElement> = FunctionInput::Witness(Witness(0));
58            assert!(solve_range_opcode(&witness_map, &input, 8).is_ok());
59        }
60    }
61}