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/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}