Upgrade to gnark 0.8 (#18)

* make proof with PIS public input

* upgraded to 0.8 gnark

* reduced pow witness

* fixed bug

* fixed test

* fixed bug

* adding profiling

* changed everything to be pointers

* convert remaining poseidon constants

* added the recursive_very_small

* added more outputs for benchmark
This commit is contained in:
Kevin Jue
2023-05-25 07:39:06 -07:00
committed by GitHub
parent cf84b032e2
commit 302b5f5bf1
31 changed files with 5336 additions and 2089 deletions

View File

@@ -8,29 +8,32 @@ import (
)
type EmulatedField = emulated.Goldilocks
type F = emulated.Element[EmulatedField]
type F = *emulated.Element[EmulatedField]
type FieldAPI = *emulated.Field[emulated.Goldilocks]
var TEST_CURVE = ecc.BN254
func NewFieldElement(x uint64) F {
return emulated.NewElement[EmulatedField](x)
}
func NewFieldElementFromString(x string) F {
return emulated.NewElement[EmulatedField](x)
}
func NewFieldAPI(api frontend.API) frontend.API {
field, err := emulated.NewField[EmulatedField](api)
func NewFieldAPI(api frontend.API) FieldAPI {
fieldAPI, err := emulated.NewField[EmulatedField](api)
if err != nil {
panic(err)
}
return field
return fieldAPI
}
var ONE_F = NewFieldElement(1)
var ZERO_F = NewFieldElement(0)
var NEG_ONE_F = NewFieldElement(EmulatedField{}.Modulus().Uint64() - 1)
func NewFieldConst(x uint64) F {
val := emulated.ValueOf[EmulatedField](x)
return &val
}
func NewFieldConstFromString(x string) F {
val := emulated.ValueOf[EmulatedField](x)
return &val
}
var ONE_F = NewFieldConst(1)
var ZERO_F = NewFieldConst(0)
var NEG_ONE_F = NewFieldConst(EmulatedField{}.Modulus().Uint64() - 1)
var GOLDILOCKS_MULTIPLICATIVE_GROUP_GENERATOR = goldilocks.NewElement(7)
var GOLDILOCKS_TWO_ADICITY = uint64(32)
@@ -65,3 +68,16 @@ func TwoAdicSubgroup(nLog uint64) []goldilocks.Element {
return res
}
func IsZero(api frontend.API, fieldAPI *emulated.Field[emulated.Goldilocks], x F) frontend.Variable {
reduced := fieldAPI.Reduce(x)
limbs := reduced.Limbs
isZero := api.IsZero(limbs[0])
for i := 1; i < len(limbs); i++ {
isZero = api.Mul(isZero, api.IsZero(limbs[i]))
}
return isZero
}

View File

@@ -1,7 +1,6 @@
package field
import (
"fmt"
"math/bits"
"github.com/consensys/gnark-crypto/field/goldilocks"
@@ -14,7 +13,8 @@ type QuadraticExtension = [2]F
type QEAlgebra = [D]QuadraticExtension
type QuadraticExtensionAPI struct {
fieldAPI frontend.API
api frontend.API
fieldAPI FieldAPI
W F
DTH_ROOT F
@@ -25,7 +25,7 @@ type QuadraticExtensionAPI struct {
ZERO_QE_ALGEBRA QEAlgebra
}
func NewQuadraticExtensionAPI(fieldAPI frontend.API, degreeBits uint64) *QuadraticExtensionAPI {
func NewQuadraticExtensionAPI(api frontend.API, fieldAPI FieldAPI, degreeBits uint64) *QuadraticExtensionAPI {
// TODO: Should degreeBits be verified that it fits within the field and that degree is within uint64?
var ZERO_QE = QuadraticExtension{ZERO_F, ZERO_F}
@@ -37,10 +37,11 @@ func NewQuadraticExtensionAPI(fieldAPI frontend.API, degreeBits uint64) *Quadrat
}
return &QuadraticExtensionAPI{
api: api,
fieldAPI: fieldAPI,
W: NewFieldElement(7),
DTH_ROOT: NewFieldElement(18446744069414584320),
W: NewFieldConst(7),
DTH_ROOT: NewFieldConst(18446744069414584320),
ONE_QE: QuadraticExtension{ONE_F, ZERO_F},
ZERO_QE: ZERO_QE,
@@ -54,20 +55,20 @@ func (c *QuadraticExtensionAPI) SquareExtension(a QuadraticExtension) QuadraticE
}
func (c *QuadraticExtensionAPI) MulExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
c_0 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[0]).(F), c.fieldAPI.Mul(c.W, a[1], b[1])).(F)
c_1 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[1]).(F), c.fieldAPI.Mul(a[1], b[0])).(F)
c_0 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[0]), c.fieldAPI.Mul(c.fieldAPI.Mul(c.W, a[1]), b[1]))
c_1 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[1]), c.fieldAPI.Mul(a[1], b[0]))
return QuadraticExtension{c_0, c_1}
}
func (c *QuadraticExtensionAPI) AddExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
c_0 := c.fieldAPI.Add(a[0], b[0]).(F)
c_1 := c.fieldAPI.Add(a[1], b[1]).(F)
c_0 := c.fieldAPI.Add(a[0], b[0])
c_1 := c.fieldAPI.Add(a[1], b[1])
return QuadraticExtension{c_0, c_1}
}
func (c *QuadraticExtensionAPI) SubExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
c_0 := c.fieldAPI.Sub(a[0], b[0]).(F)
c_1 := c.fieldAPI.Sub(a[1], b[1]).(F)
c_0 := c.fieldAPI.Sub(a[0], b[0])
c_1 := c.fieldAPI.Sub(a[1], b[1])
return QuadraticExtension{c_0, c_1}
}
@@ -76,26 +77,26 @@ func (c *QuadraticExtensionAPI) DivExtension(a QuadraticExtension, b QuadraticEx
}
func (c *QuadraticExtensionAPI) IsZero(a QuadraticExtension) frontend.Variable {
return c.fieldAPI.Mul(c.fieldAPI.IsZero(a[0]), c.fieldAPI.IsZero(a[1]))
return c.api.Mul(IsZero(c.api, c.fieldAPI, a[0]), IsZero(c.api, c.fieldAPI, a[1]))
}
// TODO: Instead of calculating the inverse within the circuit, can witness the
// inverse and assert that a_inverse * a = 1. Should reduce # of constraints.
func (c *QuadraticExtensionAPI) InverseExtension(a QuadraticExtension) QuadraticExtension {
// First assert that a doesn't have 0 value coefficients
a0_is_zero := c.fieldAPI.IsZero(a[0])
a1_is_zero := c.fieldAPI.IsZero(a[1])
a0_is_zero := IsZero(c.api, c.fieldAPI, a[0])
a1_is_zero := IsZero(c.api, c.fieldAPI, 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), ZERO_F)
c.api.AssertIsEqual(c.api.Mul(a0_is_zero, a1_is_zero), frontend.Variable(0))
a_pow_r_minus_1 := QuadraticExtension{a[0], c.fieldAPI.Mul(a[1], c.DTH_ROOT).(F)}
a_pow_r_minus_1 := QuadraticExtension{a[0], c.fieldAPI.Mul(a[1], c.DTH_ROOT)}
a_pow_r := c.MulExtension(a_pow_r_minus_1, a)
return c.ScalarMulExtension(a_pow_r_minus_1, c.fieldAPI.Inverse(a_pow_r[0]).(F))
return c.ScalarMulExtension(a_pow_r_minus_1, c.fieldAPI.Inverse(a_pow_r[0]))
}
func (c *QuadraticExtensionAPI) ScalarMulExtension(a QuadraticExtension, scalar F) QuadraticExtension {
return QuadraticExtension{c.fieldAPI.Mul(a[0], scalar).(F), c.fieldAPI.Mul(a[1], scalar).(F)}
return QuadraticExtension{c.fieldAPI.Mul(a[0], scalar), c.fieldAPI.Mul(a[1], scalar)}
}
func (c *QuadraticExtensionAPI) FieldToQE(a F) QuadraticExtension {
@@ -150,7 +151,7 @@ func (c *QuadraticExtensionAPI) Select(b frontend.Variable, qe0, qe1 QuadraticEx
var retQE QuadraticExtension
for i := 0; i < 2; i++ {
retQE[i] = c.fieldAPI.Select(b, qe0[i], qe1[i]).(F)
retQE[i] = c.fieldAPI.Select(b, qe0[i], qe1[i])
}
return retQE
@@ -160,7 +161,7 @@ func (c *QuadraticExtensionAPI) Lookup2(b0 frontend.Variable, b1 frontend.Variab
var retQE QuadraticExtension
for i := 0; i < 2; i++ {
retQE[i] = c.fieldAPI.Lookup2(b0, b1, qe0[i], qe1[i], qe2[i], qe3[i]).(F)
retQE[i] = c.fieldAPI.Lookup2(b0, b1, qe0[i], qe1[i], qe2[i], qe3[i])
}
return retQE
@@ -186,6 +187,7 @@ func (c *QuadraticExtensionAPI) InnerProductExtension(constant F, startingAcc Qu
return acc
}
/*
func (c *QuadraticExtensionAPI) Println(a QuadraticExtension) {
fmt.Print("Degree 0 coefficient")
c.fieldAPI.Println(a[0])
@@ -193,6 +195,7 @@ func (c *QuadraticExtensionAPI) Println(a QuadraticExtension) {
fmt.Print("Degree 1 coefficient")
c.fieldAPI.Println(a[1])
}
*/
func (c *QuadraticExtensionAPI) MulExtensionAlgebra(a, b QEAlgebra) QEAlgebra {
var inner [D][][2]QuadraticExtension
@@ -210,7 +213,7 @@ func (c *QuadraticExtensionAPI) MulExtensionAlgebra(a, b QEAlgebra) QEAlgebra {
var product QEAlgebra
for i := 0; i < D; i++ {
acc := c.InnerProductExtension(NewFieldElement(7), c.ZERO_QE, inner_w[i])
acc := c.InnerProductExtension(c.W, c.ZERO_QE, inner_w[i])
product[i] = c.InnerProductExtension(ONE_F, acc, inner[i])
}
@@ -268,10 +271,10 @@ func (c *QuadraticExtensionAPI) PartialInterpolateExtAlgebra(
for i := 0; i < n; i++ {
val := values[i]
x := domain[i]
xField := NewFieldElement(x.Uint64())
xField := NewFieldConst(x.Uint64())
xQE := QuadraticExtension{xField, ZERO_F}
xQEAlgebra := QEAlgebra{xQE, c.ZERO_QE}
weight := QuadraticExtension{NewFieldElement(barycentricWeights[i].Uint64()), ZERO_F}
weight := QuadraticExtension{NewFieldConst(barycentricWeights[i].Uint64()), ZERO_F}
term := c.SubExtensionAlgebra(point, xQEAlgebra)
weightedVal := c.ScalarMulExtensionAlgebra(weight, val)
newEval = c.MulExtensionAlgebra(newEval, term)

View File

@@ -13,32 +13,32 @@ import (
type TestQuadraticExtensionMulCircuit struct {
qeAPI *QuadraticExtensionAPI
operand1 QuadraticExtension
operand2 QuadraticExtension
expectedResult QuadraticExtension
Operand1 QuadraticExtension
Operand2 QuadraticExtension
ExpectedResult QuadraticExtension
}
func (c *TestQuadraticExtensionMulCircuit) Define(api frontend.API) error {
fieldAPI := NewFieldAPI(api)
degreeBits := 3
c.qeAPI = NewQuadraticExtensionAPI(fieldAPI, uint64(degreeBits))
c.qeAPI = NewQuadraticExtensionAPI(api, fieldAPI, uint64(degreeBits))
actualRes := c.qeAPI.MulExtension(c.operand1, c.operand2)
actualRes := c.qeAPI.MulExtension(c.Operand1, c.Operand2)
fieldAPI.AssertIsEqual(actualRes[0], c.expectedResult[0])
fieldAPI.AssertIsEqual(actualRes[1], c.expectedResult[1])
fieldAPI.AssertIsEqual(actualRes[0], c.ExpectedResult[0])
fieldAPI.AssertIsEqual(actualRes[1], c.ExpectedResult[1])
return nil
}
func TestQuadraticExtensionMul(t *testing.T) {
assert := test.NewAssert(t)
operand1 := QuadraticExtension{NewFieldElement(4994088319481652598), NewFieldElement(16489566008211790727)}
operand2 := QuadraticExtension{NewFieldElement(3797605683985595697), NewFieldElement(13424401189265534004)}
expectedResult := QuadraticExtension{NewFieldElement(15052319864161058789), NewFieldElement(16841416332519902625)}
operand1 := QuadraticExtension{NewFieldConst(4994088319481652598), NewFieldConst(16489566008211790727)}
operand2 := QuadraticExtension{NewFieldConst(3797605683985595697), NewFieldConst(13424401189265534004)}
expectedResult := QuadraticExtension{NewFieldConst(15052319864161058789), NewFieldConst(16841416332519902625)}
circuit := TestQuadraticExtensionMulCircuit{operand1: operand1, operand2: operand2, expectedResult: expectedResult}
witness := TestQuadraticExtensionMulCircuit{operand1: operand1, operand2: operand2, expectedResult: expectedResult}
circuit := TestQuadraticExtensionMulCircuit{Operand1: operand1, Operand2: operand2, ExpectedResult: expectedResult}
witness := TestQuadraticExtensionMulCircuit{Operand1: operand1, Operand2: operand2, ExpectedResult: expectedResult}
err := test.IsSolved(&circuit, &witness, TEST_CURVE.ScalarField())
assert.NoError(err)
}
@@ -47,20 +47,20 @@ func TestQuadraticExtensionMul(t *testing.T) {
type TestQuadraticExtensionDivCircuit struct {
qeAPI *QuadraticExtensionAPI
operand1 QuadraticExtension
operand2 QuadraticExtension
expectedResult QuadraticExtension
Operand1 QuadraticExtension
Operand2 QuadraticExtension
ExpectedResult QuadraticExtension
}
func (c *TestQuadraticExtensionDivCircuit) Define(api frontend.API) error {
fieldAPI := NewFieldAPI(api)
degreeBits := 3
c.qeAPI = NewQuadraticExtensionAPI(fieldAPI, uint64(degreeBits))
c.qeAPI = NewQuadraticExtensionAPI(api, fieldAPI, uint64(degreeBits))
actualRes := c.qeAPI.DivExtension(c.operand1, c.operand2)
actualRes := c.qeAPI.DivExtension(c.Operand1, c.Operand2)
fieldAPI.AssertIsEqual(actualRes[0], c.expectedResult[0])
fieldAPI.AssertIsEqual(actualRes[1], c.expectedResult[1])
fieldAPI.AssertIsEqual(actualRes[0], c.ExpectedResult[0])
fieldAPI.AssertIsEqual(actualRes[1], c.ExpectedResult[1])
return nil
}
@@ -68,12 +68,12 @@ func (c *TestQuadraticExtensionDivCircuit) Define(api frontend.API) error {
func TestQuadraticExtensionDiv(t *testing.T) {
assert := test.NewAssert(t)
operand1 := QuadraticExtension{NewFieldElement(4994088319481652598), NewFieldElement(16489566008211790727)}
operand2 := QuadraticExtension{NewFieldElement(7166004739148609569), NewFieldElement(14655965871663555016)}
expectedResult := QuadraticExtension{NewFieldElement(15052319864161058789), NewFieldElement(16841416332519902625)}
operand1 := QuadraticExtension{NewFieldConst(4994088319481652598), NewFieldConst(16489566008211790727)}
operand2 := QuadraticExtension{NewFieldConst(7166004739148609569), NewFieldConst(14655965871663555016)}
expectedResult := QuadraticExtension{NewFieldConst(15052319864161058789), NewFieldConst(16841416332519902625)}
circuit := TestQuadraticExtensionDivCircuit{operand1: operand1, operand2: operand2, expectedResult: expectedResult}
witness := TestQuadraticExtensionDivCircuit{operand1: operand1, operand2: operand2, expectedResult: expectedResult}
circuit := TestQuadraticExtensionDivCircuit{Operand1: operand1, Operand2: operand2, ExpectedResult: expectedResult}
witness := TestQuadraticExtensionDivCircuit{Operand1: operand1, Operand2: operand2, ExpectedResult: expectedResult}
err := test.IsSolved(&circuit, &witness, TEST_CURVE.ScalarField())
assert.NoError(err)
}