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	"github.com/succinctlabs/gnark-plonky2-verifier/variables"
 12)
 13
 14type VerifierChip struct {
 15	api               frontend.API             `gnark:"-"`
 16	glChip            *gl.Chip                 `gnark:"-"`
 17	poseidonGlChip    *poseidon.GoldilocksChip `gnark:"-"`
 18	poseidonBN254Chip *poseidon.BN254Chip      `gnark:"-"`
 19	plonkChip         *plonk.PlonkChip         `gnark:"-"`
 20	friChip           *fri.Chip                `gnark:"-"`
 21	commonData        types.CommonCircuitData  `gnark:"-"`
 22}
 23
 24func NewVerifierChip(api frontend.API, commonCircuitData types.CommonCircuitData) *VerifierChip {
 25	glChip := gl.New(api)
 26	friChip := fri.NewChip(api, &commonCircuitData, &commonCircuitData.FriParams)
 27	plonkChip := plonk.NewPlonkChip(api, commonCircuitData)
 28	poseidonGlChip := poseidon.NewGoldilocksChip(api)
 29	poseidonBN254Chip := poseidon.NewBN254Chip(api)
 30	return &VerifierChip{
 31		api:               api,
 32		glChip:            glChip,
 33		poseidonGlChip:    poseidonGlChip,
 34		poseidonBN254Chip: poseidonBN254Chip,
 35		plonkChip:         plonkChip,
 36		friChip:           friChip,
 37		commonData:        commonCircuitData,
 38	}
 39}
 40
 41func (c *VerifierChip) GetPublicInputsHash(publicInputs []gl.Variable) poseidon.GoldilocksHashOut {
 42	return c.poseidonGlChip.HashNoPad(publicInputs)
 43}
 44
 45func (c *VerifierChip) GetChallenges(
 46	proof variables.Proof,
 47	publicInputsHash poseidon.GoldilocksHashOut,
 48	verifierData variables.VerifierOnlyCircuitData,
 49) variables.ProofChallenges {
 50	config := c.commonData.Config
 51	numChallenges := config.NumChallenges
 52	challenger := challenger.NewChip(c.api)
 53
 54	var circuitDigest = verifierData.CircuitDigest
 55
 56	challenger.ObserveBN254Hash(circuitDigest)
 57	challenger.ObserveHash(publicInputsHash)
 58	challenger.ObserveCap(proof.WiresCap)
 59	plonkBetas := challenger.GetNChallenges(numChallenges)
 60	plonkGammas := challenger.GetNChallenges(numChallenges)
 61
 62	challenger.ObserveCap(proof.PlonkZsPartialProductsCap)
 63	plonkAlphas := challenger.GetNChallenges(numChallenges)
 64
 65	challenger.ObserveCap(proof.QuotientPolysCap)
 66	plonkZeta := challenger.GetExtensionChallenge()
 67
 68	challenger.ObserveOpenings(c.friChip.ToOpenings(proof.Openings))
 69
 70	return variables.ProofChallenges{
 71		PlonkBetas:  plonkBetas,
 72		PlonkGammas: plonkGammas,
 73		PlonkAlphas: plonkAlphas,
 74		PlonkZeta:   plonkZeta,
 75		FriChallenges: challenger.GetFriChallenges(
 76			proof.OpeningProof.CommitPhaseMerkleCaps,
 77			proof.OpeningProof.FinalPoly,
 78			proof.OpeningProof.PowWitness,
 79			c.commonData.DegreeBits,
 80			config.FriConfig,
 81		),
 82	}
 83}
 84
 85func (c *VerifierChip) rangeCheckProof(proof variables.Proof) {
 86	// Need to verify the plonky2 proof's openings, openings proof (other than the sibling elements), fri's final poly, pow witness.
 87
 88	// 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,
 89	// we will assume that caller is doing that check.
 90
 91	// Range check the proof's openings.
 92	for _, constant := range proof.Openings.Constants {
 93		c.glChip.RangeCheckQE(constant)
 94	}
 95
 96	for _, plonkSigma := range proof.Openings.PlonkSigmas {
 97		c.glChip.RangeCheckQE(plonkSigma)
 98	}
 99
100	for _, wire := range proof.Openings.Wires {
101		c.glChip.RangeCheckQE(wire)
102	}
103
104	for _, plonkZ := range proof.Openings.PlonkZs {
105		c.glChip.RangeCheckQE(plonkZ)
106	}
107
108	for _, plonkZNext := range proof.Openings.PlonkZsNext {
109		c.glChip.RangeCheckQE(plonkZNext)
110	}
111
112	for _, partialProduct := range proof.Openings.PartialProducts {
113		c.glChip.RangeCheckQE(partialProduct)
114	}
115
116	for _, quotientPoly := range proof.Openings.QuotientPolys {
117		c.glChip.RangeCheckQE(quotientPoly)
118	}
119
120	// Range check the openings proof.
121	for _, queryRound := range proof.OpeningProof.QueryRoundProofs {
122		for _, initialTreesElement := range queryRound.InitialTreesProof.EvalsProofs[0].Elements {
123			c.glChip.RangeCheck(initialTreesElement)
124		}
125
126		for _, queryStep := range queryRound.Steps {
127			for _, eval := range queryStep.Evals {
128				c.glChip.RangeCheckQE(eval)
129			}
130		}
131	}
132
133	// Range check the fri's final poly.
134	for _, coeff := range proof.OpeningProof.FinalPoly.Coeffs {
135		c.glChip.RangeCheckQE(coeff)
136	}
137
138	// Range check the pow witness.
139	c.glChip.RangeCheck(proof.OpeningProof.PowWitness)
140}
141
142func (c *VerifierChip) Verify(
143	proof variables.Proof,
144	publicInputs []gl.Variable,
145	verifierData variables.VerifierOnlyCircuitData,
146) {
147	c.rangeCheckProof(proof)
148
149	// Generate the parts of the witness that is for the plonky2 proof input
150	publicInputsHash := c.GetPublicInputsHash(publicInputs)
151	proofChallenges := c.GetChallenges(proof, publicInputsHash, verifierData)
152
153	c.plonkChip.Verify(proofChallenges, proof.Openings, publicInputsHash)
154
155	initialMerkleCaps := []variables.FriMerkleCap{
156		verifierData.ConstantSigmasCap,
157		proof.WiresCap,
158		proof.PlonkZsPartialProductsCap,
159		proof.QuotientPolysCap,
160	}
161
162	c.friChip.VerifyFriProof(
163		c.friChip.GetInstance(proofChallenges.PlonkZeta),
164		c.friChip.ToOpenings(proof.Openings),
165		&proofChallenges.FriChallenges,
166		initialMerkleCaps,
167		&proof.OpeningProof,
168	)
169}