Initial commit

This commit is contained in:
Pratyush Mishra
2020-10-11 19:50:41 -07:00
commit 43ca2132fd
209 changed files with 18825 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{
biginteger::{BigInteger256, BigInteger384},
field_new, Zero,
};
use crate::{Fq, Fr};
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
const COEFF_A: Fq = field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0]));
/// COEFF_B = 1
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
]));
/// 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, BigInteger256([
2013239619100046060,
4201184776506987597,
2526766393982337036,
1114629510922847535,
]));
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
/// G1_GENERATOR_X =
/// 81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695
#[rustfmt::skip]
pub const G1_GENERATOR_X: Fq = field_new!(Fq, BigInteger384([
0x260f33b9772451f4,
0xc54dd773169d5658,
0x5c1551c469a510dd,
0x761662e4425e1698,
0xc97d78cc6f065272,
0xa41206b361fd4d,
]));
/// G1_GENERATOR_Y =
/// 241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030
#[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, BigInteger384([
0x8193961fb8cb81f3,
0x638d4c5f44adb8,
0xfafaf3dad4daf54a,
0xc27849e2d655cd18,
0x2ec3ddb401d52814,
0x7da93326303c71,
]));

129
bls12_377/src/curves/g2.rs Normal file
View File

@@ -0,0 +1,129 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{
biginteger::{BigInteger256, BigInteger384},
field_new, Zero,
};
use crate::{g1, Fq, Fq2, Fr};
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq2;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = [0, 0]
#[rustfmt::skip]
const COEFF_A: Fq2 = field_new!(Fq2,
g1::Parameters::COEFF_A,
g1::Parameters::COEFF_A,
);
// As per https://eprint.iacr.org/2012/072.pdf,
// this curve has b' = b/i, where b is the COEFF_B of G1, and x^6 -i is
// the irreducible poly used to extend from Fp2 to Fp12.
// In our case, i = u (App A.3, T_6).
/// COEFF_B = [0,
/// 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906]
#[rustfmt::skip]
const COEFF_B: Fq2 = field_new!(Fq2,
field_new!(Fq, BigInteger384([0, 0, 0, 0, 0, 0])),
field_new!(Fq, BigInteger384([
9255502405446297221,
10229180150694123945,
9215585410771530959,
13357015519562362907,
5437107869987383107,
16259554076827459,
])),
);
/// COFACTOR =
/// 7923214915284317143930293550643874566881017850177945424769256759165301436616933228209277966774092486467289478618404761412630691835764674559376407658497
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x0000000000000001,
0x452217cc90000000,
0xa0f3622fba094800,
0xd693e8c36676bd09,
0x8c505634fae2e189,
0xfbb36b00e1dcc40c,
0xddd88d99a6f6a829,
0x26ba558ae9562a,
];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 6764900296503390671038341982857278410319949526107311149686707033187604810669
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
15499857013495546999,
4613531467548868169,
14546778081091178013,
549402535258503313,
]));
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
#[rustfmt::skip]
pub const G2_GENERATOR_X: Fq2 = field_new!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
#[rustfmt::skip]
pub const G2_GENERATOR_Y: Fq2 = field_new!(Fq2, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
/// G2_GENERATOR_X_C0 =
/// 233578398248691099356572568220835526895379068987715365179118596935057653620464273615301663571204657964920925606294
#[rustfmt::skip]
pub const G2_GENERATOR_X_C0: Fq = field_new!(Fq, BigInteger384([
0x68904082f268725b,
0x668f2ea74f45328b,
0xebca7a65802be84f,
0x1e1850f4c1ada3e6,
0x830dc22d588ef1e9,
0x1862a81767c0982,
]));
/// G2_GENERATOR_X_C1 =
/// 140913150380207355837477652521042157274541796891053068589147167627541651775299824604154852141315666357241556069118
#[rustfmt::skip]
pub const G2_GENERATOR_X_C1: Fq = field_new!(Fq, BigInteger384([
0x5f02a915c91c7f39,
0xf8c553ba388da2a7,
0xd51a416dbd198850,
0xe943c6f38ae3073a,
0xffe24aa8259a4981,
0x11853391e73dfdd,
]));
/// G2_GENERATOR_Y_C0 =
/// 63160294768292073209381361943935198908131692476676907196754037919244929611450776219210369229519898517858833747423
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, BigInteger384([
0xd5b19b897881430f,
0x5be9118a5b371ed,
0x6063f91f86c131ee,
0x3244a61be8f4ec19,
0xa02e425b9f9a3a12,
0x18af8c04f3360d2,
]));
/// G2_GENERATOR_Y_C1 =
/// 149157405641012693445398062341192467754805999074082136895788947234480009303640899064710353187729182149407503257491
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, BigInteger384([
0x57601ac71a5b96f5,
0xe99acc1714f2440e,
0x2339612f10118ea9,
0x8321e68a3b1cd722,
0x2b543b050cc74917,
0x590182b396c112,
]));

