Skip to content

Commit

Permalink
feat: fri verification (very high constraints, ~3.6M for 1 query round)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultrainstinct30 committed Dec 11, 2023
1 parent 9025d52 commit 9de8877
Show file tree
Hide file tree
Showing 10 changed files with 1,079 additions and 27 deletions.
52 changes: 52 additions & 0 deletions goldilocks/goldilocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import (
"github.com/consensys/gnark/std/math/emulated"
)

const TWO_ADICITY = 32
const MULTIPLICATIVE_GROUP_GENERATOR = 7

var POWER_OF_TWO_GENERATOR = new(big.Int).SetUint64(1753635133440165772)

type GoldilocksVariable struct {
Limb frontend.Variable
}
Expand Down Expand Up @@ -145,3 +150,50 @@ func InverseHint(_ *big.Int, inputs []*big.Int, outputs []*big.Int) error {
output.ModInverse(output, MODULUS)
return nil
}

func ExpPow2(
api frontend.API,
rangeChecker frontend.Rangechecker,
in GoldilocksVariable,
degree_bits int,
) GoldilocksVariable {
out := in
for i := 0; i < degree_bits; i++ {
out = Mul(api, rangeChecker, out, out)
}
return out
}

func Exp(
api frontend.API,
rangeChecker frontend.Rangechecker,
in GoldilocksVariable,
degree_in_bits []frontend.Variable,
) GoldilocksVariable {
current := in
product := GetGoldilocksVariable(1)
for _, bit := range degree_in_bits {
productXcurrent := Mul(api, rangeChecker, product, current)
product.Limb = api.Select(bit, productXcurrent.Limb, product.Limb)
current = Mul(api, rangeChecker, current, current)
}
return product
}

func ExpPow2BigInt(base *big.Int, power_log int) *big.Int {
res := base
for i := 0; i < power_log; i++ {
res = new(big.Int).Mod(new(big.Int).Mul(res, res), MODULUS)
}
return res
}

