From 72a18b6ecfa0f5c0375d71dd5e68dc0218e80736 Mon Sep 17 00:00:00 2001 From: mmagician Date: Mon, 11 Sep 2023 15:29:38 -0600 Subject: [PATCH] GLV implementation for BLS12_377, BLS12_381 and BN254 (#158) --- CHANGELOG.md | 1 + bls12_377/src/curves/g1.rs | 39 ++++++++++++++++++++++++++-- bls12_377/src/curves/g2.rs | 36 +++++++++++++++++++++++--- bls12_377/src/curves/tests/mod.rs | 2 ++ bls12_381/src/curves/g1.rs | 37 +++++++++++++++++++++++++- bls12_381/src/curves/g2.rs | 33 +++++++++++++++++++++++- bls12_381/src/curves/tests/mod.rs | 2 ++ bn254/src/curves/g1.rs | 42 ++++++++++++++++++++++++++++-- bn254/src/curves/g2.rs | 34 ++++++++++++++++++++++-- bn254/src/curves/tests.rs | 2 ++ bw6_761/src/curves/g1.rs | 43 ++++++++++++++++++++++++++++++- bw6_761/src/curves/g2.rs | 43 ++++++++++++++++++++++++++++++- bw6_761/src/curves/tests.rs | 2 ++ pallas/src/curves/mod.rs | 37 +++++++++++++++++++++++++- pallas/src/curves/tests.rs | 1 + vesta/src/curves/mod.rs | 37 +++++++++++++++++++++++++- vesta/src/curves/tests.rs | 1 + 17 files changed, 377 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d9adfa..87fda6b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/bls12_377/src/curves/g1.rs b/bls12_377/src/curves/g1.rs index 8073f8f6..52054403 100644 --- a/bls12_377/src/curves/g1.rs +++ b/bls12_377/src/curves/g1.rs @@ -3,14 +3,15 @@ use ark_ec::{ 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}; @@ -49,6 +50,12 @@ impl SWCurveConfig for Config { 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. @@ -59,6 +66,34 @@ impl SWCurveConfig for Config { } } +impl GLVConfig for Config { + const ENDO_COEFFS: &'static[Self::BaseField] = &[ + MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231") + ]; + + const LAMBDA: Self::ScalarField = + MontFp!("8444461749428370424248824938781546531284005582649182570233710176290576793600"); + + const SCALAR_DECOMP_COEFFS: [(bool, ::BigInt); 4] = [ + (true, BigInt!("91893752504881257701523279626832445441")), + (true, BigInt!("1")), + (false, BigInt!("1")), + (true, BigInt!("91893752504881257701523279626832445440")), + ]; + + fn endomorphism(p: &SWProjective) -> SWProjective { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &SWAffine) -> SWAffine { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } +} + fn x_minus_one() -> Fr { const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X); X - Fr::one() diff --git a/bls12_377/src/curves/g2.rs b/bls12_377/src/curves/g2.rs index 5ccbfc5b..2b07beb9 100644 --- a/bls12_377/src/curves/g2.rs +++ b/bls12_377/src/curves/g2.rs @@ -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::*; @@ -98,6 +98,36 @@ impl SWCurveConfig for Config { } } +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, ::BigInt); 4] = [ + (false, BigInt!("91893752504881257701523279626832445440")), + (true, BigInt!("1")), + (false, BigInt!("1")), + (false, BigInt!("91893752504881257701523279626832445441")), + ]; + + fn endomorphism(p: &Projective) -> Projective { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine) -> Affine { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } +} + pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); diff --git a/bls12_377/src/curves/tests/mod.rs b/bls12_377/src/curves/tests/mod.rs index 43944c3e..02dc9e4e 100755 --- a/bls12_377/src/curves/tests/mod.rs +++ b/bls12_377/src/curves/tests/mod.rs @@ -5,6 +5,8 @@ test_group!(g1; G1Projective; sw); test_group!(g2; G2Projective; sw); test_group!(pairing_output; ark_ec::pairing::PairingOutput; 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); diff --git a/bls12_381/src/curves/g1.rs b/bls12_381/src/curves/g1.rs index 23e88adb..8aa203fb 100644 --- a/bls12_381/src/curves/g1.rs +++ b/bls12_381/src/curves/g1.rs @@ -3,10 +3,11 @@ use ark_ec::{ 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}; @@ -52,6 +53,12 @@ impl SWCurveConfig for Config { 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 is_in_correct_subgroup_assuming_on_curve(p: &G1Affine) -> bool { // Algorithm from Section 6 of https://eprint.iacr.org/2021/1130. @@ -142,6 +149,34 @@ impl SWCurveConfig for Config { } } +impl GLVConfig for Config { + const ENDO_COEFFS: &'static[Self::BaseField] = &[ + MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350") + ]; + + const LAMBDA: Self::ScalarField = + MontFp!("52435875175126190479447740508185965837461563690374988244538805122978187051009"); + + const SCALAR_DECOMP_COEFFS: [(bool, ::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) -> Affine { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } +} + fn one_minus_x() -> Fr { const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X); Fr::one() - X diff --git a/bls12_381/src/curves/g2.rs b/bls12_381/src/curves/g2.rs index 39ac6b99..9cc9a2a7 100644 --- a/bls12_381/src/curves/g2.rs +++ b/bls12_381/src/curves/g2.rs @@ -5,10 +5,11 @@ use ark_ec::{ 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::{ @@ -185,6 +186,36 @@ impl SWCurveConfig for Config { } } +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, ::BigInt); 4] = [ + (false, BigInt!("228988810152649578064853576960394133503")), + (true, BigInt!("1")), + (false, BigInt!("1")), + (false, BigInt!("228988810152649578064853576960394133504")), + ]; + + fn endomorphism(p: &Projective) -> Projective { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine) -> Affine { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } +} + pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); diff --git a/bls12_381/src/curves/tests/mod.rs b/bls12_381/src/curves/tests/mod.rs index a75fb5b1..8ae02729 100755 --- a/bls12_381/src/curves/tests/mod.rs +++ b/bls12_381/src/curves/tests/mod.rs @@ -8,6 +8,8 @@ use crate::{Bls12_381, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projecti 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; msm); test_pairing!(pairing; crate::Bls12_381); test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12381G1"; crate::g1::Config; crate::Fq; crate::Fq; 1); diff --git a/bn254/src/curves/g1.rs b/bn254/src/curves/g1.rs index a4c08d8e..e389300c 100644 --- a/bn254/src/curves/g1.rs +++ b/bn254/src/curves/g1.rs @@ -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}; @@ -36,6 +38,42 @@ impl SWCurveConfig for Config { fn mul_by_a(_: Self::BaseField) -> Self::BaseField { Self::BaseField::zero() } + + #[inline] + fn mul_projective( + p: &bn::G1Projective, + scalar: &[u64], + ) -> bn::G1Projective { + 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, ::BigInt); 4] = [ + (false, BigInt!("147946756881789319000765030803803410728")), + (true, BigInt!("9931322734385697763")), + (false, BigInt!("9931322734385697763")), + (false, BigInt!("147946756881789319010696353538189108491")), + ]; + + fn endomorphism(p: &Projective) -> Projective { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + fn endomorphism_affine(p: &Affine) -> Affine { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } } /// G1_GENERATOR_X = 1 diff --git a/bn254/src/curves/g2.rs b/bn254/src/curves/g2.rs index cc49a566..924d2dbe 100644 --- a/bn254/src/curves/g2.rs +++ b/bn254/src/curves/g2.rs @@ -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}; @@ -50,6 +51,35 @@ impl SWCurveConfig for Config { } } +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, ::BigInt); 4] = [ + (false, BigInt!("147946756881789319010696353538189108491")), + (false, BigInt!("9931322734385697763")), + (true, BigInt!("9931322734385697763")), + (false, BigInt!("147946756881789319000765030803803410728")), + ]; + + fn endomorphism(p: &Projective) -> Projective { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine) -> Affine { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } +} + pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); diff --git a/bn254/src/curves/tests.rs b/bn254/src/curves/tests.rs index 6e21e5eb..cc9d1840 100755 --- a/bn254/src/curves/tests.rs +++ b/bn254/src/curves/tests.rs @@ -7,3 +7,5 @@ test_group!(g1; G1Projective; sw); test_group!(g2; G2Projective; sw); test_group!(pairing_output; ark_ec::pairing::PairingOutput; msm); test_pairing!(pairing; crate::Bn254); +test_group!(g1_glv; G1Projective; glv); +test_group!(g2_glv; G2Projective; glv); diff --git a/bw6_761/src/curves/g1.rs b/bw6_761/src/curves/g1.rs index e9020578..e0ff8a57 100644 --- a/bw6_761/src/curves/g1.rs +++ b/bw6_761/src/curves/g1.rs @@ -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}; @@ -49,6 +50,46 @@ impl SWCurveConfig for Config { } } +impl GLVConfig for Config { + const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!( + "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648" + )]; + + const LAMBDA: Self::ScalarField = + MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"); + + const SCALAR_DECOMP_COEFFS: [(bool, ::BigInt); 4] = [ + ( + true, + BigInt!("293634935485640680722085584138834120324914961969255022593"), + ), + ( + false, + BigInt!("293634935485640680722085584138834120315328839056164388863"), + ), + ( + true, + BigInt!("293634935485640680722085584138834120315328839056164388863"), + ), + ( + true, + BigInt!("587269870971281361444171168277668240640243801025419411456"), + ), + ]; + + fn endomorphism(p: &Projective) -> Projective { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine) -> Affine { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } +} + /// G1_GENERATOR_X = /// 6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237 pub const G1_GENERATOR_X: Fq = MontFp!("6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237"); diff --git a/bw6_761/src/curves/g2.rs b/bw6_761/src/curves/g2.rs index 996c6422..97b68bed 100644 --- a/bw6_761/src/curves/g2.rs +++ b/bw6_761/src/curves/g2.rs @@ -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}; @@ -50,6 +51,46 @@ impl SWCurveConfig for Config { } } +impl GLVConfig for Config { + const ENDO_COEFFS: &'static [Self::BaseField] = &[ + MontFp!("4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"), + ]; + + const LAMBDA: Self::ScalarField = + MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"); + + const SCALAR_DECOMP_COEFFS: [(bool, ::BigInt); 4] = [ + ( + true, + BigInt!("293634935485640680722085584138834120315328839056164388863"), + ), + ( + false, + BigInt!("293634935485640680722085584138834120324914961969255022593"), + ), + ( + true, + BigInt!("293634935485640680722085584138834120324914961969255022593"), + ), + ( + true, + BigInt!("587269870971281361444171168277668240640243801025419411456"), + ), + ]; + + fn endomorphism(p: &Projective) -> Projective { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } + + fn endomorphism_affine(p: &Affine) -> Affine { + let mut res = (*p).clone(); + res.x *= Self::ENDO_COEFFS[0]; + res + } +} + /// G2_GENERATOR_X = /// 6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428 pub const G2_GENERATOR_X: Fq = MontFp!("6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428"); diff --git a/bw6_761/src/curves/tests.rs b/bw6_761/src/curves/tests.rs index 1a8d4ed2..c91564f1 100644 --- a/bw6_761/src/curves/tests.rs +++ b/bw6_761/src/curves/tests.rs @@ -6,3 +6,5 @@ test_group!(g1; G1Projective; sw); test_group!(g2; G2Projective; sw); test_group!(pairing_output; ark_ec::pairing::PairingOutput; msm); test_pairing!(pairing; crate::BW6_761); +test_group!(g1_glv; G1Projective; glv); +test_group!(g2_glv; G2Projective; glv); diff --git a/pallas/src/curves/mod.rs b/pallas/src/curves/mod.rs index 486e890f..90f0f31d 100644 --- a/pallas/src/curves/mod.rs +++ b/pallas/src/curves/mod.rs @@ -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}; @@ -42,6 +43,40 @@ impl SWCurveConfig for PallasConfig { } } +impl GLVConfig for PallasConfig { + const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!( + "20444556541222657078399132219657928148671392403212669005631716460534733845831" + )]; + + const LAMBDA: Self::ScalarField = + MontFp!("26005156700822196841419187675678338661165322343552424574062261873906994770353"); + + const SCALAR_DECOMP_COEFFS: [(bool, ::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 + } +} + /// G_GENERATOR_X = -1 pub const G_GENERATOR_X: Fq = MontFp!("-1"); diff --git a/pallas/src/curves/tests.rs b/pallas/src/curves/tests.rs index f7bc50cd..19fc7312 100755 --- a/pallas/src/curves/tests.rs +++ b/pallas/src/curves/tests.rs @@ -2,3 +2,4 @@ use crate::Projective; use ark_algebra_test_templates::*; test_group!(g1; Projective; sw); +test_group!(g1_glv; Projective; glv); diff --git a/vesta/src/curves/mod.rs b/vesta/src/curves/mod.rs index e4233877..fb1394c6 100644 --- a/vesta/src/curves/mod.rs +++ b/vesta/src/curves/mod.rs @@ -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; @@ -41,6 +42,40 @@ impl SWCurveConfig for VestaConfig { } } +impl GLVConfig for VestaConfig { + const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!( + "26005156700822196841419187675678338661165322343552424574062261873906994770353" + )]; + + const LAMBDA: Self::ScalarField = + MontFp!("20444556541222657078399132219657928148671392403212669005631716460534733845831"); + + const SCALAR_DECOMP_COEFFS: [(bool, ::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 + } +} + /// G_GENERATOR_X = -1 /// Encoded in Montgomery form, so the value here is -R mod p. pub const G_GENERATOR_X: Fq = MontFp!("-1"); diff --git a/vesta/src/curves/tests.rs b/vesta/src/curves/tests.rs index f7bc50cd..19fc7312 100755 --- a/vesta/src/curves/tests.rs +++ b/vesta/src/curves/tests.rs @@ -2,3 +2,4 @@ use crate::Projective; use ark_algebra_test_templates::*; test_group!(g1; Projective; sw); +test_group!(g1_glv; Projective; glv);