Skip to main content

ark_groth16/
verifier.rs

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
12/// Prepare the verifying key `vk` for use in proof verification.
13pub 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    /// Prepare proof inputs for use with [`verify_proof_with_prepared_inputs`],
24    /// wrt the prepared verification key `pvk` and instance public inputs.
25    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    /// Verify a Groth16 proof `proof` against the prepared verification key
38    /// `pvk` and prepared public inputs. This should be preferred over
39    /// [`verify_proof`] if the instance's public inputs are
40    /// known in advance.
41    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    /// Verify a Groth16 proof `proof` against the prepared verification key
65    /// `pvk`, with respect to the instance `public_inputs`.
66    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}