4 Commits

Author SHA1 Message Date
Solomon
60b6e5d63b Renamed add_nocarry and sub_noborrow for curves 2021-10-21 12:24:02 -07:00
zhenfei
461e4190b1 adding SW parameters for Bandersnatch curve (#67)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2021-10-20 10:12:15 -07:00
zhenfei
5fe1862c9a Twisted Edwards parameters for BLS12-377 (#76)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2021-10-19 11:30:41 -07:00
Simon Masson
2118e14b6a Use Scott's subgroup membership tests for G1 and G2 of BLS12-381. (#74)
* implementation of the fast subgroup check for bls12_381

* add a bench

* subgroup check for g1

* subgroup check modifications

* remove useless test

* fmt

* need the last version of arkworks/algebra

* remove Parameters0

* using projective points is more efficient

* use of projective coordinates in G2

* fmt

* documentation on the constants and the psi function

* references for algorithms of eprint 2021/1130

* fmt

* sed ^ **

* minor improvement

* fmt

* fix Cargo toml

* nits

* some cleanup for g1

* add the beta test back

* fmt

* g2

* changelog

* add a  note on the Cargo.toml

* nits

* avoid variable name conflicts

* add the early-out optimization

Co-authored-by: weikeng <w.k@berkeley.edu>
2021-09-25 10:34:13 -07:00
46 changed files with 828 additions and 235 deletions

View File

@@ -2,12 +2,16 @@
## Pending ## Pending
- [\#76](https://github.com/arkworks-rs/curves/pull/76) twisted Edwards parameters for bls12-377
### Breaking changes ### Breaking changes
### Features ### Features
### Improvements ### Improvements
- [\#74](https://github.com/arkworks-rs/curves/pull/74) Use Scott's subgroup membership tests for `G1` and `G2` of BLS12-381.
### Bug fixes ### Bug fixes
## v0.3.0 ## v0.3.0

View File

@@ -57,5 +57,8 @@ incremental = true
debug-assertions = true debug-assertions = true
debug = true debug = true
# To be removed in the new release.
[patch.crates-io] [patch.crates-io]
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", branch = "reduce-generics", optional = true, default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra" }
ark-ff = { git = "https://github.com/arkworks-rs/algebra" }
ark-serialize = { git = "https://github.com/arkworks-rs/algebra" }

View File

@@ -1,11 +1,22 @@
use crate::Parameters; use crate::Parameters;
use ark_r1cs_std::groups::bls12; use ark_ec::bls12::Bls12Parameters;
use ark_ec::ModelParameters;
use ark_r1cs_std::{
fields::fp::FpVar,
groups::{bls12, curves::twisted_edwards::AffineVar as TEAffineVar},
};
/// An element of G1 in the BLS12-377 bilinear group. /// An element of G1 in the BLS12-377 bilinear group.
pub type G1Var = bls12::G1Var<Parameters>; pub type G1Var = bls12::G1Var<Parameters>;
/// An element of G2 in the BLS12-377 bilinear group. /// An element of G2 in the BLS12-377 bilinear group.
pub type G2Var = bls12::G2Var<Parameters>; pub type G2Var = bls12::G2Var<Parameters>;
/// An element of G1 (in TE Affine form) in the BLS12-377 bilinear group.
pub type G1TEAffineVar = TEAffineVar<
<Parameters as Bls12Parameters>::G1Parameters,
FpVar<<<Parameters as Bls12Parameters>::G1Parameters as ModelParameters>::BaseField>,
>;
/// Represents the cached precomputation that can be performed on a G1 element /// Represents the cached precomputation that can be performed on a G1 element
/// which enables speeding up pairing computation. /// which enables speeding up pairing computation.
pub type G1PreparedVar = bls12::G1PreparedVar<Parameters>; pub type G1PreparedVar = bls12::G1PreparedVar<Parameters>;
@@ -16,8 +27,19 @@ pub type G2PreparedVar = bls12::G2PreparedVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use ark_ec::models::bls12::Bls12Parameters; use ark_ec::models::bls12::Bls12Parameters;
ark_curve_constraint_tests::curves::sw_test::<<Parameters as Bls12Parameters>::G1Parameters>() ark_curve_constraint_tests::curves::sw_test::<
<Parameters as Bls12Parameters>::G1Parameters,
G1Var,
>()
.unwrap(); .unwrap();
ark_curve_constraint_tests::curves::sw_test::<<Parameters as Bls12Parameters>::G2Parameters>() ark_curve_constraint_tests::curves::te_test::<
<Parameters as Bls12Parameters>::G1Parameters,
G1TEAffineVar,
>()
.unwrap();
ark_curve_constraint_tests::curves::sw_test::<
<Parameters as Bls12Parameters>::G2Parameters,
G2Var,
>()
.unwrap(); .unwrap();
} }

View File

@@ -130,17 +130,17 @@
//! let pairing_result_native = Bls12_377::pairing(a_native, b_native); //! let pairing_result_native = Bls12_377::pairing(a_native, b_native);
//! //!
//! // Prepare `a` and `b` for pairing. //! // Prepare `a` and `b` for pairing.
//! let a_prep = Bls12_377::prepare_g1(&a)?; //! let a_prep = constraints::PairingVar::prepare_g1(&a)?;
//! let b_prep = Bls12_377::prepare_g2(&b)?; //! let b_prep = constraints::PairingVar::prepare_g2(&b)?;
//! let pairing_result = Bls12_377::pairing_gadget(a_prep, b_prep)?; //! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?;
//! //!
//! // Check that the value of &a + &b is correct. //! // Check that the value of &a + &b is correct.
//! assert_eq!(pairing_result.value()?, pairing_result_native); //! assert_eq!(pairing_result.value()?, pairing_result_native);
//! //!
//! // Check that operations on variables and constants are equivalent. //! // Check that operations on variables and constants are equivalent.
//! let a_prep_const = Bls12_377::prepare_g1(&a_const)?; //! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?;
//! let b_prep_const = Bls12_377::prepare_g2(&b_const)?; //! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?;
//! let pairing_result_const = Bls12_377::pairing_gadget(a_prep_const, b_prep_const)?; //! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?;
//! println!("Done here 3"); //! println!("Done here 3");
//! //!
//! pairing_result.enforce_equal(&pairing_result_const)?; //! pairing_result.enforce_equal(&pairing_result_const)?;

View File

@@ -1,8 +1,10 @@
use crate::Parameters;
/// Specifies the constraints for computing a pairing in the BLS12-377 bilinear group. /// Specifies the constraints for computing a pairing in the BLS12-377 bilinear group.
pub use crate::Bls12_377; pub type PairingVar = ark_r1cs_std::pairing::bls12::PairingVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use crate::Bls12_377; use crate::Bls12_377;
ark_curve_constraint_tests::pairing::bilinearity_test::<Bls12_377>().unwrap() ark_curve_constraint_tests::pairing::bilinearity_test::<Bls12_377, PairingVar>().unwrap()
} }

View File

