GLV implementation for BLS12_377, BLS12_381 and BN254 (#158)
jump to
@@ -11,6 +11,7 @@
### Improvements - [\#156](https://github.com/arkworks-rs/curves/pull/156) The hard part of the final exponentiation for bw6-761 relocated from arkworks/algebra. +- [\#158](https://github.com/arkworks-rs/curves/pull/158) Enabled GLV as the default scalar multiplication for BLS12-377, BLS12-381 and BN254. ### Bugfixes
@@ -3,14 +3,15 @@ bls12,
bls12::Bls12Config, hashing::curve_maps::wb::{IsogenyMap, WBConfig}, models::{ - short_weierstrass::{Affine as SWAffine, SWCurveConfig}, + short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig}, twisted_edwards::{ Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig, }, }, + scalar_mul::glv::GLVConfig, CurveConfig, }; -use ark_ff::{AdditiveGroup, Field, MontFp, PrimeField, Zero}; +use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero}; use ark_std::{ops::Neg, One}; use super::g1_swu_iso::{SwuIsoConfig, ISOGENY_MAP_TO_G1};@@ -50,12 +51,46 @@ Self::BaseField::zero()
} #[inline] + fn mul_projective(p: &G1Projective, scalar: &[u64]) -> G1Projective { + let s = Self::ScalarField::from_sign_and_limbs(true, scalar); + GLVConfig::glv_mul_projective(*p, s) + } + + #[inline] fn clear_cofactor(p: &G1SWAffine) -> G1SWAffine { // Using the effective cofactor. // // It is enough to multiply by (x - 1), instead of (x - 1)^2 / 3 let h_eff = x_minus_one().into_bigint(); <Config as SWCurveConfig>::mul_affine(p, h_eff.as_ref()).into() + } +} + +impl GLVConfig for Config { + const ENDO_COEFFS: &'static[Self::BaseField] = &[ + MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231") + ]; + + const LAMBDA: Self::ScalarField = + MontFp!("8444461749428370424248824938781546531284005582649182570233710176290576793600"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + (true, BigInt!("91893752504881257701523279626832445441")), + (true, BigInt!("1")), + (false, BigInt!("1")), + (true, BigInt!("91893752504881257701523279626832445440")), + ]; + + fn endomorphism(p: &SWProjective<Self>) -> SWProjective<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &SWAffine<Self>) -> SWAffine<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -2,12 +2,12 @@ use ark_ec::{
bls12, bls12::Bls12Config, hashing::curve_maps::wb::{IsogenyMap, WBConfig}, - models::CurveConfig, + scalar_mul::glv::GLVConfig, short_weierstrass::{Affine, Projective, SWCurveConfig}, - AffineRepr, CurveGroup, PrimeGroup, + AffineRepr, CurveConfig, CurveGroup, PrimeGroup, }; -use ark_ff::{AdditiveGroup, Field, MontFp, Zero}; +use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero}; use ark_std::ops::Neg; use crate::*;@@ -95,6 +95,36 @@ psi2_p2 += tmp2;
psi2_p2 -= x_p; psi2_p2 += &-psi_p; (psi2_p2 - p_projective).into_affine() + } +} + +impl GLVConfig for Config { + const ENDO_COEFFS: &'static[Self::BaseField] = &[ + Fq2::new( + MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"), + Fq::ZERO + ) + ]; + + const LAMBDA: Self::ScalarField = MontFp!("91893752504881257701523279626832445440"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + (false, BigInt!("91893752504881257701523279626832445440")), + (true, BigInt!("1")), + (false, BigInt!("1")), + (false, BigInt!("91893752504881257701523279626832445441")), + ]; + + fn endomorphism(p: &Projective<Self>) -> Projective<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -5,6 +5,8 @@ test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw); test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_377>; msm); test_pairing!(pairing; crate::Bls12_377); +test_group!(g1_glv; G1Projective; glv); +test_group!(g2_glv; G2Projective; glv); test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12377G1"; crate::g1::Config; crate::Fq; crate::Fq; 1); test_h2c!(g2_hc2; "./src/curves/tests"; "BLS12377G2"; crate::g2::Config; crate::Fq2; crate::Fq; 2);
@@ -3,10 +3,11 @@ bls12,
bls12::Bls12Config, hashing::curve_maps::wb::{IsogenyMap, WBConfig}, models::CurveConfig, + scalar_mul::glv::GLVConfig, short_weierstrass::{Affine, SWCurveConfig}, AffineRepr, PrimeGroup, }; -use ark_ff::{AdditiveGroup, MontFp, PrimeField, Zero}; +use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField, Zero}; use ark_serialize::{Compress, SerializationError}; use ark_std::{ops::Neg, One};@@ -50,6 +51,12 @@
#[inline(always)] fn mul_by_a(_: Self::BaseField) -> Self::BaseField { Self::BaseField::zero() + } + + #[inline] + fn mul_projective(p: &G1Projective, scalar: &[u64]) -> G1Projective { + let s = Self::ScalarField::from_sign_and_limbs(true, scalar); + GLVConfig::glv_mul_projective(*p, s) } #[inline]@@ -139,6 +146,34 @@ G1_SERIALIZED_SIZE
} else { G1_SERIALIZED_SIZE * 2 } + } +} + +impl GLVConfig for Config { + const ENDO_COEFFS: &'static[Self::BaseField] = &[ + MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350") + ]; + + const LAMBDA: Self::ScalarField = + MontFp!("52435875175126190479447740508185965837461563690374988244538805122978187051009"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + (true, BigInt!("228988810152649578064853576960394133504")), + (true, BigInt!("1")), + (false, BigInt!("1")), + (true, BigInt!("228988810152649578064853576960394133503")), + ]; + + fn endomorphism(p: &G1Projective) -> G1Projective { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -5,10 +5,11 @@ bls12,
bls12::Bls12Config, hashing::curve_maps::wb::{IsogenyMap, WBConfig}, models::CurveConfig, + scalar_mul::glv::GLVConfig, short_weierstrass::{Affine, Projective, SWCurveConfig}, AffineRepr, CurveGroup, PrimeGroup, }; -use ark_ff::{AdditiveGroup, Field, MontFp, Zero}; +use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero}; use ark_serialize::{Compress, SerializationError}; use super::{@@ -182,6 +183,36 @@ G2_SERIALIZED_SIZE
} else { 2 * G2_SERIALIZED_SIZE } + } +} + +impl GLVConfig for Config { + const ENDO_COEFFS: &'static[Self::BaseField] = &[ + Fq2::new( + MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"), + Fq::ZERO + ) + ]; + + const LAMBDA: Self::ScalarField = MontFp!("228988810152649578064853576960394133503"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + (false, BigInt!("228988810152649578064853576960394133503")), + (true, BigInt!("1")), + (false, BigInt!("1")), + (false, BigInt!("228988810152649578064853576960394133504")), + ]; + + fn endomorphism(p: &Projective<Self>) -> Projective<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -8,6 +8,8 @@ use crate::{Bls12_381, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
test_group!(g1; G1Projective; sw); test_group!(g2; G2Projective; sw); +test_group!(g1_glv; G1Projective; glv); +test_group!(g2_glv; G2Projective; glv); test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_381>; msm); test_pairing!(pairing; crate::Bls12_381); test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12381G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);
@@ -1,8 +1,10 @@
use ark_ec::{ + bn, models::{short_weierstrass::SWCurveConfig, CurveConfig}, - short_weierstrass::Affine, + scalar_mul::glv::GLVConfig, + short_weierstrass::{Affine, Projective}, }; -use ark_ff::{AdditiveGroup, Field, MontFp, Zero}; +use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero}; use crate::{Fq, Fr};@@ -35,6 +37,42 @@
#[inline(always)] fn mul_by_a(_: Self::BaseField) -> Self::BaseField { Self::BaseField::zero() + } + + #[inline] + fn mul_projective( + p: &bn::G1Projective<crate::Config>, + scalar: &[u64], + ) -> bn::G1Projective<crate::Config> { + let s = Self::ScalarField::from_sign_and_limbs(true, scalar); + GLVConfig::glv_mul_projective(*p, s) + } +} + +impl GLVConfig for Config { + const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!( + "21888242871839275220042445260109153167277707414472061641714758635765020556616" + )]; + + const LAMBDA: Self::ScalarField = + MontFp!("21888242871839275217838484774961031246154997185409878258781734729429964517155"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + (false, BigInt!("147946756881789319000765030803803410728")), + (true, BigInt!("9931322734385697763")), + (false, BigInt!("9931322734385697763")), + (false, BigInt!("147946756881789319010696353538189108491")), + ]; + + fn endomorphism(p: &Projective<Self>) -> Projective<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -1,8 +1,9 @@
use ark_ec::{ models::{short_weierstrass::SWCurveConfig, CurveConfig}, - short_weierstrass::Affine, + scalar_mul::glv::GLVConfig, + short_weierstrass::{Affine, Projective}, }; -use ark_ff::{AdditiveGroup, MontFp, Zero}; +use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField, Zero}; use crate::{Fq, Fq2, Fr};@@ -47,6 +48,35 @@
#[inline(always)] fn mul_by_a(_: Self::BaseField) -> Self::BaseField { Self::BaseField::zero() + } +} + +impl GLVConfig for Config { + const ENDO_COEFFS: &'static [Self::BaseField] = &[Fq2::new( + MontFp!("21888242871839275220042445260109153167277707414472061641714758635765020556616"), + Fq::ZERO, + )]; + + const LAMBDA: Self::ScalarField = + MontFp!("4407920970296243842393367215006156084916469457145843978461"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + (false, BigInt!("147946756881789319010696353538189108491")), + (false, BigInt!("9931322734385697763")), + (true, BigInt!("9931322734385697763")), + (false, BigInt!("147946756881789319000765030803803410728")), + ]; + + fn endomorphism(p: &Projective<Self>) -> Projective<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -7,3 +7,5 @@ test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw); test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bn254>; msm); test_pairing!(pairing; crate::Bn254); +test_group!(g1_glv; G1Projective; glv); +test_group!(g2_glv; G2Projective; glv);
@@ -1,8 +1,9 @@
use ark_ec::{ models::{short_weierstrass::SWCurveConfig, CurveConfig}, + scalar_mul::glv::GLVConfig, short_weierstrass::{Affine, Projective}, }; -use ark_ff::{AdditiveGroup, MontFp}; +use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField}; use crate::{Fq, Fr};@@ -46,6 +47,46 @@ #[inline(always)]
fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField { use ark_ff::Zero; Self::BaseField::zero() + } +} + +impl GLVConfig for Config { + const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!( + "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648" + )]; + + const LAMBDA: Self::ScalarField = + MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + ( + true, + BigInt!("293634935485640680722085584138834120324914961969255022593"), + ), + ( + false, + BigInt!("293634935485640680722085584138834120315328839056164388863"), + ), + ( + true, + BigInt!("293634935485640680722085584138834120315328839056164388863"), + ), + ( + true, + BigInt!("587269870971281361444171168277668240640243801025419411456"), + ), + ]; + + fn endomorphism(p: &Projective<Self>) -> Projective<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -1,8 +1,9 @@
use ark_ec::{ models::{short_weierstrass::SWCurveConfig, CurveConfig}, + scalar_mul::glv::GLVConfig, short_weierstrass::{Affine, Projective}, }; -use ark_ff::{AdditiveGroup, MontFp}; +use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField}; use crate::{Fq, Fr};@@ -47,6 +48,46 @@ #[inline(always)]
fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField { use ark_ff::Zero; Self::BaseField::zero() + } +} + +impl GLVConfig for Config { + const ENDO_COEFFS: &'static [Self::BaseField] = &[ + MontFp!("4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"), + ]; + + const LAMBDA: Self::ScalarField = + MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + ( + true, + BigInt!("293634935485640680722085584138834120315328839056164388863"), + ), + ( + false, + BigInt!("293634935485640680722085584138834120324914961969255022593"), + ), + ( + true, + BigInt!("293634935485640680722085584138834120324914961969255022593"), + ), + ( + true, + BigInt!("587269870971281361444171168277668240640243801025419411456"), + ), + ]; + + fn endomorphism(p: &Projective<Self>) -> Projective<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -6,3 +6,5 @@ test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw); test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_761>; msm); test_pairing!(pairing; crate::BW6_761); +test_group!(g1_glv; G1Projective; glv); +test_group!(g2_glv; G2Projective; glv);
@@ -1,8 +1,9 @@
use ark_ec::{ models::CurveConfig, + scalar_mul::glv::GLVConfig, short_weierstrass::{self as sw, SWCurveConfig}, }; -use ark_ff::{AdditiveGroup, Field, MontFp, Zero}; +use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero}; use crate::{fq::Fq, fr::Fr};@@ -39,6 +40,40 @@
#[inline(always)] fn mul_by_a(_: Self::BaseField) -> Self::BaseField { Self::BaseField::zero() + } +} + +impl GLVConfig for PallasConfig { + const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!( + "20444556541222657078399132219657928148671392403212669005631716460534733845831" + )]; + + const LAMBDA: Self::ScalarField = + MontFp!("26005156700822196841419187675678338661165322343552424574062261873906994770353"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + (false, BigInt!("98231058071100081932162823354453065728")), + (true, BigInt!("98231058071186745657228807397848383489")), + (false, BigInt!("196462116142286827589391630752301449217")), + (false, BigInt!("98231058071100081932162823354453065728")), + ]; + + fn endomorphism(p: &Projective) -> Projective { + // Endomorphism of the points on the curve. + // endomorphism_p(x,y) = (BETA * x, y) + // where BETA is a non-trivial cubic root of unity in Fq. + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine) -> Affine { + // Endomorphism of the points on the curve. + // endomorphism_p(x,y) = (BETA * x, y) + // where BETA is a non-trivial cubic root of unity in Fq. + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -2,3 +2,4 @@ use crate::Projective;
use ark_algebra_test_templates::*; test_group!(g1; Projective; sw); +test_group!(g1_glv; Projective; glv);
@@ -1,9 +1,10 @@
use crate::{fq::Fq, fr::Fr}; use ark_ec::{ models::CurveConfig, + scalar_mul::glv::GLVConfig, short_weierstrass::{self as sw, SWCurveConfig}, }; -use ark_ff::{AdditiveGroup, Field, MontFp, Zero}; +use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero}; #[cfg(test)] mod tests;@@ -38,6 +39,40 @@
#[inline(always)] fn mul_by_a(_: Self::BaseField) -> Self::BaseField { Self::BaseField::zero() + } +} + +impl GLVConfig for VestaConfig { + const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!( + "26005156700822196841419187675678338661165322343552424574062261873906994770353" + )]; + + const LAMBDA: Self::ScalarField = + MontFp!("20444556541222657078399132219657928148671392403212669005631716460534733845831"); + + const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [ + (false, BigInt!("98231058071100081932162823354453065729")), + (true, BigInt!("98231058071186745657228807397848383488")), + (false, BigInt!("196462116142286827589391630752301449217")), + (false, BigInt!("98231058071100081932162823354453065729")), + ]; + + fn endomorphism(p: &Projective) -> Projective { + // Endomorphism of the points on the curve. + // endomorphism_p(x,y) = (BETA * x, y) + // where BETA is a non-trivial cubic root of unity in Fq. + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine) -> Affine { + // Endomorphism of the points on the curve. + // endomorphism_p(x,y) = (BETA * x, y) + // where BETA is a non-trivial cubic root of unity in Fq. + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res } }
@@ -2,3 +2,4 @@ use crate::Projective;
use ark_algebra_test_templates::*; test_group!(g1; Projective; sw); +test_group!(g1_glv; Projective; glv);