use halo2curves::bn256::{Bn256, Fr, G1Affine, G2Affine, Gt, G1};
use halo2curves::pairing::Engine;
use crate::traits::PairingEngine;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Bn254;
impl PairingEngine for Bn254 {
type Fr = Fr;
type G1Affine = G1Affine;
type G1 = G1;
type G2Affine = G2Affine;
type Gt = Gt;
fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
Bn256::pairing(p, q)
}
fn multi_pairing<'a>(
pairs: impl IntoIterator<Item = (&'a Self::G1Affine, &'a Self::G2Affine)>,
) -> Self::Gt {
let pairs: Vec<_> = pairs.into_iter().collect();
if pairs.is_empty() {
return Gt::identity();
}
let mut result = Gt::identity();
for (p, q) in pairs {
result += Bn256::pairing(p, q);
}
result
}
}
#[cfg(test)]
mod tests {
use super::*;
use ff::Field;
use group::{Curve, Group};
use rand::rngs::OsRng;
#[test]
fn bn254_pairing_is_bilinear() {
let a = Fr::random(OsRng);
let b = Fr::random(OsRng);
let p = G1::random(OsRng);
let q = halo2curves::bn256::G2::random(OsRng);
let ap = (p * a).to_affine();
let bq = (q * b).to_affine();
let p_affine = p.to_affine();
let q_affine = q.to_affine();
let lhs = Bn254::pairing(&ap, &bq);
let rhs = Bn254::pairing(&p_affine, &q_affine) * (a * b);
assert_eq!(lhs, rhs);
}
#[test]
fn bn254_pairing_identity() {
let p = G1::identity().to_affine();
let q = halo2curves::bn256::G2::random(OsRng).to_affine();
let result = Bn254::pairing(&p, &q);
assert_eq!(result, Gt::identity());
}
#[test]
fn bn254_multi_pairing_empty() {
let pairs: Vec<(&G1Affine, &G2Affine)> = vec![];
let result = Bn254::multi_pairing(pairs);
assert_eq!(result, Gt::identity());
}
#[test]
fn bn254_multi_pairing_single() {
let p = G1::random(OsRng).to_affine();
let q = halo2curves::bn256::G2::random(OsRng).to_affine();
let single = Bn254::pairing(&p, &q);
let multi = Bn254::multi_pairing([(&p, &q)]);
assert_eq!(single, multi);
}
}