mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Implement variable-sized windows into multiexp
Closes https://github.com/serai-dex/serai/issues/17 by using the PrimeFieldBits API to do so. Should greatly speed up small batches, along with batches in the hundreds. Saves almost a full second on the cross-group DLEq proof.
This commit is contained in:
@@ -35,8 +35,6 @@ macro_rules! dalek_curve {
|
||||
const GENERATOR: Self::G = $POINT;
|
||||
const GENERATOR_TABLE: Self::T = &$TABLE;
|
||||
|
||||
const LITTLE_ENDIAN: bool = true;
|
||||
|
||||
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F {
|
||||
let mut seed = vec![0; 32];
|
||||
rng.fill_bytes(&mut seed);
|
||||
|
||||
@@ -29,8 +29,6 @@ macro_rules! kp_curve {
|
||||
const GENERATOR: Self::G = $lib::ProjectivePoint::GENERATOR;
|
||||
const GENERATOR_TABLE: Self::G = $lib::ProjectivePoint::GENERATOR;
|
||||
|
||||
const LITTLE_ENDIAN: bool = false;
|
||||
|
||||
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F {
|
||||
let mut seed = vec![0; 32];
|
||||
rng.fill_bytes(&mut seed);
|
||||
|
||||
@@ -4,7 +4,8 @@ use thiserror::Error;
|
||||
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use group::{ff::PrimeField, Group, GroupOps, prime::PrimeGroup};
|
||||
use ff::{PrimeField, PrimeFieldBits};
|
||||
use group::{Group, GroupOps, prime::PrimeGroup};
|
||||
|
||||
#[cfg(any(test, feature = "dalek"))]
|
||||
mod dalek;
|
||||
@@ -40,7 +41,7 @@ pub enum CurveError {
|
||||
pub trait Curve: Clone + Copy + PartialEq + Eq + Debug {
|
||||
/// Scalar field element type
|
||||
// This is available via G::Scalar yet `C::G::Scalar` is ambiguous, forcing horrific accesses
|
||||
type F: PrimeField;
|
||||
type F: PrimeField + PrimeFieldBits;
|
||||
/// Group element type
|
||||
type G: Group<Scalar = Self::F> + GroupOps + PrimeGroup;
|
||||
/// Precomputed table type
|
||||
@@ -57,9 +58,6 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug {
|
||||
/// If there isn't a precomputed table available, the generator itself should be used
|
||||
const GENERATOR_TABLE: Self::T;
|
||||
|
||||
/// If little endian is used for the scalar field's Repr
|
||||
const LITTLE_ENDIAN: bool;
|
||||
|
||||
/// Securely generate a random nonce. H4 from the IETF draft
|
||||
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F;
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ fn complete_r2<R: RngCore + CryptoRng, C: Curve>(
|
||||
res
|
||||
};
|
||||
|
||||
let mut batch = BatchVerifier::new(shares.len(), C::LITTLE_ENDIAN);
|
||||
let mut batch = BatchVerifier::new(shares.len());
|
||||
for (l, share) in &shares {
|
||||
if *l == params.i() {
|
||||
continue;
|
||||
@@ -254,7 +254,7 @@ fn complete_r2<R: RngCore + CryptoRng, C: Curve>(
|
||||
// Calculate each user's verification share
|
||||
let mut verification_shares = HashMap::new();
|
||||
for i in 1 ..= params.n() {
|
||||
verification_shares.insert(i, multiexp_vartime(&exponential(i, &stripes), C::LITTLE_ENDIAN));
|
||||
verification_shares.insert(i, multiexp_vartime(&exponential(i, &stripes)));
|
||||
}
|
||||
// Removing this check would enable optimizing the above from t + (n * t) to t + ((n - 1) * t)
|
||||
debug_assert_eq!(C::GENERATOR_TABLE * secret_share, verification_shares[¶ms.i()]);
|
||||
|
||||
@@ -46,7 +46,7 @@ pub(crate) fn batch_verify<C: Curve, R: RngCore + CryptoRng>(
|
||||
triplets: &[(u16, C::G, C::F, SchnorrSignature<C>)]
|
||||
) -> Result<(), u16> {
|
||||
let mut values = [(C::F::one(), C::GENERATOR); 3];
|
||||
let mut batch = BatchVerifier::new(triplets.len(), C::LITTLE_ENDIAN);
|
||||
let mut batch = BatchVerifier::new(triplets.len());
|
||||
for triple in triplets {
|
||||
// s = r + ca
|
||||
// sG == R + cA
|
||||
|
||||
@@ -21,7 +21,8 @@ pub fn test_curve<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
// TODO: Test the Curve functions themselves
|
||||
|
||||
// Test successful multiexp, with enough pairs to trigger its variety of algorithms
|
||||
// TODO: This should probably be under multiexp
|
||||
// Multiexp has its own tests, yet only against k256 and Ed25519 (which should be sufficient
|
||||
// as-is to prove multiexp), and this doesn't hurt
|
||||
{
|
||||
let mut pairs = Vec::with_capacity(1000);
|
||||
let mut sum = C::G::identity();
|
||||
@@ -30,8 +31,8 @@ pub fn test_curve<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
pairs.push((C::F::random(&mut *rng), C::GENERATOR * C::F::random(&mut *rng)));
|
||||
sum += pairs[pairs.len() - 1].1 * pairs[pairs.len() - 1].0;
|
||||
}
|
||||
assert_eq!(multiexp::multiexp(&pairs, C::LITTLE_ENDIAN), sum);
|
||||
assert_eq!(multiexp::multiexp_vartime(&pairs, C::LITTLE_ENDIAN), sum);
|
||||
assert_eq!(multiexp::multiexp(&pairs), sum);
|
||||
assert_eq!(multiexp::multiexp_vartime(&pairs), sum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user