gnark-plonky2-verifier/verifier/verifier.go
verifier/verifier.goRaw
1package verifier
2
3import (
4 "github.com/consensys/gnark/frontend"
5 "github.com/succinctlabs/gnark-plonky2-verifier/challenger"
6 "github.com/succinctlabs/gnark-plonky2-verifier/fri"
7 gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
8 "github.com/succinctlabs/gnark-plonky2-verifier/plonk"
9 "github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
10 "github.com/succinctlabs/gnark-plonky2-verifier/types"
11)
12
13type VerifierChip struct {
14 api frontend.API `gnark:"-"`
15 poseidonGlChip *poseidon.GoldilocksChip
16 poseidonBN254Chip *poseidon.BN254Chip
17 plonkChip *plonk.PlonkChip
18 friChip *fri.Chip
19}
20
21func NewVerifierChip(api frontend.API, commonCircuitData types.CommonCircuitData) *VerifierChip {
22 friChip := fri.NewChip(api, &commonCircuitData.FriParams)
23 plonkChip := plonk.NewPlonkChip(api, commonCircuitData)
24 poseidonGlChip := poseidon.NewGoldilocksChip(api)
25 poseidonBN254Chip := poseidon.NewBN254Chip(api)
26 return &VerifierChip{
27 api: api,
28 poseidonGlChip: poseidonGlChip,
29 poseidonBN254Chip: poseidonBN254Chip,
30 plonkChip: plonkChip,
31 friChip: friChip,
32 }
33}
34
35func (c *VerifierChip) GetPublicInputsHash(publicInputs []gl.Variable) poseidon.GoldilocksHashOut {
36 return c.poseidonGlChip.HashNoPad(publicInputs)
37}
38
39func (c *VerifierChip) GetChallenges(
40 proof types.Proof,
41 publicInputsHash poseidon.GoldilocksHashOut,
42 commonData types.CommonCircuitData,
43 verifierData types.VerifierOnlyCircuitData,
44) types.ProofChallenges {
45 config := commonData.Config
46 numChallenges := config.NumChallenges
47 challenger := challenger.NewChip(c.api)
48
49 var circuitDigest = verifierData.CircuitDigest
50
51 challenger.ObserveBN254Hash(circuitDigest)
52 challenger.ObserveHash(publicInputsHash)
53 challenger.ObserveCap(proof.WiresCap)
54 plonkBetas := challenger.GetNChallenges(numChallenges)
55 plonkGammas := challenger.GetNChallenges(numChallenges)
56
57 challenger.ObserveCap(proof.PlonkZsPartialProductsCap)
58 plonkAlphas := challenger.GetNChallenges(numChallenges)
59
60 challenger.ObserveCap(proof.QuotientPolysCap)
61 plonkZeta := challenger.GetExtensionChallenge()
62
63 challenger.ObserveOpenings(fri.ToOpenings(proof.Openings))
64
65 return types.ProofChallenges{
66 PlonkBetas: plonkBetas,
67 PlonkGammas: plonkGammas,
68 PlonkAlphas: plonkAlphas,
69 PlonkZeta: plonkZeta,
70 FriChallenges: challenger.GetFriChallenges(
71 proof.OpeningProof.CommitPhaseMerkleCaps,
72 proof.OpeningProof.FinalPoly,
73 proof.OpeningProof.PowWitness,
74 commonData.DegreeBits,
75 config.FriConfig,
76 ),
77 }
78}
79
80/*
81func (c *VerifierChip) generateProofInput(commonData common.CommonCircuitData) common.ProofWithPublicInputs {
82 // Generate the parts of the witness that is for the plonky2 proof input
83
84 capHeight := commonData.Config.FriConfig.CapHeight
85
86 friCommitPhaseMerkleCaps := []common.MerkleCap{}
87 for i := 0; i < len(commonData.FriParams.ReductionArityBits); i++ {
88 friCommitPhaseMerkleCaps = append(friCommitPhaseMerkleCaps, common.NewMerkleCap(capHeight))
89 }
90
91 salt := commonData.SaltSize()
92 numLeavesPerOracle := []uint{
93 commonData.NumPreprocessedPolys(),
94 commonData.Config.NumWires + salt,
95 commonData.NumZsPartialProductsPolys() + salt,
96 commonData.NumQuotientPolys() + salt,
97 }
98 friQueryRoundProofs := []common.FriQueryRound{}
99 for i := uint64(0); i < commonData.FriParams.Config.NumQueryRounds; i++ {
100 evalProofs := []common.EvalProof{}
101 merkleProofLen := commonData.FriParams.LDEBits() - capHeight
102 for _, numLeaves := range numLeavesPerOracle {
103 leaves := make([]field.F, numLeaves)
104 merkleProof := common.NewMerkleProof(merkleProofLen)
105 evalProofs = append(evalProofs, common.NewEvalProof(leaves, merkleProof))
106 }
107
108 initialTreesProof := common.NewFriInitialTreeProof(evalProofs)
109 steps := []common.FriQueryStep{}
110 for _, arityBit := range commonData.FriParams.ReductionArityBits {
111 if merkleProofLen < arityBit {
112 panic("merkleProofLen < arityBits")
113 }
114
115 steps = append(steps, common.NewFriQueryStep(arityBit, merkleProofLen))
116 }
117
118 friQueryRoundProofs = append(friQueryRoundProofs, common.NewFriQueryRound(steps, initialTreesProof))
119 }
120
121 proofInput := common.ProofWithPublicInputs{
122 Proof: common.Proof{
123 WiresCap: common.NewMerkleCap(capHeight),
124 PlonkZsPartialProductsCap: common.NewMerkleCap(capHeight),
125 QuotientPolysCap: common.NewMerkleCap(capHeight),
126 Openings: common.NewOpeningSet(
127 commonData.Config.NumConstants,
128 commonData.Config.NumRoutedWires,
129 commonData.Config.NumWires,
130 commonData.Config.NumChallenges,
131 commonData.NumPartialProducts,
132 commonData.QuotientDegreeFactor,
133 ),
134 OpeningProof: common.FriProof{
135 CommitPhaseMerkleCaps: friCommitPhaseMerkleCaps,
136 QueryRoundProofs: friQueryRoundProofs,
137 FinalPoly: common.NewPolynomialCoeffs(commonData.FriParams.FinalPolyLen()),
138 },
139 },
140 PublicInputs: make([]field.F, commonData.NumPublicInputs),
141 }
142
143 return proofInput
144}
145*/
146
147func (c *VerifierChip) Verify(
148 proof types.Proof,
149 publicInputs []gl.Variable,
150 verifierData types.VerifierOnlyCircuitData,
151 commonData types.CommonCircuitData,
152) {
153 glApi := gl.NewChip(c.api)
154 // TODO: Need to range check all the proof and public input elements to make sure they are within goldilocks field
155
156 // Generate the parts of the witness that is for the plonky2 proof input
157 publicInputsHash := c.GetPublicInputsHash(publicInputs)
158 proofChallenges := c.GetChallenges(proof, publicInputsHash, commonData, verifierData)
159
160 c.plonkChip.Verify(proofChallenges, proof.Openings, publicInputsHash)
161
162 initialMerkleCaps := []types.FriMerkleCap{
163 verifierData.ConstantSigmasCap,
164 proof.WiresCap,
165 proof.PlonkZsPartialProductsCap,
166 proof.QuotientPolysCap,
167 }
168
169 // Seems like there is a bug in the emulated field code.
170 // Add ZERO to all of the fri challenges values to reduce them.
171 proofChallenges.PlonkZeta[0] = glApi.Add(proofChallenges.PlonkZeta[0], gl.Zero())
172 proofChallenges.PlonkZeta[1] = glApi.Add(proofChallenges.PlonkZeta[1], gl.Zero())
173
174 proofChallenges.FriChallenges.FriAlpha[0] = glApi.Add(proofChallenges.FriChallenges.FriAlpha[0], gl.Zero())
175 proofChallenges.FriChallenges.FriAlpha[1] = glApi.Add(proofChallenges.FriChallenges.FriAlpha[1], gl.Zero())
176
177 for i := 0; i < len(proofChallenges.FriChallenges.FriBetas); i++ {
178 proofChallenges.FriChallenges.FriBetas[i][0] = glApi.Add(proofChallenges.FriChallenges.FriBetas[i][0], gl.Zero())
179 proofChallenges.FriChallenges.FriBetas[i][1] = glApi.Add(proofChallenges.FriChallenges.FriBetas[i][1], gl.Zero())
180 }
181
182 proofChallenges.FriChallenges.FriPowResponse = glApi.Add(proofChallenges.FriChallenges.FriPowResponse, gl.Zero())
183
184 for i := 0; i < len(proofChallenges.FriChallenges.FriQueryIndices); i++ {
185 proofChallenges.FriChallenges.FriQueryIndices[i] = glApi.Add(proofChallenges.FriChallenges.FriQueryIndices[i], gl.Zero())
186 }
187
188 c.friChip.VerifyFriProof(
189 fri.GetInstance(&commonData, glApi, proofChallenges.PlonkZeta, commonData.DegreeBits),
190 fri.ToOpenings(proof.Openings),
191 &proofChallenges.FriChallenges,
192 initialMerkleCaps,
193 &proof.OpeningProof,
194 )
195}