acvm/pwg/blackbox/
embedded_curve_ops.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use acir::{
    AcirField,
    circuit::opcodes::FunctionInput,
    native_types::{Witness, WitnessMap},
};
use acvm_blackbox_solver::BlackBoxFunctionSolver;

use crate::pwg::{OpcodeResolutionError, input_to_value, insert_value};

pub(super) fn multi_scalar_mul<F: AcirField>(
    backend: &impl BlackBoxFunctionSolver<F>,
    initial_witness: &mut WitnessMap<F>,
    points: &[FunctionInput<F>],
    scalars: &[FunctionInput<F>],
    outputs: (Witness, Witness, Witness),
) -> Result<(), OpcodeResolutionError<F>> {
    let points: Result<Vec<_>, _> =
        points.iter().map(|input| input_to_value(initial_witness, *input)).collect();
    let points: Vec<_> = points?.into_iter().collect();

    let scalars: Result<Vec<_>, _> =
        scalars.iter().map(|input| input_to_value(initial_witness, *input)).collect();
    let mut scalars_lo = Vec::new();
    let mut scalars_hi = Vec::new();
    for (i, scalar) in scalars?.into_iter().enumerate() {
        if i % 2 == 0 {
            scalars_lo.push(scalar);
        } else {
            scalars_hi.push(scalar);
        }
    }
    // Call the backend's multi-scalar multiplication function
    let (res_x, res_y, is_infinite) =
        backend.multi_scalar_mul(&points, &scalars_lo, &scalars_hi)?;

    // Insert the resulting point into the witness map
    insert_value(&outputs.0, res_x, initial_witness)?;
    insert_value(&outputs.1, res_y, initial_witness)?;
    insert_value(&outputs.2, is_infinite, initial_witness)?;
    Ok(())
}

pub(super) fn embedded_curve_add<F: AcirField>(
    backend: &impl BlackBoxFunctionSolver<F>,
    initial_witness: &mut WitnessMap<F>,
    input1: [FunctionInput<F>; 3],
    input2: [FunctionInput<F>; 3],
    outputs: (Witness, Witness, Witness),
) -> Result<(), OpcodeResolutionError<F>> {
    let input1_x = input_to_value(initial_witness, input1[0])?;
    let input1_y = input_to_value(initial_witness, input1[1])?;
    let input1_infinite = input_to_value(initial_witness, input1[2])?;
    let input2_x = input_to_value(initial_witness, input2[0])?;
    let input2_y = input_to_value(initial_witness, input2[1])?;
    let input2_infinite = input_to_value(initial_witness, input2[2])?;
    let (res_x, res_y, res_infinite) = backend.ec_add(
        &input1_x,
        &input1_y,
        &input1_infinite,
        &input2_x,
        &input2_y,
        &input2_infinite,
    )?;

    insert_value(&outputs.0, res_x, initial_witness)?;
    insert_value(&outputs.1, res_y, initial_witness)?;
    insert_value(&outputs.2, res_infinite, initial_witness)?;
    Ok(())
}