@ -1,26 +1,34 @@
use crate ::{ Fq , Fr } ;
use crate ::{ Fq , Fr } ;
use ark_ec ::{
use ark_ec ::{
models ::{ ModelParameters , MontgomeryModelParameters , TEModelParameters } ,
models ::{ ModelParameters , MontgomeryModelParameters , TEModelParameters } ,
short_weierstrass_jacobian ::{
GroupAffine as SWGroupAffine , GroupProjective as SWGroupProjective ,
} ,
twisted_edwards_extended ::{ GroupAffine , GroupProjective } ,
twisted_edwards_extended ::{ GroupAffine , GroupProjective } ,
SWModelParameters ,
} ;
} ;
use ark_ff ::{ field_new , Field } ;
use ark_ff ::{ field_new , Field } ;
#[ cfg(test) ]
#[ cfg(test) ]
mod tests ;
mod tests ;
pub type EdwardsAffine = GroupAffine < EdwardsParameters > ;
pub type EdwardsProjective = GroupProjective < EdwardsParameters > ;
pub type EdwardsAffine = GroupAffine < BandersnatchParameters > ;
pub type EdwardsProjective = GroupProjective < BandersnatchParameters > ;
pub type SWAffine = SWGroupAffine < BandersnatchParameters > ;
pub type SWProjective = SWGroupProjective < BandersnatchParameters > ;
/// `banersnatch` is a twisted Edwards curve. These curves have equations of the
/// `band ersnatch` is a twisted Edwards curve. These curves have equations of the
/// form: ax² + y² = 1 - dx²y².
/// form: ax² + y² = 1 - dx²y².
/// over some base finite field Fq.
/// over some base finite field Fq.
///
///
/// banersnatch's curve equation: -5x² + y² = 1 - dx²y²
/// band ersnatch's curve equation: -5x² + y² = 1 - dx²y²
///
///
/// q = 52435875175126190479447740508185965837690552500527637822603658699938581184513.
/// q = 52435875175126190479447740508185965837690552500527637822603658699938581184513.
///
///
/// a = 52435875175126190479447740508185965837690552500527637822603658699938581184508 .
/// a = -5 .
/// d = (138827208126141220649022263972958607803/
/// d = (138827208126141220649022263972958607803/
/// 171449701953573178309673572579671231137) mod q
/// 171449701953573178309673572579671231137) mod q
/// = 45022363124591815672509500913686876175488063829319466900776701791074614335719.
/// = 45022363124591815672509500913686876175488063829319466900776701791074614335719.
///
///
/// Sage script to calculate these:
/// Sage script to calculate these:
@ -32,17 +40,30 @@ pub type EdwardsProjective = GroupProjective;
/// ```
/// ```
/// These parameters and the sage script obtained from:
/// These parameters and the sage script obtained from:
/// <https://github.com/asanso/Bandersnatch/>
/// <https://github.com/asanso/Bandersnatch/>
///
/// bandersnatch also has a short Weierstrass curve form, following the
/// form: y² = x³ + A * x + B
/// where
///
/// A = 10773120815616481058602537765553212789256758185246796157495669123169359657269
/// B = 29569587568322301171008055308580903175558631321415017492731745847794083609535
///
/// Script to transfer between different curves are available
/// <https://github.com/zhenfeizhang/bandersnatch/blob/main/bandersnatch/script/bandersnatch.sage>
///
#[ derive(Clone, Default, PartialEq, Eq) ]
#[ derive(Clone, Default, PartialEq, Eq) ]
pub struct EdwardsParameters ;
pub struct BandersnatchParameters ;
pub type EdwardsParameters = BandersnatchParameters ;
pub type SWParameters = BandersnatchParameters ;
impl ModelParameters for EdwardsParameters {
impl ModelParameters for Bandersnatch Parameters {
type BaseField = Fq ;
type BaseField = Fq ;
type ScalarField = Fr ;
type ScalarField = Fr ;
}
}
impl TEModelParameters for EdwardsParameters {
impl TEModelParameters for Bandersnatch Parameters {
/// COEFF_A = -5
/// COEFF_A = -5
#[ rustfmt::skip ]
const COEFF_A : Fq = field_new ! ( Fq , "-5" ) ;
const COEFF_A : Fq = field_new ! ( Fq , "-5" ) ;
/// COEFF_D = (138827208126141220649022263972958607803/
/// COEFF_D = (138827208126141220649022263972958607803/
@ -59,9 +80,10 @@ impl TEModelParameters for EdwardsParameters {
const COFACTOR_INV : Fr = field_new ! ( Fr , "9831726595336160714896451345284868594481866920080427688839802480047265754601" ) ;
const COFACTOR_INV : Fr = field_new ! ( Fr , "9831726595336160714896451345284868594481866920080427688839802480047265754601" ) ;
/// AFFINE_GENERATOR_COEFFS = (GENERATOR_X, GENERATOR_Y)
/// AFFINE_GENERATOR_COEFFS = (GENERATOR_X, GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS : ( Self ::BaseField , Self ::BaseField ) = ( GENERATOR_X , GENERATOR_Y ) ;
const AFFINE_GENERATOR_COEFFS : ( Self ::BaseField , Self ::BaseField ) =
( TE_GENERATOR_X , TE_GENERATOR_Y ) ;
type MontgomeryModelParameters = Edwards Parameters;
type MontgomeryModelParameters = Bandersnatch Parameters;
/// Multiplication by `a` is multiply by `-5`.
/// Multiplication by `a` is multiply by `-5`.
#[ inline(always) ]
#[ inline(always) ]
@ -71,24 +93,56 @@ impl TEModelParameters for EdwardsParameters {
}
}
}
}
impl MontgomeryModelParameters for Edwards Parameters {
impl MontgomeryModelParameters for Bandersnatch Parameters {
/// COEFF_A = 29978822694968839326280996386011761570173833766074948509196803838190355340952
/// COEFF_A = 29978822694968839326280996386011761570173833766074948509196803838190355340952
#[ rustfmt::skip ]
#[ rustfmt::skip ]
const COEFF_A : Fq = field_new ! ( Fq , "29978822694968839326280996386011761570173833766074948509196803838190355340952" ) ;
const COEFF_A : Fq = field_new ! ( Fq , "29978822694968839326280996386011761570173833766074948509196803838190355340952" ) ;
/// COEFF_B = 25465760566081946422412445027709227188579564747101592991722834452325077642517
/// COEFF_B = 25465760566081946422412445027709227188579564747101592991722834452325077642517
#[ rustfmt::skip ]
#[ rustfmt::skip ]
const COEFF_B : Fq = field_new ! ( Fq , "25465760566081946422412445027709227188579564747101592991722834452325077642517" ) ;
const COEFF_B : Fq = field_new ! ( Fq , "25465760566081946422412445027709227188579564747101592991722834452325077642517" ) ;
type TEModelParameters = Edwards Parameters;
type TEModelParameters = Bandersnatch Parameters;
}
}
// using the generator from bench.py (in affine form)
// P = BandersnatchPoint(
// 13738737789055671334382939318077718462576533426798874551591468520593954805549,
// 11575885077368931610486103676191793534029821920164915325066801506752632626968,
// 14458123306641001284399433086015669988340559992755622870694102351476334505845,
// C)
// The TE form generator is generated following Zcash's fashion:
// "The generators of G1 and G2 are computed by finding the lexicographically smallest
// valid x-coordinate, and its lexicographically smallest y-coordinate and scaling it
// by the cofactor such that the result is not the point at infinity."
// The SW form generator is the same TE generator converted into SW form, obtained from the scripts:
// <https://github.com/zhenfeizhang/bandersnatch/blob/main/bandersnatch/script/bandersnatch.sage>
/// x coordinate for TE curve generator
#[ rustfmt::skip ]
#[ rustfmt::skip ]
const GENERATOR_X : Fq = field_new ! ( Fq , "29627151942733444043031429156003786749302466371339015363120350521834195802525" ) ;
const TE_GENERATOR_X : Fq = field_new ! ( Fq , "18886178867200960497001835917649091219057080094937609519140440539760939937304" ) ;
/// y coordinate for TE curve generator
#[ rustfmt::skip ]
#[ rustfmt::skip ]
const GENERATOR_Y : Fq = field_new ! ( Fq , "27488387519748396681411951718153463804682561779047093991696427532072116857978" ) ;
const TE_GENERATOR_Y : Fq = field_new ! ( Fq , "19188667384257783945677642223292697773471335439753913231509108946878080696678" ) ;
/// x coordinate for SW curve generator
#[ rustfmt::skip ]
const SW_GENERATOR_X : Fq = field_new ! ( Fq , "30900340493481298850216505686589334086208278925799850409469406976849338430199" ) ;
/// y coordinate for SW curve generator
#[ rustfmt::skip ]
const SW_GENERATOR_Y : Fq = field_new ! ( Fq , "12663882780877899054958035777720958383845500985908634476792678820121468453298" ) ;
impl SWModelParameters for BandersnatchParameters {
/// COEFF_A = 10773120815616481058602537765553212789256758185246796157495669123169359657269
#[ rustfmt::skip ]
const COEFF_A : Self ::BaseField = field_new ! ( Fq , "10773120815616481058602537765553212789256758185246796157495669123169359657269" ) ;
/// COEFF_B = 29569587568322301171008055308580903175558631321415017492731745847794083609535
#[ rustfmt::skip ]
const COEFF_B : Self ::BaseField = field_new ! ( Fq , "29569587568322301171008055308580903175558631321415017492731745847794083609535" ) ;
/// COFACTOR = 4
const COFACTOR : & 'static [ u64 ] = & [ 4 ] ;
/// COFACTOR^(-1) mod r =
/// 9831726595336160714896451345284868594481866920080427688839802480047265754601
#[ rustfmt::skip ]
const COFACTOR_INV : Fr = field_new ! ( Fr , "9831726595336160714896451345284868594481866920080427688839802480047265754601" ) ;
/// generators
const AFFINE_GENERATOR_COEFFS : ( Self ::BaseField , Self ::BaseField ) =
( SW_GENERATOR_X , SW_GENERATOR_Y ) ;
}