mirror of
https://github.com/arnaucube/ark-curves-cherry-picked.git
synced 2026-01-09 07:21:30 +01:00
Initial commit
This commit is contained in:
31
bn254/Cargo.toml
Normal file
31
bn254/Cargo.toml
Normal file
@@ -0,0 +1,31 @@
|
||||
[package]
|
||||
name = "ark-bn254"
|
||||
version = "0.1.0"
|
||||
authors = [ "arkworks contributors" ]
|
||||
description = "The BN254 pairing-friendly elliptic curve"
|
||||
homepage = "https://arworks.rs"
|
||||
repository = "https://github.com/arkworks/algebra"
|
||||
documentation = "https://docs.rs/ark-bn254/"
|
||||
keywords = ["cryptography", "finite fields", "elliptic curves" ]
|
||||
categories = ["cryptography"]
|
||||
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
license = "MIT/Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
|
||||
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
|
||||
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
|
||||
ark-curve-tests = { path = "../curve-tests", default-features = false }
|
||||
rand = { version = "0.7", default-features = false }
|
||||
rand_xorshift = "0.2"
|
||||
|
||||
[features]
|
||||
default = [ "curve" ]
|
||||
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
|
||||
|
||||
curve = [ "scalar_field" ]
|
||||
scalar_field = []
|
||||
1
bn254/LICENSE-APACHE
Symbolic link
1
bn254/LICENSE-APACHE
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-APACHE
|
||||
1
bn254/LICENSE-MIT
Symbolic link
1
bn254/LICENSE-MIT
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-MIT
|
||||
67
bn254/src/curves/g1.rs
Normal file
67
bn254/src/curves/g1.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
use ark_ec::models::{ModelParameters, SWModelParameters};
|
||||
use ark_ff::{biginteger::BigInteger256, 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, BigInteger256([0x0, 0x0, 0x0, 0x0]));
|
||||
|
||||
/// COEFF_B = 3
|
||||
#[rustfmt::skip]
|
||||
const COEFF_B: Fq = field_new!(Fq, BigInteger256([
|
||||
0x7a17caa950ad28d7,
|
||||
0x1f6ac17ae15521b9,
|
||||
0x334bea4e696bd284,
|
||||
0x2a1f6744ce179d8e,
|
||||
]));
|
||||
|
||||
/// COFACTOR = 1
|
||||
const COFACTOR: &'static [u64] = &[0x1];
|
||||
|
||||
/// COFACTOR_INV = COFACTOR^{-1} mod r = 1
|
||||
#[rustfmt::skip]
|
||||
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
|
||||
0xac96341c4ffffffb,
|
||||
0x36fc76959f60cd29,
|
||||
0x666ea36f7879462e,
|
||||
0xe0a77c19a07df2f,
|
||||
]));
|
||||
|
||||
/// 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 =
|
||||
/// 1
|
||||
#[rustfmt::skip]
|
||||
pub const G1_GENERATOR_X: Fq = field_new!(Fq, BigInteger256([
|
||||
0xd35d438dc58f0d9d,
|
||||
0x0a78eb28f5c70b3d,
|
||||
0x666ea36f7879462c,
|
||||
0x0e0a77c19a07df2f,
|
||||
]));
|
||||
|
||||
/// G1_GENERATOR_Y =
|
||||
/// 2
|
||||
#[rustfmt::skip]
|
||||
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, BigInteger256([
|
||||
0xa6ba871b8b1e1b3a,
|
||||
0x14f1d651eb8e167b,
|
||||
0xccdd46def0f28c58,
|
||||
0x1c14ef83340fbe5e,
|
||||
]));
|
||||
112
bn254/src/curves/g2.rs
Normal file
112
bn254/src/curves/g2.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use ark_ec::models::{ModelParameters, SWModelParameters};
|
||||
use ark_ff::{biginteger::BigInteger256, 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,
|
||||
);
|
||||
|
||||
/// COEFF_B = 3/(u+9)
|
||||
/// = (19485874751759354771024239261021720505790618469301721065564631296452457478373, 266929791119991161246907387137283842545076965332900288569378510910307636690)
|
||||
#[rustfmt::skip]
|
||||
const COEFF_B: Fq2 = field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x3bf938e377b802a8,
|
||||
0x020b1b273633535d,
|
||||
0x26b7edf049755260,
|
||||
0x2514c6324384a86d,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x38e7ecccd1dcff67,
|
||||
0x65f0b37d93ce0d3e,
|
||||
0xd749d0dd22ac00aa,
|
||||
0x0141b9ce4a688d4d,
|
||||
])),
|
||||
);
|
||||
|
||||
/// COFACTOR = (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1
|
||||
/// = 21888242871839275222246405745257275088844257914179612981679871602714643921549
|
||||
#[rustfmt::skip]
|
||||
const COFACTOR: &'static [u64] = &[
|
||||
0x345f2299c0f9fa8d,
|
||||
0x06ceecda572a2489,
|
||||
0xb85045b68181585e,
|
||||
0x30644e72e131a029,
|
||||
];
|
||||
|
||||
/// COFACTOR_INV = COFACTOR^{-1} mod r
|
||||
#[rustfmt::skip]
|
||||
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
|
||||
0x7fff17d53ff2895e,
|
||||
0xd0617390cf7919e5,
|
||||
0xb9af426b22d0eb61,
|
||||
0x270485e31bd72a4d,
|
||||
]));
|
||||
|
||||
/// 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 =
|
||||
/// 10857046999023057135944570762232829481370756359578518086990519993285655852781
|
||||
#[rustfmt::skip]
|
||||
pub const G2_GENERATOR_X_C0: Fq = field_new!(Fq, BigInteger256([
|
||||
0x8e83b5d102bc2026,
|
||||
0xdceb1935497b0172,
|
||||
0xfbb8264797811adf,
|
||||
0x19573841af96503b,
|
||||
]));
|
||||
|
||||
/// G2_GENERATOR_X_C1 =
|
||||
/// 11559732032986387107991004021392285783925812861821192530917403151452391805634
|
||||
#[rustfmt::skip]
|
||||
pub const G2_GENERATOR_X_C1: Fq = field_new!(Fq, BigInteger256([
|
||||
0xafb4737da84c6140,
|
||||
0x6043dd5a5802d8c4,
|
||||
0x09e950fc52a02f86,
|
||||
0x14fef0833aea7b6b,
|
||||
]));
|
||||
|
||||
/// G2_GENERATOR_Y_C0 =
|
||||
/// 8495653923123431417604973247489272438418190587263600148770280649306958101930
|
||||
#[rustfmt::skip]
|
||||
pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, BigInteger256([
|
||||
0x619dfa9d886be9f6,
|
||||
0xfe7fd297f59e9b78,
|
||||
0xff9e1a62231b7dfe,
|
||||
0x28fd7eebae9e4206,
|
||||
]));
|
||||
|
||||
/// G2_GENERATOR_Y_C1 =
|
||||
/// 4082367875863433681332203403145435568316851327593401208105741076214120093531
|
||||
#[rustfmt::skip]
|
||||
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, BigInteger256([
|
||||
0x64095b56c71856ee,
|
||||
0xdc57f922327d3cbb,
|
||||
0x55f935be33351076,
|
||||
0x0da4a0e693fd6482,
|
||||
]));
|
||||
82
bn254/src/curves/mod.rs
Normal file
82
bn254/src/curves/mod.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
use crate::*;
|
||||
use ark_ec::{
|
||||
bn,
|
||||
bn::{Bn, BnParameters, TwistType},
|
||||
};
|
||||
use ark_ff::{biginteger::BigInteger256, field_new};
|
||||
pub mod g1;
|
||||
pub mod g2;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub struct Parameters;
|
||||
|
||||
impl BnParameters for Parameters {
|
||||
const X: &'static [u64] = &[4965661367192848881];
|
||||
/// `x` is positive.
|
||||
const X_IS_NEGATIVE: bool = false;
|
||||
const ATE_LOOP_COUNT: &'static [i8] = &[
|
||||
0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0,
|
||||
0, 1, 1, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 0, 1, 1, 0,
|
||||
-1, 0, 0, 1, 0, 1, 1,
|
||||
];
|
||||
/// `ate_loop_count` is positive.
|
||||
const ATE_LOOP_COUNT_IS_NEGATIVE: bool = false;
|
||||
const TWIST_MUL_BY_Q_X: Fq2 = field_new!(
|
||||
Fq2,
|
||||
field_new!(
|
||||
Fq,
|
||||
BigInteger256([
|
||||
0xb5773b104563ab30,
|
||||
0x347f91c8a9aa6454,
|
||||
0x7a007127242e0991,
|
||||
0x1956bcd8118214ec,
|
||||
])
|
||||
),
|
||||
field_new!(
|
||||
Fq,
|
||||
BigInteger256([
|
||||
0x6e849f1ea0aa4757,
|
||||
0xaa1c7b6d89f89141,
|
||||
0xb6e713cdfae0ca3a,
|
||||
0x26694fbb4e82ebc3,
|
||||
])
|
||||
),
|
||||
);
|
||||
const TWIST_MUL_BY_Q_Y: Fq2 = field_new!(
|
||||
Fq2,
|
||||
field_new!(
|
||||
Fq,
|
||||
BigInteger256([
|
||||
0xe4bbdd0c2936b629,
|
||||
0xbb30f162e133bacb,
|
||||
0x31a9d1b6f9645366,
|
||||
0x253570bea500f8dd,
|
||||
])
|
||||
),
|
||||
field_new!(
|
||||
Fq,
|
||||
BigInteger256([
|
||||
0xa1d77ce45ffe77c7,
|
||||
0x07affd117826d1db,
|
||||
0x6d16bd27bb7edc6b,
|
||||
0x2c87200285defecc,
|
||||
])
|
||||
),
|
||||
);
|
||||
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 Bn254 = Bn<Parameters>;
|
||||
|
||||
pub type G1Affine = bn::G1Affine<Parameters>;
|
||||
pub type G1Projective = bn::G1Projective<Parameters>;
|
||||
pub type G2Affine = bn::G2Affine<Parameters>;
|
||||
pub type G2Projective = bn::G2Projective<Parameters>;
|
||||
85
bn254/src/curves/tests.rs
Normal file
85
bn254/src/curves/tests.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
#![allow(unused_imports)]
|
||||
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve};
|
||||
use ark_ff::{
|
||||
fields::{Field, FpParameters, PrimeField, SquareRootField},
|
||||
test_rng, One, Zero,
|
||||
};
|
||||
use ark_serialize::CanonicalSerialize;
|
||||
use core::ops::{AddAssign, MulAssign};
|
||||
use rand::Rng;
|
||||
|
||||
use crate::{g1, g2, Bn254, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
|
||||
|
||||
use ark_curve_tests::{curves::*, groups::*};
|
||||
|
||||
#[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 = Bn254::pairing(sa, b);
|
||||
let ans2 = Bn254::pairing(a, sb);
|
||||
let ans3 = Bn254::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());
|
||||
}
|
||||
96
bn254/src/fields/fq.rs
Normal file
96
bn254/src/fields/fq.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
use ark_ff::{biginteger::BigInteger256 as BigInteger, field_new, fields::*};
|
||||
|
||||
pub type Fq = Fp256<FqParameters>;
|
||||
|
||||
pub struct FqParameters;
|
||||
|
||||
impl Fp256Parameters for FqParameters {}
|
||||
impl FftParameters for FqParameters {
|
||||
type BigInt = BigInteger;
|
||||
|
||||
const TWO_ADICITY: u32 = 1;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
|
||||
0x68c3488912edefaa,
|
||||
0x8d087f6872aabf4f,
|
||||
0x51e1a24709081231,
|
||||
0x2259d6b14729c0fa,
|
||||
]);
|
||||
}
|
||||
impl FpParameters for FqParameters {
|
||||
/// MODULUS = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
|
||||
#[rustfmt::skip]
|
||||
const MODULUS: BigInteger = BigInteger([
|
||||
0x3c208c16d87cfd47,
|
||||
0x97816a916871ca8d,
|
||||
0xb85045b68181585d,
|
||||
0x30644e72e131a029,
|
||||
]);
|
||||
|
||||
const MODULUS_BITS: u32 = 254;
|
||||
|
||||
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
|
||||
|
||||
const REPR_SHAVE_BITS: u32 = 2;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const R: BigInteger = BigInteger([
|
||||
0xd35d438dc58f0d9d,
|
||||
0x0a78eb28f5c70b3d,
|
||||
0x666ea36f7879462c,
|
||||
0xe0a77c19a07df2f,
|
||||
]);
|
||||
|
||||
#[rustfmt::skip]
|
||||
const R2: BigInteger = BigInteger([
|
||||
0xf32cfc5b538afa89,
|
||||
0xb5e71911d44501fb,
|
||||
0x47ab1eff0a417ff6,
|
||||
0x6d89f71cab8351f,
|
||||
]);
|
||||
|
||||
const INV: u64 = 9786893198990664585u64;
|
||||
|
||||
// GENERATOR = 3
|
||||
#[rustfmt::skip]
|
||||
const GENERATOR: BigInteger = BigInteger([
|
||||
0x7a17caa950ad28d7,
|
||||
0x1f6ac17ae15521b9,
|
||||
0x334bea4e696bd284,
|
||||
0x2a1f6744ce179d8e,
|
||||
]);
|
||||
|
||||
#[rustfmt::skip]
|
||||
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
|
||||
0x9e10460b6c3e7ea3,
|
||||
0xcbc0b548b438e546,
|
||||
0xdc2822db40c0ac2e,
|
||||
0x183227397098d014,
|
||||
]);
|
||||
|
||||
// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
|
||||
|
||||
// T = (MODULUS - 1) // 2^S =
|
||||
// 10944121435919637611123202872628637544348155578648911831344518947322613104291
|
||||
#[rustfmt::skip]
|
||||
const T: BigInteger = BigInteger([
|
||||
0x9e10460b6c3e7ea3,
|
||||
0xcbc0b548b438e546,
|
||||
0xdc2822db40c0ac2e,
|
||||
0x183227397098d014,
|
||||
]);
|
||||
|
||||
// (T - 1) // 2 =
|
||||
// 1837921289030710838195067919506396475074392872918698035817074744121558668640693829665401097909504529
|
||||
#[rustfmt::skip]
|
||||
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
|
||||
0x4f082305b61f3f51,
|
||||
0x65e05aa45a1c72a3,
|
||||
0x6e14116da0605617,
|
||||
0xc19139cb84c680a,
|
||||
]);
|
||||
}
|
||||
|
||||
pub const FQ_ONE: Fq = field_new!(Fq, FqParameters::R);
|
||||
pub const FQ_ZERO: Fq = field_new!(Fq, BigInteger([0, 0, 0, 0]));
|
||||
159
bn254/src/fields/fq12.rs
Normal file
159
bn254/src/fields/fq12.rs
Normal file
@@ -0,0 +1,159 @@
|
||||
use super::*;
|
||||
use ark_ff::{biginteger::BigInteger256, 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)
|
||||
FQ2_ONE,
|
||||
// Fp2::NONRESIDUE^(((q^1) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xaf9ba69633144907,
|
||||
0xca6b1d7387afb78a,
|
||||
0x11bded5ef08a2087,
|
||||
0x02f34d751a1f3a7c,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xa222ae234c492d72,
|
||||
0xd00f02a4565de15b,
|
||||
0xdc2ff3a253dfc926,
|
||||
0x10a75716b3899551,
|
||||
])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^2) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xca8d800500fa1bf2,
|
||||
0xf0c5d61468b39769,
|
||||
0x0e201271ad0d4418,
|
||||
0x04290f65bad856e6,
|
||||
])),
|
||||
FQ_ZERO,
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^3) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x365316184e46d97d,
|
||||
0x0af7129ed4c96d9f,
|
||||
0x659da72fca1009b5,
|
||||
0x08116d8983a20d23,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xb1df4af7c39c1939,
|
||||
0x3d9f02878a73bf7f,
|
||||
0x9b2220928caf0ae0,
|
||||
0x26684515eff054a6,
|
||||
])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^4) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x3350c88e13e80b9c,
|
||||
0x7dce557cdb5e56b9,
|
||||
0x6001b4b8b615564a,
|
||||
0x2682e617020217e0,
|
||||
])),
|
||||
FQ_ZERO,
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^5) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x86b76f821b329076,
|
||||
0x408bf52b4d19b614,
|
||||
0x53dfb9d0d985e92d,
|
||||
0x051e20146982d2a7,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x0fbc9cd47752ebc7,
|
||||
0x6d8fffe33415de24,
|
||||
0xbef22cf038cf41b9,
|
||||
0x15c0edff3c66bf54,
|
||||
])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^6) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x68c3488912edefaa,
|
||||
0x8d087f6872aabf4f,
|
||||
0x51e1a24709081231,
|
||||
0x2259d6b14729c0fa,
|
||||
])),
|
||||
FQ_ZERO,
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^7) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x8c84e580a568b440,
|
||||
0xcd164d1de0c21302,
|
||||
0xa692585790f737d5,
|
||||
0x2d7100fdc71265ad,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x99fdddf38c33cfd5,
|
||||
0xc77267ed1213e931,
|
||||
0xdc2052142da18f36,
|
||||
0x1fbcf75c2da80ad7,
|
||||
])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^8) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x71930c11d782e155,
|
||||
0xa6bb947cffbe3323,
|
||||
0xaa303344d4741444,
|
||||
0x2c3b3f0d26594943,
|
||||
])),
|
||||
FQ_ZERO,
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^9) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x05cd75fe8a3623ca,
|
||||
0x8c8a57f293a85cee,
|
||||
0x52b29e86b7714ea8,
|
||||
0x2852e0e95d8f9306,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x8a41411f14e0e40e,
|
||||
0x59e26809ddfe0b0d,
|
||||
0x1d2e2523f4d24d7d,
|
||||
0x09fc095cf1414b83,
|
||||
])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^10) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x08cfc388c494f1ab,
|
||||
0x19b315148d1373d4,
|
||||
0x584e90fdcb6c0213,
|
||||
0x09e1685bdf2f8849,
|
||||
])),
|
||||
FQ_ZERO,
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^11) - 1) / 6)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xb5691c94bd4a6cd1,
|
||||
0x56f575661b581478,
|
||||
0x64708be5a7fb6f30,
|
||||
0x2b462e5e77aecd82,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x2c63ef42612a1180,
|
||||
0x29f16aae345bec69,
|
||||
0xf95e18c648b216a4,
|
||||
0x1aa36073a4cae0d4,
|
||||
])),
|
||||
),
|
||||
];
|
||||
}
|
||||
63
bn254/src/fields/fq2.rs
Normal file
63
bn254/src/fields/fq2.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use super::*;
|
||||
use ark_ff::{biginteger::BigInteger256 as BigInteger, field_new, fields::*};
|
||||
|
||||
pub type Fq2 = Fp2<Fq2Parameters>;
|
||||
|
||||
pub struct Fq2Parameters;
|
||||
|
||||
impl Fp2Parameters for Fq2Parameters {
|
||||
type Fp = Fq;
|
||||
|
||||
/// NONRESIDUE = -1
|
||||
#[rustfmt::skip]
|
||||
const NONRESIDUE: Fq = field_new!(Fq, BigInteger([
|
||||
0x68c3488912edefaa,
|
||||
0x8d087f6872aabf4f,
|
||||
0x51e1a24709081231,
|
||||
0x2259d6b14729c0fa,
|
||||
]));
|
||||
|
||||
/// QUADRATIC_NONRESIDUE = U+2
|
||||
#[rustfmt::skip]
|
||||
const QUADRATIC_NONRESIDUE: (Fq, Fq) = (
|
||||
field_new!(Fq, BigInteger([
|
||||
12014063508332092218u64,
|
||||
1509222997478479483u64,
|
||||
14762033076929465432u64,
|
||||
2023505479389396574u64,
|
||||
])),
|
||||
field_new!(Fq, BigInteger([
|
||||
202099033278250856u64,
|
||||
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([
|
||||
0xd35d438dc58f0d9d,
|
||||
0x0a78eb28f5c70b3d,
|
||||
0x666ea36f7879462c,
|
||||
0xe0a77c19a07df2f,
|
||||
])),
|
||||
// NONRESIDUE**(((q^1) - 1) / 2)
|
||||
field_new!(Fq, BigInteger([
|
||||
0x68c3488912edefaa,
|
||||
0x8d087f6872aabf4f,
|
||||
0x51e1a24709081231,
|
||||
0x2259d6b14729c0fa,
|
||||
])),
|
||||
];
|
||||
|
||||
#[inline(always)]
|
||||
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
|
||||
-(*fe)
|
||||
}
|
||||
}
|
||||
|
||||
pub const FQ2_ZERO: Fq2 = field_new!(Fq2, FQ_ZERO, FQ_ZERO);
|
||||
pub const FQ2_ONE: Fq2 = field_new!(Fq2, FQ_ONE, FQ_ZERO);
|
||||
195
bn254/src/fields/fq6.rs
Normal file
195
bn254/src/fields/fq6.rs
Normal file
@@ -0,0 +1,195 @@
|
||||
use super::*;
|
||||
use ark_ff::{biginteger::BigInteger256, field_new, fields::*};
|
||||
|
||||
pub type Fq6 = Fp6<Fq6Parameters>;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Fq6Parameters;
|
||||
|
||||
impl Fp6Parameters for Fq6Parameters {
|
||||
type Fp2Params = Fq2Parameters;
|
||||
|
||||
/// NONRESIDUE = U+9
|
||||
#[rustfmt::skip]
|
||||
const NONRESIDUE: Fq2 = field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xf60647ce410d7ff7,
|
||||
0x2f3d6f4dd31bd011,
|
||||
0x2943337e3940c6d1,
|
||||
0x1d9598e8a7e39857,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
202099033278250856u64,
|
||||
8885205928937022213u64,
|
||||
5545221690922665192u64,
|
||||
39800542322357402u64,
|
||||
])),
|
||||
);
|
||||
|
||||
#[rustfmt::skip]
|
||||
const FROBENIUS_COEFF_FP6_C1: &'static [Fq2] = &[
|
||||
// Fp2::NONRESIDUE^(((q^0) - 1) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xd35d438dc58f0d9d,
|
||||
0x0a78eb28f5c70b3d,
|
||||
0x666ea36f7879462c,
|
||||
0xe0a77c19a07df2f,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^1) - 1) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xb5773b104563ab30,
|
||||
0x347f91c8a9aa6454,
|
||||
0x7a007127242e0991,
|
||||
0x1956bcd8118214ec,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x6e849f1ea0aa4757,
|
||||
0xaa1c7b6d89f89141,
|
||||
0xb6e713cdfae0ca3a,
|
||||
0x26694fbb4e82ebc3,
|
||||
])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^2) - 1) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x3350c88e13e80b9c,
|
||||
0x7dce557cdb5e56b9,
|
||||
0x6001b4b8b615564a,
|
||||
0x2682e617020217e0,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^3) - 1) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xc9af22f716ad6bad,
|
||||
0xb311782a4aa662b2,
|
||||
0x19eeaf64e248c7f4,
|
||||
0x20273e77e3439f82,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xacc02860f7ce93ac,
|
||||
0x3933d5817ba76b4c,
|
||||
0x69e6188b446c8467,
|
||||
0xa46036d4417cc55,
|
||||
])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^4) - 1) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x71930c11d782e155,
|
||||
0xa6bb947cffbe3323,
|
||||
0xaa303344d4741444,
|
||||
0x2c3b3f0d26594943,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^(((q^5) - 1) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xf91aba2654e8e3b1,
|
||||
0x4771cb2fdc92ce12,
|
||||
0xdcb16ae0fc8bdf35,
|
||||
0x274aa195cd9d8be4,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x5cfc50ae18811f8b,
|
||||
0x4bb28433cb43988c,
|
||||
0x4fd35f13c3b56219,
|
||||
0x301949bd2fc8883a,
|
||||
])),
|
||||
),
|
||||
];
|
||||
#[rustfmt::skip]
|
||||
const FROBENIUS_COEFF_FP6_C2: &'static [Fq2] = &[
|
||||
// Fp2::NONRESIDUE^((2*(q^0) - 2) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xd35d438dc58f0d9d,
|
||||
0x0a78eb28f5c70b3d,
|
||||
0x666ea36f7879462c,
|
||||
0xe0a77c19a07df2f,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^((2*(q^1) - 2) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x7361d77f843abe92,
|
||||
0xa5bb2bd3273411fb,
|
||||
0x9c941f314b3e2399,
|
||||
0x15df9cddbb9fd3ec,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x5dddfd154bd8c949,
|
||||
0x62cb29a5a4445b60,
|
||||
0x37bc870a0c7dd2b9,
|
||||
0x24830a9d3171f0fd,
|
||||
])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^((2*(q^2) - 2) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x71930c11d782e155,
|
||||
0xa6bb947cffbe3323,
|
||||
0xaa303344d4741444,
|
||||
0x2c3b3f0d26594943,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^((2*(q^3) - 2) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x448a93a57b6762df,
|
||||
0xbfd62df528fdeadf,
|
||||
0xd858f5d00e9bd47a,
|
||||
0x6b03d4d3476ec58,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x2b19daf4bcc936d1,
|
||||
0xa1a54e7a56f4299f,
|
||||
0xb533eee05adeaef1,
|
||||
0x170c812b84dda0b2,
|
||||
])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^((2*(q^4) - 2) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x3350c88e13e80b9c,
|
||||
0x7dce557cdb5e56b9,
|
||||
0x6001b4b8b615564a,
|
||||
0x2682e617020217e0,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
|
||||
),
|
||||
// Fp2::NONRESIDUE^((2*(q^5) - 2) / 3)
|
||||
field_new!(Fq2,
|
||||
field_new!(Fq, BigInteger256([
|
||||
0x843420f1d8dadbd6,
|
||||
0x31f010c9183fcdb2,
|
||||
0x436330b527a76049,
|
||||
0x13d47447f11adfe4,
|
||||
])),
|
||||
field_new!(Fq, BigInteger256([
|
||||
0xef494023a857fa74,
|
||||
0x2a925d02d5ab101a,
|
||||
0x83b015829ba62f10,
|
||||
0x2539111d0c13aea3,
|
||||
])),
|
||||
),
|
||||
];
|
||||
|
||||
#[inline(always)]
|
||||
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
|
||||
// (c0+u*c1)*(9+u) = (9*c0-c1)+u*(9*c1+c0)
|
||||
let mut f = *fe;
|
||||
f.double_in_place().double_in_place().double_in_place();
|
||||
let c0 = f.c0 + fe.c0 + Fq2Parameters::mul_fp_by_nonresidue(&fe.c1);
|
||||
let c1 = f.c1 + fe.c1 + fe.c0;
|
||||
field_new!(Fq2, c0, c1)
|
||||
}
|
||||
}
|
||||
95
bn254/src/fields/fr.rs
Normal file
95
bn254/src/fields/fr.rs
Normal 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 = 28;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
|
||||
7164790868263648668u64,
|
||||
11685701338293206998u64,
|
||||
6216421865291908056u64,
|
||||
1756667274303109607u64,
|
||||
]);
|
||||
}
|
||||
impl FpParameters for FrParameters {
|
||||
/// MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617
|
||||
#[rustfmt::skip]
|
||||
const MODULUS: BigInteger = BigInteger([
|
||||
4891460686036598785u64,
|
||||
2896914383306846353u64,
|
||||
13281191951274694749u64,
|
||||
3486998266802970665u64,
|
||||
]);
|
||||
|
||||
const MODULUS_BITS: u32 = 254;
|
||||
|
||||
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
|
||||
|
||||
const REPR_SHAVE_BITS: u32 = 2;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const R: BigInteger = BigInteger([
|
||||
12436184717236109307u64,
|
||||
3962172157175319849u64,
|
||||
7381016538464732718u64,
|
||||
1011752739694698287u64,
|
||||
]);
|
||||
|
||||
#[rustfmt::skip]
|
||||
const R2: BigInteger = BigInteger([
|
||||
1997599621687373223u64,
|
||||
6052339484930628067u64,
|
||||
10108755138030829701u64,
|
||||
150537098327114917u64,
|
||||
]);
|
||||
|
||||
const INV: u64 = 14042775128853446655u64;
|
||||
|
||||
// GENERATOR = 5
|
||||
#[rustfmt::skip]
|
||||
const GENERATOR: BigInteger = BigInteger([
|
||||
1949230679015292902u64,
|
||||
16913946402569752895u64,
|
||||
5177146667339417225u64,
|
||||
1571765431670520771u64,
|
||||
]);
|
||||
|
||||
/// (r - 1)/2 =
|
||||
/// 10944121435919637611123202872628637544274182200208017171849102093287904247808
|
||||
#[rustfmt::skip]
|
||||
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
|
||||
0xa1f0fac9f8000000,
|
||||
0x9419f4243cdcb848,
|
||||
0xdc2822db40c0ac2e,
|
||||
0x183227397098d014,
|
||||
]);
|
||||
|
||||
// T and T_MINUS_ONE_DIV_TWO, where r - 1 = 2^s * t
|
||||
|
||||
/// t = (r - 1) / 2^s =
|
||||
/// 81540058820840996586704275553141814055101440848469862132140264610111
|
||||
#[rustfmt::skip]
|
||||
const T: BigInteger = BigInteger([
|
||||
0x9b9709143e1f593f,
|
||||
0x181585d2833e8487,
|
||||
0x131a029b85045b68,
|
||||
0x30644e72e,
|
||||
]);
|
||||
|
||||
/// (t - 1) / 2 =
|
||||
/// 40770029410420498293352137776570907027550720424234931066070132305055
|
||||
#[rustfmt::skip]
|
||||
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
|
||||
0xcdcb848a1f0fac9f,
|
||||
0x0c0ac2e9419f4243,
|
||||
0x098d014dc2822db4,
|
||||
0x183227397,
|
||||
]);
|
||||
}
|
||||
27
bn254/src/fields/mod.rs
Normal file
27
bn254/src/fields/mod.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
#[cfg(feature = "scalar_field")]
|
||||
pub mod fr;
|
||||
#[cfg(feature = "scalar_field")]
|
||||
pub use self::fr::*;
|
||||
|
||||
#[cfg(feature = "curve")]
|
||||
pub mod fq;
|
||||
#[cfg(feature = "curve")]
|
||||
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;
|
||||
504
bn254/src/fields/tests.rs
Normal file
504
bn254/src/fields/tests.rs
Normal file
@@ -0,0 +1,504 @@
|
||||
use ark_ff::{
|
||||
biginteger::{BigInteger, BigInteger256},
|
||||
fields::{
|
||||
fp6_3over2::Fp6Parameters, FftField, FftParameters, Field, 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, 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!(BigInteger256::from(100), BigInteger256([100, 0, 0, 0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq_repr_is_odd() {
|
||||
assert!(!BigInteger256::from(0).is_odd());
|
||||
assert!(BigInteger256::from(0).is_even());
|
||||
assert!(BigInteger256::from(1).is_odd());
|
||||
assert!(!BigInteger256::from(1).is_even());
|
||||
assert!(!BigInteger256::from(324834872).is_odd());
|
||||
assert!(BigInteger256::from(324834872).is_even());
|
||||
assert!(BigInteger256::from(324834873).is_odd());
|
||||
assert!(!BigInteger256::from(324834873).is_even());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq_repr_is_zero() {
|
||||
assert!(BigInteger256::from(0).is_zero());
|
||||
assert!(!BigInteger256::from(1).is_zero());
|
||||
assert!(!BigInteger256([0, 0, 1, 0]).is_zero());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq_repr_num_bits() {
|
||||
let mut a = BigInteger256::from(0);
|
||||
assert_eq!(0, a.num_bits());
|
||||
a = BigInteger256::from(1);
|
||||
for i in 1..257 {
|
||||
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, 254);
|
||||
assert_eq!(FqParameters::CAPACITY, 253);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq_root_of_unity() {
|
||||
assert_eq!(FqParameters::TWO_ADICITY, 1);
|
||||
assert_eq!(
|
||||
Fq::multiplicative_generator().pow([
|
||||
0x9e10460b6c3e7ea3,
|
||||
0xcbc0b548b438e546,
|
||||
0xdc2822db40c0ac2e,
|
||||
0x183227397098d014,
|
||||
]),
|
||||
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() {
|
||||
// BigInteger256'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(BigInteger256::from(i + 1)) > Fq::from(BigInteger256::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(BigInteger256::from(4)).legendre()
|
||||
);
|
||||
assert_eq!(
|
||||
QuadraticNonResidue,
|
||||
Fq::from(BigInteger256::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_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);
|
||||
}
|
||||
}
|
||||
40
bn254/src/lib.rs
Normal file
40
bn254/src/lib.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![deny(
|
||||
warnings,
|
||||
unused,
|
||||
future_incompatible,
|
||||
nonstandard_style,
|
||||
rust_2018_idioms
|
||||
)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
//! This library implements the BN254 curve that was sampled as part of the [[BCTV14]][https://eprint.iacr.org/2013/879.pdf] paper .
|
||||
//! The name denotes that it is a Barreto--Naehrig curve of embedding degree 12,
|
||||
//! defined over a 254-bit (prime) field. The scalar field is highly 2-adic.
|
||||
//!
|
||||
//! This curve is also implemented in [libff](https://github.com/scipr-lab/libff/tree/master/libff/algebra/curves/alt_bn128) under the name `bn128`.
|
||||
//! It is the same as the `bn256` curve used in Ethereum (eg: [go-ethereum](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn254/cloudflare)).
|
||||
//!
|
||||
//! #CAUTION
|
||||
//! **This curve does not satisfy the 128-bit security level anymore.**
|
||||
//!
|
||||
//!
|
||||
//! Curve information:
|
||||
//! * Base field: q = 21888242871839275222246405745257275088696311157297823662689037894645226208583
|
||||
//! * Scalar field: r = 21888242871839275222246405745257275088548364400416034343698204186575808495617
|
||||
//! * valuation(q - 1, 2) = 1
|
||||
//! * valuation(r - 1, 2) = 28
|
||||
//! * G1 curve equation: y^2 = x^3 + 3
|
||||
//! * G2 curve equation: y^2 = x^3 + B, where
|
||||
//! * B = 3/(u+9) where Fq2[u]=Fq/u+1
|
||||
//! = Fq2(19485874751759354771024239261021720505790618469301721065564631296452457478373, 266929791119991161246907387137283842545076965332900288569378510910307636690)
|
||||
|
||||
#[cfg(feature = "curve")]
|
||||
mod curves;
|
||||
|
||||
mod fields;
|
||||
|
||||
#[cfg(feature = "curve")]
|
||||
pub use curves::*;
|
||||
|
||||
pub use fields::*;
|
||||
Reference in New Issue
Block a user