From aa8540c2c9607b4da21a25002b939d58d47fa433 Mon Sep 17 00:00:00 2001 From: Victor Lopez Date: Tue, 16 Nov 2021 20:04:30 +0100 Subject: [PATCH] Add `ec:msm:{Fixed,Variable}Base:msm_checked_len` Add the new methods for checked fixed and variable base multi-scalar multiplication. They will return `None` if the arguments don't have the same length. This way, the users may confidently call this function without having to check the length themselves. Also, `ec:msm:{Fixed,Variable}BaseMSM` was renamed to `ec:msm::{Fixed,Variable}Base` to avoid redundancy. The import path contained `msm` several times, and now it contains only one incidence for the type resolution and one for the function call. Closes #319 --- CHANGELOG.md | 2 ++ ec/src/msm/fixed_base.rs | 8 +++--- ec/src/msm/variable_base.rs | 26 ++++++++++++++++--- test-curves/src/bls12_381/tests.rs | 7 ++++- .../src/bn384_small_two_adicity/tests.rs | 7 ++++- test-templates/src/msm.rs | 4 +-- 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 197654801..08995f8e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,12 +10,14 @@ - [\#338](https://github.com/arkworks-rs/algebra/pull/338) (ark-ec) Add missing `UniformRand` trait bound to `GroupAffine`. - [\#338](https://github.com/arkworks-rs/algebra/pull/338) (workspace) Change to Rust 2021 edition. - [\#345](https://github.com/arkworks-rs/algebra/pull/345) (arc-ec, ark-serialize) Change the serialization format for Twisted Edwards Curves. We now encode the Y coordinate and take the sign bit of the X co-ordinate, the default flag is also now the Positive X value. The old methods for backwards compatibility are located [here](https://github.com/arkworks-rs/algebra/pull/345/files#diff-3621a48bb33f469144044d8d5fc663f767e103132a764812cda6be6c25877494R860) +- [\#348](https://github.com/arkworks-rs/algebra/pull/348) (arc-ec) Rename `msm:{Fixed,Variable}BaseMSM:multi_scalar_mul` to `msm:{Fixed,Variable}:msm` to avoid redundancy. ### Features - [\#321](https://github.com/arkworks-rs/algebra/pull/321) (ark-ff) Change bigint conversions to impl `From` instead of `Into`. - [\#301](https://github.com/arkworks-rs/algebra/pull/301) (ark-ec) Add `GLVParameters` trait definition. - [\#312](https://github.com/arkworks-rs/algebra/pull/312) (ark-ec) Add `is_in_correct_subgroup_assuming_on_curve` for all `SWModelParameters`. +- [\#348](https://github.com/arkworks-rs/algebra/pull/348) (ark-ec) Add `msm:{Fixed,Variable}Base:msm_checked_len`. ### Improvements diff --git a/ec/src/msm/fixed_base.rs b/ec/src/msm/fixed_base.rs index ea7c29f75..27360fe38 100644 --- a/ec/src/msm/fixed_base.rs +++ b/ec/src/msm/fixed_base.rs @@ -5,9 +5,9 @@ use ark_std::{cfg_iter, cfg_iter_mut, vec::Vec}; #[cfg(feature = "parallel")] use rayon::prelude::*; -pub struct FixedBaseMSM; +pub struct FixedBase; -impl FixedBaseMSM { +impl FixedBase { pub fn get_mul_window_size(num_scalars: usize) -> usize { if num_scalars < 32 { 3 @@ -79,7 +79,9 @@ impl FixedBaseMSM { res } - pub fn multi_scalar_mul( + // TODO use const-generics for the scalar size and window + // TODO use iterators of iterators of T::Affine instead of taking owned Vec + pub fn msm( scalar_size: usize, window: usize, table: &[Vec], diff --git a/ec/src/msm/variable_base.rs b/ec/src/msm/variable_base.rs index 57f4fa4d7..14031cffc 100644 --- a/ec/src/msm/variable_base.rs +++ b/ec/src/msm/variable_base.rs @@ -6,10 +6,30 @@ use crate::{AffineCurve, ProjectiveCurve}; #[cfg(feature = "parallel")] use rayon::prelude::*; -pub struct VariableBaseMSM; +pub struct VariableBase; -impl VariableBaseMSM { - pub fn multi_scalar_mul( +impl VariableBase { + /// Optimized implementation of multi-scalar multiplication. + /// + /// Will return `None` if `bases` and `scalar` have different lengths. + /// + /// Reference: [`VariableBase::msm`] + pub fn msm_checked_len( + bases: &[G], + scalars: &[::BigInt], + ) -> Option { + (bases.len() == scalars.len()).then(|| Self::msm(bases, scalars)) + } + + /// Optimized implementation of multi-scalar multiplication. + /// + /// Will multiply the tuples of the diagonal product of `bases × scalars` + /// and sum the resulting set. Will iterate only for the elements of the + /// smallest of the two sets, ignoring the remaining elements of the biggest + /// set. + /// + /// ∑i (Bi · Si) + pub fn msm( bases: &[G], scalars: &[::BigInt], ) -> G::Projective { diff --git a/test-curves/src/bls12_381/tests.rs b/test-curves/src/bls12_381/tests.rs index 7c83fe4d7..d61dfdee4 100644 --- a/test-curves/src/bls12_381/tests.rs +++ b/test-curves/src/bls12_381/tests.rs @@ -3,7 +3,7 @@ use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCu use ark_ff::{Field, One, UniformRand, Zero}; use crate::bls12_381::{g1, Fq, Fq2, Fq6, FqParameters, Fr, G1Affine, G1Projective}; -use ark_algebra_test_templates::{curves::*, fields::*, groups::*}; +use ark_algebra_test_templates::{curves::*, fields::*, groups::*, msm::*}; use ark_std::rand::Rng; pub(crate) const ITERATIONS: usize = 5; @@ -55,6 +55,11 @@ fn test_fq6() { frobenius_test::(Fq::characteristic(), 13); } +#[test] +fn test_g1_affine_curve() { + test_var_base_msm::(); +} + #[test] fn test_g1_projective_curve() { curve_tests::(); diff --git a/test-curves/src/bn384_small_two_adicity/tests.rs b/test-curves/src/bn384_small_two_adicity/tests.rs index 6268718f9..05c3c6c46 100644 --- a/test-curves/src/bn384_small_two_adicity/tests.rs +++ b/test-curves/src/bn384_small_two_adicity/tests.rs @@ -4,7 +4,7 @@ use ark_ff::{One, UniformRand, Zero}; use ark_std::rand::Rng; use crate::bn384_small_two_adicity::{g1, Fq, FqParameters, Fr, G1Affine, G1Projective}; -use ark_algebra_test_templates::{curves::*, fields::*, groups::*}; +use ark_algebra_test_templates::{curves::*, fields::*, groups::*, msm::*}; pub(crate) const ITERATIONS: usize = 5; @@ -32,6 +32,11 @@ fn test_fq() { } } +#[test] +fn test_g1_affine_curve() { + test_var_base_msm::(); +} + #[test] fn test_g1_projective_curve() { curve_tests::(); diff --git a/test-templates/src/msm.rs b/test-templates/src/msm.rs index 7d06a1c7b..5c92bcdda 100644 --- a/test-templates/src/msm.rs +++ b/test-templates/src/msm.rs @@ -1,4 +1,4 @@ -use ark_ec::{msm::VariableBaseMSM, AffineCurve, ProjectiveCurve}; +use ark_ec::{msm::VariableBase, AffineCurve, ProjectiveCurve}; use ark_ff::{PrimeField, UniformRand, Zero}; fn naive_var_base_msm( @@ -27,7 +27,7 @@ pub fn test_var_base_msm() { let g = ::batch_normalization_into_affine(&g); let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); - let fast = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + let fast = VariableBase::msm(g.as_slice(), v.as_slice()); assert_eq!(naive.into_affine(), fast.into_affine()); }