diff --git a/.gitignore b/.gitignore index 1d76c98a1ac..334901860d9 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ codegen **/cspell.json !./cspell.json + +mutants.out +mutants.out.old diff --git a/acvm-repo/acvm/src/pwg/arithmetic.rs b/acvm-repo/acvm/src/pwg/arithmetic.rs index 78da63ddc0f..a2921bcbc9b 100644 --- a/acvm-repo/acvm/src/pwg/arithmetic.rs +++ b/acvm-repo/acvm/src/pwg/arithmetic.rs @@ -254,7 +254,52 @@ mod tests { use acir::FieldElement; #[test] - fn expression_solver_smoke_test() { + fn solves_simple_assignment() { + let a = Witness(0); + + // a - 1 == 0; + let opcode_a = Expression { + mul_terms: vec![], + linear_combinations: vec![(FieldElement::one(), a)], + q_c: -FieldElement::one(), + }; + + let mut values = WitnessMap::new(); + assert_eq!(ExpressionSolver::solve(&mut values, &opcode_a), Ok(())); + + assert_eq!(values.get(&a).unwrap(), &FieldElement::from(1_i128)); + } + + #[test] + fn solves_unknown_in_mul_term() { + let a = Witness(0); + let b = Witness(1); + let c = Witness(2); + let d = Witness(3); + + // a * b - b - c - d == 0; + let opcode_a = Expression { + mul_terms: vec![(FieldElement::one(), a, b)], + linear_combinations: vec![ + (-FieldElement::one(), b), + (-FieldElement::one(), c), + (-FieldElement::one(), d), + ], + q_c: FieldElement::zero(), + }; + + let mut values = WitnessMap::new(); + values.insert(b, FieldElement::from(2_i128)); + values.insert(c, FieldElement::from(1_i128)); + values.insert(d, FieldElement::from(1_i128)); + + assert_eq!(ExpressionSolver::solve(&mut values, &opcode_a), Ok(())); + + assert_eq!(values.get(&a).unwrap(), &FieldElement::from(2_i128)); + } + + #[test] + fn solves_unknown_in_linear_term() { let a = Witness(0); let b = Witness(1); let c = Witness(2); diff --git a/acvm-repo/acvm/src/pwg/blackbox/hash.rs b/acvm-repo/acvm/src/pwg/blackbox/hash.rs index 93f9ea410bc..a4af9de55cf 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/hash.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/hash.rs @@ -136,11 +136,10 @@ pub(crate) fn solve_poseidon2_permutation_opcode( } // Read witness assignments - let mut state = Vec::new(); - for input in inputs.iter() { - let witness_assignment = input_to_value(initial_witness, *input, false)?; - state.push(witness_assignment); - } + let state: Vec = inputs + .iter() + .map(|input| input_to_value(initial_witness, *input, false)) + .collect::>()?; let state = backend.poseidon2_permutation(&state, len)?; diff --git a/acvm-repo/acvm/src/pwg/blackbox/range.rs b/acvm-repo/acvm/src/pwg/blackbox/range.rs index 927706f4671..039a04b9063 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/range.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/range.rs @@ -21,3 +21,36 @@ pub(crate) fn solve_range_opcode( } Ok(()) } + +#[cfg(test)] +mod tests { + use std::collections::BTreeMap; + + use acir::{ + 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 = FunctionInput::witness(Witness(0), 8); + assert!(solve_range_opcode(&witness_map, &input, false).is_err()); + } + + #[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 = FunctionInput::witness(Witness(0), 8); + assert!(solve_range_opcode(&witness_map, &input, false).is_ok()); + } + } +} diff --git a/acvm-repo/blackbox_solver/src/curve_specific_solver.rs b/acvm-repo/blackbox_solver/src/curve_specific_solver.rs index 37fe5d05363..af0104b54f0 100644 --- a/acvm-repo/blackbox_solver/src/curve_specific_solver.rs +++ b/acvm-repo/blackbox_solver/src/curve_specific_solver.rs @@ -25,8 +25,8 @@ pub trait BlackBoxFunctionSolver { ) -> Result<(F, F, F), BlackBoxResolutionError>; fn poseidon2_permutation( &self, - _inputs: &[F], - _len: u32, + inputs: &[F], + len: u32, ) -> Result, BlackBoxResolutionError>; }