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