@@ -1,5 +1,11 @@
use ark_ec::models::{ModelParameters, SWModelParameters}; use ark_ec::models::{
twisted_edwards_extended::{
GroupAffine as TEGroupAffine, GroupProjective as TEGroupProjective,
},
ModelParameters, MontgomeryModelParameters, SWModelParameters, TEModelParameters,
};
use ark_ff::{field_new, Zero}; use ark_ff::{field_new, Zero};
use core::ops::Neg;
use crate::{ use crate::{
fields::{FQ_ONE, FQ_ZERO}, fields::{FQ_ONE, FQ_ZERO},
@@ -40,6 +46,129 @@ impl SWModelParameters for Parameters {
} }
} }
pub type G1TEAffine = TEGroupAffine<Parameters>;
pub type G1TEProjective = TEGroupProjective<Parameters>;
/// Bls12_377::G1 also has a twisted Edwards form.
/// It can be obtained via the following script, implementing
/// 1. SW -> Montgomery -> TE1 transformation: <https://en.wikipedia.org/wiki/Montgomery_curve>
/// 2. TE1 -> TE2 normalization (enforcing `a = -1`)
/// ``` sage
///
/// # modulus
/// p = 0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001
/// Fp = Zmod(p)
///
/// #####################################################
/// # Weierstrass curve: y² = x³ + A * x + B
/// #####################################################
/// # curve y^2 = x^3 + 1
/// WA = Fp(0)
/// WB = Fp(1)
///
/// #####################################################
/// # Montgomery curve: By² = x³ + A * x² + x
/// #####################################################
/// # root for x^3 + 1 = 0
/// alpha = -1
/// # s = 1 / (sqrt(3alpha^2 + a))
/// s = 1/(Fp(3).sqrt())
///
/// # MA = 3 * alpha * s
/// MA = Fp(228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384)
/// # MB = s
/// MB = Fp(10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931)
///
/// # #####################################################
/// # # Twisted Edwards curve 1: a * x² + y² = 1 + d * x² * y²
/// # #####################################################
/// # We first convert to TE form obtaining a curve with a != -1, and then
/// # apply a transformation to obtain a TE curve with a = -1.
/// # a = (MA+2)/MB
/// TE1a = Fp(61134141799337779744243169579317764548490943457438569789767076791016838392692895365021181670618017873462480451583)
/// # b = (MA-2)/MB
/// TE1d = Fp(197530284213631314266409564115575768987902569297476090750117185875703629955647927409947706468955342250977841006588)
///
/// # #####################################################
/// # # Twisted Edwards curve 2: a * x² + y² = 1 + d * x² * y²
/// # #####################################################
/// # a = -1
/// TE2a = Fp(-1)
/// # b = -TE1d/TE1a
/// TE2d = Fp(122268283598675559488486339158635529096981886914877139579534153582033676785385790730042363341236035746924960903179)
///
/// ```
impl TEModelParameters for Parameters {
/// COEFF_A = -1
const COEFF_A: Fq = field_new!(Fq, "-1");
/// COEFF_D = 122268283598675559488486339158635529096981886914877139579534153582033676785385790730042363341236035746924960903179 mod q
#[rustfmt::skip]
const COEFF_D: Fq = field_new!(Fq, "122268283598675559488486339158635529096981886914877139579534153582033676785385790730042363341236035746924960903179");
/// COFACTOR = (x - 1)^2 / 3 = 30631250834960419227450344600217059328
const COFACTOR: &'static [u64] = &[0x0, 0x170b5d4430000000];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 5285428838741532253824584287042945485047145357130994810877
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, "5285428838741532253824584287042945485047145357130994810877");
/// AFFINE_GENERATOR_COEFFS = (GENERATOR_X, GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(TE_GENERATOR_X, TE_GENERATOR_Y);
type MontgomeryModelParameters = Parameters;
/// Multiplication by `a` is multiply by `-1`.
#[inline(always)]
fn mul_by_a(elem: &Self::BaseField) -> Self::BaseField {
elem.neg()
}
}
// BLS12-377::G1 also has a Montgomery form.
// BLS12-377::G1 also has a twisted Edwards form.
// It can be obtained via the following script, implementing
// SW -> Montgomery transformation: <https://en.wikipedia.org/wiki/Montgomery_curve>
// ``` sage
//
// # modulus
// p=0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001
// Fp=Zmod(p)
//
// #####################################################
// # Weierstrass curve: y² = x³ + A * x + B
// #####################################################
// # curve y^2 = x^3 + 1
// WA=Fp(0)
// WB=Fp(1)
//
// #####################################################
// # Montgomery curve: By² = x³ + A * x² + x
// #####################################################
// # root for x^3 + 1 = 0
// alpha = -1
// # s = 1 / (sqrt(3alpha^2 + a))
// s = 1/(Fp(3).sqrt())
//
// # MA = 3 * alpha * s
// MA=Fp(228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384)
// # MB = s
// MB=Fp(10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931)
// ```
impl MontgomeryModelParameters for Parameters {
/// COEFF_A = 228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384
#[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, "228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384");
/// COEFF_B = 10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, "10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931");
type TEModelParameters = Parameters;
}
/// G1_GENERATOR_X = /// G1_GENERATOR_X =
/// 81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695 /// 81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695
#[rustfmt::skip] #[rustfmt::skip]
@@ -49,3 +178,56 @@ pub const G1_GENERATOR_X: Fq = field_new!(Fq, "819379993731509642399382555734659
/// 241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030 /// 241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030
#[rustfmt::skip] #[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, "241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030"); pub const G1_GENERATOR_Y: Fq = field_new!(Fq, "241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030");
// The generator for twisted Edward form is the same SW generator converted into the normalized TE form (TE2).
// ``` sage
// # following scripts in previous section
// #####################################################
// # Weierstrass curve generator
// #####################################################
// Wx = Fp(81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695)
// Wy = Fp(241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030)
//
// assert(Wy^2 - Wx^3 - WA * Wx - WB == 0)
//
// #####################################################
// # Montgomery curve generator
// #####################################################
// # x = s * (x - alpha)
// Mx = Fp(251803586774461569862800610331871502335378228972505599912537082323947581271784390797244487924068052270360793200630)
// # y = s * y
// My = Fp(77739247071951651095607889637653357561348174979132042929587539214321586851215673796661346812932566642719051699820)
//
// assert(MB * My^2 == Mx^3+ MA * Mx^2 + Mx)
//
// # #####################################################
// # # Twisted Edwards curve 1 generator
// # #####################################################
// # x = Mx/My
// TE1x = Fp(82241236807150726090333472814441006963902378430536027612759193445733851062772474760677400112551677454953925168208)
// # y = (Mx - 1)/(Mx+1)
// TE1y = Fp(6177051365529633638563236407038680211609544222665285371549726196884440490905471891908272386851767077598415378235)
//
// assert( TE1a * TE1x^2 + TE1y^2 == 1 + TE1d * TE1x^2 * TE1y^2 )
//
//
// # #####################################################
// # # Twisted Edwards curve 2 generator
// # #####################################################
// beta = (-TE1a).sqrt()
// # x = TE1x * sqrt(-TE1a)
// TE2x = Fp(71222569531709137229370268896323705690285216175189308202338047559628438110820800641278662592954630774340654489393)
// # y = TE1y
// TE2y = Fp(6177051365529633638563236407038680211609544222665285371549726196884440490905471891908272386851767077598415378235)
//
// assert( TE2a * TE2x^2 + TE2y^2 == 1 + TE2d * TE2x^2 * TE2y^2 )
// ```
/// TE_GENERATOR_X =
/// 71222569531709137229370268896323705690285216175189308202338047559628438110820800641278662592954630774340654489393
#[rustfmt::skip]
pub const TE_GENERATOR_X: Fq = field_new!(Fq, "71222569531709137229370268896323705690285216175189308202338047559628438110820800641278662592954630774340654489393");
/// TE_GENERATOR_Y =
/// 6177051365529633638563236407038680211609544222665285371549726196884440490905471891908272386851767077598415378235
#[rustfmt::skip]
pub const TE_GENERATOR_Y: Fq = field_new!(Fq, "6177051365529633638563236407038680211609544222665285371549726196884440490905471891908272386851767077598415378235");

View File

@@ -31,3 +31,5 @@ pub type G1Affine = bls12::G1Affine<Parameters>;
pub type G1Projective = bls12::G1Projective<Parameters>; pub type G1Projective = bls12::G1Projective<Parameters>;
pub type G2Affine = bls12::G2Affine<Parameters>; pub type G2Affine = bls12::G2Affine<Parameters>;
pub type G2Projective = bls12::G2Projective<Parameters>; pub type G2Projective = bls12::G2Projective<Parameters>;
pub use g1::{G1TEAffine, G1TEProjective};

View File

@@ -1,19 +1,22 @@
#![allow(unused_imports)] #![allow(unused_imports)]
use crate::{
g1, g2, Bls12_377, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G1TEProjective, G2Affine,
G2Projective,
};
use ark_ec::{
models::SWModelParameters, short_weierstrass_jacobian, AffineCurve, PairingEngine,
ProjectiveCurve,
};
use ark_ff::{ use ark_ff::{
fields::{Field, FpParameters, PrimeField, SquareRootField}, fields::{Field, FpParameters, PrimeField, SquareRootField},
One, Zero, One, Zero,
}; };
use ark_serialize::CanonicalSerialize; use ark_serialize::CanonicalSerialize;
use ark_std::test_rng; use ark_std::{rand::Rng, test_rng};
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_std::rand::Rng;
use core::ops::{AddAssign, MulAssign}; use core::ops::{AddAssign, MulAssign};
use crate::{g1, g2, Bls12_377, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_algebra_test_templates::{ use ark_algebra_test_templates::{
curves::{curve_tests, sw_tests}, curves::{curve_tests, edwards_tests, sw_tests},
groups::group_test, groups::group_test,
}; };
@@ -22,6 +25,7 @@ fn test_g1_projective_curve() {
curve_tests::<G1Projective>(); curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>(); sw_tests::<g1::Parameters>();
edwards_tests::<g1::Parameters>();
} }
#[test] #[test]
@@ -30,6 +34,10 @@ fn test_g1_projective_group() {
let a: G1Projective = rng.gen(); let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen(); let b: G1Projective = rng.gen();
group_test(a, b); group_test(a, b);
let c = rng.gen();
let d = rng.gen();
group_test::<G1TEProjective>(c, d);
} }
#[test] #[test]

View File

