#![doc = include_str!("../perf/multiscalar/secp256k1.svg")]
use crate::{Curve, Point, Scalar};
#[cfg(feature = "alloc")]
mod straus;
#[cfg(feature = "alloc")]
pub use self::straus::Straus;
pub trait MultiscalarMul<E: Curve> {
fn multiscalar_mul<S, P>(scalar_points: impl ExactSizeIterator<Item = (S, P)>) -> Point<E>
where
S: AsRef<Scalar<E>>,
P: AsRef<Point<E>>;
}
pub struct Default;
#[cfg(not(feature = "alloc"))]
impl<E: Curve> MultiscalarMul<E> for Default {
fn multiscalar_mul<S, P>(scalar_points: impl ExactSizeIterator<Item = (S, P)>) -> Point<E>
where
S: AsRef<Scalar<E>>,
P: AsRef<Point<E>>,
{
Naive::multiscalar_mul(scalar_points)
}
}
#[cfg(feature = "alloc")]
impl<E: Curve> MultiscalarMul<E> for Default {
fn multiscalar_mul<S, P>(scalar_points: impl ExactSizeIterator<Item = (S, P)>) -> Point<E>
where
S: AsRef<Scalar<E>>,
P: AsRef<Point<E>>,
{
Straus::multiscalar_mul(scalar_points)
}
}
pub struct Naive;
impl<E: Curve> MultiscalarMul<E> for Naive {
fn multiscalar_mul<S, P>(scalar_points: impl IntoIterator<Item = (S, P)>) -> Point<E>
where
S: AsRef<Scalar<E>>,
P: AsRef<Point<E>>,
{
scalar_points
.into_iter()
.map(|(scalar, point)| scalar.as_ref() * point.as_ref())
.sum()
}
}
#[doc = include_str!("../perf/multiscalar/ed25519.svg")]
#[cfg(all(feature = "curve-ed25519", feature = "alloc"))]
pub struct Dalek;
#[cfg(all(feature = "curve-ed25519", feature = "alloc"))]
impl MultiscalarMul<crate::curves::Ed25519> for Dalek {
fn multiscalar_mul<S, P>(
scalar_points: impl IntoIterator<Item = (S, P)>,
) -> Point<crate::curves::Ed25519>
where
S: AsRef<Scalar<crate::curves::Ed25519>>,
P: AsRef<Point<crate::curves::Ed25519>>,
{
use alloc::vec::Vec;
use curve25519::traits::VartimeMultiscalarMul;
use generic_ec_core::{OnCurve, SmallFactor};
use crate::as_raw::AsRaw;
let scalar_points = scalar_points.into_iter().collect::<Vec<_>>();
let scalars = scalar_points.iter().map(|(s, _)| &s.as_ref().as_raw().0);
let points = scalar_points.iter().map(|(_, p)| &p.as_ref().as_raw().0);
let result = curve25519::EdwardsPoint::vartime_multiscalar_mul(scalars, points);
let result = generic_ec_curves::ed25519::Point(result);
debug_assert!(result.is_on_curve().into() && result.is_torsion_free().into());
Point::from_raw_unchecked(result)
}
}