use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; use ark_ff::PrimeField; use crate::{r1cs_to_qap::R1CSToQAP, Groth16}; use super::{PreparedVerifyingKey, Proof, VerifyingKey}; use ark_relations::gr1cs::Result as R1CSResult; use core::ops::{AddAssign, Neg}; /// Prepare the verifying key `vk` for use in proof verification. pub fn prepare_verifying_key(vk: &VerifyingKey) -> PreparedVerifyingKey { PreparedVerifyingKey { vk: vk.clone(), alpha_g1_beta_g2: E::pairing(vk.alpha_g1, vk.beta_g2).0, gamma_g2_neg_pc: vk.gamma_g2.into_group().neg().into_affine().into(), delta_g2_neg_pc: vk.delta_g2.into_group().neg().into_affine().into(), } } impl Groth16 { /// Prepare proof inputs for use with [`verify_proof_with_prepared_inputs`], /// wrt the prepared verification key `pvk` and instance public inputs. pub fn prepare_inputs( pvk: &PreparedVerifyingKey, public_inputs: &[E::ScalarField], ) -> R1CSResult { let mut g_ic = pvk.vk.gamma_abc_g1[0].into_group(); for (i, b) in public_inputs.iter().zip(pvk.vk.gamma_abc_g1.iter().skip(1)) { g_ic.add_assign(&b.mul_bigint(i.into_bigint())); } Ok(g_ic) } /// Verify a Groth16 proof `proof` against the prepared verification key /// `pvk` and prepared public inputs. This should be preferred over /// [`verify_proof`] if the instance's public inputs are /// known in advance. pub fn verify_proof_with_prepared_inputs( pvk: &PreparedVerifyingKey, proof: &Proof, prepared_inputs: &E::G1, ) -> R1CSResult { let qap = E::multi_miller_loop( [ >::into(proof.a), prepared_inputs.into_affine().into(), proof.c.into(), ], [ proof.b.into(), pvk.gamma_g2_neg_pc.clone(), pvk.delta_g2_neg_pc.clone(), ], ); let test = E::final_exponentiation(qap).unwrap(); Ok(test.0 == pvk.alpha_g1_beta_g2) } /// Verify a Groth16 proof `proof` against the prepared verification key /// `pvk`, with respect to the instance `public_inputs`. pub fn verify_proof( pvk: &PreparedVerifyingKey, proof: &Proof, public_inputs: &[E::ScalarField], ) -> R1CSResult { let prepared_inputs = Self::prepare_inputs(pvk, public_inputs)?; Self::verify_proof_with_prepared_inputs(pvk, proof, &prepared_inputs) } }