diff --git a/crypto/multiexp/src/lib.rs b/crypto/multiexp/src/lib.rs index 321c5b87..df4da3e3 100644 --- a/crypto/multiexp/src/lib.rs +++ b/crypto/multiexp/src/lib.rs @@ -19,6 +19,8 @@ pub use batch::BatchVerifier; #[cfg(test)] mod tests; +// Convert scalars to `window`-sized bit groups, as needed to index a table +// This algorithm works for `window <= 8` pub(crate) fn prep_bits(pairs: &[(G::Scalar, G)], window: u8) -> Vec> where G::Scalar: PrimeFieldBits, @@ -31,10 +33,9 @@ where let mut bits = pair.0.to_le_bits(); groupings.push(vec![0; (bits.len() + (w_usize - 1)) / w_usize]); - #[allow(unused_assignments)] for (i, mut raw_bit) in bits.iter_mut().enumerate() { let mut bit = u8::from(*raw_bit); - *raw_bit = false; + (*raw_bit).zeroize(); groupings[p][i / w_usize] |= bit << (i % w_usize); bit.zeroize(); @@ -44,20 +45,6 @@ where groupings } -pub(crate) fn prep_tables(pairs: &[(G::Scalar, G)], window: u8) -> Vec> { - let mut tables = Vec::with_capacity(pairs.len()); - for pair in pairs { - let p = tables.len(); - tables.push(vec![G::identity(); 2_usize.pow(window.into())]); - let mut accum = G::identity(); - for i in 1 .. tables[p].len() { - accum += pair.1; - tables[p][i] = accum; - } - } - tables -} - #[derive(Clone, Copy, PartialEq, Eq, Debug)] enum Algorithm { Null, diff --git a/crypto/multiexp/src/pippenger.rs b/crypto/multiexp/src/pippenger.rs index 79d945cb..aca872d0 100644 --- a/crypto/multiexp/src/pippenger.rs +++ b/crypto/multiexp/src/pippenger.rs @@ -5,6 +5,8 @@ use group::Group; use crate::prep_bits; +// Pippenger's algorithm for multiexponentation, as published in the SIAM Journal on Computing +// DOI: 10.1137/0209022 pub(crate) fn pippenger(pairs: &[(G::Scalar, G)], window: u8) -> G where G::Scalar: PrimeFieldBits, diff --git a/crypto/multiexp/src/straus.rs b/crypto/multiexp/src/straus.rs index a670cc74..283d7948 100644 --- a/crypto/multiexp/src/straus.rs +++ b/crypto/multiexp/src/straus.rs @@ -3,8 +3,25 @@ use zeroize::Zeroize; use ff::PrimeFieldBits; use group::Group; -use crate::{prep_bits, prep_tables}; +use crate::prep_bits; +// Create tables for every included point of size 2^window +fn prep_tables(pairs: &[(G::Scalar, G)], window: u8) -> Vec> { + let mut tables = Vec::with_capacity(pairs.len()); + for pair in pairs { + let p = tables.len(); + tables.push(vec![G::identity(); 2_usize.pow(window.into())]); + let mut accum = G::identity(); + for i in 1 .. tables[p].len() { + accum += pair.1; + tables[p][i] = accum; + } + } + tables +} + +// Straus's algorithm for multiexponentation, as published in The American Mathematical Monthly +// DOI: 10.2307/2310929 pub(crate) fn straus(pairs: &[(G::Scalar, G)], window: u8) -> G where G::Scalar: PrimeFieldBits + Zeroize,