diff --git a/acvm/src/pwg/logic.rs b/acvm/src/pwg/logic.rs index 489bc4569..3f4a98e5e 100644 --- a/acvm/src/pwg/logic.rs +++ b/acvm/src/pwg/logic.rs @@ -1,58 +1,28 @@ use super::{insert_value, witness_to_value}; use crate::{pwg::OpcodeResolution, OpcodeResolutionError}; -use acir::{circuit::opcodes::BlackBoxFuncCall, native_types::Witness, BlackBoxFunc, FieldElement}; +use acir::{circuit::opcodes::BlackBoxFuncCall, native_types::Witness, FieldElement}; use std::collections::BTreeMap; -pub fn solve_logic_opcode( +/// Solves a [`BlackBoxFunc::And`][acir::circuit::black_box_functions::BlackBoxFunc::AND] opcode and inserts +/// the result into the supplied witness map +pub fn and( initial_witness: &mut BTreeMap, - func_call: &BlackBoxFuncCall, + gate: &BlackBoxFuncCall, ) -> Result { - match func_call.name { - BlackBoxFunc::AND => LogicSolver::solve_and_gate(initial_witness, func_call), - BlackBoxFunc::XOR => LogicSolver::solve_xor_gate(initial_witness, func_call), - _ => Err(OpcodeResolutionError::UnexpectedOpcode("logic opcode", func_call.name)), - } + let (a, b, result, num_bits) = extract_input_output(gate); + solve_logic_gate(initial_witness, &a, &b, result, |left, right| left.and(right, num_bits)) } -pub struct LogicSolver; - -impl LogicSolver { - /// Derives the rest of the witness based on the initial low level variables - fn solve_logic_gate( - initial_witness: &mut BTreeMap, - a: &Witness, - b: &Witness, - result: Witness, - num_bits: u32, - is_xor_gate: bool, - ) -> Result { - let w_l_value = witness_to_value(initial_witness, *a)?; - let w_r_value = witness_to_value(initial_witness, *b)?; - - let assignment = if is_xor_gate { - w_l_value.xor(w_r_value, num_bits) - } else { - w_l_value.and(w_r_value, num_bits) - }; - insert_value(&result, assignment, initial_witness)?; - Ok(OpcodeResolution::Solved) - } - - pub fn solve_and_gate( - initial_witness: &mut BTreeMap, - gate: &BlackBoxFuncCall, - ) -> Result { - let (a, b, result, num_bits) = extract_input_output(gate); - LogicSolver::solve_logic_gate(initial_witness, &a, &b, result, num_bits, false) - } - pub fn solve_xor_gate( - initial_witness: &mut BTreeMap, - gate: &BlackBoxFuncCall, - ) -> Result { - let (a, b, result, num_bits) = extract_input_output(gate); - LogicSolver::solve_logic_gate(initial_witness, &a, &b, result, num_bits, true) - } +/// Solves a [`BlackBoxFunc::XOR`][acir::circuit::black_box_functions::BlackBoxFunc::XOR] opcode and inserts +/// the result into the supplied witness map +pub fn xor( + initial_witness: &mut BTreeMap, + gate: &BlackBoxFuncCall, +) -> Result { + let (a, b, result, num_bits) = extract_input_output(gate); + solve_logic_gate(initial_witness, &a, &b, result, |left, right| left.xor(right, num_bits)) } + // TODO: Is there somewhere else that we can put this? // TODO: extraction methods are needed for some opcodes like logic and range pub(crate) fn extract_input_output( @@ -69,3 +39,19 @@ pub(crate) fn extract_input_output( (a.witness, b.witness, *result, num_bits) } + +/// Derives the rest of the witness based on the initial low level variables +fn solve_logic_gate( + initial_witness: &mut BTreeMap, + a: &Witness, + b: &Witness, + result: Witness, + logic_op: impl Fn(&FieldElement, &FieldElement) -> FieldElement, +) -> Result { + let w_l_value = witness_to_value(initial_witness, *a)?; + let w_r_value = witness_to_value(initial_witness, *b)?; + let assignment = logic_op(w_l_value, w_r_value); + + insert_value(&result, assignment, initial_witness)?; + Ok(OpcodeResolution::Solved) +}