From 393059b51dbdcda2967f2f622ff55ea98ce21740 Mon Sep 17 00:00:00 2001 From: Kevin Jue Date: Thu, 10 Nov 2022 12:54:57 -0800 Subject: [PATCH] added the function friCombineInitial --- plonky2_verifier/fri.go | 136 +++++++++++++++++------- plonky2_verifier/fri_test.go | 1 + plonky2_verifier/quadratic_extension.go | 35 +++++- 3 files changed, 133 insertions(+), 39 deletions(-) diff --git a/plonky2_verifier/fri.go b/plonky2_verifier/fri.go index 7a9b3b2..cda72ab 100644 --- a/plonky2_verifier/fri.go +++ b/plonky2_verifier/fri.go @@ -12,26 +12,6 @@ import ( "github.com/consensys/gnark/frontend" ) -type FriOpeningBatch struct { - values []QuadraticExtension -} - -type FriOpenings struct { - Batches []FriOpeningBatch -} - -func (c *OpeningSet) ToFriOpenings() FriOpenings { - values := c.Constants - values = append(values, c.PlonkSigmas...) - values = append(values, c.Wires...) - values = append(values, c.PlonkZs...) - values = append(values, c.PartialProducts...) - values = append(values, c.QuotientPolys...) - zetaBatch := FriOpeningBatch{values: values} - zetaNextBatch := FriOpeningBatch{values: c.PlonkZsNext} - return FriOpenings{Batches: []FriOpeningBatch{zetaBatch, zetaNextBatch}} -} - type FriChip struct { api frontend.API fieldAPI frontend.API @@ -190,22 +170,10 @@ func (f *FriChip) assertNoncanonicalIndicesOK() { } } -func (f *FriChip) verifyQueryRound( - challenges *FriChallenges, - precomputedReducedEval []QuadraticExtension, - initialMerkleCaps []MerkleCap, - proof *FriProof, - xIndex F, - n uint64, +func (f *FriChip) calculateSubgroupX( + xIndexBits []frontend.Variable, nLog uint64, - roundProof *FriQueryRound, -) { - f.assertNoncanonicalIndicesOK() - xIndexBits := f.fieldAPI.ToBinary(xIndex, int(nLog)) - capIndexBits := xIndexBits[len(xIndexBits)-int(f.friParams.Config.CapHeight):] - - f.verifyInitialProof(xIndexBits, &roundProof.InitialTreesProof, initialMerkleCaps, capIndexBits) - +) F { // Compute x from its index // `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain. // TODO - Make these as global values @@ -240,10 +208,105 @@ func (f *FriChip) verifyQueryRound( ).(F) } - subgroupX := f.fieldAPI.Mul(g, product).(F) + return f.fieldAPI.Mul(g, product).(F) +} + +func (f *FriChip) friCombineInitial( + instance FriInstanceInfo, + proof FriInitialTreeProof, + friAlpha QuadraticExtension, + subgroupX_QE QuadraticExtension, + precomputedReducedEval []QuadraticExtension, +) QuadraticExtension { + sum := f.qeAPI.ZERO_QE + + if len(instance.Batches) != len(precomputedReducedEval) { + panic("len(openings) != len(precomputedReducedEval)") + } + + for i := 0; i < len(instance.Batches); i++ { + batch := instance.Batches[i] + reducedOpenings := precomputedReducedEval[i] + + point := batch.Point + evals := make([]QuadraticExtension, 0) + for _, polynomial := range batch.Polynomials { + evals = append( + evals, + QuadraticExtension{proof.EvalsProofs[polynomial.OracleIndex].Elements[polynomial.PolynomialInfo], field.ZERO_F}, + ) + } + + reducedEvals := reduceWithPowers(f.qeAPI, evals, friAlpha) + numerator := f.qeAPI.SubExtension(reducedEvals, reducedOpenings) + denominator := f.qeAPI.SubExtension(subgroupX_QE, point) + sum = f.qeAPI.MulExtension(f.qeAPI.ExpU64Extension(friAlpha, uint64(len(evals))), sum) + sum = f.qeAPI.AddExtension( + f.qeAPI.DivExtension( + numerator, + denominator, + ), + sum, + ) + } + + return f.qeAPI.MulExtension(sum, subgroupX_QE) +} + +func (f *FriChip) finalPolyEval(finalPoly PolynomialCoeffs, point QuadraticExtension) QuadraticExtension { + ret := f.qeAPI.ZERO_QE + for i := len(finalPoly.Coeffs) - 1; i >= 0; i-- { + ret = f.qeAPI.AddExtension( + f.qeAPI.MulExtension( + ret, + point, + ), + finalPoly.Coeffs[i], + ) + } + return ret +} + +func (f *FriChip) verifyQueryRound( + instance FriInstanceInfo, + challenges *FriChallenges, + precomputedReducedEval []QuadraticExtension, + initialMerkleCaps []MerkleCap, + proof *FriProof, + xIndex F, + n uint64, + nLog uint64, + roundProof *FriQueryRound, +) { + f.assertNoncanonicalIndicesOK() + xIndexBits := f.fieldAPI.ToBinary(xIndex, int(nLog)) + capIndexBits := xIndexBits[len(xIndexBits)-int(f.friParams.Config.CapHeight):] + + f.verifyInitialProof(xIndexBits, &roundProof.InitialTreesProof, initialMerkleCaps, capIndexBits) + + subgroupX := f.calculateSubgroupX( + xIndexBits, + nLog, + ) + + subgroupX_QE := QuadraticExtension{subgroupX, field.ZERO_F} + + oldEval := f.friCombineInitial( + instance, + roundProof.InitialTreesProof, + challenges.FriAlpha, + subgroupX_QE, + precomputedReducedEval, + ) + + finalPolyEval := f.finalPolyEval(proof.FinalPoly, subgroupX_QE) + + f.fieldAPI.AssertIsEqual(oldEval[0], finalPolyEval[0]) + f.fieldAPI.AssertIsEqual(oldEval[1], finalPolyEval[1]) } func (f *FriChip) VerifyFriProof( + instance FriInstanceInfo, openings FriOpenings, friChallenges *FriChallenges, initialMerkleCaps []MerkleCap, @@ -281,6 +344,7 @@ func (f *FriChip) VerifyFriProof( roundProof := friProof.QueryRoundProofs[idx] f.verifyQueryRound( + instance, friChallenges, precomputedReducedEvals, initialMerkleCaps, diff --git a/plonky2_verifier/fri_test.go b/plonky2_verifier/fri_test.go index cc3bcf3..07867cc 100644 --- a/plonky2_verifier/fri_test.go +++ b/plonky2_verifier/fri_test.go @@ -68,6 +68,7 @@ func (circuit *TestFriCircuit) Define(api frontend.API) error { } friChip.VerifyFriProof( + commonCircuitData.GetFriInstance(), proofWithPis.Proof.Openings.ToFriOpenings(), &friChallenges, initialMerkleCaps, diff --git a/plonky2_verifier/quadratic_extension.go b/plonky2_verifier/quadratic_extension.go index 1435b9a..31a3f9c 100644 --- a/plonky2_verifier/quadratic_extension.go +++ b/plonky2_verifier/quadratic_extension.go @@ -2,7 +2,9 @@ package plonky2_verifier import ( "fmt" + "gnark-ed25519/field" . "gnark-ed25519/field" + "math/bits" "github.com/consensys/gnark/frontend" ) @@ -12,7 +14,6 @@ type QuadraticExtensionAPI struct { W F DTH_ROOT F - ZERO_F F ONE QuadraticExtension ZERO_QE QuadraticExtension @@ -66,7 +67,7 @@ func (c *QuadraticExtensionAPI) InverseExtension(a QuadraticExtension) Quadratic a1_is_zero := c.fieldAPI.IsZero(a[1]) // assert that a0_is_zero OR a1_is_zero == false - c.fieldAPI.AssertIsEqual(c.fieldAPI.Mul(a0_is_zero, a1_is_zero).(F), c.ZERO_F) + c.fieldAPI.AssertIsEqual(c.fieldAPI.Mul(a0_is_zero, a1_is_zero).(F), field.ZERO_F) a_pow_r_minus_1 := QuadraticExtension{a[0], c.fieldAPI.Mul(a[1], c.DTH_ROOT).(F)} a_pow_r := c.MulExtension(a_pow_r_minus_1, a) @@ -78,7 +79,35 @@ func (c *QuadraticExtensionAPI) ScalarMulExtension(a QuadraticExtension, scalar } func (c *QuadraticExtensionAPI) FieldToQE(a F) QuadraticExtension { - return QuadraticExtension{a, c.ZERO_F} + return QuadraticExtension{a, field.ZERO_F} +} + +// / Exponentiate `base` to the power of a known `exponent`. +func (c *QuadraticExtensionAPI) ExpU64Extension(a QuadraticExtension, exponent uint64) QuadraticExtension { + switch exponent { + case 0: + return c.ONE + case 1: + return a + case 2: + return c.SquareExtension(a) + default: + } + + current := a + product := c.ONE + + for i := 0; i < bits.Len64(exponent); i++ { + if i != 0 { + current = c.SquareExtension(current) + } + + if (exponent >> i & 1) != 0 { + product = c.MulExtension(product, current) + } + } + + return product } func (c *QuadraticExtensionAPI) Println(a QuadraticExtension) {