use crate::{
core::{
circuits::traits::curve_circuit::CurveCircuit,
expressions::expr::EvalFailure,
global_value::{curve_value::CurveValue, value::FieldValue},
},
utils::{curve_point::CurvePoint, field::ScalarField},
};
use curve25519_dalek_arcium_fork::traits::MultiscalarMul as DalekMultiscalarMul;
use primitives::algebra::elliptic_curve::{curve25519::Curve25519Ristretto, Curve};
#[derive(Debug, Default, Clone)]
#[allow(dead_code)]
pub struct MultiscalarMul;
impl CurveCircuit for MultiscalarMul {
fn eval(
&self,
curve_points: Vec<CurvePoint>,
scalars: Vec<ScalarField>,
) -> Result<Vec<CurvePoint>, EvalFailure> {
if scalars.len() != curve_points.len() {
return EvalFailure::err_ub("lengths don't match");
}
Ok(vec![CurvePoint::new(
<Curve25519Ristretto as Curve>::Point::multiscalar_mul(
scalars
.into_iter()
.map(|scalar| {
<Curve25519Ristretto as Curve>::Scalar::from_canonical_bytes(
scalar.to_le_bytes(),
)
.unwrap()
})
.collect::<Vec<<Curve25519Ristretto as Curve>::Scalar>>(),
curve_points
.into_iter()
.map(|point| point.inner())
.collect::<Vec<<Curve25519Ristretto as Curve>::Point>>(),
),
)])
}
fn run(
&self,
curve_vals: Vec<CurveValue>,
scalar_vals: Vec<FieldValue<ScalarField>>,
) -> Vec<CurveValue> {
vec![CurveValue::multiscalar_mul(scalar_vals, curve_vals)]
}
}
#[cfg(test)]
mod tests {
use crate::core::circuits::{
curve::multiscalar_mul::MultiscalarMul,
traits::curve_circuit::tests::TestedCurveCircuit,
};
impl TestedCurveCircuit for MultiscalarMul {
fn gen_desc<R: rand::Rng + ?Sized>(_rng: &mut R) -> Self {
Self
}
fn gen_n_points<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> usize {
let mut n_points = 1;
while rng.gen_bool(0.875) {
n_points += 1;
}
n_points
}
fn gen_n_scalars<R: rand::Rng + ?Sized>(&self, _rng: &mut R, n_points: usize) -> usize {
n_points
}
}
#[test]
fn test_multiscalar_mul() {
MultiscalarMul::test(4, 4)
}
}