use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::PrimeField;
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
use ark_relations::r1cs::{Result as R1CSResult, SynthesisError};
use core::ops::{AddAssign, Neg};
pub fn prepare_verifying_key<E: PairingEngine>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
PreparedVerifyingKey {
vk: vk.clone(),
alpha_g1_beta_g2: E::pairing(vk.alpha_g1, vk.beta_g2),
gamma_g2_neg_pc: vk.gamma_g2.neg().into(),
delta_g2_neg_pc: vk.delta_g2.neg().into(),
}
}
pub fn prepare_inputs<E: PairingEngine>(
pvk: &PreparedVerifyingKey<E>,
public_inputs: &[E::Fr],
) -> R1CSResult<E::G1Projective> {
if (public_inputs.len() + 1) != pvk.vk.gamma_abc_g1.len() {
return Err(SynthesisError::MalformedVerifyingKey);
}
let mut g_ic = pvk.vk.gamma_abc_g1[0].into_projective();
for (i, b) in public_inputs.iter().zip(pvk.vk.gamma_abc_g1.iter().skip(1)) {
g_ic.add_assign(&b.mul(i.into_repr()));
}
Ok(g_ic)
}
pub fn verify_proof_with_prepared_inputs<E: PairingEngine>(
pvk: &PreparedVerifyingKey<E>,
proof: &Proof<E>,
prepared_inputs: &E::G1Projective,
) -> R1CSResult<bool> {
let qap = E::miller_loop(
[
(proof.a.into(), proof.b.into()),
(
prepared_inputs.into_affine().into(),
pvk.gamma_g2_neg_pc.clone(),
),
(proof.c.into(), pvk.delta_g2_neg_pc.clone()),
]
.iter(),
);
let test = E::final_exponentiation(&qap).ok_or(SynthesisError::UnexpectedIdentity)?;
Ok(test == pvk.alpha_g1_beta_g2)
}
pub fn verify_proof<E: PairingEngine>(
pvk: &PreparedVerifyingKey<E>,
proof: &Proof<E>,
public_inputs: &[E::Fr],
) -> R1CSResult<bool> {
let prepared_inputs = prepare_inputs(pvk, public_inputs)?;
verify_proof_with_prepared_inputs(pvk, proof, &prepared_inputs)
}