mirror of
https://github.com/saymrwulf/risc0-curve25519-dalek-source.git
synced 2026-09-04 20:03:40 +00:00
Remove constant-time multiscalar precomputation.
This doesn't (yet) give any speedup over the non-precomputed multiscalar multiplication, and it's not clear that it's a good idea to commit to supporting it in the future. Removing it means that it's not committed-to as part of the public API, but the source is still there in the tree if we want to revisit it later.
This commit is contained in:
parent
27daa5215e
commit
092ff52cb0
6 changed files with 6 additions and 465 deletions
|
|
@ -110,37 +110,6 @@ mod multiscalar_benches {
|
|||
);
|
||||
}
|
||||
|
||||
fn precomputed_ct_straus_helper(c: &mut Criterion, dynamic_fraction: f64) {
|
||||
let label = format!(
|
||||
"Constant-time mixed-base Straus ({:.2}pct dyn)",
|
||||
100.0*dynamic_fraction,
|
||||
);
|
||||
c.bench_function_over_inputs(
|
||||
&label,
|
||||
move |b, &&total_size| {
|
||||
let dynamic_size = ((total_size as f64) * dynamic_fraction) as usize;
|
||||
let static_size = total_size - dynamic_size;
|
||||
|
||||
let (static_scalars, static_points) = construct(static_size);
|
||||
let (dynamic_scalars, dynamic_points) = construct(dynamic_size);
|
||||
|
||||
use curve25519_dalek::edwards::EdwardsPrecomputation;
|
||||
use curve25519_dalek::traits::PrecomputedMultiscalarMul;
|
||||
|
||||
let precomp = EdwardsPrecomputation::new(&static_points);
|
||||
|
||||
b.iter(|| {
|
||||
precomp.mixed_multiscalar_mul(
|
||||
&static_scalars,
|
||||
&dynamic_scalars,
|
||||
&dynamic_points,
|
||||
)
|
||||
});
|
||||
},
|
||||
&MULTISCALAR_SIZES,
|
||||
);
|
||||
}
|
||||
|
||||
fn precomputed_vt_straus_helper(c: &mut Criterion, dynamic_fraction: f64) {
|
||||
let label = format!(
|
||||
"Variable-time mixed-base Straus ({:.2}pct dyn)",
|
||||
|
|
@ -172,18 +141,6 @@ mod multiscalar_benches {
|
|||
);
|
||||
}
|
||||
|
||||
fn precomputed_ct_straus_00_pct_dynamic(c: &mut Criterion) {
|
||||
precomputed_ct_straus_helper(c, 0.0);
|
||||
}
|
||||
|
||||
fn precomputed_ct_straus_20_pct_dynamic(c: &mut Criterion) {
|
||||
precomputed_ct_straus_helper(c, 0.2);
|
||||
}
|
||||
|
||||
fn precomputed_ct_straus_50_pct_dynamic(c: &mut Criterion) {
|
||||
precomputed_ct_straus_helper(c, 0.5);
|
||||
}
|
||||
|
||||
fn precomputed_vt_straus_00_pct_dynamic(c: &mut Criterion) {
|
||||
precomputed_vt_straus_helper(c, 0.0);
|
||||
}
|
||||
|
|
@ -203,9 +160,6 @@ mod multiscalar_benches {
|
|||
targets =
|
||||
consttime_multiscalar_mul,
|
||||
vartime_multiscalar_mul,
|
||||
precomputed_ct_straus_00_pct_dynamic,
|
||||
precomputed_ct_straus_20_pct_dynamic,
|
||||
precomputed_ct_straus_50_pct_dynamic,
|
||||
precomputed_vt_straus_00_pct_dynamic,
|
||||
precomputed_vt_straus_20_pct_dynamic,
|
||||
precomputed_vt_straus_50_pct_dynamic,
|
||||
|
|
|
|||
|
|
@ -13,99 +13,18 @@
|
|||
|
||||
use core::borrow::Borrow;
|
||||
|
||||
use clear_on_drop::ClearOnDrop;
|
||||
|
||||
use backend::serial::curve_models::{
|
||||
AffineNielsPoint, CompletedPoint, ProjectiveNielsPoint, ProjectivePoint,
|
||||
};
|
||||
use edwards::EdwardsPoint;
|
||||
use scalar::Scalar;
|
||||
use traits::Identity;
|
||||
use traits::{PrecomputedMultiscalarMul, VartimePrecomputedMultiscalarMul};
|
||||
use window::{LookupTable, NafLookupTable5, NafLookupTable8};
|
||||
use traits::VartimePrecomputedMultiscalarMul;
|
||||
use window::{NafLookupTable5, NafLookupTable8};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use prelude::*;
|
||||
|
||||
pub struct PrecomputedStraus {
|
||||
static_lookup_tables: Vec<LookupTable<AffineNielsPoint>>,
|
||||
}
|
||||
|
||||
impl PrecomputedMultiscalarMul for PrecomputedStraus {
|
||||
type Point = EdwardsPoint;
|
||||
|
||||
fn new<I>(static_points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Self::Point>,
|
||||
{
|
||||
PrecomputedStraus {
|
||||
static_lookup_tables: static_points
|
||||
.into_iter()
|
||||
.map(|point| LookupTable::<AffineNielsPoint>::from(point.borrow()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mixed_multiscalar_mul<I, J, K>(
|
||||
&self,
|
||||
static_scalars: I,
|
||||
dynamic_scalars: J,
|
||||
dynamic_points: K,
|
||||
) -> Self::Point
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Scalar>,
|
||||
J: IntoIterator,
|
||||
J::Item: Borrow<Scalar>,
|
||||
K: IntoIterator,
|
||||
K::Item: Borrow<Self::Point>,
|
||||
{
|
||||
// This does two allocs for the scalar digits instead of
|
||||
// putting them in a contiguous array, which makes handling
|
||||
// the two kinds of lookup tables slightly easier.
|
||||
// Use a ClearOnDrop wrapper.
|
||||
|
||||
let static_scalar_digits_vec: Vec<_> = static_scalars
|
||||
.into_iter()
|
||||
.map(|s| s.borrow().to_radix_16())
|
||||
.collect();
|
||||
let static_scalar_digits = ClearOnDrop::new(static_scalar_digits_vec);
|
||||
|
||||
let dynamic_scalar_digits_vec: Vec<_> = dynamic_scalars
|
||||
.into_iter()
|
||||
.map(|s| s.borrow().to_radix_16())
|
||||
.collect();
|
||||
let dynamic_scalar_digits = ClearOnDrop::new(dynamic_scalar_digits_vec);
|
||||
|
||||
// Build lookup tables for dynamic points
|
||||
let dynamic_lookup_tables: Vec<_> = dynamic_points
|
||||
.into_iter()
|
||||
.map(|point| LookupTable::<ProjectiveNielsPoint>::from(point.borrow()))
|
||||
.collect();
|
||||
|
||||
let sp = self.static_lookup_tables.len();
|
||||
let dp = dynamic_lookup_tables.len();
|
||||
assert_eq!(sp, static_scalar_digits.len());
|
||||
assert_eq!(dp, dynamic_scalar_digits.len());
|
||||
|
||||
let mut R = EdwardsPoint::identity();
|
||||
for j in (0..64).rev() {
|
||||
R = R.mul_by_pow_2(4);
|
||||
for i in 0..dp {
|
||||
let t_ij = dynamic_scalar_digits[i][j];
|
||||
R = (&R + &dynamic_lookup_tables[i].select(t_ij)).to_extended();
|
||||
}
|
||||
for i in 0..sp {
|
||||
let s_ij = static_scalar_digits[i][j];
|
||||
R = (&R + &self.static_lookup_tables[i].select(s_ij)).to_extended();
|
||||
}
|
||||
}
|
||||
|
||||
R
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VartimePrecomputedStraus {
|
||||
static_lookup_tables: Vec<NafLookupTable8<AffineNielsPoint>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,96 +13,16 @@
|
|||
|
||||
use core::borrow::Borrow;
|
||||
|
||||
use clear_on_drop::ClearOnDrop;
|
||||
|
||||
use backend::vector::{CachedPoint, ExtendedPoint};
|
||||
use edwards::EdwardsPoint;
|
||||
use scalar::Scalar;
|
||||
use traits::Identity;
|
||||
use traits::{PrecomputedMultiscalarMul, VartimePrecomputedMultiscalarMul};
|
||||
use window::{LookupTable, NafLookupTable5, NafLookupTable8};
|
||||
use traits::VartimePrecomputedMultiscalarMul;
|
||||
use window::{NafLookupTable5, NafLookupTable8};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use prelude::*;
|
||||
|
||||
pub struct PrecomputedStraus {
|
||||
static_lookup_tables: Vec<LookupTable<CachedPoint>>,
|
||||
}
|
||||
|
||||
impl PrecomputedMultiscalarMul for PrecomputedStraus {
|
||||
type Point = EdwardsPoint;
|
||||
|
||||
fn new<I>(static_points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Self::Point>,
|
||||
{
|
||||
PrecomputedStraus {
|
||||
static_lookup_tables: static_points
|
||||
.into_iter()
|
||||
.map(|point| LookupTable::<CachedPoint>::from(point.borrow()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mixed_multiscalar_mul<I, J, K>(
|
||||
&self,
|
||||
static_scalars: I,
|
||||
dynamic_scalars: J,
|
||||
dynamic_points: K,
|
||||
) -> Self::Point
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Scalar>,
|
||||
J: IntoIterator,
|
||||
J::Item: Borrow<Scalar>,
|
||||
K: IntoIterator,
|
||||
K::Item: Borrow<Self::Point>,
|
||||
{
|
||||
// This does two allocs for the scalar digits instead of
|
||||
// putting them in a contiguous array, which makes handling
|
||||
// the two kinds of lookup tables slightly easier.
|
||||
// Use a ClearOnDrop wrapper.
|
||||
|
||||
let static_scalar_digits_vec: Vec<_> = static_scalars
|
||||
.into_iter()
|
||||
.map(|s| s.borrow().to_radix_16())
|
||||
.collect();
|
||||
let static_scalar_digits = ClearOnDrop::new(static_scalar_digits_vec);
|
||||
|
||||
let dynamic_scalar_digits_vec: Vec<_> = dynamic_scalars
|
||||
.into_iter()
|
||||
.map(|s| s.borrow().to_radix_16())
|
||||
.collect();
|
||||
let dynamic_scalar_digits = ClearOnDrop::new(dynamic_scalar_digits_vec);
|
||||
|
||||
// Build lookup tables for dynamic points
|
||||
let dynamic_lookup_tables: Vec<_> = dynamic_points
|
||||
.into_iter()
|
||||
.map(|point| LookupTable::<CachedPoint>::from(point.borrow()))
|
||||
.collect();
|
||||
|
||||
let sp = self.static_lookup_tables.len();
|
||||
let dp = dynamic_lookup_tables.len();
|
||||
assert_eq!(sp, static_scalar_digits.len());
|
||||
assert_eq!(dp, dynamic_scalar_digits.len());
|
||||
|
||||
let mut R = ExtendedPoint::identity();
|
||||
for j in (0..64).rev() {
|
||||
R = R.mul_by_pow_2(4);
|
||||
for i in 0..dp {
|
||||
let t_ij = dynamic_scalar_digits[i][j];
|
||||
R = &R + &dynamic_lookup_tables[i].select(t_ij);
|
||||
}
|
||||
for i in 0..sp {
|
||||
let s_ij = static_scalar_digits[i][j];
|
||||
R = &R + &self.static_lookup_tables[i].select(s_ij);
|
||||
}
|
||||
}
|
||||
|
||||
R.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VartimePrecomputedStraus {
|
||||
static_lookup_tables: Vec<NafLookupTable8<CachedPoint>>,
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ use traits::ValidityCheck;
|
|||
use traits::{Identity, IsIdentity};
|
||||
|
||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||
use traits::{MultiscalarMul, PrecomputedMultiscalarMul};
|
||||
use traits::MultiscalarMul;
|
||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||
use traits::{VartimeMultiscalarMul, VartimePrecomputedMultiscalarMul};
|
||||
|
||||
|
|
@ -673,13 +673,6 @@ impl VartimeMultiscalarMul for EdwardsPoint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Precomputation for multiscalar multiplication with `EdwardsPoint`s.
|
||||
// This wraps the inner implementation in a facade type so that we can
|
||||
// decouple stability of the inner type from the stability of the
|
||||
// outer type.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub struct EdwardsPrecomputation(scalar_mul::precomputed_straus::PrecomputedStraus);
|
||||
|
||||
/// Precomputation for variable-time multiscalar multiplication with `EdwardsPoint`s.
|
||||
// This wraps the inner implementation in a facade type so that we can
|
||||
// decouple stability of the inner type from the stability of the
|
||||
|
|
@ -687,39 +680,6 @@ pub struct EdwardsPrecomputation(scalar_mul::precomputed_straus::PrecomputedStra
|
|||
#[cfg(feature = "alloc")]
|
||||
pub struct VartimeEdwardsPrecomputation(scalar_mul::precomputed_straus::VartimePrecomputedStraus);
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl PrecomputedMultiscalarMul for EdwardsPrecomputation {
|
||||
type Point = EdwardsPoint;
|
||||
|
||||
fn new<I>(static_points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Self::Point>,
|
||||
{
|
||||
Self(scalar_mul::precomputed_straus::PrecomputedStraus::new(
|
||||
static_points,
|
||||
))
|
||||
}
|
||||
|
||||
fn mixed_multiscalar_mul<I, J, K>(
|
||||
&self,
|
||||
static_scalars: I,
|
||||
dynamic_scalars: J,
|
||||
dynamic_points: K,
|
||||
) -> Self::Point
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Scalar>,
|
||||
J: IntoIterator,
|
||||
J::Item: Borrow<Scalar>,
|
||||
K: IntoIterator,
|
||||
K::Item: Borrow<Self::Point>,
|
||||
{
|
||||
self.0
|
||||
.mixed_multiscalar_mul(static_scalars, dynamic_scalars, dynamic_points)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl VartimePrecomputedMultiscalarMul for VartimeEdwardsPrecomputation {
|
||||
type Point = EdwardsPoint;
|
||||
|
|
@ -1280,49 +1240,6 @@ mod test {
|
|||
assert!(P1.compress().to_bytes() == P2.compress().to_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn precomputed_vs_nonprecomputed_multiscalar() {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let B = &::constants::ED25519_BASEPOINT_TABLE;
|
||||
|
||||
let static_scalars = (0..128)
|
||||
.map(|_| Scalar::random(&mut rng))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let dynamic_scalars = (0..128)
|
||||
.map(|_| Scalar::random(&mut rng))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let check_scalar: Scalar = static_scalars
|
||||
.iter()
|
||||
.chain(dynamic_scalars.iter())
|
||||
.map(|s| s * s)
|
||||
.sum();
|
||||
|
||||
let static_points = static_scalars.iter().map(|s| s * B).collect::<Vec<_>>();
|
||||
let dynamic_points = dynamic_scalars.iter().map(|s| s * B).collect::<Vec<_>>();
|
||||
|
||||
let precomputation = EdwardsPrecomputation::new(static_points.iter());
|
||||
|
||||
let P = precomputation.mixed_multiscalar_mul(
|
||||
&static_scalars,
|
||||
&dynamic_scalars,
|
||||
&dynamic_points,
|
||||
);
|
||||
|
||||
use traits::MultiscalarMul;
|
||||
let Q = EdwardsPoint::multiscalar_mul(
|
||||
static_scalars.iter().chain(dynamic_scalars.iter()),
|
||||
static_points.iter().chain(dynamic_points.iter()),
|
||||
);
|
||||
|
||||
let R = &check_scalar * B;
|
||||
|
||||
assert_eq!(P.compress(), R.compress());
|
||||
assert_eq!(Q.compress(), R.compress());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vartime_precomputed_vs_nonprecomputed_multiscalar() {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
|
|
|||
|
|
@ -187,10 +187,7 @@ use scalar::Scalar;
|
|||
|
||||
use traits::Identity;
|
||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||
use traits::{
|
||||
MultiscalarMul, PrecomputedMultiscalarMul, VartimeMultiscalarMul,
|
||||
VartimePrecomputedMultiscalarMul,
|
||||
};
|
||||
use traits::{MultiscalarMul, VartimeMultiscalarMul, VartimePrecomputedMultiscalarMul};
|
||||
|
||||
#[cfg(not(all(
|
||||
feature = "simd_backend",
|
||||
|
|
@ -909,13 +906,6 @@ impl VartimeMultiscalarMul for RistrettoPoint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Precomputation for multiscalar multiplication with `RistrettoPoint`s.
|
||||
// This wraps the inner implementation in a facade type so that we can
|
||||
// decouple stability of the inner type from the stability of the
|
||||
// outer type.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub struct RistrettoPrecomputation(scalar_mul::precomputed_straus::PrecomputedStraus);
|
||||
|
||||
/// Precomputation for variable-time multiscalar multiplication with `RistrettoPoint`s.
|
||||
// This wraps the inner implementation in a facade type so that we can
|
||||
// decouple stability of the inner type from the stability of the
|
||||
|
|
@ -923,42 +913,6 @@ pub struct RistrettoPrecomputation(scalar_mul::precomputed_straus::PrecomputedSt
|
|||
#[cfg(feature = "alloc")]
|
||||
pub struct VartimeRistrettoPrecomputation(scalar_mul::precomputed_straus::VartimePrecomputedStraus);
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl PrecomputedMultiscalarMul for RistrettoPrecomputation {
|
||||
type Point = RistrettoPoint;
|
||||
|
||||
fn new<I>(static_points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Self::Point>,
|
||||
{
|
||||
Self(scalar_mul::precomputed_straus::PrecomputedStraus::new(
|
||||
static_points.into_iter().map(|P| P.borrow().0),
|
||||
))
|
||||
}
|
||||
|
||||
fn mixed_multiscalar_mul<I, J, K>(
|
||||
&self,
|
||||
static_scalars: I,
|
||||
dynamic_scalars: J,
|
||||
dynamic_points: K,
|
||||
) -> Self::Point
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Scalar>,
|
||||
J: IntoIterator,
|
||||
J::Item: Borrow<Scalar>,
|
||||
K: IntoIterator,
|
||||
K::Item: Borrow<Self::Point>,
|
||||
{
|
||||
RistrettoPoint(self.0.mixed_multiscalar_mul(
|
||||
static_scalars,
|
||||
dynamic_scalars,
|
||||
dynamic_points.into_iter().map(|P| P.borrow().0),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl VartimePrecomputedMultiscalarMul for VartimeRistrettoPrecomputation {
|
||||
type Point = RistrettoPoint;
|
||||
|
|
@ -1366,49 +1320,6 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn precomputed_vs_nonprecomputed_multiscalar() {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let B = &::constants::RISTRETTO_BASEPOINT_TABLE;
|
||||
|
||||
let static_scalars = (0..128)
|
||||
.map(|_| Scalar::random(&mut rng))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let dynamic_scalars = (0..128)
|
||||
.map(|_| Scalar::random(&mut rng))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let check_scalar: Scalar = static_scalars
|
||||
.iter()
|
||||
.chain(dynamic_scalars.iter())
|
||||
.map(|s| s * s)
|
||||
.sum();
|
||||
|
||||
let static_points = static_scalars.iter().map(|s| s * B).collect::<Vec<_>>();
|
||||
let dynamic_points = dynamic_scalars.iter().map(|s| s * B).collect::<Vec<_>>();
|
||||
|
||||
let precomputation = RistrettoPrecomputation::new(static_points.iter());
|
||||
|
||||
let P = precomputation.mixed_multiscalar_mul(
|
||||
&static_scalars,
|
||||
&dynamic_scalars,
|
||||
&dynamic_points,
|
||||
);
|
||||
|
||||
use traits::MultiscalarMul;
|
||||
let Q = RistrettoPoint::multiscalar_mul(
|
||||
static_scalars.iter().chain(dynamic_scalars.iter()),
|
||||
static_points.iter().chain(dynamic_points.iter()),
|
||||
);
|
||||
|
||||
let R = &check_scalar * B;
|
||||
|
||||
assert_eq!(P.compress(), R.compress());
|
||||
assert_eq!(Q.compress(), R.compress());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vartime_precomputed_vs_nonprecomputed_multiscalar() {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
|
|
|||
|
|
@ -225,86 +225,6 @@ pub trait VartimeMultiscalarMul {
|
|||
}
|
||||
}
|
||||
|
||||
/// A trait for constant-time multiscalar multiplication with precomputation.
|
||||
///
|
||||
/// A general multiscalar multiplication with precomputation can be written as
|
||||
/// $$
|
||||
/// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m,
|
||||
/// $$
|
||||
/// where the \\(B_i\\) are *static* points, for which precomputation
|
||||
/// is possible, and the \\(A_j\\) are *dynamic* points, for which
|
||||
/// precomputation is not possible.
|
||||
pub trait PrecomputedMultiscalarMul: Sized {
|
||||
/// The type of point to be multiplied, e.g., `RistrettoPoint`.
|
||||
type Point;
|
||||
|
||||
/// Given the static points \\( B_i \\), perform precomputation
|
||||
/// and return the precomputation data.
|
||||
fn new<I>(static_points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Self::Point>;
|
||||
|
||||
/// Given `static_scalars`, an iterator of (possibly secret)
|
||||
/// scalars \\(b_i\\), `dynamic_scalars`, an iterator of (possibly
|
||||
/// secret) scalars \\(a_i\\), and `dynamic_points`, an iterator
|
||||
/// of points \\(A_i\\), compute
|
||||
/// $$
|
||||
/// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m,
|
||||
/// $$
|
||||
/// where the \\(B_j\\) are the points that were supplied to `new`.
|
||||
///
|
||||
/// It is an error to call this function with iterators of
|
||||
/// inconsistent lengths.
|
||||
///
|
||||
/// The trait bound aims for maximum flexibility: the inputs must be
|
||||
/// convertable to iterators (`I: IntoIter`), and the iterator's items
|
||||
/// must be `Borrow<Scalar>` (or `Borrow<Point>`), to allow
|
||||
/// iterators returning either `Scalar`s or `&Scalar`s.
|
||||
fn mixed_multiscalar_mul<I, J, K>(
|
||||
&self,
|
||||
static_scalars: I,
|
||||
dynamic_scalars: J,
|
||||
dynamic_points: K,
|
||||
) -> Self::Point
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Scalar>,
|
||||
J: IntoIterator,
|
||||
J::Item: Borrow<Scalar>,
|
||||
K: IntoIterator,
|
||||
K::Item: Borrow<Self::Point>;
|
||||
|
||||
/// Given `static_scalars`, an iterator of (possibly secret)
|
||||
/// scalars \\(b_i\\), compute
|
||||
/// $$
|
||||
/// Q = b_1 B_1 + \cdots + b_m B_m,
|
||||
/// $$
|
||||
/// where the \\(B_j\\) are the points that were supplied to `new`.
|
||||
///
|
||||
/// It is an error to call this function with iterators of
|
||||
/// inconsistent lengths.
|
||||
///
|
||||
/// The trait bound aims for maximum flexibility: the input must
|
||||
/// be convertable to iterators (`I: IntoIter`), and the
|
||||
/// iterator's items must be `Borrow<Scalar>`, to allow iterators
|
||||
/// returning either `Scalar`s or `&Scalar`s.
|
||||
fn multiscalar_mul<I>(&self, static_scalars: I) -> Self::Point
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<Scalar>,
|
||||
{
|
||||
use core::iter;
|
||||
|
||||
Self::mixed_multiscalar_mul(
|
||||
self,
|
||||
static_scalars,
|
||||
iter::empty::<Scalar>(),
|
||||
iter::empty::<Self::Point>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for variable-time multiscalar multiplication with precomputation.
|
||||
///
|
||||
/// A general multiscalar multiplication with precomputation can be written as
|
||||
|
|
|
|||
Loading…
Reference in a new issue