use group::Group;
pub trait MultiScalarMul: Group {
fn msm(scalars: &[Self::Scalar], bases: &[Self]) -> Self {
assert_eq!(scalars.len(), bases.len());
core::iter::zip(bases, scalars).map(|(g, x)| *g * *x).sum()
}
}
#[cfg(feature = "curve25519-dalek")]
mod curve25519 {
use super::MultiScalarMul;
use curve25519_dalek::{traits::MultiscalarMul as _, EdwardsPoint, RistrettoPoint, Scalar};
use group::Group;
impl MultiScalarMul for RistrettoPoint {
fn msm(scalars: &[Scalar], bases: &[Self]) -> Self {
assert_eq!(scalars.len(), bases.len());
match scalars.len() {
0 => Self::identity(),
1.. => Self::multiscalar_mul(scalars, bases),
}
}
}
impl MultiScalarMul for EdwardsPoint {
fn msm(scalars: &[Scalar], bases: &[Self]) -> Self {
assert_eq!(scalars.len(), bases.len());
match scalars.len() {
0 => Self::identity(),
1.. => Self::multiscalar_mul(scalars, bases),
}
}
}
}
#[cfg(feature = "bls12_381")]
mod bls12_381 {
use super::MultiScalarMul;
use bls12_381::{G1Projective, G2Projective};
impl MultiScalarMul for G1Projective {}
impl MultiScalarMul for G2Projective {}
}
#[cfg(feature = "k256")]
mod k256 {
use super::MultiScalarMul;
use alloc::vec::Vec;
use k256::{elliptic_curve::ops::LinearCombinationExt, ProjectivePoint, Scalar};
impl MultiScalarMul for ProjectivePoint {
fn msm(scalars: &[Scalar], bases: &[Self]) -> Self {
assert_eq!(scalars.len(), bases.len());
LinearCombinationExt::lincomb_ext(
core::iter::zip(bases.iter().copied(), scalars.iter().copied())
.collect::<Vec<_>>()
.as_slice(),
)
}
}
}
#[cfg(feature = "p256")]
mod p256 {
use super::MultiScalarMul;
use p256::ProjectivePoint;
impl MultiScalarMul for ProjectivePoint {}
}