use std::ops::Mul;
use snarkvm_curves::{
bls12_377::{Bls12_377, Fq, Fr, G1Projective, G2Projective},
traits::PairingEngine,
};
use snarkvm_fields::{Field, PrimeField};
use snarkvm_r1cs::{ConstraintSystem, TestConstraintSystem};
use snarkvm_utilities::bititerator::BitIteratorBE;
use crate::{
bits::Boolean,
curves::{
bls12_377::{G1Gadget, G1PreparedGadget, G2Gadget, G2PreparedGadget},
templates::bls12::Bls12PairingGadget,
},
traits::{alloc::AllocGadget, curves::PairingGadget, eq::EqGadget, fields::FieldGadget},
};
#[test]
fn bls12_377_gadget_bilinearity_test() {
let mut cs = TestConstraintSystem::<Fq>::new();
let a: G1Projective = rand::random();
let b: G2Projective = rand::random();
let s: Fr = rand::random();
let sa = a.mul(s);
let sb = b.mul(s);
let a_g = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let b_g = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let sa_g = G1Gadget::alloc(&mut cs.ns(|| "sa"), || Ok(sa)).unwrap();
let sb_g = G2Gadget::alloc(&mut cs.ns(|| "sb"), || Ok(sb)).unwrap();
let a_prep_g = G1PreparedGadget::from_affine(&mut cs.ns(|| "a_prep"), a_g).unwrap();
let b_prep_g = G2PreparedGadget::from_affine(&mut cs.ns(|| "b_prep"), b_g).unwrap();
let sa_prep_g = G1PreparedGadget::from_affine(&mut cs.ns(|| "sa_prep"), sa_g).unwrap();
let sb_prep_g = G2PreparedGadget::from_affine(&mut cs.ns(|| "sb_prep"), sb_g).unwrap();
let (ans1_g, ans1_n) = {
let ans_g = Bls12PairingGadget::pairing(cs.ns(|| "pair(sa, b)"), sa_prep_g, b_prep_g.clone()).unwrap();
let ans_n = Bls12_377::pairing(sa, b);
(ans_g, ans_n)
};
let (ans2_g, ans2_n) = {
let ans_g = Bls12PairingGadget::pairing(cs.ns(|| "pair(a, sb)"), a_prep_g.clone(), sb_prep_g).unwrap();
let ans_n = Bls12_377::pairing(a, sb);
(ans_g, ans_n)
};
let (ans3_g, ans3_n) = {
let s_iter = BitIteratorBE::new(s.to_repr())
.map(Boolean::constant)
.collect::<Vec<_>>();
let mut ans_g = Bls12PairingGadget::pairing(cs.ns(|| "pair(a, b)"), a_prep_g, b_prep_g).unwrap();
let mut ans_n = Bls12_377::pairing(a, b);
ans_n = ans_n.pow(s.to_repr());
ans_g = ans_g.pow(cs.ns(|| "pow"), &s_iter).unwrap();
(ans_g, ans_n)
};
assert_eq!(ans1_n, ans2_n, "Failed ans1_native == ans2_native");
assert_eq!(ans2_n, ans3_n, "Failed ans2_native == ans3_native");
assert_eq!(ans1_g.get_value(), ans3_g.get_value(), "Failed ans1 == ans3");
assert_eq!(ans1_g.get_value(), ans2_g.get_value(), "Failed ans1 == ans2");
assert_eq!(ans2_g.get_value(), ans3_g.get_value(), "Failed ans2 == ans3");
ans1_g.enforce_equal(&mut cs.ns(|| "ans1 == ans2?"), &ans2_g).unwrap();
ans2_g.enforce_equal(&mut cs.ns(|| "ans2 == ans3?"), &ans3_g).unwrap();
assert_eq!(ans1_g.get_value().unwrap(), ans1_n, "Failed native test 1");
assert_eq!(ans2_g.get_value().unwrap(), ans2_n, "Failed native test 2");
assert_eq!(ans3_g.get_value().unwrap(), ans3_n, "Failed native test 3");
if !cs.is_satisfied() {
println!("Unsatisfied: {:?}", cs.which_is_unsatisfied());
}
assert!(cs.is_satisfied(), "cs is not satisfied");
}