@@ -1,4 +1,4 @@
///! Bls12-377 scalar field. //! Bls12-377 scalar field.
/// ///
/// Roots of unity computed from modulus and R using this sage code: /// Roots of unity computed from modulus and R using this sage code:
/// ///
@@ -76,7 +76,8 @@ impl FpParameters for FrParameters {
/// GENERATOR = 22 /// GENERATOR = 22
/// Encoded in Montgomery form, so the value is /// Encoded in Montgomery form, so the value is
/// (22 * R) % q = 5642976643016801619665363617888466827793962762719196659561577942948671127251 /// (22 * R) % q =
/// 5642976643016801619665363617888466827793962762719196659561577942948671127251
#[rustfmt::skip] #[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([ const GENERATOR: BigInteger = BigInteger([
2984901390528151251u64, 2984901390528151251u64,

View File

@@ -7,8 +7,7 @@ use ark_ff::{
One, UniformRand, Zero, One, UniformRand, Zero,
}; };
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize}; use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use ark_std::rand::Rng; use ark_std::{rand::Rng, test_rng};
use ark_std::test_rng;
use core::{ use core::{
cmp::Ordering, cmp::Ordering,
ops::{AddAssign, MulAssign, SubAssign}, ops::{AddAssign, MulAssign, SubAssign},

View File

@@ -1,9 +1,13 @@
use crate::*; use crate::*;
use ark_ec::{ use ark_ec::{
bls12, bls12,
bls12::Bls12Parameters,
models::{ModelParameters, SWModelParameters}, models::{ModelParameters, SWModelParameters},
short_weierstrass_jacobian::GroupAffine,
AffineCurve, ProjectiveCurve,
}; };
use ark_ff::{field_new, Zero}; use ark_ff::{biginteger::BigInteger256, field_new, Zero};
use ark_std::ops::Neg;
pub type G1Affine = bls12::G1Affine<crate::Parameters>; pub type G1Affine = bls12::G1Affine<crate::Parameters>;
pub type G1Projective = bls12::G1Projective<crate::Parameters>; pub type G1Projective = bls12::G1Projective<crate::Parameters>;
@@ -40,6 +44,25 @@ impl SWModelParameters for Parameters {
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero() Self::BaseField::zero()
} }
fn is_in_correct_subgroup_assuming_on_curve(p: &GroupAffine<Parameters>) -> bool {
// Algorithm from Section 6 of https://eprint.iacr.org/2021/1130.
//
// Check that endomorphism_p(P) == -[X^2]P
let x = BigInteger256::new([crate::Parameters::X[0], 0, 0, 0]);
// An early-out optimization described in Section 6.
// If uP == P but P != point of infinity, then the point is not in the right subgroup.
let x_times_p = p.mul(x);
if x_times_p.eq(p) && !p.infinity {
return false;
}
let minus_x_squared_times_p = x_times_p.mul(x).neg();
let endomorphism_p = endomorphism(p);
minus_x_squared_times_p.eq(&endomorphism_p)
}
} }
/// G1_GENERATOR_X = /// G1_GENERATOR_X =
@@ -51,3 +74,14 @@ pub const G1_GENERATOR_X: Fq = field_new!(Fq, "368541675371338701678108831518307
/// 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 /// 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
#[rustfmt::skip] #[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, "1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569"); pub const G1_GENERATOR_Y: Fq = field_new!(Fq, "1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569");
/// BETA is a non-trivial cubic root of unity in Fq.
pub const BETA: Fq = field_new!(Fq, "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350");
pub fn endomorphism(p: &GroupAffine<Parameters>) -> GroupAffine<Parameters> {
// 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 *= BETA;
res
}

View File

@@ -1,9 +1,12 @@
use crate::*; use crate::*;
use ark_ec::bls12::Bls12Parameters;
use ark_ec::{ use ark_ec::{
bls12, bls12,
models::{ModelParameters, SWModelParameters}, models::{ModelParameters, SWModelParameters},
short_weierstrass_jacobian::GroupAffine,
AffineCurve,
}; };
use ark_ff::{field_new, Zero}; use ark_ff::{biginteger::BigInteger256, field_new, Field, Zero};
pub type G2Affine = bls12::G2Affine<crate::Parameters>; pub type G2Affine = bls12::G2Affine<crate::Parameters>;
pub type G2Projective = bls12::G2Projective<crate::Parameters>; pub type G2Projective = bls12::G2Projective<crate::Parameters>;
@@ -51,6 +54,21 @@ impl SWModelParameters for Parameters {
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero() Self::BaseField::zero()
} }
fn is_in_correct_subgroup_assuming_on_curve(point: &GroupAffine<Parameters>) -> bool {
// Algorithm from Section 4 of https://eprint.iacr.org/2021/1130.
//
// Checks that [p]P = [X]P
let mut x_times_point = point.mul(BigInteger256([crate::Parameters::X[0], 0, 0, 0]));
if crate::Parameters::X_IS_NEGATIVE {
x_times_point = -x_times_point;
}
let p_times_point = p_power_endomorphism(point);
x_times_point.eq(&p_times_point)
}
} }
pub const G2_GENERATOR_X: Fq2 = field_new!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); pub const G2_GENERATOR_X: Fq2 = field_new!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
@@ -75,3 +93,52 @@ pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, "198515060228729193556805452117
/// 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582 /// 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582
#[rustfmt::skip] #[rustfmt::skip]
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, "927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582"); pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, "927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582");
// psi(x,y) = (x**p * PSI_X, y**p * PSI_Y) is the Frobenius composed
// with the quadratic twist and its inverse
// PSI_X = 1/(u+1)^((p-1)/3)
pub const P_POWER_ENDOMORPHISM_COEFF_0 : Fq2 = field_new!(
Fq2,
FQ_ZERO,
field_new!(
Fq,
"4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437"
)
);
// PSI_Y = 1/(u+1)^((p-1)/2)
pub const P_POWER_ENDOMORPHISM_COEFF_1: Fq2 = field_new!(
Fq2,
field_new!(
Fq,
"2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"),
field_new!(
Fq,
"1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257")
);
pub fn p_power_endomorphism(p: &GroupAffine<Parameters>) -> GroupAffine<Parameters> {
// The p-power endomorphism for G2 is defined as follows:
// 1. Note that G2 is defined on curve E': y^2 = x^3 + 4(u+1). To map a point (x, y) in E' to (s, t) in E,
// one set s = x / ((u+1) ^ (1/3)), t = y / ((u+1) ^ (1/2)), because E: y^2 = x^3 + 4.
// 2. Apply the Frobenius endomorphism (s, t) => (s', t'), another point on curve E,
// where s' = s^p, t' = t^p.
// 3. Map the point from E back to E'; that is,
// one set x' = s' * ((u+1) ^ (1/3)), y' = t' * ((u+1) ^ (1/2)).
//
// To sum up, it maps
// (x,y) -> (x^p / ((u+1)^((p-1)/3)), y^p / ((u+1)^((p-1)/2)))
// as implemented in the code as follows.
let mut res = *p;
res.x.frobenius_map(1);
res.y.frobenius_map(1);
let tmp_x = res.x.clone();
res.x.c0 = -P_POWER_ENDOMORPHISM_COEFF_0.c1 * &tmp_x.c1;
res.x.c1 = P_POWER_ENDOMORPHISM_COEFF_0.c1 * &tmp_x.c0;
res.y *= P_POWER_ENDOMORPHISM_COEFF_1;
res
}

View File

