1use acir::{
2 AcirField,
3 circuit::opcodes::{BlackBoxFuncCall, FunctionInput},
4 native_types::{Witness, WitnessMap},
5};
6use acvm_blackbox_solver::{blake2s, blake3, keccakf1600};
7
8use self::{aes128::solve_aes128_encryption_opcode, hash::solve_poseidon2_permutation_opcode};
9
10use super::{OpcodeNotSolvable, OpcodeResolutionError, insert_value};
11use crate::{BlackBoxFunctionSolver, pwg::input_to_value};
12
13pub(crate) mod aes128;
14pub(crate) mod embedded_curve_ops;
15pub(crate) mod hash;
16mod logic;
17mod range;
18pub(crate) mod signature;
19pub(crate) mod utils;
20
21use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul};
22use hash::{solve_generic_256_hash_opcode, solve_sha_256_permutation_opcode};
24use logic::{and, xor};
25pub(crate) use range::solve_range_opcode;
26use signature::ecdsa::{secp256k1_prehashed, secp256r1_prehashed};
27
28fn first_missing_assignment<F>(
32 witness_assignments: &WitnessMap<F>,
33 inputs: &[FunctionInput<F>],
34) -> Option<Witness> {
35 inputs.iter().find_map(|input| {
36 if let FunctionInput::Witness(witness) = input {
37 if witness_assignments.contains_key(witness) { None } else { Some(*witness) }
38 } else {
39 None
40 }
41 })
42}
43
44fn contains_all_inputs<F>(
46 witness_assignments: &WitnessMap<F>,
47 inputs: &[FunctionInput<F>],
48) -> bool {
49 first_missing_assignment(witness_assignments, inputs).is_none()
50}
51
52pub(crate) fn solve<F: AcirField>(
66 backend: &impl BlackBoxFunctionSolver<F>,
67 initial_witness: &mut WitnessMap<F>,
68 bb_func: &BlackBoxFuncCall<F>,
69) -> Result<(), OpcodeResolutionError<F>> {
70 let inputs = bb_func.get_inputs_vec();
71 if !contains_all_inputs(initial_witness, &inputs) {
72 let unassigned_witness = first_missing_assignment(initial_witness, &inputs)
73 .expect("Some assignments must be missing because it does not contains all inputs");
74 return Err(OpcodeResolutionError::OpcodeNotSolvable(
75 OpcodeNotSolvable::MissingAssignment(unassigned_witness.0),
76 ));
77 }
78
79 match bb_func {
80 BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } => {
81 solve_aes128_encryption_opcode(initial_witness, inputs, iv, key, outputs)
82 }
83 BlackBoxFuncCall::AND { lhs, rhs, num_bits, output } => {
84 and(initial_witness, lhs, rhs, *num_bits, output)
85 }
86 BlackBoxFuncCall::XOR { lhs, rhs, num_bits, output } => {
87 xor(initial_witness, lhs, rhs, *num_bits, output)
88 }
89 BlackBoxFuncCall::RANGE { input, num_bits } => {
90 solve_range_opcode(initial_witness, input, *num_bits)
91 }
92 BlackBoxFuncCall::Blake2s { outputs, .. } => {
93 let inputs = bb_func.get_inputs_vec();
94 solve_generic_256_hash_opcode(initial_witness, &inputs, None, outputs, blake2s)
95 }
96 BlackBoxFuncCall::Blake3 { outputs, .. } => {
97 let inputs = bb_func.get_inputs_vec();
98 solve_generic_256_hash_opcode(initial_witness, &inputs, None, outputs, blake3)
99 }
100 BlackBoxFuncCall::Keccakf1600 { inputs, outputs } => {
101 let mut state = [0; 25];
102 for (it, input) in state.iter_mut().zip(inputs.as_ref()) {
103 let witness_assignment = input_to_value(initial_witness, *input)?;
104 let lane = witness_assignment.try_to_u64();
105 *it = lane.unwrap();
106 }
107 let output_state = keccakf1600(state)?;
108 for (output_witness, value) in outputs.iter().zip(output_state.into_iter()) {
109 insert_value(output_witness, F::from(u128::from(value)), initial_witness)?;
110 }
111 Ok(())
112 }
113 BlackBoxFuncCall::EcdsaSecp256k1 {
114 public_key_x,
115 public_key_y,
116 signature,
117 hashed_message: message,
118 output,
119 predicate,
120 } => secp256k1_prehashed(
121 initial_witness,
122 public_key_x,
123 public_key_y,
124 signature,
125 message.as_ref(),
126 predicate,
127 *output,
128 ),
129 BlackBoxFuncCall::EcdsaSecp256r1 {
130 public_key_x,
131 public_key_y,
132 signature,
133 hashed_message: message,
134 output,
135 predicate,
136 } => secp256r1_prehashed(
137 initial_witness,
138 public_key_x,
139 public_key_y,
140 signature,
141 message.as_ref(),
142 predicate,
143 *output,
144 ),
145 BlackBoxFuncCall::MultiScalarMul { points, scalars, outputs, predicate } => {
146 multi_scalar_mul(backend, initial_witness, points, scalars, *predicate, *outputs)
147 }
148 BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, outputs, predicate } => {
149 embedded_curve_add(backend, initial_witness, **input1, **input2, *predicate, *outputs)
150 }
151 BlackBoxFuncCall::RecursiveAggregation { .. } => Ok(()),
153 BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => {
154 solve_sha_256_permutation_opcode(initial_witness, inputs, hash_values, outputs)
155 }
156 BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } => {
157 solve_poseidon2_permutation_opcode(backend, initial_witness, inputs, outputs)
158 }
159 }
160}