Browse Source

finished interpolate function in fri round verification

main
Kevin Jue 2 years ago
parent
commit
d847bbd8e8
3 changed files with 108 additions and 20 deletions
  1. +59
    -10
      plonky2_verifier/fri.go
  2. +31
    -6
      plonky2_verifier/plonk.go
  3. +18
    -4
      plonky2_verifier/quadratic_extension.go

+ 59
- 10
plonky2_verifier/fri.go

@ -277,6 +277,54 @@ func (f *FriChip) finalPolyEval(finalPoly PolynomialCoeffs, point QuadraticExten
return ret return ret
} }
func (f *FriChip) interpolate(x QuadraticExtension, xPoints []QuadraticExtension, yPoints []QuadraticExtension, barycentricWeights []QuadraticExtension) QuadraticExtension {
if len(xPoints) != len(yPoints) || len(xPoints) != len(barycentricWeights) {
panic("length of xPoints, yPoints, and barycentricWeights are inconsistent")
}
lX := f.qeAPI.ONE_QE
for i := 0; i < len(xPoints); i++ {
lX = f.qeAPI.MulExtension(
lX,
f.qeAPI.SubExtension(
x,
xPoints[i],
),
)
}
sum := f.qeAPI.ZERO_QE
for i := 0; i < len(xPoints); i++ {
sum = f.qeAPI.AddExtension(
f.qeAPI.MulExtension(
f.qeAPI.DivExtension(
barycentricWeights[i],
f.qeAPI.SubExtension(
x,
xPoints[i],
),
),
yPoints[i],
),
sum,
)
}
interpolation := f.qeAPI.MulExtension(lX, sum)
returnField := interpolation
// Now check if x is already within the xPoints
for i := 0; i < len(xPoints); i++ {
returnField = f.qeAPI.Select(
f.qeAPI.IsZero(f.qeAPI.SubExtension(x, xPoints[i])),
yPoints[i],
returnField,
)
}
return returnField
}
func (f *FriChip) computeEvaluation( func (f *FriChip) computeEvaluation(
x F, x F,
xIndexWithinCosetBits []frontend.Variable, xIndexWithinCosetBits []frontend.Variable,
@ -314,34 +362,35 @@ func (f *FriChip) computeEvaluation(
start := f.expFromBitsConstBase(gInv, revXIndexWithinCosetBits) start := f.expFromBitsConstBase(gInv, revXIndexWithinCosetBits)
cosetStart := f.fieldAPI.Mul(start, x).(F) cosetStart := f.fieldAPI.Mul(start, x).(F)
xPoints := make([]F, len(evals))
xPoints := make([]QuadraticExtension, len(evals))
yPoints := permutedEvals yPoints := permutedEvals
// TODO: Make g_F a constant // TODO: Make g_F a constant
g_F := NewFieldElement(g.Uint64()) g_F := NewFieldElement(g.Uint64())
xPoints[0] = cosetStart
xPoints[0] = f.qeAPI.FieldToQE(cosetStart)
for i := 1; i < len(evals); i++ { for i := 1; i < len(evals); i++ {
xPoints[i] = f.fieldAPI.Mul(xPoints[i-1], g_F).(F)
xPoints[i] = f.qeAPI.FieldToQE(f.fieldAPI.Mul(xPoints[i-1], g_F).(F))
} }
// TODO: This is n^2. Is there a way to do this better? // TODO: This is n^2. Is there a way to do this better?
// Compute the barycentric weights // Compute the barycentric weights
barycentricWeights := make([]F, len(xPoints))
barycentricWeights := make([]QuadraticExtension, len(xPoints))
for i := 0; i < len(xPoints); i++ { for i := 0; i < len(xPoints); i++ {
barycentricWeights[i] = ONE_F
barycentricWeights[i] = f.qeAPI.ONE_QE
for j := 0; j < len(xPoints); j++ { for j := 0; j < len(xPoints); j++ {
if i != j { if i != j {
barycentricWeights[i] = f.fieldAPI.Mul(
f.fieldAPI.Sub(xPoints[i], xPoints[j]),
barycentricWeights[i] = f.qeAPI.MulExtension(
f.qeAPI.SubExtension(xPoints[i], xPoints[j]),
barycentricWeights[i], barycentricWeights[i],
).(F)
)
} }
} }
// Take the inverse of the barycentric weights // Take the inverse of the barycentric weights
// TODO: Can provide a witness to this value // TODO: Can provide a witness to this value
barycentricWeights[i] = f.fieldAPI.Inverse(barycentricWeights[i]).(F)
barycentricWeights[i] = f.qeAPI.InverseExtension(barycentricWeights[i])
} }
return f.interpolate(beta, xPoints, yPoints, barycentricWeights)
} }
func (f *FriChip) verifyQueryRound( func (f *FriChip) verifyQueryRound(
@ -405,7 +454,7 @@ func (f *FriChip) verifyQueryRound(
newEval := f.qeAPI.Lookup2(xIndexWithinCosetBits[2], xIndexWithinCosetBits[3], evals[0], evals[1], evals[2], evals[3]) newEval := f.qeAPI.Lookup2(xIndexWithinCosetBits[2], xIndexWithinCosetBits[3], evals[0], evals[1], evals[2], evals[3])
f.qeAPI.AssertIsEqual(newEval, oldEval) f.qeAPI.AssertIsEqual(newEval, oldEval)
oldEval := f.computeEvaluation(
oldEval = f.computeEvaluation(
subgroupX, subgroupX,
xIndexWithinCosetBits, xIndexWithinCosetBits,
arityBits, arityBits,

+ 31
- 6
plonky2_verifier/plonk.go

@ -1,11 +1,37 @@
package plonky2_verifier package plonky2_verifier
import ( import (
"gnark-ed25519/field"
. "gnark-ed25519/field" . "gnark-ed25519/field"
"github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend"
) )
type PlonkOracle struct {
index uint64
blinding bool
}
var CONSTANTS_SIGMAS = PlonkOracle{
index: 0,
blinding: false,
}
var WIRES = PlonkOracle{
index: 1,
blinding: true,
}
var ZS_PARTIAL_PRODUCTS = PlonkOracle{
index: 2,
blinding: true,
}
var QUOTIENT = PlonkOracle{
index: 3,
blinding: true,
}
type PlonkChip struct { type PlonkChip struct {
api frontend.API api frontend.API
qe *QuadraticExtensionAPI qe *QuadraticExtensionAPI
@ -30,7 +56,7 @@ func NewPlonkChip(api frontend.API, qe *QuadraticExtensionAPI, commonData Common
DEGREE: NewFieldElement(1 << commonData.DegreeBits), DEGREE: NewFieldElement(1 << commonData.DegreeBits),
DEGREE_BITS_F: NewFieldElement(commonData.DegreeBits), DEGREE_BITS_F: NewFieldElement(commonData.DegreeBits),
DEGREE_QE: QuadraticExtension{NewFieldElement(1 << commonData.DegreeBits), NewFieldElement(0)},
DEGREE_QE: QuadraticExtension{NewFieldElement(1 << commonData.DegreeBits), field.ZERO_F},
} }
} }
@ -46,7 +72,7 @@ func (p *PlonkChip) evalL0(x QuadraticExtension, xPowN QuadraticExtension) Quadr
// L_0(x) = (x^n - 1) / (n * (x - 1)) // L_0(x) = (x^n - 1) / (n * (x - 1))
evalZeroPoly := p.qe.SubExtension( evalZeroPoly := p.qe.SubExtension(
xPowN, xPowN,
p.qe.ONE,
p.qe.ONE_QE,
) )
denominator := p.qe.SubExtension( denominator := p.qe.SubExtension(
p.qe.ScalarMulExtension(x, p.DEGREE), p.qe.ScalarMulExtension(x, p.DEGREE),
@ -109,7 +135,7 @@ func (p *PlonkChip) evalVanishingPoly(zetaPowN QuadraticExtension) []QuadraticEx
// L_0(zeta) (Z(zeta) - 1) = 0 // L_0(zeta) (Z(zeta) - 1) = 0
z1_term := p.qe.MulExtension( z1_term := p.qe.MulExtension(
l0Zeta, l0Zeta,
p.qe.SubExtension(p.openings.PlonkZs[i], p.qe.ONE))
p.qe.SubExtension(p.openings.PlonkZs[i], p.qe.ONE_QE))
vanishingZ1Terms = append(vanishingZ1Terms, z1_term) vanishingZ1Terms = append(vanishingZ1Terms, z1_term)
numeratorValues := make([]QuadraticExtension, 0, p.commonData.Config.NumRoutedWires) numeratorValues := make([]QuadraticExtension, 0, p.commonData.Config.NumRoutedWires)
@ -187,7 +213,7 @@ func (p *PlonkChip) Verify() {
vanishingPolysZeta := p.evalVanishingPoly(zetaPowN) vanishingPolysZeta := p.evalVanishingPoly(zetaPowN)
// Calculate Z(H) // Calculate Z(H)
zHZeta := p.qe.SubExtension(zetaPowN, p.qe.ONE)
zHZeta := p.qe.SubExtension(zetaPowN, p.qe.ONE_QE)
// `quotient_polys_zeta` holds `num_challenges * quotient_degree_factor` evaluations. // `quotient_polys_zeta` holds `num_challenges * quotient_degree_factor` evaluations.
// Each chunk of `quotient_degree_factor` holds the evaluations of `t_0(zeta),...,t_{quotient_degree_factor-1}(zeta)` // Each chunk of `quotient_degree_factor` holds the evaluations of `t_0(zeta),...,t_{quotient_degree_factor-1}(zeta)`
@ -197,8 +223,7 @@ func (p *PlonkChip) Verify() {
for i := 0; i < len(p.openings.QuotientPolys); i += int(p.commonData.QuotientDegreeFactor) { for i := 0; i < len(p.openings.QuotientPolys); i += int(p.commonData.QuotientDegreeFactor) {
prod := p.qe.MulExtension( prod := p.qe.MulExtension(
zHZeta, zHZeta,
reduceWithPowers(
p.qe,
p.qe.ReduceWithPowers(
p.openings.QuotientPolys[i:i+int(p.commonData.QuotientDegreeFactor)], p.openings.QuotientPolys[i:i+int(p.commonData.QuotientDegreeFactor)],
zetaPowN, zetaPowN,
), ),

+ 18
- 4
plonky2_verifier/quadratic_extension.go

@ -14,7 +14,7 @@ type QuadraticExtensionAPI struct {
W F W F
DTH_ROOT F DTH_ROOT F
ONE QuadraticExtension
ONE_QE QuadraticExtension
ZERO_QE QuadraticExtension ZERO_QE QuadraticExtension
} }
@ -27,7 +27,7 @@ func NewQuadraticExtensionAPI(fieldAPI frontend.API, degreeBits uint64) *Quadrat
W: NewFieldElement(7), W: NewFieldElement(7),
DTH_ROOT: NewFieldElement(18446744069414584320), DTH_ROOT: NewFieldElement(18446744069414584320),
ONE: QuadraticExtension{ONE_F, ZERO_F},
ONE_QE: QuadraticExtension{ONE_F, ZERO_F},
ZERO_QE: QuadraticExtension{ZERO_F, ZERO_F}, ZERO_QE: QuadraticExtension{ZERO_F, ZERO_F},
} }
} }
@ -58,6 +58,10 @@ func (c *QuadraticExtensionAPI) DivExtension(a QuadraticExtension, b QuadraticEx
return c.MulExtension(a, c.InverseExtension(b)) return c.MulExtension(a, c.InverseExtension(b))
} }
func (c *QuadraticExtensionAPI) IsZero(a QuadraticExtension) frontend.Variable {
return c.fieldAPI.Mul(c.fieldAPI.IsZero(a[0]), c.fieldAPI.IsZero(a[1]))
}
// TODO: Instead of calculating the inverse within the circuit, can witness the // TODO: Instead of calculating the inverse within the circuit, can witness the
// inverse and assert that a_inverse * a = 1. Should reduce # of constraints. // inverse and assert that a_inverse * a = 1. Should reduce # of constraints.
func (c *QuadraticExtensionAPI) InverseExtension(a QuadraticExtension) QuadraticExtension { func (c *QuadraticExtensionAPI) InverseExtension(a QuadraticExtension) QuadraticExtension {
@ -85,7 +89,7 @@ func (c *QuadraticExtensionAPI) FieldToQE(a F) QuadraticExtension {
func (c *QuadraticExtensionAPI) ExpU64Extension(a QuadraticExtension, exponent uint64) QuadraticExtension { func (c *QuadraticExtensionAPI) ExpU64Extension(a QuadraticExtension, exponent uint64) QuadraticExtension {
switch exponent { switch exponent {
case 0: case 0:
return c.ONE
return c.ONE_QE
case 1: case 1:
return a return a
case 2: case 2:
@ -94,7 +98,7 @@ func (c *QuadraticExtensionAPI) ExpU64Extension(a QuadraticExtension, exponent u
} }
current := a current := a
product := c.ONE
product := c.ONE_QE
for i := 0; i < bits.Len64(exponent); i++ { for i := 0; i < bits.Len64(exponent); i++ {
if i != 0 { if i != 0 {
@ -125,6 +129,16 @@ func (c *QuadraticExtensionAPI) ReduceWithPowers(terms []QuadraticExtension, sca
return sum return sum
} }
func (c *QuadraticExtensionAPI) Select(b0 frontend.Variable, qe0, qe1 QuadraticExtension) QuadraticExtension {
var retQE QuadraticExtension
for i := 0; i < 2; i++ {
retQE[i] = c.fieldAPI.Select(b0, qe0[i], qe1[i]).(F)
}
return retQE
}
func (c *QuadraticExtensionAPI) Lookup2(b0 frontend.Variable, b1 frontend.Variable, qe0, qe1, qe2, qe3 QuadraticExtension) QuadraticExtension { func (c *QuadraticExtensionAPI) Lookup2(b0 frontend.Variable, b1 frontend.Variable, qe0, qe1, qe2, qe3 QuadraticExtension) QuadraticExtension {
var retQE QuadraticExtension var retQE QuadraticExtension

Loading…
Cancel
Save