@@ -1,8 +1,12 @@
#![allow(unused_imports)] #![allow(unused_imports)]
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve}; use ark_ec::{
models::SWModelParameters,
short_weierstrass_jacobian::{GroupAffine, GroupProjective},
AffineCurve, PairingEngine, ProjectiveCurve,
};
use ark_ff::{ use ark_ff::{
fields::{Field, FpParameters, PrimeField, SquareRootField}, fields::{Field, FpParameters, PrimeField, SquareRootField},
One, Zero, BitIteratorBE, One, UniformRand, Zero,
}; };
use ark_serialize::CanonicalSerialize; use ark_serialize::CanonicalSerialize;
use ark_std::rand::Rng; use ark_std::rand::Rng;
@@ -11,6 +15,7 @@ use core::ops::{AddAssign, MulAssign};
use crate::{g1, g2, Bls12_381, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective}; use crate::{g1, g2, Bls12_381, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_algebra_test_templates::{curves::*, groups::*}; use ark_algebra_test_templates::{curves::*, groups::*};
use ark_ec::group::Group;
#[test] #[test]
fn test_g1_projective_curve() { fn test_g1_projective_curve() {
@@ -115,3 +120,54 @@ fn test_g1_generator_raw() {
x.add_assign(&Fq::one()); x.add_assign(&Fq::one());
} }
} }
#[test]
fn test_g1_endomorphism_beta() {
assert!(g1::BETA.pow(&[3u64]).is_one());
}
#[test]
fn test_g1_subgroup_membership_via_endomorphism() {
let mut rng = test_rng();
let generator = G1Projective::rand(&mut rng).into_affine();
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g1_subgroup_non_membership_via_endomorphism() {
let mut rng = test_rng();
loop {
let x = Fq::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = G1Affine::get_point_from_x(x, greatest) {
if !p.into_projective().mul(Fr::characteristic()).is_zero() {
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
return;
}
}
}
}
#[test]
fn test_g2_subgroup_membership_via_endomorphism() {
let mut rng = test_rng();
let generator = G2Projective::rand(&mut rng).into_affine();
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_subgroup_non_membership_via_endomorphism() {
let mut rng = test_rng();
loop {
let x = Fq2::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = G2Affine::get_point_from_x(x, greatest) {
if !p.into_projective().mul(Fr::characteristic()).is_zero() {
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
return;
}
}
}
}

View File

@@ -1004,7 +1004,7 @@ fn test_fq_repr_num_bits() {
} }
#[test] #[test]
fn test_fq_repr_sub_noborrow() { fn test_fq_repr_sub_ret_borrow() {
let mut rng = ark_std::test_rng(); let mut rng = ark_std::test_rng();
let mut t = BigInteger384([ let mut t = BigInteger384([
@@ -1015,7 +1015,7 @@ fn test_fq_repr_sub_noborrow() {
0xad0eb3948a5c34fd, 0xad0eb3948a5c34fd,
0xd56f7b5ab8b5ce8, 0xd56f7b5ab8b5ce8,
]); ]);
t.sub_noborrow(&BigInteger384([ t.sub_ret_borrow(&BigInteger384([
0xc7867917187ca02b, 0xc7867917187ca02b,
0x5d75679d4911ffef, 0x5d75679d4911ffef,
0x8c5b3e48b1a71c15, 0x8c5b3e48b1a71c15,
@@ -1050,12 +1050,12 @@ fn test_fq_repr_sub_noborrow() {
assert!(b < c); assert!(b < c);
let mut csub_ba = c; let mut csub_ba = c;
csub_ba.sub_noborrow(&b); csub_ba.sub_ret_borrow(&b);
csub_ba.sub_noborrow(&a); csub_ba.sub_ret_borrow(&a);
let mut csub_ab = c; let mut csub_ab = c;
csub_ab.sub_noborrow(&a); csub_ab.sub_ret_borrow(&a);
csub_ab.sub_noborrow(&b); csub_ab.sub_ret_borrow(&b);
assert_eq!(csub_ab, csub_ba); assert_eq!(csub_ab, csub_ba);
} }
@@ -1069,7 +1069,7 @@ fn test_fq_repr_sub_noborrow() {
0x4b1ba7b6434bacd7, 0x4b1ba7b6434bacd7,
0x1a0111ea397fe69a, 0x1a0111ea397fe69a,
]); ]);
qplusone.sub_noborrow(&BigInteger384([ qplusone.sub_ret_borrow(&BigInteger384([
0xb9feffffffffaaac, 0xb9feffffffffaaac,
0x1eabfffeb153ffff, 0x1eabfffeb153ffff,
0x6730d2a0f6b0f624, 0x6730d2a0f6b0f624,
@@ -1091,7 +1091,7 @@ fn test_fq_repr_sub_noborrow() {
} }
#[test] #[test]
fn test_fq_repr_add_nocarry() { fn test_fq_repr_add_ret_carry() {
let mut rng = ark_std::test_rng(); let mut rng = ark_std::test_rng();
let mut t = BigInteger384([ let mut t = BigInteger384([
@@ -1102,7 +1102,7 @@ fn test_fq_repr_add_nocarry() {
0xad0eb3948a5c34fd, 0xad0eb3948a5c34fd,
0xd56f7b5ab8b5ce8, 0xd56f7b5ab8b5ce8,
]); ]);
t.add_nocarry(&BigInteger384([ t.add_ret_carry(&BigInteger384([
0xc7867917187ca02b, 0xc7867917187ca02b,
0x5d75679d4911ffef, 0x5d75679d4911ffef,
0x8c5b3e48b1a71c15, 0x8c5b3e48b1a71c15,
@@ -1133,28 +1133,28 @@ fn test_fq_repr_add_nocarry() {
c.0[5] >>= 3; c.0[5] >>= 3;
let mut abc = a; let mut abc = a;
abc.add_nocarry(&b); abc.add_ret_carry(&b);
abc.add_nocarry(&c); abc.add_ret_carry(&c);
let mut acb = a; let mut acb = a;
acb.add_nocarry(&c); acb.add_ret_carry(&c);
acb.add_nocarry(&b); acb.add_ret_carry(&b);
let mut bac = b; let mut bac = b;
bac.add_nocarry(&a); bac.add_ret_carry(&a);
bac.add_nocarry(&c); bac.add_ret_carry(&c);
let mut bca = b; let mut bca = b;
bca.add_nocarry(&c); bca.add_ret_carry(&c);
bca.add_nocarry(&a); bca.add_ret_carry(&a);
let mut cab = c; let mut cab = c;
cab.add_nocarry(&a); cab.add_ret_carry(&a);
cab.add_nocarry(&b); cab.add_ret_carry(&b);
let mut cba = c; let mut cba = c;
cba.add_nocarry(&b); cba.add_ret_carry(&b);
cba.add_nocarry(&a); cba.add_ret_carry(&a);
assert_eq!(abc, acb); assert_eq!(abc, acb);
assert_eq!(abc, bac); assert_eq!(abc, bac);
@@ -1172,7 +1172,7 @@ fn test_fq_repr_add_nocarry() {
0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0xffffffffffffffff,
]); ]);
x.add_nocarry(&BigInteger384::from(1)); x.add_ret_carry(&BigInteger384::from(1));
assert!(x.is_zero()); assert!(x.is_zero());
} }

View File

@@ -196,6 +196,32 @@ macro_rules! ec_bench {
}); });
} }
fn deser_uncompressed(b: &mut $crate::bencher::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let mut num_bytes = 0;
let tmp = <$projective>::rand(&mut rng).into_affine();
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
tmp.serialize_uncompressed(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
<$affine>::deserialize_uncompressed(&v[index..(index + num_bytes)]).unwrap()
});
}
fn msm_131072(b: &mut $crate::bencher::Bencher) { fn msm_131072(b: &mut $crate::bencher::Bencher) {
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 131072; const SAMPLES: usize = 131072;
@@ -224,6 +250,7 @@ macro_rules! ec_bench {
deser, deser,
ser_unchecked, ser_unchecked,
deser_unchecked, deser_unchecked,
deser_uncompressed,
msm_131072, msm_131072,
); );
}; };

View File

@@ -24,8 +24,8 @@ macro_rules! f_bench {
// sqrt field stuff // sqrt field stuff
sqrt, sqrt,
// prime field stuff // prime field stuff
repr_add_nocarry, repr_add_ret_carry,
repr_sub_noborrow, repr_sub_ret_borrow,
repr_num_bits, repr_num_bits,
repr_mul2, repr_mul2,
repr_div2, repr_div2,
@@ -322,7 +322,7 @@ macro_rules! sqrt {
#[macro_export] #[macro_export]
macro_rules! prime_field { macro_rules! prime_field {
($f:ident, $f_type:ty, $f_repr:ident, $f_repr_type:ty) => { ($f:ident, $f_type:ty, $f_repr:ident, $f_repr_type:ty) => {
fn repr_add_nocarry(b: &mut $crate::bencher::Bencher) { fn repr_add_ret_carry(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000; const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng(); let mut rng = ark_std::test_rng();
@@ -343,13 +343,13 @@ macro_rules! prime_field {
let mut count = 0; let mut count = 0;
b.iter(|| { b.iter(|| {
let mut tmp = v[count].0; let mut tmp = v[count].0;
n_fold!(tmp, v, add_nocarry, count); n_fold!(tmp, v, add_ret_carry, count);
count = (count + 1) % SAMPLES; count = (count + 1) % SAMPLES;
tmp tmp
}); });
} }
fn repr_sub_noborrow(b: &mut $crate::bencher::Bencher) { fn repr_sub_ret_borrow(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000; const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng(); let mut rng = ark_std::test_rng();
@@ -369,7 +369,7 @@ macro_rules! prime_field {
let mut count = 0; let mut count = 0;
b.iter(|| { b.iter(|| {
let mut tmp = v[count].0; let mut tmp = v[count].0;
n_fold!(tmp, v, sub_noborrow, count); n_fold!(tmp, v, sub_ret_borrow, count);
count = (count + 1) % SAMPLES; count = (count + 1) % SAMPLES;
tmp; tmp;
}); });
@@ -448,7 +448,7 @@ macro_rules! prime_field {
let mut count = 0; let mut count = 0;
b.iter(|| { b.iter(|| {
count = (count + 1) % SAMPLES; count = (count + 1) % SAMPLES;
$f::from(v[count]); let _ = $f::from(v[count]);
}); });
} }
}; };

View File

@@ -233,8 +233,7 @@ pub mod fields {
pub mod curves { pub mod curves {
use ark_ec::{ use ark_ec::{
short_weierstrass_jacobian::GroupProjective as SWProjective, short_weierstrass_jacobian::GroupProjective as SWProjective,
twisted_edwards_extended::GroupProjective as TEProjective, ModelParameters, twisted_edwards_extended::GroupProjective as TEProjective, ProjectiveCurve,
ProjectiveCurve,
}; };
use ark_ff::{BitIteratorLE, Field, FpParameters, One, PrimeField}; use ark_ff::{BitIteratorLE, Field, FpParameters, One, PrimeField};
use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
@@ -242,13 +241,12 @@ pub mod curves {
use ark_r1cs_std::prelude::*; use ark_r1cs_std::prelude::*;
type ConstraintF<P> = <<P as ModelParameters>::BaseField as Field>::BasePrimeField; pub fn group_test<C, ConstraintF, GG>() -> Result<(), SynthesisError>
pub fn group_test<C, ConstraintF>() -> Result<(), SynthesisError>
where where
C: CurveWithVar<ConstraintF>, C: ProjectiveCurve,
ConstraintF: Field, ConstraintF: Field,
for<'a> &'a C::Var: GroupOpsBounds<'a, C, C::Var>, GG: CurveVar<C, ConstraintF>,
for<'a> &'a GG: GroupOpsBounds<'a, C, GG>,
{ {
let modes = [ let modes = [
AllocationMode::Input, AllocationMode::Input,
@@ -261,14 +259,12 @@ pub mod curves {
let mut rng = test_rng(); let mut rng = test_rng();
let a_native = C::rand(&mut rng); let a_native = C::rand(&mut rng);
let b_native = C::rand(&mut rng); let b_native = C::rand(&mut rng);
let a = let a = GG::new_variable(ark_relations::ns!(cs, "generate_a"), || Ok(a_native), mode)
C::Var::new_variable(ark_relations::ns!(cs, "generate_a"), || Ok(a_native), mode)
.unwrap(); .unwrap();
let b = let b = GG::new_variable(ark_relations::ns!(cs, "generate_b"), || Ok(b_native), mode)
C::Var::new_variable(ark_relations::ns!(cs, "generate_b"), || Ok(b_native), mode)
.unwrap(); .unwrap();
let zero = C::Var::zero(); let zero = GG::zero();
assert_eq!(zero.value()?, zero.value()?); assert_eq!(zero.value()?, zero.value()?);
// a == a // a == a
@@ -277,14 +273,14 @@ pub mod curves {
assert_eq!((&a + &zero).value()?, a.value()?); assert_eq!((&a + &zero).value()?, a.value()?);
// a - 0 = a // a - 0 = a
assert_eq!((&a - &zero).value()?, a.value()?); assert_eq!((&a - &zero).value()?, a.value()?);
// a - a = 0
assert_eq!((&a - &a).value()?, zero.value()?);
// a + b = b + a // a + b = b + a
let a_b = &a + &b; let a_b = &a + &b;
let b_a = &b + &a; let b_a = &b + &a;
assert_eq!(a_b.value()?, b_a.value()?); assert_eq!(a_b.value()?, b_a.value()?);
a_b.enforce_equal(&b_a)?; a_b.enforce_equal(&b_a)?;
assert!(cs.is_satisfied().unwrap()); assert!(cs.is_satisfied().unwrap());
// a - a = 0
assert_eq!((&a - &a).value()?, zero.value()?);
// (a + b) + a = a + (b + a) // (a + b) + a = a + (b + a)
let ab_a = &a_b + &a; let ab_a = &a_b + &a;
@@ -384,15 +380,13 @@ pub mod curves {
Ok(()) Ok(())
} }
type SWVar<P> = <SWProjective<P> as CurveWithVar<ConstraintF<P>>>::Var; pub fn sw_test<P, GG>() -> Result<(), SynthesisError>
pub fn sw_test<P>() -> Result<(), SynthesisError>
where where
P: ark_ec::SWModelParameters, P: ark_ec::SWModelParameters,
SWProjective<P>: CurveWithVar<ConstraintF<P>> + ProjectiveCurve, GG: CurveVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>,
for<'a> &'a SWVar<P>: GroupOpsBounds<'a, SWProjective<P>, SWVar<P>>, for<'a> &'a GG: GroupOpsBounds<'a, SWProjective<P>, GG>,
{ {
group_test::<SWProjective<P>, _>()?; group_test::<SWProjective<P>, _, GG>()?;
let modes = [ let modes = [
AllocationMode::Input, AllocationMode::Input,
AllocationMode::Witness, AllocationMode::Witness,
@@ -411,12 +405,14 @@ pub mod curves {
let b_affine = b.into_affine(); let b_affine = b.into_affine();
let ns = ark_relations::ns!(cs, "allocating variables"); let ns = ark_relations::ns!(cs, "allocating variables");
let mut gadget_a = SWVar::<P>::new_variable(cs.clone(), || Ok(a), mode)?; let mut gadget_a = GG::new_variable(cs.clone(), || Ok(a), mode)?;
let gadget_b = SWVar::<P>::new_variable(cs.clone(), || Ok(b), mode)?; let gadget_b = GG::new_variable(cs.clone(), || Ok(b), mode)?;
let zero = SWVar::<P>::zero(); let zero = GG::zero();
drop(ns); drop(ns);
assert_eq!(gadget_a.value()?.into_affine(), a_affine); assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x);
assert_eq!(gadget_b.value()?.into_affine(), b_affine); assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y);
assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x);
assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y);
assert_eq!(cs.which_is_unsatisfied().unwrap(), None); assert_eq!(cs.which_is_unsatisfied().unwrap(), None);
// Check addition // Check addition
@@ -457,15 +453,13 @@ pub mod curves {
Ok(()) Ok(())
} }
type TEVar<P> = <TEProjective<P> as CurveWithVar<ConstraintF<P>>>::Var; pub fn te_test<P, GG>() -> Result<(), SynthesisError>
pub fn te_test<P>() -> Result<(), SynthesisError>
where where
P: ark_ec::TEModelParameters, P: ark_ec::TEModelParameters,
TEProjective<P>: CurveWithVar<ConstraintF<P>> + ProjectiveCurve, GG: CurveVar<TEProjective<P>, <P::BaseField as Field>::BasePrimeField>,
for<'a> &'a TEVar<P>: GroupOpsBounds<'a, TEProjective<P>, TEVar<P>>, for<'a> &'a GG: GroupOpsBounds<'a, TEProjective<P>, GG>,
{ {
group_test::<TEProjective<P>, _>()?; group_test::<TEProjective<P>, _, GG>()?;
let modes = [ let modes = [
AllocationMode::Input, AllocationMode::Input,
AllocationMode::Witness, AllocationMode::Witness,
@@ -484,12 +478,14 @@ pub mod curves {
let b_affine = b.into_affine(); let b_affine = b.into_affine();
let ns = ark_relations::ns!(cs, "allocating variables"); let ns = ark_relations::ns!(cs, "allocating variables");
let mut gadget_a = TEVar::<P>::new_variable(cs.clone(), || Ok(a), mode)?; let mut gadget_a = GG::new_variable(cs.clone(), || Ok(a), mode)?;
let gadget_b = TEVar::<P>::new_variable(cs.clone(), || Ok(b), mode)?; let gadget_b = GG::new_variable(cs.clone(), || Ok(b), mode)?;
drop(ns); drop(ns);
assert_eq!(gadget_a.value()?.into_affine(), a_affine); assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x);
assert_eq!(gadget_b.value()?.into_affine(), b_affine); assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y);
assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x);
assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y);
assert_eq!(cs.which_is_unsatisfied()?, None); assert_eq!(cs.which_is_unsatisfied()?, None);
// Check addition // Check addition
@@ -531,21 +527,16 @@ pub mod curves {
pub mod pairing { pub mod pairing {
use ark_ec::{PairingEngine, ProjectiveCurve}; use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{BitIteratorLE, Field, PrimeField}; use ark_ff::{BitIteratorLE, Field, PrimeField};
use ark_r1cs_std::{fields::fp::FpVar, prelude::*}; use ark_r1cs_std::prelude::*;
use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
use ark_std::{test_rng, vec::Vec, UniformRand}; use ark_std::{test_rng, vec::Vec, UniformRand};
#[allow(dead_code)] #[allow(dead_code)]
pub fn bilinearity_test<P: PairingGadget>() -> Result<(), SynthesisError> pub fn bilinearity_test<E: PairingEngine, P: PairingVar<E>>() -> Result<(), SynthesisError>
where where
for<'a> &'a P::G1Var: GroupOpsBounds<'a, P::G1Projective, P::G1Var>, for<'a> &'a P::G1Var: GroupOpsBounds<'a, E::G1Projective, P::G1Var>,
for<'a> &'a P::G2Var: GroupOpsBounds<'a, P::G2Projective, P::G2Var>, for<'a> &'a P::G2Var: GroupOpsBounds<'a, E::G2Projective, P::G2Var>,
for<'a> &'a P::GTVar: FieldOpsBounds<'a, P::Fqk, P::GTVar>, for<'a> &'a P::GTVar: FieldOpsBounds<'a, E::Fqk, P::GTVar>,
P::Fq: FieldWithVar<Var = FpVar<P::Fq>>,
P::Fqe: FieldWithVar,
P::Fqk: FieldWithVar<Var = P::GTVar>,
P::G1Projective: CurveWithVar<P::Fq, Var = P::G1Var>,
P::G2Projective: CurveWithVar<P::Fq, Var = P::G2Var>,
{ {
let modes = [ let modes = [
AllocationMode::Input, AllocationMode::Input,
@@ -553,12 +544,12 @@ pub mod pairing {
AllocationMode::Constant, AllocationMode::Constant,
]; ];
for &mode in &modes { for &mode in &modes {
let cs = ConstraintSystem::<P::Fq>::new_ref(); let cs = ConstraintSystem::<E::Fq>::new_ref();
let mut rng = test_rng(); let mut rng = test_rng();
let a = P::G1Projective::rand(&mut rng); let a = E::G1Projective::rand(&mut rng);
let b = P::G2Projective::rand(&mut rng); let b = E::G2Projective::rand(&mut rng);
let s = P::Fr::rand(&mut rng); let s = E::Fr::rand(&mut rng);
let mut sa = a; let mut sa = a;
sa *= s; sa *= s;
@@ -580,16 +571,16 @@ pub mod pairing {
let (ans1_g, ans1_n) = { let (ans1_g, ans1_n) = {
let _ml_constraints = cs.num_constraints(); let _ml_constraints = cs.num_constraints();
let ml_g = P::miller_loop_gadget(&[sa_prep_g], &[b_prep_g.clone()])?; let ml_g = P::miller_loop(&[sa_prep_g], &[b_prep_g.clone()])?;
let _fe_constraints = cs.num_constraints(); let _fe_constraints = cs.num_constraints();
let ans_g = P::final_exponentiation_gadget(&ml_g)?; let ans_g = P::final_exponentiation(&ml_g)?;
let ans_n = <P as PairingEngine>::pairing(sa, b); let ans_n = E::pairing(sa, b);
(ans_g, ans_n) (ans_g, ans_n)
}; };
let (ans2_g, ans2_n) = { let (ans2_g, ans2_n) = {
let ans_g = P::pairing_gadget(a_prep_g.clone(), sb_prep_g)?; let ans_g = P::pairing(a_prep_g.clone(), sb_prep_g)?;
let ans_n = <P as PairingEngine>::pairing(a, sb); let ans_n = E::pairing(a, sb);
(ans_g, ans_n) (ans_g, ans_n)
}; };
@@ -598,8 +589,8 @@ pub mod pairing {
.map(Boolean::constant) .map(Boolean::constant)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut ans_g = P::pairing_gadget(a_prep_g, b_prep_g)?; let mut ans_g = P::pairing(a_prep_g, b_prep_g)?;
let mut ans_n = <P as PairingEngine>::pairing(a, b); let mut ans_n = E::pairing(a, b);
ans_n = ans_n.pow(s.into_repr()); ans_n = ans_n.pow(s.into_repr());
ans_g = ans_g.pow_le(&s_iter)?; ans_g = ans_g.pow_le(&s_iter)?;

View File

@@ -1,10 +1,12 @@
use crate::*; use crate::*;
use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar;
use crate::constraints::FqVar;
/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. /// A variable that is the R1CS equivalent of `crate::EdwardsAffine`.
pub type EdwardsVar = AffineVar<EdwardsParameters>; pub type EdwardsVar = AffineVar<EdwardsParameters, FqVar>;
#[test] #[test]
fn test() { fn test() {
ark_curve_constraint_tests::curves::te_test::<EdwardsParameters>().unwrap(); ark_curve_constraint_tests::curves::te_test::<EdwardsParameters, EdwardsVar>().unwrap();
} }

View File

@@ -1,10 +1,17 @@
use crate::*; use crate::*;
use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; use ark_r1cs_std::groups::curves::{short_weierstrass::ProjectiveVar, twisted_edwards::AffineVar};
use crate::constraints::FqVar;
/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. /// A variable that is the R1CS equivalent of `crate::EdwardsAffine`.
pub type EdwardsVar = AffineVar<EdwardsParameters>; pub type EdwardsVar = AffineVar<JubjubParameters, FqVar>;
/// A variable that is the R1CS equivalent of `crate::SWProjective`
pub type SWVar = ProjectiveVar<JubjubParameters, FqVar>;
#[test] #[test]
fn test() { fn test() {
ark_curve_constraint_tests::curves::te_test::<EdwardsParameters>().unwrap(); ark_curve_constraint_tests::curves::te_test::<_, EdwardsVar>().unwrap();
ark_curve_constraint_tests::curves::sw_test::<_, SWVar>().unwrap();
ark_curve_constraint_tests::curves::group_test::<_, Fq, EdwardsVar>().unwrap();
} }

View File

@@ -1,15 +1,21 @@
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; use ark_ff::field_new;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub type EdwardsAffine = GroupAffine<EdwardsParameters>; pub type EdwardsAffine = GroupAffine<JubjubParameters>;
pub type EdwardsProjective = GroupProjective<EdwardsParameters>; pub type EdwardsProjective = GroupProjective<JubjubParameters>;
pub type SWAffine = SWGroupAffine<JubjubParameters>;
pub type SWProjective = SWGroupProjective<JubjubParameters>;
/// `JubJub` is a twisted Edwards curve. These curves have equations of the /// `JubJub` is a twisted Edwards curve. These curves have equations of the
/// form: ax² + y² = 1 - dx²y². /// form: ax² + y² = 1 - dx²y².
@@ -32,15 +38,29 @@ pub type EdwardsProjective = GroupProjective<EdwardsParameters>;
/// ``` /// ```
/// These parameters and the sage script obtained from: /// These parameters and the sage script obtained from:
/// <https://github.com/zcash/zcash/issues/2230#issuecomment-317182190> /// <https://github.com/zcash/zcash/issues/2230#issuecomment-317182190>
///
///
/// `jubjub` also has a short Weierstrass curve form, following the
/// form: y² = x³ + A * x + B
/// where
///
/// A = 52296097456646850916096512823759002727550416093741407922227928430486925478210
/// B = 48351165704696163914533707656614864561753505123260775585269522553028192119009
///
/// We can use the script available
/// [here](https://github.com/zhenfeizhang/bandersnatch/blob/main/bandersnatch/script/jubjub.sage)
/// to convert between the different representations.
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct EdwardsParameters; pub struct JubjubParameters;
pub type EdwardsParameters = JubjubParameters;
pub type SWParameters = JubjubParameters;
impl ModelParameters for EdwardsParameters { impl ModelParameters for JubjubParameters {
type BaseField = Fq; type BaseField = Fq;
type ScalarField = Fr; type ScalarField = Fr;
} }
impl TEModelParameters for EdwardsParameters { impl TEModelParameters for JubjubParameters {
/// COEFF_A = -1 /// COEFF_A = -1
#[rustfmt::skip] #[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, "-1"); const COEFF_A: Fq = field_new!(Fq, "-1");
@@ -60,7 +80,7 @@ impl TEModelParameters for EdwardsParameters {
/// 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) = (GENERATOR_X, GENERATOR_Y);
type MontgomeryModelParameters = EdwardsParameters; type MontgomeryModelParameters = JubjubParameters;
/// Multiplication by `a` is simply negation here. /// Multiplication by `a` is simply negation here.
#[inline(always)] #[inline(always)]
@@ -69,7 +89,7 @@ impl TEModelParameters for EdwardsParameters {
} }
} }
impl MontgomeryModelParameters for EdwardsParameters { impl MontgomeryModelParameters for JubjubParameters {
/// COEFF_A = 40962 /// COEFF_A = 40962
#[rustfmt::skip] #[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, "40962"); const COEFF_A: Fq = field_new!(Fq, "40962");
@@ -77,10 +97,39 @@ impl MontgomeryModelParameters for EdwardsParameters {
#[rustfmt::skip] #[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, "-40964"); const COEFF_B: Fq = field_new!(Fq, "-40964");
type TEModelParameters = EdwardsParameters; type TEModelParameters = JubjubParameters;
} }
#[rustfmt::skip] #[rustfmt::skip]
const GENERATOR_X: Fq = field_new!(Fq, "8076246640662884909881801758704306714034609987455869804520522091855516602923"); const GENERATOR_X: Fq = field_new!(Fq, "8076246640662884909881801758704306714034609987455869804520522091855516602923");
#[rustfmt::skip] #[rustfmt::skip]
const GENERATOR_Y: Fq = field_new!(Fq, "13262374693698910701929044844600465831413122818447359594527400194675274060458"); const GENERATOR_Y: Fq = field_new!(Fq, "13262374693698910701929044844600465831413122818447359594527400194675274060458");
impl SWModelParameters for JubjubParameters {
/// COEFF_A = 52296097456646850916096512823759002727550416093741407922227928430486925478210
#[rustfmt::skip]
const COEFF_A: Self::BaseField = field_new!(Fq, "52296097456646850916096512823759002727550416093741407922227928430486925478210");
/// COEFF_B = 48351165704696163914533707656614864561753505123260775585269522553028192119009
#[rustfmt::skip]
const COEFF_B: Self::BaseField = field_new!(Fq, "48351165704696163914533707656614864561753505123260775585269522553028192119009");
/// COFACTOR = 8
const COFACTOR: &'static [u64] = &[8];
/// COFACTOR^(-1) mod r =
/// 819310549611346726241370945440405716213240158234039660170669895299022906775
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, "819310549611346726241370945440405716213240158234039660170669895299022906775");
/// generators
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(SW_GENERATOR_X, SW_GENERATOR_Y);
}
/// x coordinate for SW curve generator
#[rustfmt::skip]
const SW_GENERATOR_X: Fq = field_new!(Fq, "33835869156188682335217394949746694649676633840125476177319971163079011318731");
/// y coordinate for SW curve generator
#[rustfmt::skip]
const SW_GENERATOR_Y: Fq = field_new!(Fq, "43777270878440091394432848052353307184915192688165709016756678962558652055320");

View File

@@ -1,8 +1,6 @@
use ark_ec::{AffineCurve, ProjectiveCurve}; use ark_ec::{AffineCurve, ProjectiveCurve};
use ark_ff::{bytes::FromBytes, Zero}; use ark_ff::{bytes::FromBytes, Zero};
use ark_std::rand::Rng; use ark_std::{rand::Rng, str::FromStr, test_rng};
use ark_std::str::FromStr;
use ark_std::test_rng;
use crate::*; use crate::*;
@@ -12,7 +10,9 @@ use ark_algebra_test_templates::{curves::*, groups::*};
fn test_projective_curve() { fn test_projective_curve() {
curve_tests::<EdwardsProjective>(); curve_tests::<EdwardsProjective>();
edwards_tests::<EdwardsParameters>(); edwards_tests::<JubjubParameters>();
montgomery_conversion_test::<JubjubParameters>();
sw_tests::<JubjubParameters>();
} }
#[test] #[test]
@@ -20,8 +20,13 @@ fn test_projective_group() {
let mut rng = test_rng(); let mut rng = test_rng();
let a = rng.gen(); let a = rng.gen();
let b = rng.gen(); let b = rng.gen();
let c = rng.gen();
let d = rng.gen();
for _i in 0..100 { for _i in 0..100 {
group_test::<EdwardsProjective>(a, b); group_test::<EdwardsProjective>(a, b);
group_test::<SWProjective>(c, d);
} }
} }
@@ -37,9 +42,15 @@ fn test_affine_group() {
#[test] #[test]
fn test_generator() { fn test_generator() {
// edward curve
let generator = EdwardsAffine::prime_subgroup_generator(); let generator = EdwardsAffine::prime_subgroup_generator();
assert!(generator.is_on_curve()); assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve()); assert!(generator.is_in_correct_subgroup_assuming_on_curve());
// weierstrass curve
let generator = SWAffine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
} }
#[test] #[test]
@@ -103,5 +114,5 @@ fn test_bytes() {
#[test] #[test]
fn test_montgomery_conversion() { fn test_montgomery_conversion() {
montgomery_conversion_test::<EdwardsParameters>(); montgomery_conversion_test::<JubjubParameters>();
} }

View File

@@ -9,8 +9,7 @@ use ark_std::test_rng;
use ark_algebra_test_templates::fields::*; use ark_algebra_test_templates::fields::*;
use ark_std::rand::Rng; use ark_std::{rand::Rng, str::FromStr};
use ark_std::str::FromStr;
#[test] #[test]
fn test_fr() { fn test_fr() {

View File

@@ -8,14 +8,16 @@
)] )]
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
//! This library implements a twisted Edwards curve whose base field is the scalar field of the //! This library implements a twisted Edwards curve whose base field is the
//! curve BLS12-381. This allows defining cryptographic primitives that use elliptic curves over //! scalar field of the curve BLS12-381. This allows defining cryptographic
//! the scalar field of the latter curve. This curve was generated by Sean Bowe, and is also known //! primitives that use elliptic curves over the scalar field of the latter
//! as [Jubjub](https://github.com/zkcrypto/jubjub). //! curve. This curve was generated by Sean Bowe, and is also known as [Jubjub](https://github.com/zkcrypto/jubjub).
//! //!
//! Curve information: //! Curve information:
//! * Base field: q = 52435875175126190479447740508185965837690552500527637822603658699938581184513 //! * Base field: q =
//! * Scalar field: r = 6554484396890773809930967563523245729705921265872317281365359162392183254199 //! 52435875175126190479447740508185965837690552500527637822603658699938581184513
//! * Scalar field: r =
//! 6554484396890773809930967563523245729705921265872317281365359162392183254199
//! * Valuation(q - 1, 2) = 32 //! * Valuation(q - 1, 2) = 32
//! * Valuation(r - 1, 2) = 1 //! * Valuation(r - 1, 2) = 1
//! * Curve equation: ax^2 + y^2 =1 + dx^2y^2, where //! * Curve equation: ax^2 + y^2 =1 + dx^2y^2, where

View File

@@ -1,10 +1,15 @@
use crate::*; use crate::{constraints::FqVar, *};
use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; use ark_r1cs_std::groups::curves::{short_weierstrass::ProjectiveVar, twisted_edwards::AffineVar};
/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. /// A variable that is the R1CS equivalent of `crate::BandersnatchParameters`.
pub type EdwardsVar = AffineVar<EdwardsParameters>; pub type EdwardsVar = AffineVar<BandersnatchParameters, FqVar>;
/// A variable that is the R1CS equivalent of `crate::SWProjective`
pub type SWVar = ProjectiveVar<BandersnatchParameters, FqVar>;
#[test] #[test]
fn test() { fn test() {
ark_curve_constraint_tests::curves::te_test::<EdwardsParameters>().unwrap(); ark_curve_constraint_tests::curves::te_test::<_, EdwardsVar>().unwrap();
ark_curve_constraint_tests::curves::sw_test::<_, SWVar>().unwrap();
ark_curve_constraint_tests::curves::group_test::<_, Fq, EdwardsVar>().unwrap();
} }

View File

@@ -1,24 +1,32 @@
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 EdwardsAffine = GroupAffine<BandersnatchParameters>;
pub type EdwardsProjective = GroupProjective<EdwardsParameters>; pub type EdwardsProjective = GroupProjective<BandersnatchParameters>;
/// `banersnatch` is a twisted Edwards curve. These curves have equations of the pub type SWAffine = SWGroupAffine<BandersnatchParameters>;
pub type SWProjective = SWGroupProjective<BandersnatchParameters>;
/// `bandersnatch` 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² /// bandersnatch'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.
@@ -32,17 +40,30 @@ pub type EdwardsProjective = GroupProjective<EdwardsParameters>;
/// ``` /// ```
/// 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;
impl ModelParameters for EdwardsParameters { pub type EdwardsParameters = BandersnatchParameters;
pub type SWParameters = BandersnatchParameters;
impl ModelParameters for BandersnatchParameters {
type BaseField = Fq; type BaseField = Fq;
type ScalarField = Fr; type ScalarField = Fr;
} }
impl TEModelParameters for EdwardsParameters { impl TEModelParameters for BandersnatchParameters {
/// 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 = EdwardsParameters; type MontgomeryModelParameters = BandersnatchParameters;
/// 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 EdwardsParameters { impl MontgomeryModelParameters for BandersnatchParameters {
/// 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 = EdwardsParameters; type TEModelParameters = BandersnatchParameters;
} }
// using the generator from bench.py (in affine form) // The TE form generator is generated following Zcash's fashion:
// P = BandersnatchPoint( // "The generators of G1 and G2 are computed by finding the lexicographically smallest
// 13738737789055671334382939318077718462576533426798874551591468520593954805549, // valid x-coordinate, and its lexicographically smallest y-coordinate and scaling it
// 11575885077368931610486103676191793534029821920164915325066801506752632626968, // by the cofactor such that the result is not the point at infinity."
// 14458123306641001284399433086015669988340559992755622870694102351476334505845, // The SW form generator is the same TE generator converted into SW form, obtained from the scripts:
// C) // <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);
}

View File

@@ -8,7 +8,9 @@ use ark_std::{rand::Rng, str::FromStr, test_rng};
fn test_projective_curve() { fn test_projective_curve() {
curve_tests::<EdwardsProjective>(); curve_tests::<EdwardsProjective>();
edwards_tests::<EdwardsParameters>(); edwards_tests::<BandersnatchParameters>();
montgomery_conversion_test::<BandersnatchParameters>();
sw_tests::<BandersnatchParameters>();
} }
#[test] #[test]
@@ -16,8 +18,13 @@ fn test_projective_group() {
let mut rng = test_rng(); let mut rng = test_rng();
let a = rng.gen(); let a = rng.gen();
let b = rng.gen(); let b = rng.gen();
let c = rng.gen();
let d = rng.gen();
for _i in 0..100 { for _i in 0..100 {
group_test::<EdwardsProjective>(a, b); group_test::<EdwardsProjective>(a, b);
group_test::<SWProjective>(c, d);
} }
} }
@@ -33,13 +40,20 @@ fn test_affine_group() {
#[test] #[test]
fn test_generator() { fn test_generator() {
// edward curve
let generator = EdwardsAffine::prime_subgroup_generator(); let generator = EdwardsAffine::prime_subgroup_generator();
assert!(generator.is_on_curve()); assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve()); assert!(generator.is_in_correct_subgroup_assuming_on_curve());
// weierstrass curve
let generator = SWAffine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
} }
#[test] #[test]
fn test_conversion() { fn test_conversion() {
// edward curve
let mut rng = test_rng(); let mut rng = test_rng();
let a: EdwardsAffine = rng.gen(); let a: EdwardsAffine = rng.gen();
let b: EdwardsAffine = rng.gen(); let b: EdwardsAffine = rng.gen();
@@ -52,6 +66,14 @@ fn test_conversion() {
.double(); .double();
assert_eq!(a_b, a_b2.into_affine()); assert_eq!(a_b, a_b2.into_affine());
assert_eq!(a_b.into_projective(), a_b2); assert_eq!(a_b.into_projective(), a_b2);
// weierstrass curve
let mut rng = test_rng();
let a: SWProjective = rng.gen();
let b: SWProjective = rng.gen();
let a_b = { (a + &b).double().double() };
let a_b2 = (a + &b).double().double();
assert_eq!(a_b.into_affine(), a_b2.into_affine());
} }
#[test] #[test]
@@ -99,5 +121,5 @@ fn test_bytes() {
#[test] #[test]
fn test_montgomery_conversion() { fn test_montgomery_conversion() {
montgomery_conversion_test::<EdwardsParameters>(); montgomery_conversion_test::<BandersnatchParameters>();
} }

View File

@@ -11,8 +11,8 @@
//! This library implements the Bendersnatch curve, a twisted Edwards curve //! This library implements the Bendersnatch curve, a twisted Edwards curve
//! whose base field is the scalar field of the curve BLS12-381. This allows //! whose base field is the scalar field of the curve BLS12-381. This allows
//! defining cryptographic primitives that use elliptic curves over the scalar //! defining cryptographic primitives that use elliptic curves over the scalar
//! field of the latter curve. This curve was generated by Simon Masson from Anoma, //! field of the latter curve. This curve was generated by Simon Masson from
//! and Antonio Sanso from Ethereum Foundation, and is also known as [bandersnatch](https://ethresear.ch/t/introducing-bandersnatch-a-fast-elliptic-curve-built-over-the-bls12-381-scalar-field/9957). //! Anoma, and Antonio Sanso from Ethereum Foundation, and is also known as [bandersnatch](https://ethresear.ch/t/introducing-bandersnatch-a-fast-elliptic-curve-built-over-the-bls12-381-scalar-field/9957).
//! //!
//! See [here](https://github.com/asanso/Bandersnatch/blob/main/README.md) for the specification of the curve. //! See [here](https://github.com/asanso/Bandersnatch/blob/main/README.md) for the specification of the curve.
//! There was also a Python implementation [here](https://github.com/asanso/Bandersnatch/). //! There was also a Python implementation [here](https://github.com/asanso/Bandersnatch/).

View File

@@ -1,10 +1,12 @@
use crate::*; use crate::*;
use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar;
use crate::constraints::FqVar;
/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. /// A variable that is the R1CS equivalent of `crate::EdwardsAffine`.
pub type EdwardsVar = AffineVar<EdwardsParameters>; pub type EdwardsVar = AffineVar<EdwardsParameters, FqVar>;
#[test] #[test]
fn test() { fn test() {
ark_curve_constraint_tests::curves::te_test::<EdwardsParameters>().unwrap(); ark_curve_constraint_tests::curves::te_test::<_, EdwardsVar>().unwrap();
} }

View File

@@ -1,10 +1,12 @@
use crate::*; use crate::*;
use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar;
use crate::constraints::FqVar;
/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. /// A variable that is the R1CS equivalent of `crate::EdwardsAffine`.
pub type EdwardsVar = AffineVar<EdwardsParameters>; pub type EdwardsVar = AffineVar<EdwardsParameters, FqVar>;
#[test] #[test]
fn test() { fn test() {
ark_curve_constraint_tests::curves::te_test::<EdwardsParameters>().unwrap(); ark_curve_constraint_tests::curves::te_test::<EdwardsParameters, EdwardsVar>().unwrap();
} }

View File

@@ -1,10 +1,12 @@
use crate::*; use crate::*;
use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar;
use crate::constraints::fields::FqVar;
/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. /// A variable that is the R1CS equivalent of `crate::EdwardsAffine`.
pub type EdwardsVar = AffineVar<EdwardsParameters>; pub type EdwardsVar = AffineVar<EdwardsParameters, FqVar>;
#[test] #[test]
fn test() { fn test() {
ark_curve_constraint_tests::curves::te_test::<EdwardsParameters>().unwrap(); ark_curve_constraint_tests::curves::te_test::<EdwardsParameters, EdwardsVar>().unwrap();
} }

View File

@@ -1,10 +1,12 @@
use crate::*; use crate::*;
use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar;
use crate::constraints::fields::FqVar;
/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. /// A variable that is the R1CS equivalent of `crate::EdwardsAffine`.
pub type EdwardsVar = AffineVar<EdwardsParameters>; pub type EdwardsVar = AffineVar<EdwardsParameters, FqVar>;
#[test] #[test]
fn test() { fn test() {
ark_curve_constraint_tests::curves::te_test::<EdwardsParameters>().unwrap(); ark_curve_constraint_tests::curves::te_test::<EdwardsParameters, EdwardsVar>().unwrap();
} }

View File

@@ -16,8 +16,14 @@ pub type G2PreparedVar = mnt4::G2PreparedVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use ark_ec::models::mnt4::MNT4Parameters; use ark_ec::models::mnt4::MNT4Parameters;
ark_curve_constraint_tests::curves::sw_test::<<Parameters as MNT4Parameters>::G1Parameters>() ark_curve_constraint_tests::curves::sw_test::<
<Parameters as MNT4Parameters>::G1Parameters,
G1Var,
>()
.unwrap(); .unwrap();
ark_curve_constraint_tests::curves::sw_test::<<Parameters as MNT4Parameters>::G2Parameters>() ark_curve_constraint_tests::curves::sw_test::<
<Parameters as MNT4Parameters>::G2Parameters,
G2Var,
>()
.unwrap(); .unwrap();
} }

View File

@@ -130,17 +130,17 @@
//! let pairing_result_native = MNT4_298::pairing(a_native, b_native); //! let pairing_result_native = MNT4_298::pairing(a_native, b_native);
//! //!
//! // Prepare `a` and `b` for pairing. //! // Prepare `a` and `b` for pairing.
//! let a_prep = MNT4_298::prepare_g1(&a)?; //! let a_prep = constraints::PairingVar::prepare_g1(&a)?;
//! let b_prep = MNT4_298::prepare_g2(&b)?; //! let b_prep = constraints::PairingVar::prepare_g2(&b)?;
//! let pairing_result = MNT4_298::pairing_gadget(a_prep, b_prep)?; //! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?;
//! //!
//! // Check that the value of &a + &b is correct. //! // Check that the value of &a + &b is correct.
//! assert_eq!(pairing_result.value()?, pairing_result_native); //! assert_eq!(pairing_result.value()?, pairing_result_native);
//! //!
//! // Check that operations on variables and constants are equivalent. //! // Check that operations on variables and constants are equivalent.
//! let a_prep_const = MNT4_298::prepare_g1(&a_const)?; //! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?;
//! let b_prep_const = MNT4_298::prepare_g2(&b_const)?; //! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?;
//! let pairing_result_const = MNT4_298::pairing_gadget(a_prep_const, b_prep_const)?; //! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?;
//! println!("Done here 3"); //! println!("Done here 3");
//! //!
//! pairing_result.enforce_equal(&pairing_result_const)?; //! pairing_result.enforce_equal(&pairing_result_const)?;

View File

@@ -1,8 +1,10 @@
use crate::Parameters;
/// Specifies the constraints for computing a pairing in the MNT4-298 bilinear group. /// Specifies the constraints for computing a pairing in the MNT4-298 bilinear group.
pub use crate::MNT4_298; pub type PairingVar = ark_r1cs_std::pairing::mnt4::PairingVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use crate::MNT4_298; use crate::MNT4_298;
ark_curve_constraint_tests::pairing::bilinearity_test::<MNT4_298>().unwrap() ark_curve_constraint_tests::pairing::bilinearity_test::<MNT4_298, PairingVar>().unwrap()
} }

View File

@@ -16,8 +16,14 @@ pub type G2PreparedVar = mnt4::G2PreparedVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use ark_ec::models::mnt4::MNT4Parameters; use ark_ec::models::mnt4::MNT4Parameters;
ark_curve_constraint_tests::curves::sw_test::<<Parameters as MNT4Parameters>::G1Parameters>() ark_curve_constraint_tests::curves::sw_test::<
<Parameters as MNT4Parameters>::G1Parameters,
G1Var,
>()
.unwrap(); .unwrap();
ark_curve_constraint_tests::curves::sw_test::<<Parameters as MNT4Parameters>::G2Parameters>() ark_curve_constraint_tests::curves::sw_test::<
<Parameters as MNT4Parameters>::G2Parameters,
G2Var,
>()
.unwrap(); .unwrap();
} }

View File

@@ -130,17 +130,17 @@
//! let pairing_result_native = MNT4_753::pairing(a_native, b_native); //! let pairing_result_native = MNT4_753::pairing(a_native, b_native);
//! //!
//! // Prepare `a` and `b` for pairing. //! // Prepare `a` and `b` for pairing.
//! let a_prep = MNT4_753::prepare_g1(&a)?; //! let a_prep = constraints::PairingVar::prepare_g1(&a)?;
//! let b_prep = MNT4_753::prepare_g2(&b)?; //! let b_prep = constraints::PairingVar::prepare_g2(&b)?;
//! let pairing_result = MNT4_753::pairing_gadget(a_prep, b_prep)?; //! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?;
//! //!
//! // Check that the value of &a + &b is correct. //! // Check that the value of &a + &b is correct.
//! assert_eq!(pairing_result.value()?, pairing_result_native); //! assert_eq!(pairing_result.value()?, pairing_result_native);
//! //!
//! // Check that operations on variables and constants are equivalent. //! // Check that operations on variables and constants are equivalent.
//! let a_prep_const = MNT4_753::prepare_g1(&a_const)?; //! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?;
//! let b_prep_const = MNT4_753::prepare_g2(&b_const)?; //! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?;
//! let pairing_result_const = MNT4_753::pairing_gadget(a_prep_const, b_prep_const)?; //! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?;
//! println!("Done here 3"); //! println!("Done here 3");
//! //!
//! pairing_result.enforce_equal(&pairing_result_const)?; //! pairing_result.enforce_equal(&pairing_result_const)?;

View File

@@ -1,8 +1,10 @@
use crate::Parameters;
/// Specifies the constraints for computing a pairing in the MNT4-753 bilinear group. /// Specifies the constraints for computing a pairing in the MNT4-753 bilinear group.
pub use crate::MNT4_753; pub type PairingVar = ark_r1cs_std::pairing::mnt4::PairingVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use crate::MNT4_753; use crate::MNT4_753;
ark_curve_constraint_tests::pairing::bilinearity_test::<MNT4_753>().unwrap() ark_curve_constraint_tests::pairing::bilinearity_test::<MNT4_753, PairingVar>().unwrap()
} }

View File

@@ -16,8 +16,14 @@ pub type G2PreparedVar = mnt6::G2PreparedVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use ark_ec::models::mnt6::MNT6Parameters; use ark_ec::models::mnt6::MNT6Parameters;
ark_curve_constraint_tests::curves::sw_test::<<Parameters as MNT6Parameters>::G1Parameters>() ark_curve_constraint_tests::curves::sw_test::<
<Parameters as MNT6Parameters>::G1Parameters,
G1Var,
>()
.unwrap(); .unwrap();
ark_curve_constraint_tests::curves::sw_test::<<Parameters as MNT6Parameters>::G2Parameters>() ark_curve_constraint_tests::curves::sw_test::<
<Parameters as MNT6Parameters>::G2Parameters,
G2Var,
>()
.unwrap(); .unwrap();
} }

View File

@@ -130,17 +130,17 @@
//! let pairing_result_native = MNT6_298::pairing(a_native, b_native); //! let pairing_result_native = MNT6_298::pairing(a_native, b_native);
//! //!
//! // Prepare `a` and `b` for pairing. //! // Prepare `a` and `b` for pairing.
//! let a_prep = MNT6_298::prepare_g1(&a)?; //! let a_prep = constraints::PairingVar::prepare_g1(&a)?;
//! let b_prep = MNT6_298::prepare_g2(&b)?; //! let b_prep = constraints::PairingVar::prepare_g2(&b)?;
//! let pairing_result = MNT6_298::pairing_gadget(a_prep, b_prep)?; //! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?;
//! //!
//! // Check that the value of &a + &b is correct. //! // Check that the value of &a + &b is correct.
//! assert_eq!(pairing_result.value()?, pairing_result_native); //! assert_eq!(pairing_result.value()?, pairing_result_native);
//! //!
//! // Check that operations on variables and constants are equivalent. //! // Check that operations on variables and constants are equivalent.
//! let a_prep_const = MNT6_298::prepare_g1(&a_const)?; //! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?;
//! let b_prep_const = MNT6_298::prepare_g2(&b_const)?; //! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?;
//! let pairing_result_const = MNT6_298::pairing_gadget(a_prep_const, b_prep_const)?; //! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?;
//! println!("Done here 3"); //! println!("Done here 3");
//! //!
//! pairing_result.enforce_equal(&pairing_result_const)?; //! pairing_result.enforce_equal(&pairing_result_const)?;

View File

@@ -1,8 +1,10 @@
use crate::Parameters;
/// Specifies the constraints for computing a pairing in the MNT6-298 bilinear group. /// Specifies the constraints for computing a pairing in the MNT6-298 bilinear group.
pub use crate::MNT6_298; pub type PairingVar = ark_r1cs_std::pairing::mnt6::PairingVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use crate::MNT6_298; use crate::MNT6_298;
ark_curve_constraint_tests::pairing::bilinearity_test::<MNT6_298>().unwrap() ark_curve_constraint_tests::pairing::bilinearity_test::<MNT6_298, PairingVar>().unwrap()
} }

View File

@@ -16,8 +16,14 @@ pub type G2PreparedVar = mnt6::G2PreparedVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use ark_ec::models::mnt6::MNT6Parameters; use ark_ec::models::mnt6::MNT6Parameters;
ark_curve_constraint_tests::curves::sw_test::<<Parameters as MNT6Parameters>::G1Parameters>() ark_curve_constraint_tests::curves::sw_test::<
<Parameters as MNT6Parameters>::G1Parameters,
G1Var,
>()
.unwrap(); .unwrap();
ark_curve_constraint_tests::curves::sw_test::<<Parameters as MNT6Parameters>::G2Parameters>() ark_curve_constraint_tests::curves::sw_test::<
<Parameters as MNT6Parameters>::G2Parameters,
G2Var,
>()
.unwrap(); .unwrap();
} }

View File

@@ -130,17 +130,17 @@
//! let pairing_result_native = MNT6_753::pairing(a_native, b_native); //! let pairing_result_native = MNT6_753::pairing(a_native, b_native);
//! //!
//! // Prepare `a` and `b` for pairing. //! // Prepare `a` and `b` for pairing.
//! let a_prep = MNT6_753::prepare_g1(&a)?; //! let a_prep = constraints::PairingVar::prepare_g1(&a)?;
//! let b_prep = MNT6_753::prepare_g2(&b)?; //! let b_prep = constraints::PairingVar::prepare_g2(&b)?;
//! let pairing_result = MNT6_753::pairing_gadget(a_prep, b_prep)?; //! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?;
//! //!
//! // Check that the value of &a + &b is correct. //! // Check that the value of &a + &b is correct.
//! assert_eq!(pairing_result.value()?, pairing_result_native); //! assert_eq!(pairing_result.value()?, pairing_result_native);
//! //!
//! // Check that operations on variables and constants are equivalent. //! // Check that operations on variables and constants are equivalent.
//! let a_prep_const = MNT6_753::prepare_g1(&a_const)?; //! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?;
//! let b_prep_const = MNT6_753::prepare_g2(&b_const)?; //! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?;
//! let pairing_result_const = MNT6_753::pairing_gadget(a_prep_const, b_prep_const)?; //! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?;
//! println!("Done here 3"); //! println!("Done here 3");
//! //!
//! pairing_result.enforce_equal(&pairing_result_const)?; //! pairing_result.enforce_equal(&pairing_result_const)?;

View File

@@ -1,8 +1,10 @@
use crate::Parameters;
/// Specifies the constraints for computing a pairing in the MNT6-753 bilinear group. /// Specifies the constraints for computing a pairing in the MNT6-753 bilinear group.
pub use crate::MNT6_753; pub type PairingVar = ark_r1cs_std::pairing::mnt6::PairingVar<Parameters>;
#[test] #[test]
fn test() { fn test() {
use crate::MNT6_753; use crate::MNT6_753;
ark_curve_constraint_tests::pairing::bilinearity_test::<MNT6_753>().unwrap() ark_curve_constraint_tests::pairing::bilinearity_test::<MNT6_753, PairingVar>().unwrap()
} }

View File

@@ -1,10 +1,12 @@
use crate::*; use crate::*;
use ark_r1cs_std::groups::curves::short_weierstrass::ProjectiveVar; use ark_r1cs_std::groups::curves::short_weierstrass::ProjectiveVar;
use crate::constraints::FBaseVar;
/// A group element in the Pallas prime-order group. /// A group element in the Pallas prime-order group.
pub type GVar = ProjectiveVar<PallasParameters>; pub type GVar = ProjectiveVar<PallasParameters, FBaseVar>;
#[test] #[test]
fn test() { fn test() {
ark_curve_constraint_tests::curves::sw_test::<PallasParameters>().unwrap(); ark_curve_constraint_tests::curves::sw_test::<PallasParameters, GVar>().unwrap();
} }

View File

@@ -1,10 +1,12 @@
use crate::*; use crate::*;
use ark_r1cs_std::groups::curves::short_weierstrass::ProjectiveVar; use ark_r1cs_std::groups::curves::short_weierstrass::ProjectiveVar;
use crate::constraints::FBaseVar;
/// A group element in the Vesta prime-order group. /// A group element in the Vesta prime-order group.
pub type GVar = ProjectiveVar<VestaParameters>; pub type GVar = ProjectiveVar<VestaParameters, FBaseVar>;
#[test] #[test]
fn test() { fn test() {
ark_curve_constraint_tests::curves::sw_test::<VestaParameters>().unwrap(); ark_curve_constraint_tests::curves::sw_test::<VestaParameters, GVar>().unwrap();
} }