1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use crate::snark::gm17::{PreparedVerifyingKey, Proof, VerifyingKey};
use snarkvm_curves::traits::{AffineCurve, PairingCurve, PairingEngine, ProjectiveCurve};
use snarkvm_fields::{One, PrimeField};
use snarkvm_r1cs::errors::SynthesisError;
use std::{
iter,
ops::{AddAssign, MulAssign, Neg},
};
pub fn prepare_verifying_key<E: PairingEngine>(vk: VerifyingKey<E>) -> PreparedVerifyingKey<E> {
let g_alpha = vk.g_alpha_g1;
let h_beta = vk.h_beta_g2;
let g_alpha_h_beta_ml = E::miller_loop(iter::once((&g_alpha.prepare(), &h_beta.prepare())));
let g_gamma_pc = vk.g_gamma_g1.prepare();
let h_gamma_pc = vk.h_gamma_g2.prepare();
let h_pc = vk.h_g2.prepare();
PreparedVerifyingKey {
vk,
g_alpha,
h_beta,
g_alpha_h_beta_ml,
g_gamma_pc,
h_gamma_pc,
h_pc,
}
}
pub fn verify_proof<E: PairingEngine>(
pvk: &PreparedVerifyingKey<E>,
proof: &Proof<E>,
public_inputs: &[E::Fr],
) -> Result<bool, SynthesisError> {
if (public_inputs.len() + 1) != pvk.query().len() {
return Err(SynthesisError::MalformedVerifyingKey);
}
let mut g_psi = pvk.query()[0].into_projective();
for (i, b) in public_inputs.iter().zip(pvk.query().iter().skip(1)) {
g_psi.add_assign(&b.mul(i.into_repr()));
}
let mut test1_a_g_alpha = proof.a.into_projective();
test1_a_g_alpha.add_assign(&pvk.g_alpha.into_projective());
let test1_a_g_alpha = test1_a_g_alpha.into_affine();
let mut test1_b_h_beta = proof.b.into_projective();
test1_b_h_beta.add_assign(&pvk.h_beta.into_projective());
let test1_b_h_beta = test1_b_h_beta.into_affine();
let test1_r1 = pvk.g_alpha_h_beta_ml;
let test1_r2 = E::miller_loop(
[
(&test1_a_g_alpha.neg().prepare(), &test1_b_h_beta.prepare()),
(&g_psi.into_affine().prepare(), &pvk.h_gamma_pc),
(&proof.c.prepare(), &pvk.h_pc),
]
.iter()
.copied(),
);
let mut test1_exp = test1_r2;
test1_exp.mul_assign(&test1_r1);
let test1 = E::final_exponentiation(&test1_exp).unwrap();
let test2_exp = E::miller_loop(
[
(&proof.a.prepare(), &pvk.h_gamma_pc),
(&pvk.g_gamma_pc, &proof.b.neg().prepare()),
]
.iter()
.copied(),
);
let test2 = E::final_exponentiation(&test2_exp).unwrap();
Ok(test1 == E::Fqk::one() && test2 == E::Fqk::one())
}