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