acvm/pwg/blackbox/
embedded_curve_ops.rs

1use acir::{
2    AcirField,
3    circuit::opcodes::FunctionInput,
4    native_types::{Witness, WitnessMap},
5};
6use acvm_blackbox_solver::BlackBoxFunctionSolver;
7
8use crate::pwg::{OpcodeResolutionError, input_to_value, insert_value};
9
10pub(super) fn multi_scalar_mul<F: AcirField>(
11    backend: &impl BlackBoxFunctionSolver<F>,
12    initial_witness: &mut WitnessMap<F>,
13    points: &[FunctionInput<F>],
14    scalars: &[FunctionInput<F>],
15    predicate: FunctionInput<F>,
16    outputs: (Witness, Witness, Witness),
17) -> Result<(), OpcodeResolutionError<F>> {
18    let (res_x, res_y, is_infinite) =
19        execute_multi_scalar_mul(backend, initial_witness, points, scalars, predicate)?;
20
21    // Insert the resulting point into the witness map
22    insert_value(&outputs.0, res_x, initial_witness)?;
23    insert_value(&outputs.1, res_y, initial_witness)?;
24    insert_value(&outputs.2, is_infinite, initial_witness)?;
25    Ok(())
26}
27
28pub(crate) fn execute_multi_scalar_mul<F: AcirField>(
29    backend: &impl BlackBoxFunctionSolver<F>,
30    initial_witness: &WitnessMap<F>,
31    points: &[FunctionInput<F>],
32    scalars: &[FunctionInput<F>],
33    predicate: FunctionInput<F>,
34) -> Result<(F, F, F), OpcodeResolutionError<F>> {
35    assert!(scalars.len().is_multiple_of(2), "Number of scalars must be even");
36    assert!(points.len().is_multiple_of(3), "Number of points must be a multiple of 3");
37    assert_eq!(
38        scalars.len() / 2,
39        points.len() / 3,
40        "Number of scalars must be the same as the number of points"
41    );
42
43    let points: Result<Vec<_>, _> =
44        points.iter().map(|input| input_to_value(initial_witness, *input)).collect();
45    let points: Vec<_> = points?.into_iter().collect();
46
47    let scalars: Result<Vec<_>, _> =
48        scalars.iter().map(|input| input_to_value(initial_witness, *input)).collect();
49
50    let predicate = input_to_value(initial_witness, predicate)?.is_one();
51
52    let mut scalars_lo = Vec::new();
53    let mut scalars_hi = Vec::new();
54    for (i, scalar) in scalars?.into_iter().enumerate() {
55        if i % 2 == 0 {
56            scalars_lo.push(scalar);
57        } else {
58            scalars_hi.push(scalar);
59        }
60    }
61    // Call the backend's multi-scalar multiplication function
62    let (res_x, res_y, is_infinite) =
63        backend.multi_scalar_mul(&points, &scalars_lo, &scalars_hi, predicate)?;
64    Ok((res_x, res_y, is_infinite))
65}
66
67pub(super) fn embedded_curve_add<F: AcirField>(
68    backend: &impl BlackBoxFunctionSolver<F>,
69    initial_witness: &mut WitnessMap<F>,
70    input1: [FunctionInput<F>; 3],
71    input2: [FunctionInput<F>; 3],
72    predicate: FunctionInput<F>,
73    outputs: (Witness, Witness, Witness),
74) -> Result<(), OpcodeResolutionError<F>> {
75    let (res_x, res_y, res_infinite) =
76        execute_embedded_curve_add(backend, initial_witness, input1, input2, predicate)?;
77
78    insert_value(&outputs.0, res_x, initial_witness)?;
79    insert_value(&outputs.1, res_y, initial_witness)?;
80    insert_value(&outputs.2, res_infinite, initial_witness)?;
81    Ok(())
82}
83
84pub(crate) fn execute_embedded_curve_add<F: AcirField>(
85    backend: &impl BlackBoxFunctionSolver<F>,
86    initial_witness: &WitnessMap<F>,
87    input1: [FunctionInput<F>; 3],
88    input2: [FunctionInput<F>; 3],
89    predicate: FunctionInput<F>,
90) -> Result<(F, F, F), OpcodeResolutionError<F>> {
91    let input1_x = input_to_value(initial_witness, input1[0])?;
92    let input1_y = input_to_value(initial_witness, input1[1])?;
93    let input1_infinite = input_to_value(initial_witness, input1[2])?;
94    let input2_x = input_to_value(initial_witness, input2[0])?;
95    let input2_y = input_to_value(initial_witness, input2[1])?;
96    let input2_infinite = input_to_value(initial_witness, input2[2])?;
97    let predicate = input_to_value(initial_witness, predicate)?.is_one();
98    let (res_x, res_y, res_infinite) = backend.ec_add(
99        &input1_x,
100        &input1_y,
101        &input1_infinite,
102        &input2_x,
103        &input2_y,
104        &input2_infinite,
105        predicate,
106    )?;
107
108    Ok((res_x, res_y, res_infinite))
109}