View File

@@ -0,0 +1,33 @@
use crate::*;
use ark_ec::{
bls12,
bls12::{Bls12, Bls12Parameters, TwistType},
};
pub mod g1;
pub mod g2;
#[cfg(test)]
mod tests;
pub struct Parameters;
impl Bls12Parameters for Parameters {
const X: &'static [u64] = &[0x8508c00000000001];
/// `x` is positive.
const X_IS_NEGATIVE: bool = false;
const TWIST_TYPE: TwistType = TwistType::D;
type Fp = Fq;
type Fp2Params = Fq2Parameters;
type Fp6Params = Fq6Parameters;
type Fp12Params = Fq12Parameters;
type G1Parameters = g1::Parameters;
type G2Parameters = g2::Parameters;
}
pub type Bls12_377 = Bls12<Parameters>;
pub type G1Affine = bls12::G1Affine<Parameters>;
pub type G1Projective = bls12::G1Projective<Parameters>;
pub type G2Affine = bls12::G2Affine<Parameters>;
pub type G2Projective = bls12::G2Projective<Parameters>;

View File

@@ -0,0 +1,121 @@
#![allow(unused_imports)]
use ark_ff::{
fields::{Field, FpParameters, PrimeField, SquareRootField},
test_rng, One, Zero,
};
use ark_serialize::CanonicalSerialize;
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve};
use core::ops::{AddAssign, MulAssign};
use rand::Rng;
use crate::{g1, g2, Bls12_377, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_curve_tests::{
curves::{curve_tests, sw_tests},
groups::group_test,
};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let mut sa = a;
sa.mul_assign(s);
let mut sb = b;
sb.mul_assign(s);
let ans1 = Bls12_377::pairing(sa, b);
let ans2 = Bls12_377::pairing(a, sb);
let ans3 = Bls12_377::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq12::one());
assert_ne!(ans2, Fq12::one());
assert_ne!(ans3, Fq12::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq12::one());
}
#[test]
fn test_g1_generator_raw() {
let mut x = Fq::zero();
let mut i = 0;
loop {
// y^2 = x^3 + b
let mut rhs = x;
rhs.square_in_place();
rhs.mul_assign(&x);
rhs.add_assign(&g1::Parameters::COEFF_B);
if let Some(y) = rhs.sqrt() {
let p = G1Affine::new(x, if y < -y { y } else { -y }, false);
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
let g1 = p.scale_by_cofactor();
if !g1.is_zero() {
assert_eq!(i, 1);
let g1 = G1Affine::from(g1);
assert!(g1.is_in_correct_subgroup_assuming_on_curve());
assert_eq!(g1, G1Affine::prime_subgroup_generator());
break;
}
}
i += 1;
x.add_assign(&Fq::one());
}
}

114
bls12_377/src/fields/fq.rs Normal file
View File

