use super::{Engine, Group, GroupAffine, Field, PrimeField}; use rand; mod fields; mod groups; fn test_multiexp>(e: &E) { fn naiveexp>(e: &E, g: &[G::Affine], s: &[E::Fr]) -> G { assert!(g.len() == s.len()); let mut expected = G::zero(e); for (g, s) in g.iter().zip(s.iter()) { expected.add_assign(e, &g.mul(e, s)); } expected } { let rng = &mut rand::thread_rng(); let g: Vec = (0..1000).map(|_| G::random(e, rng).to_affine(e)).collect(); let s: Vec = (0..1000).map(|_| E::Fr::random(e, rng)).collect(); let naive = naiveexp::(e, &g, &s); let multi = e.multiexp::(&g, &s).unwrap(); assert!(naive.is_equal(e, &multi)); assert!(multi.is_equal(e, &naive)); } { let rng = &mut rand::thread_rng(); let g: Vec = (0..2).map(|_| G::random(e, rng).to_affine(e)).collect(); let s = vec![E::Fr::from_str(e, "3435973836800000000000000000000000").unwrap(), E::Fr::from_str(e, "3435973836700000000000000000000000").unwrap()]; let naive = naiveexp::(e, &g, &s); let multi = e.multiexp::(&g, &s).unwrap(); assert!(naive.is_equal(e, &multi)); assert!(multi.is_equal(e, &naive)); } { let rng = &mut rand::thread_rng(); let s = vec![E::Fr::one(e); 100]; let g = vec![G::random(e, rng).to_affine(e); 101]; assert!(e.multiexp::(&g, &s).is_err()); } } fn test_bilinearity(e: &E) { let rng = &mut rand::thread_rng(); let a = E::G1::random(e, rng); let b = E::G2::random(e, rng); let s = E::Fr::random(e, rng); let mut a_s = a; a_s.mul_assign(e, &s); let mut b_s = b; b_s.mul_assign(e, &s); let test1 = e.pairing(&a_s, &b); assert!(test1 != E::Fqk::one(e)); let test2 = e.pairing(&a, &b_s); assert_eq!(test1, test2); let mut test4 = e.pairing(&a, &b); assert!(test4 != test1); test4 = test4.pow(e, &s); assert_eq!(test1, test4); } fn test_multimiller(e: &E) { let rng = &mut rand::thread_rng(); let a1 = E::G1::random(e, rng); let a2 = E::G2::random(e, rng); let b1 = E::G1::random(e, rng); let b2 = E::G2::random(e, rng); let mut p1 = e.pairing(&a1, &a2); let p2 = e.pairing(&b1, &b2); p1.mul_assign(e, &p2); let mm = e.final_exponentiation(&e.miller_loop( [ (&a1.prepare(e), &a2.prepare(e)), (&b1.prepare(e), &b2.prepare(e)) ].into_iter() )); assert_eq!(p1, mm); } pub fn test_engine() { let engine = E::new(); fields::test_prime_field::(&engine); fields::test_prime_field::(&engine); fields::test_sqrt_field::(&engine); fields::test_sqrt_field::(&engine); fields::test_sqrt_field::(&engine); fields::test_field::(&engine); fields::test_field::(&engine); fields::test_field::(&engine); fields::test_field::(&engine); groups::test_group::(&engine); groups::test_group::(&engine); test_bilinearity(&engine); test_multimiller(&engine); test_frobenius(&engine); test_multiexp::(&engine); test_multiexp::(&engine); } fn test_frobenius(e: &E) { let rng = &mut rand::thread_rng(); let modulus = E::Fq::char(e); let a = E::Fqk::random(e, rng); let mut acpy = a; acpy.frobenius_map(e, 0); assert_eq!(acpy, a); let mut a_q = a.pow(e, &modulus); for p in 1..12 { acpy = a; acpy.frobenius_map(e, p); assert_eq!(acpy, a_q); a_q = a_q.pow(e, &modulus); } }