range check inputted plonky2 proof (#29) * gl * stage 1 optimizations * working optimized poseidon * Fix posedion tests * in progress gate type refactor * working gates * working e2e * hm' * hm2 * debug saga continues * more debugging cry * more debug * it finally works * optimizations * more optimizations * new changes * more optimizations * more cleanup * some refactoring * new files * flattening of packages * working commit * more refactor * more flattening * more flattening * more more refactor * more optimizations * more optimizations * more optimizations * plonk benchmark * plonk * fix r1cs * resolve kevin's comments * Update goldilocks/base.go Co-authored-by: Kevin Jue <kjue235@gmail.com> * Update goldilocks/base.go Co-authored-by: Kevin Jue <kjue235@gmail.com> * Update goldilocks/base.go Co-authored-by: Kevin Jue <kjue235@gmail.com> * Update goldilocks/quadratic_extension.go Co-authored-by: Kevin Jue <kjue235@gmail.com> * added range check for the inputted proof * removed the go.mod replace directive * removed some hacky code * removed duplicate import * renamed rangecheckQEVariable to rangecheckQE * resolved conflict --------- Co-authored-by: John Guibas <john@succinct.xyz>
Kevin Jue kjue235@gmail.com
Mon, 24 Jul 2023 16:18:37 -0700
3 files changed,
73 insertions(+),
30 deletions(-)
M
goldilocks/quadratic_extension.go
→
goldilocks/quadratic_extension.go
@@ -232,3 +232,8 @@ ) {
p.AssertIsEqual(a[0], b[0]) p.AssertIsEqual(a[1], b[1]) } + +func (p *Chip) RangeCheckQE(a QuadraticExtensionVariable) { + p.RangeCheck(a[0]) + p.RangeCheck(a[1]) +}
M
verifier/verifier.go
→
verifier/verifier.go
@@ -11,20 +11,23 @@ "github.com/succinctlabs/gnark-plonky2-verifier/types"
) type VerifierChip struct { - api frontend.API `gnark:"-"` - poseidonGlChip *poseidon.GoldilocksChip - poseidonBN254Chip *poseidon.BN254Chip - plonkChip *plonk.PlonkChip - friChip *fri.Chip + api frontend.API `gnark:"-"` + glChip *gl.Chip `gnark:"-"` + poseidonGlChip *poseidon.GoldilocksChip `gnark:"-"` + poseidonBN254Chip *poseidon.BN254Chip `gnark:"-"` + plonkChip *plonk.PlonkChip `gnark:"-"` + friChip *fri.Chip `gnark:"-"` } func NewVerifierChip(api frontend.API, commonCircuitData types.CommonCircuitData) *VerifierChip { + glChip := gl.NewChip(api) friChip := fri.NewChip(api, &commonCircuitData.FriParams) plonkChip := plonk.NewPlonkChip(api, commonCircuitData) poseidonGlChip := poseidon.NewGoldilocksChip(api) poseidonBN254Chip := poseidon.NewBN254Chip(api) return &VerifierChip{ api: api, + glChip: glChip, poseidonGlChip: poseidonGlChip, poseidonBN254Chip: poseidonBN254Chip, plonkChip: plonkChip,@@ -144,14 +147,70 @@ return proofInput
} */ +func (c *VerifierChip) rangeCheckProof(proof types.Proof) { + // Need to verify the plonky2 proof's openings, openings proof (other than the sibling elements), fri's final poly, pow witness. + + // 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, + // we will assume that caller is doing that check. + + // Range check the proof's openings. + for _, constant := range proof.Openings.Constants { + c.glChip.RangeCheckQE(constant) + } + + for _, plonkSigma := range proof.Openings.PlonkSigmas { + c.glChip.RangeCheckQE(plonkSigma) + } + + for _, wire := range proof.Openings.Wires { + c.glChip.RangeCheckQE(wire) + } + + for _, plonkZ := range proof.Openings.PlonkZs { + c.glChip.RangeCheckQE(plonkZ) + } + + for _, plonkZNext := range proof.Openings.PlonkZsNext { + c.glChip.RangeCheckQE(plonkZNext) + } + + for _, partialProduct := range proof.Openings.PartialProducts { + c.glChip.RangeCheckQE(partialProduct) + } + + for _, quotientPoly := range proof.Openings.QuotientPolys { + c.glChip.RangeCheckQE(quotientPoly) + } + + // Range check the openings proof. + for _, queryRound := range proof.OpeningProof.QueryRoundProofs { + for _, initialTreesElement := range queryRound.InitialTreesProof.EvalsProofs[0].Elements { + c.glChip.RangeCheck(initialTreesElement) + } + + for _, queryStep := range queryRound.Steps { + for _, eval := range queryStep.Evals { + c.glChip.RangeCheckQE(eval) + } + } + } + + // Range check the fri's final poly. + for _, coeff := range proof.OpeningProof.FinalPoly.Coeffs { + c.glChip.RangeCheckQE(coeff) + } + + // Range check the pow witness. + c.glChip.RangeCheck(proof.OpeningProof.PowWitness) +} + func (c *VerifierChip) Verify( proof types.Proof, publicInputs []gl.Variable, verifierData types.VerifierOnlyCircuitData, commonData types.CommonCircuitData, ) { - glApi := gl.NewChip(c.api) - // TODO: Need to range check all the proof and public input elements to make sure they are within goldilocks field + c.rangeCheckProof(proof) // Generate the parts of the witness that is for the plonky2 proof input publicInputsHash := c.GetPublicInputsHash(publicInputs)@@ -166,27 +225,8 @@ proof.PlonkZsPartialProductsCap,
proof.QuotientPolysCap, } - // Seems like there is a bug in the emulated field code. - // Add ZERO to all of the fri challenges values to reduce them. - proofChallenges.PlonkZeta[0] = glApi.Add(proofChallenges.PlonkZeta[0], gl.Zero()) - proofChallenges.PlonkZeta[1] = glApi.Add(proofChallenges.PlonkZeta[1], gl.Zero()) - - proofChallenges.FriChallenges.FriAlpha[0] = glApi.Add(proofChallenges.FriChallenges.FriAlpha[0], gl.Zero()) - proofChallenges.FriChallenges.FriAlpha[1] = glApi.Add(proofChallenges.FriChallenges.FriAlpha[1], gl.Zero()) - - for i := 0; i < len(proofChallenges.FriChallenges.FriBetas); i++ { - proofChallenges.FriChallenges.FriBetas[i][0] = glApi.Add(proofChallenges.FriChallenges.FriBetas[i][0], gl.Zero()) - proofChallenges.FriChallenges.FriBetas[i][1] = glApi.Add(proofChallenges.FriChallenges.FriBetas[i][1], gl.Zero()) - } - - proofChallenges.FriChallenges.FriPowResponse = glApi.Add(proofChallenges.FriChallenges.FriPowResponse, gl.Zero()) - - for i := 0; i < len(proofChallenges.FriChallenges.FriQueryIndices); i++ { - proofChallenges.FriChallenges.FriQueryIndices[i] = glApi.Add(proofChallenges.FriChallenges.FriQueryIndices[i], gl.Zero()) - } - c.friChip.VerifyFriProof( - fri.GetInstance(&commonData, glApi, proofChallenges.PlonkZeta, commonData.DegreeBits), + fri.GetInstance(&commonData, c.glChip, proofChallenges.PlonkZeta, commonData.DegreeBits), fri.ToOpenings(proof.Openings), &proofChallenges.FriChallenges, initialMerkleCaps,