diff --git a/go.mod b/go.mod index 215735e..82e406c 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,4 @@ require ( golang.org/x/sys v0.5.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect -) - -// replace github.com/consensys/gnark => /Users/kevin/succinctlabs/gnark +) \ No newline at end of file diff --git a/goldilocks/quadratic_extension.go b/goldilocks/quadratic_extension.go index 92be086..d384300 100644 --- a/goldilocks/quadratic_extension.go +++ b/goldilocks/quadratic_extension.go @@ -232,3 +232,8 @@ func (p *Chip) AssertIsEqualExtension( 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]) +} diff --git a/verifier/verifier.go b/verifier/verifier.go index 0b35c46..ca0d0f7 100644 --- a/verifier/verifier.go +++ b/verifier/verifier.go @@ -11,20 +11,23 @@ import ( ) 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 @@ func (c *VerifierChip) generateProofInput(commonData common.CommonCircuitData) c } */ +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 @@ func (c *VerifierChip) Verify( 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,