arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
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	glChip            *gl.GoldilocksApi        `gnark:"-"`
 16	poseidonGlChip    *poseidon.GoldilocksChip `gnark:"-"`
 17	poseidonBN254Chip *poseidon.BN254Chip      `gnark:"-"`
 18	plonkChip         *plonk.PlonkChip         `gnark:"-"`
 19	friChip           *fri.Chip                `gnark:"-"`
 20}
 21
 22func NewVerifierChip(api frontend.API, commonCircuitData types.CommonCircuitData) *VerifierChip {
 23	glChip := gl.NewGoldilocksApi(api)
 24	friChip := fri.NewChip(api, &commonCircuitData.FriParams)
 25	plonkChip := plonk.NewPlonkChip(api, commonCircuitData)
 26	poseidonGlChip := poseidon.NewGoldilocksChip(api)
 27	poseidonBN254Chip := poseidon.NewBN254Chip(api)
 28	return &VerifierChip{
 29		api:               api,
 30		glChip:            glChip,
 31		poseidonGlChip:    poseidonGlChip,
 32		poseidonBN254Chip: poseidonBN254Chip,
 33		plonkChip:         plonkChip,
 34		friChip:           friChip,
 35	}
 36}
 37
 38func (c *VerifierChip) GetPublicInputsHash(publicInputs []gl.Variable) poseidon.GoldilocksHashOut {
 39	return c.poseidonGlChip.HashNoPad(publicInputs)
 40}
 41
 42func (c *VerifierChip) GetChallenges(
 43	proof types.Proof,
 44	publicInputsHash poseidon.GoldilocksHashOut,
 45	commonData types.CommonCircuitData,
 46	verifierData types.VerifierOnlyCircuitData,
 47) types.ProofChallenges {
 48	config := commonData.Config
 49	numChallenges := config.NumChallenges
 50	challenger := challenger.NewChip(c.api)
 51
 52	var circuitDigest = verifierData.CircuitDigest
 53
 54	challenger.ObserveBN254Hash(circuitDigest)
 55	challenger.ObserveHash(publicInputsHash)
 56	challenger.ObserveCap(proof.WiresCap)
 57	plonkBetas := challenger.GetNChallenges(numChallenges)
 58	plonkGammas := challenger.GetNChallenges(numChallenges)
 59
 60	challenger.ObserveCap(proof.PlonkZsPartialProductsCap)
 61	plonkAlphas := challenger.GetNChallenges(numChallenges)
 62
 63	challenger.ObserveCap(proof.QuotientPolysCap)
 64	plonkZeta := challenger.GetExtensionChallenge()
 65
 66	challenger.ObserveOpenings(fri.ToOpenings(proof.Openings))
 67
 68	return types.ProofChallenges{
 69		PlonkBetas:  plonkBetas,
 70		PlonkGammas: plonkGammas,
 71		PlonkAlphas: plonkAlphas,
 72		PlonkZeta:   plonkZeta,
 73		FriChallenges: challenger.GetFriChallenges(
 74			proof.OpeningProof.CommitPhaseMerkleCaps,
 75			proof.OpeningProof.FinalPoly,
 76			proof.OpeningProof.PowWitness,
 77			commonData.DegreeBits,
 78			config.FriConfig,
 79		),
 80	}
 81}
 82
 83/*
 84func (c *VerifierChip) generateProofInput(commonData common.CommonCircuitData) common.ProofWithPublicInputs {
 85	// Generate the parts of the witness that is for the plonky2 proof input
 86
 87	capHeight := commonData.Config.FriConfig.CapHeight
 88
 89	friCommitPhaseMerkleCaps := []common.MerkleCap{}
 90	for i := 0; i < len(commonData.FriParams.ReductionArityBits); i++ {
 91		friCommitPhaseMerkleCaps = append(friCommitPhaseMerkleCaps, common.NewMerkleCap(capHeight))
 92	}
 93
 94	salt := commonData.SaltSize()
 95	numLeavesPerOracle := []uint{
 96		commonData.NumPreprocessedPolys(),
 97		commonData.Config.NumWires + salt,
 98		commonData.NumZsPartialProductsPolys() + salt,
 99		commonData.NumQuotientPolys() + salt,
100	}
101	friQueryRoundProofs := []common.FriQueryRound{}
102	for i := uint64(0); i < commonData.FriParams.Config.NumQueryRounds; i++ {
103		evalProofs := []common.EvalProof{}
104		merkleProofLen := commonData.FriParams.LDEBits() - capHeight
105		for _, numLeaves := range numLeavesPerOracle {
106			leaves := make([]field.F, numLeaves)
107			merkleProof := common.NewMerkleProof(merkleProofLen)
108			evalProofs = append(evalProofs, common.NewEvalProof(leaves, merkleProof))
109		}
110
111		initialTreesProof := common.NewFriInitialTreeProof(evalProofs)
112		steps := []common.FriQueryStep{}
113		for _, arityBit := range commonData.FriParams.ReductionArityBits {
114			if merkleProofLen < arityBit {
115				panic("merkleProofLen < arityBits")
116			}
117
118			steps = append(steps, common.NewFriQueryStep(arityBit, merkleProofLen))
119		}
120
121		friQueryRoundProofs = append(friQueryRoundProofs, common.NewFriQueryRound(steps, initialTreesProof))
122	}
123
124	proofInput := common.ProofWithPublicInputs{
125		Proof: common.Proof{
126			WiresCap:                  common.NewMerkleCap(capHeight),
127			PlonkZsPartialProductsCap: common.NewMerkleCap(capHeight),
128			QuotientPolysCap:          common.NewMerkleCap(capHeight),
129			Openings: common.NewOpeningSet(
130				commonData.Config.NumConstants,
131				commonData.Config.NumRoutedWires,
132				commonData.Config.NumWires,
133				commonData.Config.NumChallenges,
134				commonData.NumPartialProducts,
135				commonData.QuotientDegreeFactor,
136			),
137			OpeningProof: common.FriProof{
138				CommitPhaseMerkleCaps: friCommitPhaseMerkleCaps,
139				QueryRoundProofs:      friQueryRoundProofs,
140				FinalPoly:             common.NewPolynomialCoeffs(commonData.FriParams.FinalPolyLen()),
141			},
142		},
143		PublicInputs: make([]field.F, commonData.NumPublicInputs),
144	}
145
146	return proofInput
147}
148*/
149
150func (c *VerifierChip) rangeCheckProof(proof types.Proof) {
151	// Need to verify the plonky2 proof's openings, openings proof (other than the sibling elements), fri's final poly, pow witness.
152
153	// Note that this is NOT range checking the public inputs (first 32 elements should be no more than 8 bits and the last 4 elements should be no more than 64 bits).  Since this is currently being inputted via the smart contract,
154	// we will assume that caller is doing that check.
155
156	// Range check the proof's openings.
157	for _, constant := range proof.Openings.Constants {
158		c.glChip.RangeCheckQE(constant)
159	}
160
161	for _, plonkSigma := range proof.Openings.PlonkSigmas {
162		c.glChip.RangeCheckQE(plonkSigma)
163	}
164
165	for _, wire := range proof.Openings.Wires {
166		c.glChip.RangeCheckQE(wire)
167	}
168
169	for _, plonkZ := range proof.Openings.PlonkZs {
170		c.glChip.RangeCheckQE(plonkZ)
171	}
172
173	for _, plonkZNext := range proof.Openings.PlonkZsNext {
174		c.glChip.RangeCheckQE(plonkZNext)
175	}
176
177	for _, partialProduct := range proof.Openings.PartialProducts {
178		c.glChip.RangeCheckQE(partialProduct)
179	}
180
181	for _, quotientPoly := range proof.Openings.QuotientPolys {
182		c.glChip.RangeCheckQE(quotientPoly)
183	}
184
185	// Range check the openings proof.
186	for _, queryRound := range proof.OpeningProof.QueryRoundProofs {
187		for _, initialTreesElement := range queryRound.InitialTreesProof.EvalsProofs[0].Elements {
188			c.glChip.RangeCheck(initialTreesElement)
189		}
190
191		for _, queryStep := range queryRound.Steps {
192			for _, eval := range queryStep.Evals {
193				c.glChip.RangeCheckQE(eval)
194			}
195		}
196	}
197
198	// Range check the fri's final poly.
199	for _, coeff := range proof.OpeningProof.FinalPoly.Coeffs {
200		c.glChip.RangeCheckQE(coeff)
201	}
202
203	// Range check the pow witness.
204	c.glChip.RangeCheck(proof.OpeningProof.PowWitness)
205}
206
207func (c *VerifierChip) Verify(
208	proof types.Proof,
209	publicInputs []gl.Variable,
210	verifierData types.VerifierOnlyCircuitData,
211	commonData types.CommonCircuitData,
212) {
213	c.rangeCheckProof(proof)
214
215	// Generate the parts of the witness that is for the plonky2 proof input
216	publicInputsHash := c.GetPublicInputsHash(publicInputs)
217	proofChallenges := c.GetChallenges(proof, publicInputsHash, commonData, verifierData)
218
219	c.plonkChip.Verify(proofChallenges, proof.Openings, publicInputsHash)
220
221	initialMerkleCaps := []types.FriMerkleCap{
222		verifierData.ConstantSigmasCap,
223		proof.WiresCap,
224		proof.PlonkZsPartialProductsCap,
225		proof.QuotientPolysCap,
226	}
227
228	c.friChip.VerifyFriProof(
229		fri.GetInstance(&commonData, c.glChip, proofChallenges.PlonkZeta, commonData.DegreeBits),
230		fri.ToOpenings(proof.Openings),
231		&proofChallenges.FriChallenges,
232		initialMerkleCaps,
233		&proof.OpeningProof,
234	)
235}