|
1 | 1 | use acvm::{ |
2 | 2 | BlackBoxFunctionSolver, |
3 | | - acir::{AcirField, BlackBoxFunc, circuit::opcodes::FunctionInput}, |
| 3 | + acir::{ |
| 4 | + AcirField, BlackBoxFunc, |
| 5 | + circuit::opcodes::{ConstantOrWitnessEnum, FunctionInput}, |
| 6 | + }, |
4 | 7 | }; |
5 | 8 | use iter_extended::vecmap; |
6 | 9 | use num_bigint::BigUint; |
@@ -218,7 +221,11 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> { |
218 | 221 | | BlackBoxFunc::EmbeddedCurveAdd |
219 | 222 | ); |
220 | 223 | // Convert `AcirVar` to `FunctionInput` |
221 | | - let inputs = self.prepare_inputs_for_black_box_func_call(inputs, allow_constant_inputs)?; |
| 224 | + let mut inputs = |
| 225 | + self.prepare_inputs_for_black_box_func_call(inputs, allow_constant_inputs)?; |
| 226 | + if name == BlackBoxFunc::EmbeddedCurveAdd { |
| 227 | + inputs = self.all_or_nothing_for_ec_add(inputs)?; |
| 228 | + } |
222 | 229 | Ok(inputs) |
223 | 230 | } |
224 | 231 |
|
@@ -261,4 +268,39 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> { |
261 | 268 | } |
262 | 269 | Ok(witnesses) |
263 | 270 | } |
| 271 | + |
| 272 | + /// EcAdd has 6 inputs representing the two points to add |
| 273 | + /// Each point must be either all constant, or all witnesses |
| 274 | + fn all_or_nothing_for_ec_add( |
| 275 | + &mut self, |
| 276 | + inputs: Vec<Vec<FunctionInput<F>>>, |
| 277 | + ) -> Result<Vec<Vec<FunctionInput<F>>>, RuntimeError> { |
| 278 | + let mut has_constant = false; |
| 279 | + let mut has_witness = false; |
| 280 | + let mut result = inputs.clone(); |
| 281 | + for (i, input) in inputs.iter().enumerate() { |
| 282 | + if input[0].is_constant() { |
| 283 | + has_constant = true; |
| 284 | + } else { |
| 285 | + has_witness = true; |
| 286 | + } |
| 287 | + if i % 3 == 2 { |
| 288 | + if has_constant && has_witness { |
| 289 | + // Convert the constants to witness if mixed constant and witness, |
| 290 | + for j in i - 2..i + 1 { |
| 291 | + if let ConstantOrWitnessEnum::Constant(constant) = inputs[j][0].input() { |
| 292 | + let constant = self.add_constant(constant); |
| 293 | + let witness_var = self.get_or_create_witness_var(constant)?; |
| 294 | + let witness = self.var_to_witness(witness_var)?; |
| 295 | + result[j] = |
| 296 | + vec![FunctionInput::witness(witness, inputs[j][0].num_bits())]; |
| 297 | + } |
| 298 | + } |
| 299 | + } |
| 300 | + has_constant = false; |
| 301 | + has_witness = false; |
| 302 | + } |
| 303 | + } |
| 304 | + Ok(result) |
| 305 | + } |
264 | 306 | } |
0 commit comments