midnight-curves 0.2.0

Implementation of BLS12 381 and Jubjub curves.
Documentation
#[macro_export]
macro_rules! test_pairing {
    (
    $engine:ident,
    $g1:ident,
    $g1affine:ident,
    $g2:ident,
    $g2affine:ident,
    $base:ident,
    $target:ident,
    $scalar:ident
    ) => {
        #[test]
        fn test_miller_loop_identity() {
            use ff::Field;
            assert_eq!($base::ONE.final_exponentiation(), $target::identity());

            assert_eq!(
                multi_miller_loop(&[(&$g1affine::identity(), &$g2affine::generator().into())]),
                $base::one()
            );
            assert_eq!(
                multi_miller_loop(&[(&$g1affine::generator(), &$g2affine::identity().into())]),
                $base::one()
            );
            assert_ne!(
                multi_miller_loop(&[
                    (&$g1affine::generator(), &$g2affine::generator().into()),
                    (&-$g1affine::generator(), &$g2affine::generator().into())
                ]),
                $base::one()
            );
            assert_eq!(
                multi_miller_loop(&[
                    (&$g1affine::generator(), &$g2affine::generator().into()),
                    (&-$g1affine::generator(), &$g2affine::generator().into())
                ])
                .final_exponentiation(),
                $target::identity()
            );
        }

        #[test]
        fn test_unitary() {
            let g = $g1affine::generator();
            let h = $g2affine::generator();
            let p = -$engine::pairing(&g, &h);
            let q = $engine::pairing(&g, &-h);
            let r = $engine::pairing(&-g, &h);
            assert_eq!(p, q);
            assert_eq!(q, r);
        }

        #[test]
        fn test_bilinearity() {
            use ::ff::Field;

            let a = $scalar::random(OsRng);
            let b = $scalar::random(OsRng);

            let g1 = $g1::generator();
            let g2 = $g2::generator();

            let a1 = g1 * a;
            let b2 = g2 * b;
            let u0 = $engine::pairing(&a1.into(), &b2.into());

            let b1 = g1 * b;
            let a2 = g2 * a;
            let u1 = $engine::pairing(&b1.into(), &a2.into());
            assert_eq!(u0, u1);

            let u1 = $engine::pairing(&g1.into(), &g2.into()) * (a * b);
            assert_eq!(u0, u1);
        }

        #[test]
        pub fn engine_tests() {
            for _ in 0..10 {
                let a: $g1affine = $g1::random(OsRng).into();
                let b: $g2affine = $g2::random(OsRng).into();

                assert!(a.pairing_with(&b) == b.pairing_with(&a));
            }

            for _ in 0..1000 {
                let z1 = $g1affine::identity();
                let z2 = $g2affine::identity();

                let a = $g1::random(OsRng).into();
                let b = $g2::random(OsRng).into();
                let c = $g1::random(OsRng).into();
                let d = $g2::random(OsRng).into();

                assert_eq!(
                    $base::one(),
                    multi_miller_loop(&[(&z1, &b)]).final_exponentiation().0,
                );

                assert_eq!(
                    $base::one(),
                    multi_miller_loop(&[(&a, &z2)]).final_exponentiation().0,
                );

                assert_eq!(
                    multi_miller_loop(&[(&z1, &b), (&c, &d)]).final_exponentiation(),
                    multi_miller_loop(&[(&a, &z2), (&c, &d)]).final_exponentiation(),
                );

                assert_eq!(
                    multi_miller_loop(&[(&a, &b), (&z1, &d)]).final_exponentiation(),
                    multi_miller_loop(&[(&a, &b), (&c, &z2)]).final_exponentiation(),
                );
            }
        }

        #[test]
        fn test_pairing_check() {
            let n = 10;
            let g1 = $g1::generator().to_affine();
            let g2 = $g2::generator().to_affine();
            let scalars = (0..n)
                .map(|_| ($scalar::random(OsRng), $scalar::random(OsRng)))
                .collect::<Vec<_>>();
            let terms = scalars
                .iter()
                .map(|(a, b)| ((g1 * a).to_affine(), (g2 * b).to_affine()))
                .collect::<Vec<_>>();
            let mut terms = terms.iter().map(|(a, b)| (a, b)).collect::<Vec<_>>();
            let gt = $engine::pairing(&g1, &g2);
            let u0 = scalars.iter().fold($target::identity(), |acc, (a, b)| acc + gt * a * b);
            let u1 = multi_miller_loop(&terms[..]).final_exponentiation();
            assert_eq!(u1, u0);

            let last = scalars.iter().fold($scalar::ZERO, |acc, (u0, u1)| acc + u0 * u1);
            let negg1 = -g1;
            let accg2 = (g2 * last).into();
            terms.push((&negg1, &accg2));
            let must_be_one = multi_miller_loop(&terms[..]).final_exponentiation();
            assert_eq!(must_be_one, $target::identity());
        }
    };
}