use group::{prime::PrimeCurveAffine, Curve};
use pairing::{MillerLoopResult, MultiMillerLoop};
use std::ops::{AddAssign, Neg};
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
use crate::VerificationError;
pub mod batch;
pub fn prepare_verifying_key<E: MultiMillerLoop>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
let gamma = vk.gamma_g2.neg();
let delta = vk.delta_g2.neg();
PreparedVerifyingKey {
alpha_g1_beta_g2: E::pairing(&vk.alpha_g1, &vk.beta_g2),
neg_gamma_g2: gamma.into(),
neg_delta_g2: delta.into(),
ic: vk.ic.clone(),
}
}
pub fn verify_proof<'a, E: MultiMillerLoop>(
pvk: &'a PreparedVerifyingKey<E>,
proof: &Proof<E>,
public_inputs: &[E::Fr],
) -> Result<(), VerificationError> {
if (public_inputs.len() + 1) != pvk.ic.len() {
return Err(VerificationError::InvalidVerifyingKey);
}
let mut acc = pvk.ic[0].to_curve();
for (i, b) in public_inputs.iter().zip(pvk.ic.iter().skip(1)) {
AddAssign::<&E::G1>::add_assign(&mut acc, &(*b * i));
}
if pvk.alpha_g1_beta_g2
== E::multi_miller_loop(&[
(&proof.a, &proof.b.into()),
(&acc.to_affine(), &pvk.neg_gamma_g2),
(&proof.c, &pvk.neg_delta_g2),
])
.final_exponentiation()
{
Ok(())
} else {
Err(VerificationError::InvalidProof)
}
}