Add 'pairing/' from commit '09b6e6f9212020f385218e5cf5287e381ccd312b'
git-subtree-dir: pairing git-subtree-mainline:ad16ba6a35git-subtree-split:09b6e6f921
This commit is contained in:
420
pairing/src/tests/curve.rs
Normal file
420
pairing/src/tests/curve.rs
Normal file
@@ -0,0 +1,420 @@
|
||||
use rand::{Rand, Rng, SeedableRng, XorShiftRng};
|
||||
|
||||
use {CurveAffine, CurveProjective, EncodedPoint, Field};
|
||||
|
||||
pub fn curve_tests<G: CurveProjective>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
// Negation edge case with zero.
|
||||
{
|
||||
let mut z = G::zero();
|
||||
z.negate();
|
||||
assert!(z.is_zero());
|
||||
}
|
||||
|
||||
// Doubling edge case with zero.
|
||||
{
|
||||
let mut z = G::zero();
|
||||
z.double();
|
||||
assert!(z.is_zero());
|
||||
}
|
||||
|
||||
// Addition edge cases with zero
|
||||
{
|
||||
let mut r = G::rand(&mut rng);
|
||||
let rcopy = r;
|
||||
r.add_assign(&G::zero());
|
||||
assert_eq!(r, rcopy);
|
||||
r.add_assign_mixed(&G::Affine::zero());
|
||||
assert_eq!(r, rcopy);
|
||||
|
||||
let mut z = G::zero();
|
||||
z.add_assign(&G::zero());
|
||||
assert!(z.is_zero());
|
||||
z.add_assign_mixed(&G::Affine::zero());
|
||||
assert!(z.is_zero());
|
||||
|
||||
let mut z2 = z;
|
||||
z2.add_assign(&r);
|
||||
|
||||
z.add_assign_mixed(&r.into_affine());
|
||||
|
||||
assert_eq!(z, z2);
|
||||
assert_eq!(z, r);
|
||||
}
|
||||
|
||||
// Transformations
|
||||
{
|
||||
let a = G::rand(&mut rng);
|
||||
let b = a.into_affine().into_projective();
|
||||
let c = a
|
||||
.into_affine()
|
||||
.into_projective()
|
||||
.into_affine()
|
||||
.into_projective();
|
||||
assert_eq!(a, b);
|
||||
assert_eq!(b, c);
|
||||
}
|
||||
|
||||
random_addition_tests::<G>();
|
||||
random_multiplication_tests::<G>();
|
||||
random_doubling_tests::<G>();
|
||||
random_negation_tests::<G>();
|
||||
random_transformation_tests::<G>();
|
||||
random_wnaf_tests::<G>();
|
||||
random_encoding_tests::<G::Affine>();
|
||||
}
|
||||
|
||||
fn random_wnaf_tests<G: CurveProjective>() {
|
||||
use wnaf::*;
|
||||
use PrimeField;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
{
|
||||
let mut table = vec![];
|
||||
let mut wnaf = vec![];
|
||||
|
||||
for w in 2..14 {
|
||||
for _ in 0..100 {
|
||||
let g = G::rand(&mut rng);
|
||||
let s = G::Scalar::rand(&mut rng).into_repr();
|
||||
let mut g1 = g;
|
||||
g1.mul_assign(s);
|
||||
|
||||
wnaf_table(&mut table, g, w);
|
||||
wnaf_form(&mut wnaf, s, w);
|
||||
let g2 = wnaf_exp(&table, &wnaf);
|
||||
|
||||
assert_eq!(g1, g2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
fn only_compiles_if_send<S: Send>(_: &S) {}
|
||||
|
||||
for _ in 0..100 {
|
||||
let g = G::rand(&mut rng);
|
||||
let s = G::Scalar::rand(&mut rng).into_repr();
|
||||
let mut g1 = g;
|
||||
g1.mul_assign(s);
|
||||
|
||||
let g2 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
wnaf.base(g, 1).scalar(s)
|
||||
};
|
||||
let g3 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
wnaf.scalar(s).base(g)
|
||||
};
|
||||
let g4 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
let mut shared = wnaf.base(g, 1).shared();
|
||||
|
||||
only_compiles_if_send(&shared);
|
||||
|
||||
shared.scalar(s)
|
||||
};
|
||||
let g5 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
let mut shared = wnaf.scalar(s).shared();
|
||||
|
||||
only_compiles_if_send(&shared);
|
||||
|
||||
shared.base(g)
|
||||
};
|
||||
|
||||
let g6 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
{
|
||||
// Populate the vectors.
|
||||
wnaf.base(rng.gen(), 1).scalar(rng.gen());
|
||||
}
|
||||
wnaf.base(g, 1).scalar(s)
|
||||
};
|
||||
let g7 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
{
|
||||
// Populate the vectors.
|
||||
wnaf.base(rng.gen(), 1).scalar(rng.gen());
|
||||
}
|
||||
wnaf.scalar(s).base(g)
|
||||
};
|
||||
let g8 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
{
|
||||
// Populate the vectors.
|
||||
wnaf.base(rng.gen(), 1).scalar(rng.gen());
|
||||
}
|
||||
let mut shared = wnaf.base(g, 1).shared();
|
||||
|
||||
only_compiles_if_send(&shared);
|
||||
|
||||
shared.scalar(s)
|
||||
};
|
||||
let g9 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
{
|
||||
// Populate the vectors.
|
||||
wnaf.base(rng.gen(), 1).scalar(rng.gen());
|
||||
}
|
||||
let mut shared = wnaf.scalar(s).shared();
|
||||
|
||||
only_compiles_if_send(&shared);
|
||||
|
||||
shared.base(g)
|
||||
};
|
||||
|
||||
assert_eq!(g1, g2);
|
||||
assert_eq!(g1, g3);
|
||||
assert_eq!(g1, g4);
|
||||
assert_eq!(g1, g5);
|
||||
assert_eq!(g1, g6);
|
||||
assert_eq!(g1, g7);
|
||||
assert_eq!(g1, g8);
|
||||
assert_eq!(g1, g9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn random_negation_tests<G: CurveProjective>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let r = G::rand(&mut rng);
|
||||
|
||||
let s = G::Scalar::rand(&mut rng);
|
||||
let mut sneg = s;
|
||||
sneg.negate();
|
||||
|
||||
let mut t1 = r;
|
||||
t1.mul_assign(s);
|
||||
|
||||
let mut t2 = r;
|
||||
t2.mul_assign(sneg);
|
||||
|
||||
let mut t3 = t1;
|
||||
t3.add_assign(&t2);
|
||||
assert!(t3.is_zero());
|
||||
|
||||
let mut t4 = t1;
|
||||
t4.add_assign_mixed(&t2.into_affine());
|
||||
assert!(t4.is_zero());
|
||||
|
||||
t1.negate();
|
||||
assert_eq!(t1, t2);
|
||||
}
|
||||
}
|
||||
|
||||
fn random_doubling_tests<G: CurveProjective>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut a = G::rand(&mut rng);
|
||||
let mut b = G::rand(&mut rng);
|
||||
|
||||
// 2(a + b)
|
||||
let mut tmp1 = a;
|
||||
tmp1.add_assign(&b);
|
||||
tmp1.double();
|
||||
|
||||
// 2a + 2b
|
||||
a.double();
|
||||
b.double();
|
||||
|
||||
let mut tmp2 = a;
|
||||
tmp2.add_assign(&b);
|
||||
|
||||
let mut tmp3 = a;
|
||||
tmp3.add_assign_mixed(&b.into_affine());
|
||||
|
||||
assert_eq!(tmp1, tmp2);
|
||||
assert_eq!(tmp1, tmp3);
|
||||
}
|
||||
}
|
||||
|
||||
fn random_multiplication_tests<G: CurveProjective>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut a = G::rand(&mut rng);
|
||||
let mut b = G::rand(&mut rng);
|
||||
let a_affine = a.into_affine();
|
||||
let b_affine = b.into_affine();
|
||||
|
||||
let s = G::Scalar::rand(&mut rng);
|
||||
|
||||
// s ( a + b )
|
||||
let mut tmp1 = a;
|
||||
tmp1.add_assign(&b);
|
||||
tmp1.mul_assign(s);
|
||||
|
||||
// sa + sb
|
||||
a.mul_assign(s);
|
||||
b.mul_assign(s);
|
||||
|
||||
let mut tmp2 = a;
|
||||
tmp2.add_assign(&b);
|
||||
|
||||
// Affine multiplication
|
||||
let mut tmp3 = a_affine.mul(s);
|
||||
tmp3.add_assign(&b_affine.mul(s));
|
||||
|
||||
assert_eq!(tmp1, tmp2);
|
||||
assert_eq!(tmp1, tmp3);
|
||||
}
|
||||
}
|
||||
|
||||
fn random_addition_tests<G: CurveProjective>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let a = G::rand(&mut rng);
|
||||
let b = G::rand(&mut rng);
|
||||
let c = G::rand(&mut rng);
|
||||
let a_affine = a.into_affine();
|
||||
let b_affine = b.into_affine();
|
||||
let c_affine = c.into_affine();
|
||||
|
||||
// a + a should equal the doubling
|
||||
{
|
||||
let mut aplusa = a;
|
||||
aplusa.add_assign(&a);
|
||||
|
||||
let mut aplusamixed = a;
|
||||
aplusamixed.add_assign_mixed(&a.into_affine());
|
||||
|
||||
let mut adouble = a;
|
||||
adouble.double();
|
||||
|
||||
assert_eq!(aplusa, adouble);
|
||||
assert_eq!(aplusa, aplusamixed);
|
||||
}
|
||||
|
||||
let mut tmp = vec![G::zero(); 6];
|
||||
|
||||
// (a + b) + c
|
||||
tmp[0] = a;
|
||||
tmp[0].add_assign(&b);
|
||||
tmp[0].add_assign(&c);
|
||||
|
||||
// a + (b + c)
|
||||
tmp[1] = b;
|
||||
tmp[1].add_assign(&c);
|
||||
tmp[1].add_assign(&a);
|
||||
|
||||
// (a + c) + b
|
||||
tmp[2] = a;
|
||||
tmp[2].add_assign(&c);
|
||||
tmp[2].add_assign(&b);
|
||||
|
||||
// Mixed addition
|
||||
|
||||
// (a + b) + c
|
||||
tmp[3] = a_affine.into_projective();
|
||||
tmp[3].add_assign_mixed(&b_affine);
|
||||
tmp[3].add_assign_mixed(&c_affine);
|
||||
|
||||
// a + (b + c)
|
||||
tmp[4] = b_affine.into_projective();
|
||||
tmp[4].add_assign_mixed(&c_affine);
|
||||
tmp[4].add_assign_mixed(&a_affine);
|
||||
|
||||
// (a + c) + b
|
||||
tmp[5] = a_affine.into_projective();
|
||||
tmp[5].add_assign_mixed(&c_affine);
|
||||
tmp[5].add_assign_mixed(&b_affine);
|
||||
|
||||
// Comparisons
|
||||
for i in 0..6 {
|
||||
for j in 0..6 {
|
||||
assert_eq!(tmp[i], tmp[j]);
|
||||
assert_eq!(tmp[i].into_affine(), tmp[j].into_affine());
|
||||
}
|
||||
|
||||
assert!(tmp[i] != a);
|
||||
assert!(tmp[i] != b);
|
||||
assert!(tmp[i] != c);
|
||||
|
||||
assert!(a != tmp[i]);
|
||||
assert!(b != tmp[i]);
|
||||
assert!(c != tmp[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn random_transformation_tests<G: CurveProjective>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let g = G::rand(&mut rng);
|
||||
let g_affine = g.into_affine();
|
||||
let g_projective = g_affine.into_projective();
|
||||
assert_eq!(g, g_projective);
|
||||
}
|
||||
|
||||
// Batch normalization
|
||||
for _ in 0..10 {
|
||||
let mut v = (0..1000).map(|_| G::rand(&mut rng)).collect::<Vec<_>>();
|
||||
|
||||
for i in &v {
|
||||
assert!(!i.is_normalized());
|
||||
}
|
||||
|
||||
use rand::distributions::{IndependentSample, Range};
|
||||
let between = Range::new(0, 1000);
|
||||
// Sprinkle in some normalized points
|
||||
for _ in 0..5 {
|
||||
v[between.ind_sample(&mut rng)] = G::zero();
|
||||
}
|
||||
for _ in 0..5 {
|
||||
let s = between.ind_sample(&mut rng);
|
||||
v[s] = v[s].into_affine().into_projective();
|
||||
}
|
||||
|
||||
let expected_v = v
|
||||
.iter()
|
||||
.map(|v| v.into_affine().into_projective())
|
||||
.collect::<Vec<_>>();
|
||||
G::batch_normalization(&mut v);
|
||||
|
||||
for i in &v {
|
||||
assert!(i.is_normalized());
|
||||
}
|
||||
|
||||
assert_eq!(v, expected_v);
|
||||
}
|
||||
}
|
||||
|
||||
fn random_encoding_tests<G: CurveAffine>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
assert_eq!(
|
||||
G::zero().into_uncompressed().into_affine().unwrap(),
|
||||
G::zero()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
G::zero().into_compressed().into_affine().unwrap(),
|
||||
G::zero()
|
||||
);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut r = G::Projective::rand(&mut rng).into_affine();
|
||||
|
||||
let uncompressed = r.into_uncompressed();
|
||||
let de_uncompressed = uncompressed.into_affine().unwrap();
|
||||
assert_eq!(de_uncompressed, r);
|
||||
|
||||
let compressed = r.into_compressed();
|
||||
let de_compressed = compressed.into_affine().unwrap();
|
||||
assert_eq!(de_compressed, r);
|
||||
|
||||
r.negate();
|
||||
|
||||
let compressed = r.into_compressed();
|
||||
let de_compressed = compressed.into_affine().unwrap();
|
||||
assert_eq!(de_compressed, r);
|
||||
}
|
||||
}
|
||||
126
pairing/src/tests/engine.rs
Normal file
126
pairing/src/tests/engine.rs
Normal file
@@ -0,0 +1,126 @@
|
||||
use rand::{Rand, SeedableRng, XorShiftRng};
|
||||
|
||||
use {CurveAffine, CurveProjective, Engine, Field, PrimeField};
|
||||
|
||||
pub fn engine_tests<E: Engine>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..10 {
|
||||
let a = E::G1::rand(&mut rng).into_affine();
|
||||
let b = E::G2::rand(&mut rng).into_affine();
|
||||
|
||||
assert!(a.pairing_with(&b) == b.pairing_with(&a));
|
||||
assert!(a.pairing_with(&b) == E::pairing(a, b));
|
||||
}
|
||||
|
||||
for _ in 0..1000 {
|
||||
let z1 = E::G1Affine::zero().prepare();
|
||||
let z2 = E::G2Affine::zero().prepare();
|
||||
|
||||
let a = E::G1::rand(&mut rng).into_affine().prepare();
|
||||
let b = E::G2::rand(&mut rng).into_affine().prepare();
|
||||
let c = E::G1::rand(&mut rng).into_affine().prepare();
|
||||
let d = E::G2::rand(&mut rng).into_affine().prepare();
|
||||
|
||||
assert_eq!(
|
||||
E::Fqk::one(),
|
||||
E::final_exponentiation(&E::miller_loop(&[(&z1, &b)])).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
E::Fqk::one(),
|
||||
E::final_exponentiation(&E::miller_loop(&[(&a, &z2)])).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
E::final_exponentiation(&E::miller_loop(&[(&z1, &b), (&c, &d)])).unwrap(),
|
||||
E::final_exponentiation(&E::miller_loop(&[(&a, &z2), (&c, &d)])).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&z1, &d)])).unwrap(),
|
||||
E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&c, &z2)])).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
random_bilinearity_tests::<E>();
|
||||
random_miller_loop_tests::<E>();
|
||||
}
|
||||
|
||||
fn random_miller_loop_tests<E: Engine>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
// Exercise the miller loop for a reduced pairing
|
||||
for _ in 0..1000 {
|
||||
let a = E::G1::rand(&mut rng);
|
||||
let b = E::G2::rand(&mut rng);
|
||||
|
||||
let p2 = E::pairing(a, b);
|
||||
|
||||
let a = a.into_affine().prepare();
|
||||
let b = b.into_affine().prepare();
|
||||
|
||||
let p1 = E::final_exponentiation(&E::miller_loop(&[(&a, &b)])).unwrap();
|
||||
|
||||
assert_eq!(p1, p2);
|
||||
}
|
||||
|
||||
// Exercise a double miller loop
|
||||
for _ in 0..1000 {
|
||||
let a = E::G1::rand(&mut rng);
|
||||
let b = E::G2::rand(&mut rng);
|
||||
let c = E::G1::rand(&mut rng);
|
||||
let d = E::G2::rand(&mut rng);
|
||||
|
||||
let ab = E::pairing(a, b);
|
||||
let cd = E::pairing(c, d);
|
||||
|
||||
let mut abcd = ab;
|
||||
abcd.mul_assign(&cd);
|
||||
|
||||
let a = a.into_affine().prepare();
|
||||
let b = b.into_affine().prepare();
|
||||
let c = c.into_affine().prepare();
|
||||
let d = d.into_affine().prepare();
|
||||
|
||||
let abcd_with_double_loop =
|
||||
E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&c, &d)])).unwrap();
|
||||
|
||||
assert_eq!(abcd, abcd_with_double_loop);
|
||||
}
|
||||
}
|
||||
|
||||
fn random_bilinearity_tests<E: Engine>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let a = E::G1::rand(&mut rng);
|
||||
let b = E::G2::rand(&mut rng);
|
||||
|
||||
let c = E::Fr::rand(&mut rng);
|
||||
let d = E::Fr::rand(&mut rng);
|
||||
|
||||
let mut ac = a;
|
||||
ac.mul_assign(c);
|
||||
|
||||
let mut ad = a;
|
||||
ad.mul_assign(d);
|
||||
|
||||
let mut bc = b;
|
||||
bc.mul_assign(c);
|
||||
|
||||
let mut bd = b;
|
||||
bd.mul_assign(d);
|
||||
|
||||
let acbd = E::pairing(ac, bd);
|
||||
let adbc = E::pairing(ad, bc);
|
||||
|
||||
let mut cd = c;
|
||||
cd.mul_assign(&d);
|
||||
|
||||
let abcd = E::pairing(a, b).pow(cd.into_repr());
|
||||
|
||||
assert_eq!(acbd, adbc);
|
||||
assert_eq!(acbd, abcd);
|
||||
}
|
||||
}
|
||||
266
pairing/src/tests/field.rs
Normal file
266
pairing/src/tests/field.rs
Normal file
@@ -0,0 +1,266 @@
|
||||
use rand::{Rng, SeedableRng, XorShiftRng};
|
||||
use {Field, LegendreSymbol, PrimeField, SqrtField};
|
||||
|
||||
pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxpower: usize) {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..100 {
|
||||
for i in 0..(maxpower + 1) {
|
||||
let mut a = F::rand(&mut rng);
|
||||
let mut b = a;
|
||||
|
||||
for _ in 0..i {
|
||||
a = a.pow(&characteristic);
|
||||
}
|
||||
b.frobenius_map(i);
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn random_sqrt_tests<F: SqrtField>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..10000 {
|
||||
let a = F::rand(&mut rng);
|
||||
let mut b = a;
|
||||
b.square();
|
||||
assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue);
|
||||
|
||||
let b = b.sqrt().unwrap();
|
||||
let mut negb = b;
|
||||
negb.negate();
|
||||
|
||||
assert!(a == b || a == negb);
|
||||
}
|
||||
|
||||
let mut c = F::one();
|
||||
for _ in 0..10000 {
|
||||
let mut b = c;
|
||||
b.square();
|
||||
assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue);
|
||||
|
||||
b = b.sqrt().unwrap();
|
||||
|
||||
if b != c {
|
||||
b.negate();
|
||||
}
|
||||
|
||||
assert_eq!(b, c);
|
||||
|
||||
c.add_assign(&F::one());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn random_field_tests<F: Field>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
random_multiplication_tests::<F, _>(&mut rng);
|
||||
random_addition_tests::<F, _>(&mut rng);
|
||||
random_subtraction_tests::<F, _>(&mut rng);
|
||||
random_negation_tests::<F, _>(&mut rng);
|
||||
random_doubling_tests::<F, _>(&mut rng);
|
||||
random_squaring_tests::<F, _>(&mut rng);
|
||||
random_inversion_tests::<F, _>(&mut rng);
|
||||
random_expansion_tests::<F, _>(&mut rng);
|
||||
|
||||
assert!(F::zero().is_zero());
|
||||
{
|
||||
let mut z = F::zero();
|
||||
z.negate();
|
||||
assert!(z.is_zero());
|
||||
}
|
||||
|
||||
assert!(F::zero().inverse().is_none());
|
||||
|
||||
// Multiplication by zero
|
||||
{
|
||||
let mut a = F::rand(&mut rng);
|
||||
a.mul_assign(&F::zero());
|
||||
assert!(a.is_zero());
|
||||
}
|
||||
|
||||
// Addition by zero
|
||||
{
|
||||
let mut a = F::rand(&mut rng);
|
||||
let copy = a;
|
||||
a.add_assign(&F::zero());
|
||||
assert_eq!(a, copy);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str_tests<F: PrimeField>() {
|
||||
{
|
||||
let a = "84395729384759238745923745892374598234705297301958723458712394587103249587213984572934750213947582345792304758273458972349582734958273495872304598234";
|
||||
let b = "38495729084572938457298347502349857029384609283450692834058293405982304598230458230495820394850293845098234059823049582309485203948502938452093482039";
|
||||
let c = "3248875134290623212325429203829831876024364170316860259933542844758450336418538569901990710701240661702808867062612075657861768196242274635305077449545396068598317421057721935408562373834079015873933065667961469731886739181625866970316226171512545167081793907058686908697431878454091011239990119126";
|
||||
|
||||
let mut a = F::from_str(a).unwrap();
|
||||
let b = F::from_str(b).unwrap();
|
||||
let c = F::from_str(c).unwrap();
|
||||
|
||||
a.mul_assign(&b);
|
||||
|
||||
assert_eq!(a, c);
|
||||
}
|
||||
|
||||
{
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let n: u64 = rng.gen();
|
||||
|
||||
let a = F::from_str(&format!("{}", n)).unwrap();
|
||||
let b = F::from_repr(n.into()).unwrap();
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(F::from_str("").is_none());
|
||||
assert!(F::from_str("0").unwrap().is_zero());
|
||||
assert!(F::from_str("00").is_none());
|
||||
assert!(F::from_str("00000000000").is_none());
|
||||
}
|
||||
|
||||
fn random_multiplication_tests<F: Field, R: Rng>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
let a = F::rand(rng);
|
||||
let b = F::rand(rng);
|
||||
let c = F::rand(rng);
|
||||
|
||||
let mut t0 = a; // (a * b) * c
|
||||
t0.mul_assign(&b);
|
||||
t0.mul_assign(&c);
|
||||
|
||||
let mut t1 = a; // (a * c) * b
|
||||
t1.mul_assign(&c);
|
||||
t1.mul_assign(&b);
|
||||
|
||||
let mut t2 = b; // (b * c) * a
|
||||
t2.mul_assign(&c);
|
||||
t2.mul_assign(&a);
|
||||
|
||||
assert_eq!(t0, t1);
|
||||
assert_eq!(t1, t2);
|
||||
}
|
||||
}
|
||||
|
||||
fn random_addition_tests<F: Field, R: Rng>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
let a = F::rand(rng);
|
||||
let b = F::rand(rng);
|
||||
let c = F::rand(rng);
|
||||
|
||||
let mut t0 = a; // (a + b) + c
|
||||
t0.add_assign(&b);
|
||||
t0.add_assign(&c);
|
||||
|
||||
let mut t1 = a; // (a + c) + b
|
||||
t1.add_assign(&c);
|
||||
t1.add_assign(&b);
|
||||
|
||||
let mut t2 = b; // (b + c) + a
|
||||
t2.add_assign(&c);
|
||||
t2.add_assign(&a);
|
||||
|
||||
assert_eq!(t0, t1);
|
||||
assert_eq!(t1, t2);
|
||||
}
|
||||
}
|
||||
|
||||
fn random_subtraction_tests<F: Field, R: Rng>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
let a = F::rand(rng);
|
||||
let b = F::rand(rng);
|
||||
|
||||
let mut t0 = a; // (a - b)
|
||||
t0.sub_assign(&b);
|
||||
|
||||
let mut t1 = b; // (b - a)
|
||||
t1.sub_assign(&a);
|
||||
|
||||
let mut t2 = t0; // (a - b) + (b - a) = 0
|
||||
t2.add_assign(&t1);
|
||||
|
||||
assert!(t2.is_zero());
|
||||
}
|
||||
}
|
||||
|
||||
fn random_negation_tests<F: Field, R: Rng>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
let a = F::rand(rng);
|
||||
let mut b = a;
|
||||
b.negate();
|
||||
b.add_assign(&a);
|
||||
|
||||
assert!(b.is_zero());
|
||||
}
|
||||
}
|
||||
|
||||
fn random_doubling_tests<F: Field, R: Rng>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
let mut a = F::rand(rng);
|
||||
let mut b = a;
|
||||
a.add_assign(&b);
|
||||
b.double();
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
fn random_squaring_tests<F: Field, R: Rng>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
let mut a = F::rand(rng);
|
||||
let mut b = a;
|
||||
a.mul_assign(&b);
|
||||
b.square();
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
fn random_inversion_tests<F: Field, R: Rng>(rng: &mut R) {
|
||||
assert!(F::zero().inverse().is_none());
|
||||
|
||||
for _ in 0..10000 {
|
||||
let mut a = F::rand(rng);
|
||||
let b = a.inverse().unwrap(); // probablistically nonzero
|
||||
a.mul_assign(&b);
|
||||
|
||||
assert_eq!(a, F::one());
|
||||
}
|
||||
}
|
||||
|
||||
fn random_expansion_tests<F: Field, R: Rng>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
// Compare (a + b)(c + d) and (a*c + b*c + a*d + b*d)
|
||||
|
||||
let a = F::rand(rng);
|
||||
let b = F::rand(rng);
|
||||
let c = F::rand(rng);
|
||||
let d = F::rand(rng);
|
||||
|
||||
let mut t0 = a;
|
||||
t0.add_assign(&b);
|
||||
let mut t1 = c;
|
||||
t1.add_assign(&d);
|
||||
t0.mul_assign(&t1);
|
||||
|
||||
let mut t2 = a;
|
||||
t2.mul_assign(&c);
|
||||
let mut t3 = b;
|
||||
t3.mul_assign(&c);
|
||||
let mut t4 = a;
|
||||
t4.mul_assign(&d);
|
||||
let mut t5 = b;
|
||||
t5.mul_assign(&d);
|
||||
|
||||
t2.add_assign(&t3);
|
||||
t2.add_assign(&t4);
|
||||
t2.add_assign(&t5);
|
||||
|
||||
assert_eq!(t0, t2);
|
||||
}
|
||||
}
|
||||
4
pairing/src/tests/mod.rs
Normal file
4
pairing/src/tests/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub mod curve;
|
||||
pub mod engine;
|
||||
pub mod field;
|
||||
pub mod repr;
|
||||
98
pairing/src/tests/repr.rs
Normal file
98
pairing/src/tests/repr.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
use rand::{SeedableRng, XorShiftRng};
|
||||
use PrimeFieldRepr;
|
||||
|
||||
pub fn random_repr_tests<R: PrimeFieldRepr>() {
|
||||
random_encoding_tests::<R>();
|
||||
random_shl_tests::<R>();
|
||||
random_shr_tests::<R>();
|
||||
}
|
||||
|
||||
fn random_encoding_tests<R: PrimeFieldRepr>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let r = R::rand(&mut rng);
|
||||
|
||||
// Big endian
|
||||
{
|
||||
let mut rdecoded = R::default();
|
||||
|
||||
let mut v: Vec<u8> = vec![];
|
||||
r.write_be(&mut v).unwrap();
|
||||
rdecoded.read_be(&v[0..]).unwrap();
|
||||
|
||||
assert_eq!(r, rdecoded);
|
||||
}
|
||||
|
||||
// Little endian
|
||||
{
|
||||
let mut rdecoded = R::default();
|
||||
|
||||
let mut v: Vec<u8> = vec![];
|
||||
r.write_le(&mut v).unwrap();
|
||||
rdecoded.read_le(&v[0..]).unwrap();
|
||||
|
||||
assert_eq!(r, rdecoded);
|
||||
}
|
||||
|
||||
{
|
||||
let mut rdecoded_le = R::default();
|
||||
let mut rdecoded_be_flip = R::default();
|
||||
|
||||
let mut v: Vec<u8> = vec![];
|
||||
r.write_le(&mut v).unwrap();
|
||||
|
||||
// This reads in little-endian, so we are done.
|
||||
rdecoded_le.read_le(&v[..]).unwrap();
|
||||
|
||||
// This reads in big-endian, so we perform a swap of the
|
||||
// bytes beforehand.
|
||||
let v: Vec<u8> = v.into_iter().rev().collect();
|
||||
rdecoded_be_flip.read_be(&v[..]).unwrap();
|
||||
|
||||
assert_eq!(rdecoded_le, rdecoded_be_flip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn random_shl_tests<R: PrimeFieldRepr>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..100 {
|
||||
let r = R::rand(&mut rng);
|
||||
|
||||
for shift in 0..(r.num_bits() + 1) {
|
||||
let mut r1 = r;
|
||||
let mut r2 = r;
|
||||
|
||||
for _ in 0..shift {
|
||||
r1.mul2();
|
||||
}
|
||||
|
||||
r2.shl(shift);
|
||||
|
||||
assert_eq!(r1, r2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn random_shr_tests<R: PrimeFieldRepr>() {
|
||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..100 {
|
||||
let r = R::rand(&mut rng);
|
||||
|
||||
for shift in 0..(r.num_bits() + 1) {
|
||||
let mut r1 = r;
|
||||
let mut r2 = r;
|
||||
|
||||
for _ in 0..shift {
|
||||
r1.div2();
|
||||
}
|
||||
|
||||
r2.shr(shift);
|
||||
|
||||
assert_eq!(r1, r2);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user