Browse Source

added the function friCombineInitial

main
Kevin Jue 2 years ago
parent
commit
393059b51d
3 changed files with 133 additions and 39 deletions
  1. +100
    -36
      plonky2_verifier/fri.go
  2. +1
    -0
      plonky2_verifier/fri_test.go
  3. +32
    -3
      plonky2_verifier/quadratic_extension.go

+ 100
- 36
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,

+ 1
- 0
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,

+ 32
- 3
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) {

Loading…
Cancel
Save