@@ -0,0 +1,114 @@
use ark_ff::{biginteger::BigInteger384 as BigInteger, field_new, fields::*};
pub type Fq = Fp384<FqParameters>;
pub struct FqParameters;
impl Fp384Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 46u32;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
2022196864061697551u64,
17419102863309525423u64,
8564289679875062096u64,
17152078065055548215u64,
17966377291017729567u64,
68610905582439508u64,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0x8508c00000000001,
0x170b5d4430000000,
0x1ef3622fba094800,
0x1a22d9f300f5138f,
0xc63b05c06ca1493b,
0x1ae3a4617c510ea,
]);
const MODULUS_BITS: u32 = 377;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 7;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
202099033278250856u64,
5854854902718660529u64,
11492539364873682930u64,
8885205928937022213u64,
5545221690922665192u64,
39800542322357402u64,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0xb786686c9400cd22,
0x329fcaab00431b1,
0x22a5f11162d6b46d,
0xbfdf7d03827dc3ac,
0x837e92f041790bf9,
0x6dfccb1e914b88,
]);
const INV: u64 = 9586122913090633727u64;
// GENERATOR = -5
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
0xfc0b8000000002fa,
0x97d39cf6e000018b,
0x2072420fbfa05044,
0xcbbcbd50d97c3802,
0xbaf1ec35813f9eb,
0x9974a2c0945ad2,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x4284600000000000,
0xb85aea218000000,
0x8f79b117dd04a400,
0x8d116cf9807a89c7,
0x631d82e03650a49d,
0xd71d230be28875,
]);
// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
// T = (MODULUS - 1) // 2^S =
// 3675842578061421676390135839012792950148785745837396071634149488243117337281387659330802195819009059
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x7510c00000021423,
0x88bee82520005c2d,
0x67cc03d44e3c7bcd,
0x1701b28524ec688b,
0xe9185f1443ab18ec,
0x6b8,
]);
// (T - 1) // 2 =
// 1837921289030710838195067919506396475074392872918698035817074744121558668640693829665401097909504529
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xba88600000010a11,
0xc45f741290002e16,
0xb3e601ea271e3de6,
0xb80d94292763445,
0x748c2f8a21d58c76,
0x35c,
]);
}
#[allow(dead_code)]
pub const FQ_ONE: Fq = field_new!(Fq, FqParameters::R);
#[allow(dead_code)]
pub const FQ_ZERO: Fq = field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0]));

View File

@@ -0,0 +1,161 @@
use super::*;
use ark_ff::{biginteger::BigInteger384, field_new, fields::*};
pub type Fq12 = Fp12<Fq12Parameters>;
#[derive(Clone, Copy)]
pub struct Fq12Parameters;
impl Fp12Parameters for Fq12Parameters {
type Fp6Params = Fq6Parameters;
const NONRESIDUE: Fq6 = field_new!(Fq6, FQ2_ZERO, FQ2_ONE, FQ2_ZERO);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP12_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^1) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x6ec47a04a3f7ca9e,
0xa42e0cb968c1fa44,
0x578d5187fbd2bd23,
0x930eeb0ac79dd4bd,
0xa24883de1e09a9ee,
0xdaa7058067d46f,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x5892506da58478da,
0x133366940ac2a74b,
0x9b64a150cdf726cf,
0x5cc426090a9c587e,
0x5cf848adfdcd640c,
0x4702bf3ac02380,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x982c13d9d084771f,
0xfd49de0c6da34a32,
0x61a530d183ab0e53,
0xdf8fe44106dd9879,
0x40f29b58d88472bc,
0x158723199046d5d,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xdacd106da5847973,
0xd8fe2454bac2a79a,
0x1ada4fd6fd832edc,
0xfb9868449d150908,
0xd63eb8aeea32285e,
0x167d6a36f873fd0,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x296799d52c8cac81,
0x591bd15304e14fee,
0xa17df4987d85130,
0x4c80f9363f3fc3bc,
0x9eaa177aba7ac8ce,
0x7dcb2c189c98ed,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^6) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x823ac00000000099,
0xc5cabdc0b000004f,
0x7f75ae862f8c080d,
0x9ed4423b9278b089,
0x79467000ec64c452,
0x120d3e434c71c50,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^7) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x164445fb5c083563,
0x72dd508ac73e05bc,
0xc76610a7be368adc,
0x8713eee839573ed1,
0x23f281e24e979f4c,
0xd39340975d3c7b,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^8) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2c766f925a7b8727,
0x3d7f6b0253d58b5,
0x838ec0deec122131,
0xbd5eb3e9f658bb10,
0x6942bd126ed3e52e,
0x1673786dd04ed6a,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^9) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xecdcac262f7b88e2,
0x19c17f37c25cb5cd,
0xbd4e315e365e39ac,
0x3a92f5b1fa177b15,
0x85486a67941cd67e,
0x55c8147ec0a38d,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^10) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xaa3baf925a7b868e,
0x3e0d38ef753d5865,
0x4191258bc861923,
0x1e8a71ae63e00a87,
0xeffc4d11826f20dc,
0x4663a2a83dd119,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^11) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x5ba1262ad3735380,
0xbdef8bf12b1eb012,
0x14db82e63230f6cf,
0xcda1e0bcc1b54fd3,
0x2790ee45b226806c,
0x1306f19ff2877fd,
])),
FQ_ZERO,
),
];
}

