diff --git a/benches/dalek_benchmarks.rs b/benches/dalek_benchmarks.rs index 71792a3..011e6a6 100644 --- a/benches/dalek_benchmarks.rs +++ b/benches/dalek_benchmarks.rs @@ -25,9 +25,7 @@ mod edwards_benches { fn compress(c: &mut Criterion) { let B = &constants::ED25519_BASEPOINT_POINT; - c.bench_function("EdwardsPoint compression", move |b| { - b.iter(|| B.compress()) - }); + c.bench_function("EdwardsPoint compression", move |b| b.iter(|| B.compress())); } fn decompress(c: &mut Criterion) { @@ -63,16 +61,40 @@ mod edwards_benches { }); } + criterion_group!{ + name = edwards_benches; + config = Criterion::default(); + targets = + compress, + decompress, + consttime_fixed_base_scalar_mul, + consttime_variable_base_scalar_mul, + vartime_double_base_scalar_mul, + } +} + +mod multiscalar_benches { + use super::*; + use curve25519_dalek::edwards; + use curve25519_dalek::edwards::EdwardsPoint; + use curve25519_dalek::traits::MultiscalarMul; + use curve25519_dalek::traits::VartimeMultiscalarMul; + + fn construct(n: usize) -> (Vec, Vec) { + let mut rng = OsRng::new().unwrap(); + let scalars: Vec = (0..n).map(|_| Scalar::random(&mut rng)).collect(); + let points: Vec = scalars + .iter() + .map(|s| s * &constants::ED25519_BASEPOINT_TABLE) + .collect(); + (scalars, points) + } + fn consttime_multiscalar_mul(c: &mut Criterion) { c.bench_function_over_inputs( "Constant-time variable-base multiscalar multiplication", |b, &&size| { - let mut rng = OsRng::new().unwrap(); - let scalars: Vec = (0..size).map(|_| Scalar::random(&mut rng)).collect(); - let points: Vec = scalars - .iter() - .map(|s| s * &constants::ED25519_BASEPOINT_TABLE) - .collect(); + let (scalars, points) = construct(size); b.iter(|| EdwardsPoint::multiscalar_mul(&scalars, &points)); }, &MULTISCALAR_SIZES, @@ -83,29 +105,112 @@ mod edwards_benches { c.bench_function_over_inputs( "Variable-time variable-base multiscalar multiplication", |b, &&size| { - let mut rng = OsRng::new().unwrap(); - let scalars: Vec = (0..size).map(|_| Scalar::random(&mut rng)).collect(); - let points: Vec = scalars - .iter() - .map(|s| s * &constants::ED25519_BASEPOINT_TABLE) - .collect(); + let (scalars, points) = construct(size); b.iter(|| EdwardsPoint::vartime_multiscalar_mul(&scalars, &points)); }, &MULTISCALAR_SIZES, ); } + 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::PrecomputedStraus; + use curve25519_dalek::traits::PrecomputedMultiscalarMul; + + let precomp = PrecomputedStraus::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)", + 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::VartimePrecomputedStraus; + use curve25519_dalek::traits::VartimePrecomputedMultiscalarMul; + + let precomp = VartimePrecomputedStraus::new(&static_points); + + b.iter(|| { + precomp.vartime_mixed_multiscalar_mul( + &static_scalars, + &dynamic_scalars, + &dynamic_points, + ) + }); + }, + &MULTISCALAR_SIZES, + ); + } + + 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); + } + + fn precomputed_vt_straus_20_pct_dynamic(c: &mut Criterion) { + precomputed_vt_straus_helper(c, 0.2); + } + + fn precomputed_vt_straus_50_pct_dynamic(c: &mut Criterion) { + precomputed_vt_straus_helper(c, 0.5); + } + criterion_group!{ - name = edwards_benches; - config = Criterion::default(); + name = multiscalar_benches; + // Lower the sample size to run the benchmarks faster + config = Criterion::default().sample_size(15); targets = - compress, - decompress, - consttime_fixed_base_scalar_mul, - consttime_variable_base_scalar_mul, - vartime_double_base_scalar_mul, 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, } } @@ -208,4 +313,5 @@ criterion_main!( montgomery_benches::montgomery_benches, ristretto_benches::ristretto_benches, edwards_benches::edwards_benches, + multiscalar_benches::multiscalar_benches, );