1use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup};
2use ark_ff::PrimeField;
3
4use crate::{r1cs_to_qap::R1CSToQAP, Groth16};
5
6use super::{PreparedVerifyingKey, Proof, VerifyingKey};
7
8use ark_relations::gr1cs::Result as R1CSResult;
9
10use core::ops::{AddAssign, Neg};
11
12pub fn prepare_verifying_key<E: Pairing>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
14 PreparedVerifyingKey {
15 vk: vk.clone(),
16 alpha_g1_beta_g2: E::pairing(vk.alpha_g1, vk.beta_g2).0,
17 gamma_g2_neg_pc: vk.gamma_g2.into_group().neg().into_affine().into(),
18 delta_g2_neg_pc: vk.delta_g2.into_group().neg().into_affine().into(),
19 }
20}
21
22impl<E: Pairing, QAP: R1CSToQAP> Groth16<E, QAP> {
23 pub fn prepare_inputs(
26 pvk: &PreparedVerifyingKey<E>,
27 public_inputs: &[E::ScalarField],
28 ) -> R1CSResult<E::G1> {
29 let mut g_ic = pvk.vk.gamma_abc_g1[0].into_group();
30 for (i, b) in public_inputs.iter().zip(pvk.vk.gamma_abc_g1.iter().skip(1)) {
31 g_ic.add_assign(&b.mul_bigint(i.into_bigint()));
32 }
33
34 Ok(g_ic)
35 }
36
37 pub fn verify_proof_with_prepared_inputs(
42 pvk: &PreparedVerifyingKey<E>,
43 proof: &Proof<E>,
44 prepared_inputs: &E::G1,
45 ) -> R1CSResult<bool> {
46 let qap = E::multi_miller_loop(
47 [
48 <E::G1Affine as Into<E::G1Prepared>>::into(proof.a),
49 prepared_inputs.into_affine().into(),
50 proof.c.into(),
51 ],
52 [
53 proof.b.into(),
54 pvk.gamma_g2_neg_pc.clone(),
55 pvk.delta_g2_neg_pc.clone(),
56 ],
57 );
58
59 let test = E::final_exponentiation(qap).unwrap();
60
61 Ok(test.0 == pvk.alpha_g1_beta_g2)
62 }
63
64 pub fn verify_proof(
67 pvk: &PreparedVerifyingKey<E>,
68 proof: &Proof<E>,
69 public_inputs: &[E::ScalarField],
70 ) -> R1CSResult<bool> {
71 let prepared_inputs = Self::prepare_inputs(pvk, public_inputs)?;
72 Self::verify_proof_with_prepared_inputs(pvk, proof, &prepared_inputs)
73 }
74}