From 3155daf1700e25025ae96b548b4ef425923f2178 Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 8 May 2023 07:18:47 +0100 Subject: [PATCH 1/2] chore!: expose separate solvers for AND and XOR opcodes --- acvm/src/pwg/logic.rs | 83 +++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 46 deletions(-) diff --git a/acvm/src/pwg/logic.rs b/acvm/src/pwg/logic.rs index 489bc4569..8a00bff19 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, num_bits, false) } -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, num_bits, true) } + // 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,24 @@ 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, + 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) +} From c0ec9732c9069803462bc0f72914d83919919d40 Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 8 May 2023 08:34:41 +0100 Subject: [PATCH 2/2] chore: replace boolean flag and `num_bits` args with closure --- acvm/src/pwg/logic.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/acvm/src/pwg/logic.rs b/acvm/src/pwg/logic.rs index 8a00bff19..3f4a98e5e 100644 --- a/acvm/src/pwg/logic.rs +++ b/acvm/src/pwg/logic.rs @@ -10,7 +10,7 @@ pub fn and( gate: &BlackBoxFuncCall, ) -> Result { let (a, b, result, num_bits) = extract_input_output(gate); - solve_logic_gate(initial_witness, &a, &b, result, num_bits, false) + solve_logic_gate(initial_witness, &a, &b, result, |left, right| left.and(right, num_bits)) } /// Solves a [`BlackBoxFunc::XOR`][acir::circuit::black_box_functions::BlackBoxFunc::XOR] opcode and inserts @@ -20,7 +20,7 @@ pub fn xor( gate: &BlackBoxFuncCall, ) -> Result { let (a, b, result, num_bits) = extract_input_output(gate); - solve_logic_gate(initial_witness, &a, &b, result, num_bits, true) + 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? @@ -46,17 +46,12 @@ fn solve_logic_gate( a: &Witness, b: &Witness, result: Witness, - num_bits: u32, - is_xor_gate: bool, + 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); - 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) }