mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
3.7.5 Further document multiexp functions
This commit is contained in:
@@ -19,6 +19,8 @@ pub use batch::BatchVerifier;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
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<G: Group>(pairs: &[(G::Scalar, G)], window: u8) -> Vec<Vec<u8>>
|
pub(crate) fn prep_bits<G: Group>(pairs: &[(G::Scalar, G)], window: u8) -> Vec<Vec<u8>>
|
||||||
where
|
where
|
||||||
G::Scalar: PrimeFieldBits,
|
G::Scalar: PrimeFieldBits,
|
||||||
@@ -31,10 +33,9 @@ where
|
|||||||
let mut bits = pair.0.to_le_bits();
|
let mut bits = pair.0.to_le_bits();
|
||||||
groupings.push(vec![0; (bits.len() + (w_usize - 1)) / w_usize]);
|
groupings.push(vec![0; (bits.len() + (w_usize - 1)) / w_usize]);
|
||||||
|
|
||||||
#[allow(unused_assignments)]
|
|
||||||
for (i, mut raw_bit) in bits.iter_mut().enumerate() {
|
for (i, mut raw_bit) in bits.iter_mut().enumerate() {
|
||||||
let mut bit = u8::from(*raw_bit);
|
let mut bit = u8::from(*raw_bit);
|
||||||
*raw_bit = false;
|
(*raw_bit).zeroize();
|
||||||
|
|
||||||
groupings[p][i / w_usize] |= bit << (i % w_usize);
|
groupings[p][i / w_usize] |= bit << (i % w_usize);
|
||||||
bit.zeroize();
|
bit.zeroize();
|
||||||
@@ -44,20 +45,6 @@ where
|
|||||||
groupings
|
groupings
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn prep_tables<G: Group>(pairs: &[(G::Scalar, G)], window: u8) -> Vec<Vec<G>> {
|
|
||||||
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)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
enum Algorithm {
|
enum Algorithm {
|
||||||
Null,
|
Null,
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ use group::Group;
|
|||||||
|
|
||||||
use crate::prep_bits;
|
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<G: Group>(pairs: &[(G::Scalar, G)], window: u8) -> G
|
pub(crate) fn pippenger<G: Group>(pairs: &[(G::Scalar, G)], window: u8) -> G
|
||||||
where
|
where
|
||||||
G::Scalar: PrimeFieldBits,
|
G::Scalar: PrimeFieldBits,
|
||||||
|
|||||||
@@ -3,8 +3,25 @@ use zeroize::Zeroize;
|
|||||||
use ff::PrimeFieldBits;
|
use ff::PrimeFieldBits;
|
||||||
use group::Group;
|
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<G: Group>(pairs: &[(G::Scalar, G)], window: u8) -> Vec<Vec<G>> {
|
||||||
|
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<G: Group>(pairs: &[(G::Scalar, G)], window: u8) -> G
|
pub(crate) fn straus<G: Group>(pairs: &[(G::Scalar, G)], window: u8) -> G
|
||||||
where
|
where
|
||||||
G::Scalar: PrimeFieldBits + Zeroize,
|
G::Scalar: PrimeFieldBits + Zeroize,
|
||||||
|
|||||||
Reference in New Issue
Block a user