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 frontend.API `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(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
86func (c *VerifierChip) Verify(proofWithPis common.ProofWithPublicInputs, verifierData common.VerifierOnlyCircuitData, commonData common.CommonCircuitData) {
87 // TODO: Verify shape of the proof?
88
89 publicInputsHash := c.GetPublicInputsHash(proofWithPis.PublicInputs)
90 proofChallenges := c.GetChallenges(proofWithPis, publicInputsHash, commonData, verifierData)
91
92 c.plonkChip.Verify(proofChallenges, proofWithPis.Proof.Openings, publicInputsHash)
93
94 initialMerkleCaps := []common.MerkleCap{
95 verifierData.ConstantSigmasCap,
96 proofWithPis.Proof.WiresCap,
97 proofWithPis.Proof.PlonkZsPartialProductsCap,
98 proofWithPis.Proof.QuotientPolysCap,
99 }
100
101 // Seems like there is a bug in the emulated field code.
102 // Add ZERO to all of the fri challenges values to reduce them.
103 proofChallenges.PlonkZeta[0] = c.fieldAPI.Add(proofChallenges.PlonkZeta[0], field.ZERO_F).(field.F)
104 proofChallenges.PlonkZeta[1] = c.fieldAPI.Add(proofChallenges.PlonkZeta[1], field.ZERO_F).(field.F)
105
106 proofChallenges.FriChallenges.FriAlpha[0] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriAlpha[0], field.ZERO_F).(field.F)
107 proofChallenges.FriChallenges.FriAlpha[1] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriAlpha[1], field.ZERO_F).(field.F)
108
109 for i := 0; i < len(proofChallenges.FriChallenges.FriBetas); i++ {
110 proofChallenges.FriChallenges.FriBetas[i][0] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriBetas[i][0], field.ZERO_F).(field.F)
111 proofChallenges.FriChallenges.FriBetas[i][1] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriBetas[i][1], field.ZERO_F).(field.F)
112 }
113
114 proofChallenges.FriChallenges.FriPowResponse = c.fieldAPI.Add(proofChallenges.FriChallenges.FriPowResponse, field.ZERO_F).(field.F)
115
116 for i := 0; i < len(proofChallenges.FriChallenges.FriQueryIndices); i++ {
117 proofChallenges.FriChallenges.FriQueryIndices[i] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriQueryIndices[i], field.ZERO_F).(field.F)
118 }
119
120 c.friChip.VerifyFriProof(
121 fri.GetFriInstance(&commonData, c.qeAPI, proofChallenges.PlonkZeta, commonData.DegreeBits),
122 fri.ToFriOpenings(proofWithPis.Proof.Openings),
123 &proofChallenges.FriChallenges,
124 initialMerkleCaps,
125 &proofWithPis.Proof.OpeningProof,
126 )
127}