serai/crypto/multiexp/src/lib.rs

50 lines
1.5 KiB
Rust
Raw Normal View History

2022-06-07 04:02:10 +00:00
use group::Group;
2022-06-07 04:02:10 +00:00
mod straus;
use straus::*;
2022-06-07 04:02:10 +00:00
mod pippenger;
use pippenger::*;
2022-06-07 04:02:10 +00:00
#[cfg(feature = "batch")]
mod batch;
#[cfg(feature = "batch")]
pub use batch::BatchVerifier;
2022-06-07 04:02:10 +00:00
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum Algorithm {
Straus,
Pippenger
}
2022-06-07 04:02:10 +00:00
fn algorithm(pairs: usize) -> Algorithm {
// TODO: Replace this with an actual formula determining which will use less additions
// Right now, Straus is used until 600, instead of the far more accurate 300, as Pippenger
// operates per byte instead of per nibble, and therefore requires a much longer series to be
// performant
// Technically, 800 is dalek's number for when to use byte Pippenger, yet given Straus's own
// implementation limitations...
if pairs < 600 {
Algorithm::Straus
} else {
Algorithm::Pippenger
}
}
2022-06-07 04:02:10 +00:00
// Performs a multiexp, automatically selecting the optimal algorithm based on amount of pairs
// Takes in an iterator of scalars and points, with a boolean for if the scalars are little endian
// encoded in their Reprs or not
pub fn multiexp<G: Group>(pairs: &[(G::Scalar, G)], little: bool) -> G {
match algorithm(pairs.len()) {
Algorithm::Straus => straus(pairs, little),
Algorithm::Pippenger => pippenger(pairs, little)
}
}
2022-06-07 04:02:10 +00:00
pub fn multiexp_vartime<G: Group>(pairs: &[(G::Scalar, G)], little: bool) -> G {
match algorithm(pairs.len()) {
Algorithm::Straus => straus_vartime(pairs, little),
Algorithm::Pippenger => pippenger_vartime(pairs, little)
}
}