func PrimitveRootOfUnity(n_log int) GoldilocksVariable {
if n_log > TWO_ADICITY {
panic("n_log more than TWO_ADICITY_EXT2")
}
base_pow := ExpPow2BigInt(POWER_OF_TWO_GENERATOR, TWO_ADICITY-n_log)
var root GoldilocksVariable
root.Limb = base_pow
return root
}
79 changes: 79 additions & 0 deletions goldilocks/goldilocks_2extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (

const W = 7
const DTH_ROOT = 18446744069414584320
const TWO_ADICITY_EXT2 = TWO_ADICITY + 1

var EXT_POWER_OF_TWO_GENERATOR = [2]*big.Int{new(big.Int).SetUint64(0), new(big.Int).SetUint64(15659105665374529263)}

type GoldilocksExtension2Variable struct {
A GoldilocksVariable
Expand Down Expand Up @@ -166,6 +169,23 @@ func ExpPow2Ext(
return out
}

func ExpExt(
api frontend.API,
rangeChecker frontend.Rangechecker,
in GoldilocksExtension2Variable,
degree_in_bits []frontend.Variable,
) GoldilocksExtension2Variable {
current := in
product := GetGoldilocksExtensionVariable([]uint64{1, 0})
for _, bit := range degree_in_bits {
productXcurrent := MulExt(api, rangeChecker, product, current)
product.A.Limb = api.Select(bit, productXcurrent.A.Limb, product.A.Limb)
product.B.Limb = api.Select(bit, productXcurrent.B.Limb, product.B.Limb)
current = MulExt(api, rangeChecker, current, current)
}
return product
}

func DivExt(
api frontend.API,
rangeChecker frontend.Rangechecker,
Expand Down Expand Up @@ -213,3 +233,62 @@ func InvExtHint(_ *big.Int, inputs []*big.Int, outputs []*big.Int) error {
outputs[1] = new(big.Int).Mod(new(big.Int).Mul(forbenius_B, a_pow_r_inv), MODULUS)
return nil
}

func SquareExtBigInt(base [2]*big.Int) [2]*big.Int {
a0 := base[0]
a1 := base[1]

a02 := new(big.Int).Mul(a0, a0)
a12 := new(big.Int).Mul(a1, a1)

c0 := new(big.Int).Mod(new(big.Int).Add(a02, new(big.Int).Mul(new(big.Int).SetUint64(W), a12)), MODULUS)
c1 := new(big.Int).Mod(new(big.Int).Mul(a0, new(big.Int).Add(a1, a1)), MODULUS)

return [2]*big.Int{c0, c1}
}

func ExpPow2ExtBigInt(base [2]*big.Int, power_log int) [2]*big.Int {
res := base
for i := 0; i < power_log; i++ {
res = SquareExtBigInt(res)
}
return res
}

func PrimitveRootOfUnityExt(n_log int) GoldilocksExtension2Variable {
if n_log > TWO_ADICITY_EXT2 {
panic("n_log more than TWO_ADICITY_EXT2")
}
base_pow := ExpPow2ExtBigInt(EXT_POWER_OF_TWO_GENERATOR, TWO_ADICITY_EXT2-n_log)
var root GoldilocksExtension2Variable
root.A.Limb = base_pow[0]
root.B.Limb = base_pow[1]
return root
}

func SelectGoldilocksExt2(api frontend.API, b frontend.Variable, in1 GoldilocksExtension2Variable, in2 GoldilocksExtension2Variable) GoldilocksExtension2Variable {
var out GoldilocksExtension2Variable
out.A.Limb = api.Select(b, in1.A.Limb, in2.A.Limb)
out.B.Limb = api.Select(b, in1.B.Limb, in2.B.Limb)
return out
}

func SelectGoldilocksExt2Recursive(api frontend.API, b []frontend.Variable, in []GoldilocksExtension2Variable) []GoldilocksExtension2Variable {
if len(in) == 2 {
return []GoldilocksExtension2Variable{SelectGoldilocksExt2(api, b[0], in[1], in[0])}
}
first_bit_select := make([]GoldilocksExtension2Variable, len(in)/2)
for i := 0; i < len(first_bit_select); i++ {
first_bit_select[i] = SelectGoldilocksExt2(api, b[0], in[2*i+1], in[2*i])
}
return SelectGoldilocksExt2Recursive(api, b[1:], first_bit_select)
}

func Flatten(in []GoldilocksExtension2Variable) []GoldilocksVariable {
out := make([]GoldilocksVariable, len(in)*2)
for i, v := range in {
out[2*i] = v.A
out[2*i+1] = v.B
}
return out
}
135 changes: 135 additions & 0 deletions verifier/fri/fri_instance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package fri

import (
"github.com/Electron-Labs/plonky2-groth16-verifier/goldilocks"
"github.com/Electron-Labs/plonky2-groth16-verifier/verifier/types"
"github.com/consensys/gnark/frontend"
)

func FriPreprocessedPolys(common_data types.CommonData) []types.FriPolynomialInfo {
return types.FromRange(types.CONSTANT_SIGMAS.Index, types.Range{
Start: 0,
End: common_data.NumConstants + common_data.Config.NumRoutedWires,
})
}

func FriWirePolys(common_data types.CommonData) []types.FriPolynomialInfo {
return types.FromRange(types.WIRES.Index, types.Range{
Start: 0,
End: common_data.Config.NumWires,
})
}

func FriZsPartialProductsPolys(common_data types.CommonData) []types.FriPolynomialInfo {
return types.FromRange(types.ZS_PARTIAL_PRODUCTS.Index, types.Range{
Start: 0,
End: common_data.Config.NumChallenges * (1 + common_data.NumPartialProducts),
})
}

func FriQuotientPolys(common_data types.CommonData) []types.FriPolynomialInfo {
return types.FromRange(types.QUOTIENT.Index, types.Range{
Start: 0,
End: common_data.Config.NumChallenges * common_data.QuotientDegreeFactor,
})
}

func FriLookupPolys(common_data types.CommonData) []types.FriPolynomialInfo {
return types.FromRange(types.ZS_PARTIAL_PRODUCTS.Index, types.Range{
Start: common_data.Config.NumChallenges * (1 + common_data.NumPartialProducts),
End: common_data.Config.NumChallenges * (1 + common_data.NumPartialProducts + common_data.NumLookupPolys),
})
}

func FriAllPolys(common_data types.CommonData) []types.FriPolynomialInfo {
var all_polys []types.FriPolynomialInfo
all_polys = append(all_polys, FriPreprocessedPolys(common_data)...)
all_polys = append(all_polys, FriWirePolys(common_data)...)
all_polys = append(all_polys, FriZsPartialProductsPolys(common_data)...)
all_polys = append(all_polys, FriQuotientPolys(common_data)...)
all_polys = append(all_polys, FriLookupPolys(common_data)...)
return all_polys
}

func FriZsPolys(common_data types.CommonData) []types.FriPolynomialInfo {
return types.FromRange(types.ZS_PARTIAL_PRODUCTS.Index, types.Range{
Start: 0,
End: common_data.Config.NumChallenges,
})
}

func FriNextBatchPolys(common_data types.CommonData) []types.FriPolynomialInfo {
var all_polys []types.FriPolynomialInfo
all_polys = append(all_polys, FriZsPolys(common_data)...)
all_polys = append(all_polys, FriLookupPolys(common_data)...)
return all_polys
}

func FriOracles(common_data types.CommonData) []types.FriOracleInfo {
return []types.FriOracleInfo{
{
NumPolys: int(common_data.NumConstants + common_data.Config.NumRoutedWires),
Blinding: types.CONSTANT_SIGMAS.Blinding,
},
{
NumPolys: int(common_data.Config.NumWires),
Blinding: types.WIRES.Blinding,
},
{
NumPolys: int(common_data.Config.NumChallenges * (1 + common_data.NumPartialProducts + common_data.NumLookupPolys)),
Blinding: types.ZS_PARTIAL_PRODUCTS.Blinding,
},
{
NumPolys: int(common_data.Config.NumChallenges * common_data.QuotientDegreeFactor),
Blinding: types.QUOTIENT.Blinding,
},
}
}

func GetFriInstance(
api frontend.API,
rangeChecker frontend.Rangechecker,
common_data types.CommonData,
zeta goldilocks.GoldilocksExtension2Variable,
) types.FriInstanceInfo {
zeta_batch := types.FriBatchInfo{
Point: zeta,
Polynomials: FriAllPolys(common_data),
}

g := goldilocks.PrimitveRootOfUnityExt(int(common_data.FriParams.DegreeBits))
zeta_next := goldilocks.MulExt(api, rangeChecker, g, zeta)
zeta_next_batch := types.FriBatchInfo{
Point: zeta_next,
Polynomials: FriNextBatchPolys(common_data),
}

openings := []types.FriBatchInfo{zeta_batch, zeta_next_batch}
return types.FriInstanceInfo{
Oracles: FriOracles(common_data),
Batches: openings,
}
}

func GetFriOpenings(openings types.OpeningSetVariable) types.FriOpeningsVariable {
values := openings.Constants
values = append(values, openings.PlonkSigmas...)
values = append(values, openings.Wires...)
values = append(values, openings.PlonkZs...)
values = append(values, openings.PartialProducts...)
values = append(values, openings.QuotientPolys...)
values = append(values, openings.LookupZs...)
zetaBatch := types.FriOpeningBatchVariable{
Values: values,
}

values = openings.PlonkZsNext
values = append(values, openings.LookupZsNext...)
zetaNextBatch := types.FriOpeningBatchVariable{
Values: values,
}
friOpenings := types.FriOpeningsVariable{
Batches: []types.FriOpeningBatchVariable{zetaBatch, zetaNextBatch},
}
return friOpenings
}
Loading

0 comments on commit 9de8877

Please sign in to comment.