View File

@@ -0,0 +1,69 @@
use super::*;
use ark_ff::{biginteger::BigInteger384 as BigInteger, field_new, fields::*};
pub type Fq2 = Fp2<Fq2Parameters>;
pub struct Fq2Parameters;
impl Fp2Parameters for Fq2Parameters {
type Fp = Fq;
/// NONRESIDUE = -5
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, BigInteger([
0xfc0b8000000002fa,
0x97d39cf6e000018b,
0x2072420fbfa05044,
0xcbbcbd50d97c3802,
0xbaf1ec35813f9eb,
0x9974a2c0945ad2,
]));
/// QUADRATIC_NONRESIDUE = U
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE: (Fq, Fq) = (
field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0])),
field_new!(Fq, BigInteger([
202099033278250856u64,
5854854902718660529u64,
11492539364873682930u64,
8885205928937022213u64,
5545221690922665192u64,
39800542322357402u64,
])),
);
/// Coefficients for the Frobenius automorphism.
#[rustfmt::skip]
const FROBENIUS_COEFF_FP2_C1: &'static [Fq] = &[
// NONRESIDUE**(((q^0) - 1) / 2)
field_new!(Fq, BigInteger([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
// NONRESIDUE**(((q^1) - 1) / 2)
field_new!(Fq, BigInteger([
0x823ac00000000099,
0xc5cabdc0b000004f,
0x7f75ae862f8c080d,
0x9ed4423b9278b089,
0x79467000ec64c452,
0x120d3e434c71c50,
])),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
let original = fe;
let mut fe = -fe.double();
fe.double_in_place();
fe - original
}
}
pub const FQ2_ZERO: Fq2 = field_new!(Fq2, FQ_ZERO, FQ_ZERO);
pub const FQ2_ONE: Fq2 = field_new!(Fq2, FQ_ONE, FQ_ZERO);

184
bls12_377/src/fields/fq6.rs Normal file
View File

@@ -0,0 +1,184 @@
use super::*;
use ark_ff::{biginteger::BigInteger384, field_new, fields::*};
pub type Fq6 = Fp6<Fq6Parameters>;
#[derive(Clone, Copy)]
pub struct Fq6Parameters;
impl Fp6Parameters for Fq6Parameters {
type Fp2Params = Fq2Parameters;
/// NONRESIDUE = U
#[rustfmt::skip]
const NONRESIDUE: Fq2 = field_new!(Fq2,
field_new!(Fq, BigInteger384([0, 0, 0, 0, 0, 0])),
field_new!(Fq, BigInteger384([
202099033278250856u64,
5854854902718660529u64,
11492539364873682930u64,
8885205928937022213u64,
5545221690922665192u64,
39800542322357402u64,
])),
);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^1) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x5892506da58478da,
0x133366940ac2a74b,
0x9b64a150cdf726cf,
0x5cc426090a9c587e,
0x5cf848adfdcd640c,
0x4702bf3ac02380,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xdacd106da5847973,
0xd8fe2454bac2a79a,
0x1ada4fd6fd832edc,
0xfb9868449d150908,
0xd63eb8aeea32285e,
0x167d6a36f873fd0,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x823ac00000000099,
0xc5cabdc0b000004f,
0x7f75ae862f8c080d,
0x9ed4423b9278b089,
0x79467000ec64c452,
0x120d3e434c71c50,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2c766f925a7b8727,
0x3d7f6b0253d58b5,
0x838ec0deec122131,
0xbd5eb3e9f658bb10,
0x6942bd126ed3e52e,
0x1673786dd04ed6a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xaa3baf925a7b868e,
0x3e0d38ef753d5865,
0x4191258bc861923,
0x1e8a71ae63e00a87,
0xeffc4d11826f20dc,
0x4663a2a83dd119,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
];
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C2: &'static [Fq2] = &[
// Fp2::NONRESIDUE^((2*(q^0) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^1) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xdacd106da5847973,
0xd8fe2454bac2a79a,
0x1ada4fd6fd832edc,
0xfb9868449d150908,
0xd63eb8aeea32285e,
0x167d6a36f873fd0,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^2) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2c766f925a7b8727,
0x3d7f6b0253d58b5,
0x838ec0deec122131,
0xbd5eb3e9f658bb10,
0x6942bd126ed3e52e,
0x1673786dd04ed6a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^3) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^4) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xdacd106da5847973,
0xd8fe2454bac2a79a,
0x1ada4fd6fd832edc,
0xfb9868449d150908,
0xd63eb8aeea32285e,
0x167d6a36f873fd0,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^5) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2c766f925a7b8727,
0x3d7f6b0253d58b5,
0x838ec0deec122131,
0xbd5eb3e9f658bb10,
0x6942bd126ed3e52e,
0x1673786dd04ed6a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
];
#[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
// Karatsuba multiplication with constant other = u.
let c0 = Fq2Parameters::mul_fp_by_nonresidue(&fe.c1);
let c1 = fe.c0;
field_new!(Fq2, c0, c1)
}
}

