-
Notifications
You must be signed in to change notification settings - Fork 91
/
verifier.py
105 lines (84 loc) · 3.93 KB
/
verifier.py
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
101
102
103
104
105
import py_ecc.bn128 as b
from utils import *
from dataclasses import dataclass
from curve import *
from transcript import Transcript
from poly import Polynomial, Basis
@dataclass
class VerificationKey:
"""Verification key"""
# we set this to some power of 2 (so that we can FFT over it), that is at least the number of constraints we have (so we can Lagrange interpolate them)
group_order: int
# [q_M(x)]₁ (commitment to multiplication selector polynomial)
Qm: G1Point
# [q_L(x)]₁ (commitment to left selector polynomial)
Ql: G1Point
# [q_R(x)]₁ (commitment to right selector polynomial)
Qr: G1Point
# [q_O(x)]₁ (commitment to output selector polynomial)
Qo: G1Point
# [q_C(x)]₁ (commitment to constants selector polynomial)
Qc: G1Point
# [S_σ1(x)]₁ (commitment to the first permutation polynomial S_σ1(X))
S1: G1Point
# [S_σ2(x)]₁ (commitment to the second permutation polynomial S_σ2(X))
S2: G1Point
# [S_σ3(x)]₁ (commitment to the third permutation polynomial S_σ3(X))
S3: G1Point
# [x]₂ = xH, where H is a generator of G_2
X_2: G2Point
# nth root of unity (i.e. ω^1), where n is the program's group order.
w: Scalar
# More optimized version that tries hard to minimize pairings and
# elliptic curve multiplications, but at the cost of being harder
# to understand and mixing together a lot of the computations to
# efficiently batch them
def verify_proof(self, group_order: int, pf, public=[]) -> bool:
# 4. Compute challenges
# 5. Compute zero polynomial evaluation Z_H(ζ) = ζ^n - 1
# 6. Compute Lagrange polynomial evaluation L_0(ζ)
# 7. Compute public input polynomial evaluation PI(ζ).
# Compute the constant term of R. This is not literally the degree-0
# term of the R polynomial; rather, it's the portion of R that can
# be computed directly, without resorting to elliptic cutve commitments
# Compute D = (R - r0) + u * Z, and E and F
# Run one pairing check to verify the last two checks.
# What's going on here is a clever re-arrangement of terms to check
# the same equations that are being checked in the basic version,
# but in a way that minimizes the number of EC muls and even
# compressed the two pairings into one. The 2 pairings -> 1 pairing
# trick is basically to replace checking
#
# Y1 = A * (X - a) and Y2 = B * (X - b)
#
# with
#
# Y1 + A * a = A * X
# Y2 + B * b = B * X
#
# so at this point we can take a random linear combination of the two
# checks, and verify it with only one pairing.
return False
# Basic, easier-to-understand version of what's going on
def verify_proof_unoptimized(self, group_order: int, pf, public=[]) -> bool:
# 4. Compute challenges
# 5. Compute zero polynomial evaluation Z_H(ζ) = ζ^n - 1
# 6. Compute Lagrange polynomial evaluation L_0(ζ)
# 7. Compute public input polynomial evaluation PI(ζ).
# Recover the commitment to the linearization polynomial R,
# exactly the same as what was created by the prover
# Verify that R(z) = 0 and the prover-provided evaluations
# A(z), B(z), C(z), S1(z), S2(z) are all correct
# Verify that the provided value of Z(zeta*w) is correct
return False
# Compute challenges (should be same as those computed by prover)
def compute_challenges(
self, proof
) -> tuple[Scalar, Scalar, Scalar, Scalar, Scalar, Scalar]:
transcript = Transcript(b"plonk")
beta, gamma = transcript.round_1(proof.msg_1)
alpha, _fft_cofactor = transcript.round_2(proof.msg_2)
zeta = transcript.round_3(proof.msg_3)
v = transcript.round_4(proof.msg_4)
u = transcript.round_5(proof.msg_5)
return beta, gamma, alpha, zeta, v, u