View File

@@ -0,0 +1,95 @@
use ark_ff::{biginteger::BigInteger256 as BigInteger, fields::*};
pub type Fr = Fp256<FrParameters>;
pub struct FrParameters;
impl Fp256Parameters for FrParameters {}
impl FftParameters for FrParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 47;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
0x3c3d3ca739381fb2,
0x9a14cda3ec99772b,
0xd7aacc7c59724826,
0xd1ba211c5cc349c,
]);
}
impl FpParameters for FrParameters {
/// MODULUS = 8444461749428370424248824938781546531375899335154063827935233455917409239041
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
725501752471715841u64,
6461107452199829505u64,
6968279316240510977u64,
1345280370688173398u64,
]);
const MODULUS_BITS: u32 = 253;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 3;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
9015221291577245683u64,
8239323489949974514u64,
1646089257421115374u64,
958099254763297437u64,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
2726216793283724667u64,
14712177743343147295u64,
12091039717619697043u64,
81024008013859129u64,
]);
const INV: u64 = 725501752471715839u64;
// GENERATOR = 11
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
1855201571499933546u64,
8511318076631809892u64,
6222514765367795509u64,
1122129207579058019u64,
]);
/// (r - 1)/2 =
/// 4222230874714185212124412469390773265687949667577031913967616727958704619520
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x8508c00000000000,
0xacd53b7f68000000,
0x305a268f2e1bd800,
0x955b2af4d1652ab,
]);
// T and T_MINUS_ONE_DIV_TWO, where r - 1 = 2^s * t
/// t = (r - 1) / 2^s =
/// 60001509534603559531609739528203892656505753216962260608619555
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0xedfda00000021423,
0x9a3cb86f6002b354,
0xcabd34594aacc168,
0x2556,
]);
/// (t - 1) / 2 =
/// 30000754767301779765804869764101946328252876608481130304309777
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x76fed00000010a11,
0x4d1e5c37b00159aa,
0x655e9a2ca55660b4,
0x12ab,
]);
}

View File

@@ -0,0 +1,27 @@
#[cfg(feature = "scalar_field")]
pub mod fr;
#[cfg(feature = "scalar_field")]
pub use self::fr::*;
#[cfg(feature = "base_field")]
pub mod fq;
#[cfg(feature = "base_field")]
pub use self::fq::*;
#[cfg(feature = "curve")]
pub mod fq2;
#[cfg(feature = "curve")]
pub use self::fq2::*;
#[cfg(feature = "curve")]
pub mod fq6;
#[cfg(feature = "curve")]
pub use self::fq6::*;
#[cfg(feature = "curve")]
pub mod fq12;
#[cfg(feature = "curve")]
pub use self::fq12::*;
#[cfg(all(feature = "curve", test))]
mod tests;

View File

@@ -0,0 +1,530 @@
use ark_ff::{
biginteger::{BigInteger, BigInteger384},
fields::{
fp6_3over2::Fp6Parameters, FftField, FftParameters, Field, Fp2Parameters, FpParameters,
PrimeField, SquareRootField,
},
test_rng, One, UniformRand, Zero,
};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use core::{
cmp::Ordering,
ops::{AddAssign, MulAssign, SubAssign},
};
use rand::{Rng, SeedableRng};
use rand_xorshift::XorShiftRng;
use crate::{Fq, Fq12, Fq2, Fq2Parameters, Fq6, Fq6Parameters, FqParameters, Fr};
use ark_curve_tests::fields::*;
pub(crate) const ITERATIONS: usize = 5;
#[test]
fn test_fr() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fr = rng.gen();
let b: Fr = rng.gen();
field_test(a, b);
primefield_test::<Fr>();
sqrt_field_test(b);
let byte_size = a.serialized_size();
field_serialization_test::<Fr>(byte_size);
}
}
#[test]
fn test_fq() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq = rng.gen();
let b: Fq = rng.gen();
field_test(a, b);
primefield_test::<Fq>();
sqrt_field_test(a);
let byte_size = a.serialized_size();
let (_, buffer_size) = buffer_bit_byte_size(Fq::size_in_bits());
assert_eq!(byte_size, buffer_size);
field_serialization_test::<Fq>(byte_size);
}
}
#[test]
fn test_fq2() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq2 = rng.gen();
let b: Fq2 = rng.gen();
field_test(a, b);
sqrt_field_test(a);
}
frobenius_test::<Fq2, _>(Fq::characteristic(), 13);
let byte_size = Fq2::zero().serialized_size();
field_serialization_test::<Fq2>(byte_size);
}
#[test]
fn test_fq6() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq6 = rng.gen();
let h: Fq6 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq6, _>(Fq::characteristic(), 13);
let byte_size = Fq6::zero().serialized_size();
field_serialization_test::<Fq6>(byte_size);
}
#[test]
fn test_fq12() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq12 = rng.gen();
let h: Fq12 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq12, _>(Fq::characteristic(), 13);
let byte_size = Fq12::zero().serialized_size();
field_serialization_test::<Fq12>(byte_size);
}
#[test]
fn test_fq_repr_from() {
assert_eq!(
BigInteger384::from(100),
BigInteger384([100, 0, 0, 0, 0, 0])
);
}
#[test]
fn test_fq_repr_is_odd() {
assert!(!BigInteger384::from(0).is_odd());
assert!(BigInteger384::from(0).is_even());
assert!(BigInteger384::from(1).is_odd());
assert!(!BigInteger384::from(1).is_even());
assert!(!BigInteger384::from(324834872).is_odd());
assert!(BigInteger384::from(324834872).is_even());
assert!(BigInteger384::from(324834873).is_odd());
assert!(!BigInteger384::from(324834873).is_even());
}
#[test]
fn test_fq_repr_is_zero() {
assert!(BigInteger384::from(0).is_zero());
assert!(!BigInteger384::from(1).is_zero());
assert!(!BigInteger384([0, 0, 0, 0, 1, 0]).is_zero());
}
#[test]
fn test_fq_repr_num_bits() {
let mut a = BigInteger384::from(0);
assert_eq!(0, a.num_bits());
a = BigInteger384::from(1);
for i in 1..385 {
assert_eq!(i, a.num_bits());
a.mul2();
}
assert_eq!(0, a.num_bits());
}
#[test]
fn test_fq_add_assign() {
// Test associativity
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Generate a, b, c and ensure (a + b) + c == a + (b + c).
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
let mut tmp2 = b;
tmp2.add_assign(&c);
tmp2.add_assign(&a);
assert_eq!(tmp1, tmp2);
}
}
#[test]
fn test_fq_sub_assign() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Ensure that (a - b) + (b - a) = 0.
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.sub_assign(&b);
let mut tmp2 = b;
tmp2.sub_assign(&a);
tmp1.add_assign(&tmp2);
assert!(tmp1.is_zero());
}
}
#[test]
fn test_fq_mul_assign() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000000 {
// Ensure that (a * b) * c = a * (b * c)
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.mul_assign(&b);
tmp1.mul_assign(&c);
let mut tmp2 = b;
tmp2.mul_assign(&c);
tmp2.mul_assign(&a);
assert_eq!(tmp1, tmp2);
}
for _ in 0..1000000 {
// Ensure that r * (a + b + c) = r*a + r*b + r*c
let r = Fq::rand(&mut rng);
let mut a = Fq::rand(&mut rng);
let mut b = Fq::rand(&mut rng);
let mut c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
tmp1.mul_assign(&r);
a.mul_assign(&r);
b.mul_assign(&r);
c.mul_assign(&r);
a.add_assign(&b);
a.add_assign(&c);
assert_eq!(tmp1, a);
}
}
#[test]
fn test_fq_squaring() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000000 {
// Ensure that (a * a) = a^2
let a = Fq::rand(&mut rng);
let mut tmp = a;
tmp.square_in_place();
let mut tmp2 = a;
tmp2.mul_assign(&a);
assert_eq!(tmp, tmp2);
}
}
#[test]
fn test_fq_inverse() {
assert!(Fq::zero().inverse().is_none());
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let one = Fq::one();
for _ in 0..1000 {
// Ensure that a * a^-1 = 1
let mut a = Fq::rand(&mut rng);
let ainv = a.inverse().unwrap();
a.mul_assign(&ainv);
assert_eq!(a, one);
}
}
#[test]
fn test_fq_double_in_place() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Ensure doubling a is equivalent to adding a to itself.
let mut a = Fq::rand(&mut rng);
let mut b = a;
b.add_assign(&a);
a.double_in_place();
assert_eq!(a, b);
}
}
#[test]
fn test_fq_negate() {
{
let a = -Fq::zero();
assert!(a.is_zero());
}
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Ensure (a - (-a)) = 0.
let mut a = Fq::rand(&mut rng);
let b = -a;
a.add_assign(&b);
assert!(a.is_zero());
}
}
#[test]
fn test_fq_pow() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for i in 0..1000 {
// Exponentiate by various small numbers and ensure it consists with repeated
// multiplication.
let a = Fq::rand(&mut rng);
let target = a.pow(&[i]);
let mut c = Fq::one();
for _ in 0..i {
c.mul_assign(&a);
}
assert_eq!(c, target);
}
for _ in 0..1000 {
// Exponentiating by the modulus should have no effect in a prime field.
let a = Fq::rand(&mut rng);
assert_eq!(a, a.pow(Fq::characteristic()));
}
}
#[test]
fn test_fq_sqrt() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
assert_eq!(Fq::zero().sqrt().unwrap(), Fq::zero());
for _ in 0..1000 {
// Ensure sqrt(a^2) = a or -a
let a = Fq::rand(&mut rng);
let nega = -a;
let mut b = a;
b.square_in_place();
let b = b.sqrt().unwrap();
assert!(a == b || nega == b);
}
for _ in 0..1000 {
// Ensure sqrt(a)^2 = a for random a
let a = Fq::rand(&mut rng);
if let Some(mut tmp) = a.sqrt() {
tmp.square_in_place();
assert_eq!(a, tmp);
}
}
}
#[test]
fn test_fq_num_bits() {
assert_eq!(FqParameters::MODULUS_BITS, 377);
assert_eq!(FqParameters::CAPACITY, 376);
}
#[test]
fn test_fq_root_of_unity() {
assert_eq!(FqParameters::TWO_ADICITY, 46);
assert_eq!(
Fq::multiplicative_generator().pow([
0x7510c00000021423,
0x88bee82520005c2d,
0x67cc03d44e3c7bcd,
0x1701b28524ec688b,
0xe9185f1443ab18ec,
0x6b8
]),
Fq::two_adic_root_of_unity()
);
assert_eq!(
Fq::two_adic_root_of_unity().pow([1 << FqParameters::TWO_ADICITY]),
Fq::one()
);
assert!(Fq::multiplicative_generator().sqrt().is_none());
}
#[test]
fn test_fq_ordering() {
// BigInteger384's ordering is well-tested, but we still need to make sure the
// Fq elements aren't being compared in Montgomery form.
for i in 0..100 {
assert!(Fq::from(BigInteger384::from(i + 1)) > Fq::from(BigInteger384::from(i)));
}
}
#[test]
fn test_fq_legendre() {
use ark_ff::fields::LegendreSymbol::*;
assert_eq!(QuadraticResidue, Fq::one().legendre());
assert_eq!(Zero, Fq::zero().legendre());
assert_eq!(
QuadraticResidue,
Fq::from(BigInteger384::from(4)).legendre()
);
assert_eq!(
QuadraticNonResidue,
Fq::from(BigInteger384::from(5)).legendre()
);
}
#[test]
fn test_fq2_ordering() {
let mut a = Fq2::new(Fq::zero(), Fq::zero());
let mut b = a.clone();
assert!(a.cmp(&b) == Ordering::Equal);
b.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Less);
a.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Equal);
b.c1.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Less);
a.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Less);
a.c1.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Greater);
b.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Equal);
}
#[test]
fn test_fq2_basics() {
assert_eq!(Fq2::new(Fq::zero(), Fq::zero(),), Fq2::zero());
assert_eq!(Fq2::new(Fq::one(), Fq::zero(),), Fq2::one());
assert!(Fq2::zero().is_zero());
assert!(!Fq2::one().is_zero());
assert!(!Fq2::new(Fq::zero(), Fq::one(),).is_zero());
}
#[test]
fn test_fq2_legendre() {
use ark_ff::fields::LegendreSymbol::*;
assert_eq!(Zero, Fq2::zero().legendre());
// i^2 = -1
let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Parameters::mul_fp2_by_nonresidue(&m1);
assert_eq!(QuadraticNonResidue, m1.legendre());
}
#[test]
fn test_fq2_mul_nonresidue() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let nqr = Fq2::new(Fq::zero(), Fq::one());
let quadratic_non_residue = Fq2::new(
Fq2Parameters::QUADRATIC_NONRESIDUE.0,
Fq2Parameters::QUADRATIC_NONRESIDUE.1,
);
for _ in 0..1000 {
let mut a = Fq2::rand(&mut rng);
let mut b = a;
a = quadratic_non_residue * &a;
b.mul_assign(&nqr);
assert_eq!(a, b);
}
}
#[test]
fn test_fq6_mul_by_1() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c1 = Fq2::rand(&mut rng);
let mut a = Fq6::rand(&mut rng);
let mut b = a;
a.mul_by_1(&c1);
b.mul_assign(&Fq6::new(Fq2::zero(), c1, Fq2::zero()));
assert_eq!(a, b);
}
}
#[test]
fn test_fq6_mul_by_01() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c0 = Fq2::rand(&mut rng);
let c1 = Fq2::rand(&mut rng);
let mut a = Fq6::rand(&mut rng);
let mut b = a;
a.mul_by_01(&c0, &c1);
b.mul_assign(&Fq6::new(c0, c1, Fq2::zero()));
assert_eq!(a, b);
}
}
#[test]
fn test_fq12_mul_by_014() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c0 = Fq2::rand(&mut rng);
let c1 = Fq2::rand(&mut rng);
let c5 = Fq2::rand(&mut rng);
let mut a = Fq12::rand(&mut rng);
let mut b = a;
a.mul_by_014(&c0, &c1, &c5);
b.mul_assign(&Fq12::new(
Fq6::new(c0, c1, Fq2::zero()),
Fq6::new(Fq2::zero(), c5, Fq2::zero()),
));
assert_eq!(a, b);
}
}
#[test]
fn test_fq12_mul_by_034() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c0 = Fq2::rand(&mut rng);
let c3 = Fq2::rand(&mut rng);
let c4 = Fq2::rand(&mut rng);
let mut a = Fq12::rand(&mut rng);
let mut b = a;
a.mul_by_034(&c0, &c3, &c4);
b.mul_assign(&Fq12::new(
Fq6::new(c0, Fq2::zero(), Fq2::zero()),
Fq6::new(c3, c4, Fq2::zero()),
));
assert_eq!(a, b);
}
}

35
bls12_377/src/lib.rs Normal file
View File

@@ -0,0 +1,35 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This library implements the BLS12_377 curve generated in [[BCGMMW20, “Zexe”]](https://eprint.iacr.org/2018/962).
//! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree 12,
//! defined over a 377-bit (prime) field. The main feature of this curve is that
//! both the scalar field and the base field are highly 2-adic.
//! (This is in contrast to the BLS12_381 curve for which only the scalar field is highly 2-adic.)
//!
//!
//! Curve information:
//! * Base field: q = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
//! * Scalar field: r = 8444461749428370424248824938781546531375899335154063827935233455917409239041
//! * valuation(q - 1, 2) = 46
//! * valuation(r - 1, 2) = 47
//! * G1 curve equation: y^2 = x^3 + 1
//! * G2 curve equation: y^2 = x^3 + B, where
//! * B = Fq2(0, 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906)
#[cfg(feature = "curve")]
mod curves;
mod fields;
#[cfg(feature = "curve")]
pub use curves::*;
pub use fields::*;