Use optimized goldilocks in codebase (#26)

* gl

* stage 1 optimizations

* working optimized poseidon

* Fix posedion tests

* in progress gate type refactor

* working gates

* working e2e

* hm'

* hm2

* debug saga continues

* more debugging cry

* more debug

* it finally works

* optimizations

* more optimizations

* new changes

* more optimizations

* more cleanup

* some refactoring

* new files

* flattening of packages

* working commit

* more refactor

* more flattening

* more flattening

* more more refactor

* more optimizations

* more optimizations

* more optimizations

* plonk benchmark

* plonk

* fix r1cs

* resolve kevin's comments

* Update goldilocks/base.go

Co-authored-by: Kevin Jue <kjue235@gmail.com>

* Update goldilocks/base.go

Co-authored-by: Kevin Jue <kjue235@gmail.com>

* Update goldilocks/base.go

Co-authored-by: Kevin Jue <kjue235@gmail.com>

* Update goldilocks/quadratic_extension.go

Co-authored-by: Kevin Jue <kjue235@gmail.com>

* fix: resolve kevin's confusion

---------

Co-authored-by: Kevin Jue <kjue235@gmail.com>
This commit is contained in:
John Guibas
2023-07-24 16:08:17 -07:00
committed by GitHub
parent 103c7ca47d
commit b670530e7f
61 changed files with 3506 additions and 3211 deletions

View File

@@ -0,0 +1,86 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var aritheticExtensionGateRegex = regexp.MustCompile("ArithmeticExtensionGate { num_ops: (?P<numOps>[0-9]+) }")
func deserializeExtensionArithmeticGate(parameters map[string]string) Gate {
// Has the format "ArithmeticExtensionGate { num_ops: 10 }"
numOps, hasNumOps := parameters["numOps"]
if !hasNumOps {
panic("Missing field num_ops in ArithmeticExtensionGate")
}
numOpsInt, err := strconv.Atoi(numOps)
if err != nil {
panic("Invalid num_ops field in ArithmeticExtensionGate")
}
return NewArithmeticExtensionGate(uint64(numOpsInt))
}
type ArithmeticExtensionGate struct {
numOps uint64
}
func NewArithmeticExtensionGate(numOps uint64) *ArithmeticExtensionGate {
return &ArithmeticExtensionGate{
numOps: numOps,
}
}
func (g *ArithmeticExtensionGate) Id() string {
return fmt.Sprintf("ArithmeticExtensionGate { num_ops: %d }", g.numOps)
}
func (g *ArithmeticExtensionGate) wiresIthMultiplicand0(i uint64) Range {
return Range{4 * gl.D * i, 4*gl.D*i + gl.D}
}
func (g *ArithmeticExtensionGate) wiresIthMultiplicand1(i uint64) Range {
return Range{4*gl.D*i + gl.D, 4*gl.D*i + 2*gl.D}
}
func (g *ArithmeticExtensionGate) wiresIthAddend(i uint64) Range {
return Range{4*gl.D*i + 2*gl.D, 4*gl.D*i + 3*gl.D}
}
func (g *ArithmeticExtensionGate) wiresIthOutput(i uint64) Range {
return Range{4*gl.D*i + 3*gl.D, 4*gl.D*i + 4*gl.D}
}
func (g *ArithmeticExtensionGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
const0 := vars.localConstants[0]
const1 := vars.localConstants[1]
constraints := []gl.QuadraticExtensionVariable{}
for i := uint64(0); i < g.numOps; i++ {
multiplicand0 := vars.GetLocalExtAlgebra(g.wiresIthMultiplicand0(i))
multiplicand1 := vars.GetLocalExtAlgebra(g.wiresIthMultiplicand1(i))
addend := vars.GetLocalExtAlgebra(g.wiresIthAddend(i))
output := vars.GetLocalExtAlgebra(g.wiresIthOutput(i))
mul := glApi.MulExtensionAlgebra(multiplicand0, multiplicand1)
scaled_mul := glApi.ScalarMulExtensionAlgebra(const0, mul)
computed_output := glApi.ScalarMulExtensionAlgebra(const1, addend)
computed_output = glApi.AddExtensionAlgebra(computed_output, scaled_mul)
diff := glApi.SubExtensionAlgebra(output, computed_output)
for j := 0; j < gl.D; j++ {
constraints = append(constraints, diff[j])
}
}
return constraints
}

View File

@@ -0,0 +1,84 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var aritheticGateRegex = regexp.MustCompile("ArithmeticGate { num_ops: (?P<numOps>[0-9]+) }")
func deserializeArithmeticGate(parameters map[string]string) Gate {
// Has the format "ArithmeticGate { num_ops: 10 }"
numOps, hasNumOps := parameters["numOps"]
if !hasNumOps {
panic("no num_ops field in ArithmeticGate")
}
numOpsInt, err := strconv.Atoi(numOps)
if err != nil {
panic("Invalid num_ops field in ArithmeticGate")
}
return NewArithmeticGate(uint64(numOpsInt))
}
type ArithmeticGate struct {
numOps uint64
}
func NewArithmeticGate(numOps uint64) *ArithmeticGate {
return &ArithmeticGate{
numOps: numOps,
}
}
func (g *ArithmeticGate) Id() string {
return fmt.Sprintf("ArithmeticGate { num_ops: %d }", g.numOps)
}
func (g *ArithmeticGate) WireIthMultiplicand0(i uint64) uint64 {
return 4 * i
}
func (g *ArithmeticGate) WireIthMultiplicand1(i uint64) uint64 {
return 4*i + 1
}
func (g *ArithmeticGate) WireIthAddend(i uint64) uint64 {
return 4*i + 2
}
func (g *ArithmeticGate) WireIthOutput(i uint64) uint64 {
return 4*i + 3
}
func (g *ArithmeticGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
const0 := vars.localConstants[0]
const1 := vars.localConstants[1]
constraints := []gl.QuadraticExtensionVariable{}
for i := uint64(0); i < g.numOps; i++ {
multiplicand0 := vars.localWires[g.WireIthMultiplicand0(i)]
multiplicand1 := vars.localWires[g.WireIthMultiplicand1(i)]
addend := vars.localWires[g.WireIthAddend(i)]
output := vars.localWires[g.WireIthOutput(i)]
computedOutput := glApi.AddExtension(
glApi.MulExtension(glApi.MulExtension(multiplicand0, multiplicand1), const0),
glApi.MulExtension(addend, const1),
)
constraints = append(constraints, glApi.SubExtension(output, computedOutput))
}
return constraints
}

View File

@@ -0,0 +1,96 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var baseSumGateRegex = regexp.MustCompile(`BaseSumGate { num_limbs: (?P<numLimbs>[0-9]+) } \+ Base: (?P<base>[0-9]+)`)
func deserializeBaseSumGate(parameters map[string]string) Gate {
// Has the format "BaseSumGate { num_limbs: 32 } + Base: 2"
numLimbs, hasNumLimbs := parameters["numLimbs"]
base, hasBase := parameters["base"]
if !hasNumLimbs || !hasBase {
panic("Missing field num_limbs or base in BaseSumGate")
}
numLimbsInt, err := strconv.Atoi(numLimbs)
if err != nil {
panic("Invalid num_limbs field in BaseSumGate")
}
baseInt, err := strconv.Atoi(base)
if err != nil {
panic("Invalid base field in BaseSumGate")
}
return NewBaseSumGate(uint64(numLimbsInt), uint64(baseInt))
}
const (
BASESUM_GATE_WIRE_SUM = 0
BASESUM_GATE_START_LIMBS = 1
)
type BaseSumGate struct {
numLimbs uint64
base uint64
}
func NewBaseSumGate(numLimbs uint64, base uint64) *BaseSumGate {
return &BaseSumGate{
numLimbs: numLimbs,
base: base,
}
}
func (g *BaseSumGate) Id() string {
return fmt.Sprintf("BaseSumGate { num_ops: %d } + Base: %d", g.numLimbs, g.base)
}
func (g *BaseSumGate) limbs() []uint64 {
limbIndices := make([]uint64, g.numLimbs)
for i := uint64(0); i < g.numLimbs; i++ {
limbIndices[i] = uint64(BASESUM_GATE_START_LIMBS + i)
}
return limbIndices
}
func (g *BaseSumGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
sum := vars.localWires[BASESUM_GATE_WIRE_SUM]
limbs := make([]gl.QuadraticExtensionVariable, g.numLimbs)
limbIndices := g.limbs()
for i, limbIdx := range limbIndices {
limbs[i] = vars.localWires[limbIdx]
}
baseQe := gl.NewQuadraticExtensionVariable(gl.NewVariable(g.base), gl.Zero())
computedSum := glApi.ReduceWithPowers(
limbs,
baseQe,
)
var constraints []gl.QuadraticExtensionVariable
constraints = append(constraints, glApi.SubExtension(computedSum, sum))
for _, limb := range limbs {
acc := gl.OneExtension()
for i := uint64(0); i < g.base; i++ {
difference := glApi.SubExtension(limb, gl.NewQuadraticExtensionVariable(gl.NewVariable(i), gl.Zero()))
acc = glApi.MulExtension(acc, difference)
}
constraints = append(constraints, acc)
}
return constraints
}

View File

@@ -0,0 +1,69 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var constantGateRegex = regexp.MustCompile("ConstantGate { num_consts: (?P<numConsts>[0-9]+) }")
func deserializeConstantGate(parameters map[string]string) Gate {
// Has the format "ConstantGate { num_consts: 2 }"
numConsts, hasNumConsts := parameters["numConsts"]
if !hasNumConsts {
panic("Missing field num_consts in ConstantGate")
}
numConstsInt, err := strconv.Atoi(numConsts)
if err != nil {
panic("Invalid num_consts field in ConstantGate")
}
return NewConstantGate(uint64(numConstsInt))
}
type ConstantGate struct {
numConsts uint64
}
func NewConstantGate(numConsts uint64) *ConstantGate {
return &ConstantGate{
numConsts: numConsts,
}
}
func (g *ConstantGate) Id() string {
return fmt.Sprintf("ConstantGate { num_consts: %d }", g.numConsts)
}
func (g *ConstantGate) ConstInput(i uint64) uint64 {
if i > g.numConsts {
panic("Invalid constant index")
}
return i
}
func (g *ConstantGate) WireOutput(i uint64) uint64 {
if i > g.numConsts {
panic("Invalid wire index")
}
return i
}
func (g *ConstantGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
constraints := []gl.QuadraticExtensionVariable{}
for i := uint64(0); i < g.numConsts; i++ {
constraints = append(constraints, glApi.SubExtension(vars.localConstants[g.ConstInput(i)], vars.localWires[g.WireOutput(i)]))
}
return constraints
}

View File

@@ -0,0 +1,219 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"strings"
"github.com/consensys/gnark-crypto/field/goldilocks"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var cosetInterpolationGateRegex = regexp.MustCompile(`CosetInterpolationGate { subgroup_bits: (?P<subgroupBits>[0-9]+), degree: (?P<degree>[0-9]+), barycentric_weights: \[(?P<barycentricWeights>[0-9, ]+)\], _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>`)
func deserializeCosetInterpolationGate(parameters map[string]string) Gate {
// Has the format CosetInterpolationGate { subgroup_bits: 4, degree: 6, barycentric_weights: [17293822565076172801, 18374686475376656385, 18446744069413535745, 281474976645120, 17592186044416, 18446744069414584577, 18446744000695107601, 18446744065119617025, 1152921504338411520, 72057594037927936, 18446744069415632897, 18446462594437939201, 18446726477228539905, 18446744069414584065, 68719476720, 4294967296], _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>
subgroupBits, hasSubgroupBits := parameters["subgroupBits"]
degree, hasDegree := parameters["degree"]
barycentricWeights, hasBarycentricWeights := parameters["barycentricWeights"]
if !hasSubgroupBits || !hasDegree || !hasBarycentricWeights {
panic("missing subgroupBits, degree or barycentricWeights in CosetInterpolationGate")
}
subgroupBitsInt, err := strconv.ParseUint(subgroupBits, 10, 64)
if err != nil {
panic("invalid subgroupBits in CosetInterpolationGate")
}
degreeInt, err := strconv.ParseUint(degree, 10, 64)
if err != nil {
panic("invalid degree in CosetInterpolationGate")
}
barycentricWeightsStr := strings.Split(barycentricWeights, ",")
barycentricWeightsInt := make([]goldilocks.Element, len(barycentricWeightsStr))
for i, barycentricWeightStr := range barycentricWeightsStr {
barycentricWeightStr = strings.TrimSpace(barycentricWeightStr)
barycentricWeightInt, err := strconv.ParseUint(barycentricWeightStr, 10, 64)
if err != nil {
panic("invalid barycentricWeights in CosetInterpolationGate")
}
barycentricWeightsInt[i].SetUint64(barycentricWeightInt)
}
return NewCosetInterpolationGate(subgroupBitsInt, degreeInt, barycentricWeightsInt)
}
type CosetInterpolationGate struct {
subgroupBits uint64
degree uint64
barycentricWeights []goldilocks.Element
}
func NewCosetInterpolationGate(subgroupBits uint64, degree uint64, barycentricWeights []goldilocks.Element) *CosetInterpolationGate {
return &CosetInterpolationGate{
subgroupBits: subgroupBits,
degree: degree,
barycentricWeights: barycentricWeights,
}
}
func (g *CosetInterpolationGate) Id() string {
return fmt.Sprintf(
"CosetInterpolationGate { subgroup_bits: %d, degree: %d, barycentric_weights: %s }",
g.subgroupBits,
g.degree,
fmt.Sprint(g.barycentricWeights),
)
}
func (g *CosetInterpolationGate) numPoints() uint64 {
return 1 << g.subgroupBits
}
// Wire index of the coset shift.
func (g *CosetInterpolationGate) wireShift() uint64 {
return 0
}
func (g *CosetInterpolationGate) startValues() uint64 {
return 1
}
// Wire indices of the `i`th interpolant value.
func (g *CosetInterpolationGate) wiresValue(i uint64) Range {
if i >= g.numPoints() {
panic("Invalid point index")
}
start := g.startValues() + i*gl.D
return Range{start, start + gl.D}
}
func (g *CosetInterpolationGate) startEvaluationPoint() uint64 {
return g.startValues() + g.numPoints()*gl.D
}
// Wire indices of the point to evaluate the interpolant at.
func (g *CosetInterpolationGate) wiresEvaluationPoint() Range {
start := g.startEvaluationPoint()
return Range{start, start + gl.D}
}
func (g *CosetInterpolationGate) startEvaluationValue() uint64 {
return g.startEvaluationPoint() + gl.D
}
// Wire indices of the interpolated value.
func (g *CosetInterpolationGate) wiresEvaluationValue() Range {
start := g.startEvaluationValue()
return Range{start, start + gl.D}
}
func (g *CosetInterpolationGate) startIntermediates() uint64 {
return g.startEvaluationValue() + gl.D
}
func (g *CosetInterpolationGate) numIntermediates() uint64 {
return (g.numPoints() - 2) / (g.degree - 1)
}
// The wires corresponding to the i'th intermediate evaluation.
func (g *CosetInterpolationGate) wiresIntermediateEval(i uint64) Range {
if i >= g.numIntermediates() {
panic("Invalid intermediate index")
}
start := g.startIntermediates() + gl.D*i
return Range{start, start + gl.D}
}
// The wires corresponding to the i'th intermediate product.
func (g *CosetInterpolationGate) wiresIntermediateProd(i uint64) Range {
if i >= g.numIntermediates() {
panic("Invalid intermediate index")
}
start := g.startIntermediates() + gl.D*(g.numIntermediates()+i)
return Range{start, start + gl.D}
}
// Wire indices of the shifted point to evaluate the interpolant at.
func (g *CosetInterpolationGate) wiresShiftedEvaluationPoint() Range {
start := g.startIntermediates() + gl.D*2*g.numIntermediates()
return Range{start, start + gl.D}
}
func (g *CosetInterpolationGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
constraints := []gl.QuadraticExtensionVariable{}
shift := vars.localWires[g.wireShift()]
evaluationPoint := vars.GetLocalExtAlgebra(g.wiresEvaluationPoint())
shiftedEvaluationPoint := vars.GetLocalExtAlgebra(g.wiresShiftedEvaluationPoint())
negShift := glApi.ScalarMulExtension(shift, gl.NegOne())
tmp := glApi.ScalarMulExtensionAlgebra(negShift, shiftedEvaluationPoint)
tmp = glApi.AddExtensionAlgebra(tmp, evaluationPoint)
for i := 0; i < gl.D; i++ {
constraints = append(constraints, tmp[i])
}
domain := gl.TwoAdicSubgroup(g.subgroupBits)
values := []gl.QuadraticExtensionAlgebraVariable{}
for i := uint64(0); i < g.numPoints(); i++ {
values = append(values, vars.GetLocalExtAlgebra(g.wiresValue(i)))
}
weights := g.barycentricWeights
initialEval := gl.ZeroExtensionAlgebra()
initialProd := gl.OneExtensionAlgebra()
computedEval, computedProd := glApi.PartialInterpolateExtAlgebra(
domain[:g.degree],
values[:g.degree],
weights[:g.degree],
shiftedEvaluationPoint,
initialEval,
initialProd,
)
for i := uint64(0); i < g.numIntermediates(); i++ {
intermediateEval := vars.GetLocalExtAlgebra(g.wiresIntermediateEval(i))
intermediateProd := vars.GetLocalExtAlgebra(g.wiresIntermediateProd(i))
evalDiff := glApi.SubExtensionAlgebra(intermediateEval, computedEval)
for j := 0; j < gl.D; j++ {
constraints = append(constraints, evalDiff[j])
}
prodDiff := glApi.SubExtensionAlgebra(intermediateProd, computedProd)
for j := 0; j < gl.D; j++ {
constraints = append(constraints, prodDiff[j])
}
startIndex := 1 + (g.degree-1)*(i+1)
endIndex := startIndex + g.degree - 1
computedEval, computedProd = glApi.PartialInterpolateExtAlgebra(
domain[startIndex:endIndex],
values[startIndex:endIndex],
weights[startIndex:endIndex],
shiftedEvaluationPoint,
intermediateEval,
intermediateProd,
)
}
evaluationValue := vars.GetLocalExtAlgebra(g.wiresEvaluationValue())
evalDiff := glApi.SubExtensionAlgebra(evaluationValue, computedEval)
for j := 0; j < gl.D; j++ {
constraints = append(constraints, evalDiff[j])
}
return constraints
}

View File

@@ -0,0 +1,105 @@
package gates
import (
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
type EvaluateGatesChip struct {
api frontend.API
gates []Gate
numGateConstraints uint64
selectorsInfo SelectorsInfo
}
func NewEvaluateGatesChip(
api frontend.API,
gates []Gate,
numGateConstraints uint64,
selectorsInfo SelectorsInfo,
) *EvaluateGatesChip {
return &EvaluateGatesChip{
api: api,
gates: gates,
numGateConstraints: numGateConstraints,
selectorsInfo: selectorsInfo,
}
}
func (g *EvaluateGatesChip) computeFilter(
row uint64,
groupRange Range,
s gl.QuadraticExtensionVariable,
manySelector bool,
) gl.QuadraticExtensionVariable {
glApi := gl.NewChip(g.api)
product := gl.OneExtension()
for i := groupRange.start; i < groupRange.end; i++ {
if i == uint64(row) {
continue
}
tmp := gl.NewQuadraticExtensionVariable(gl.NewVariable(i), gl.Zero())
product = glApi.MulExtension(product, glApi.SubExtension(tmp, s))
}
if manySelector {
tmp := gl.NewQuadraticExtensionVariable(gl.NewVariable(UNUSED_SELECTOR), gl.Zero())
product = glApi.MulExtension(product, glApi.SubExtension(tmp, s))
}
return product
}
func (g *EvaluateGatesChip) evalFiltered(
gate Gate,
vars EvaluationVars,
row uint64,
selectorIndex uint64,
groupRange Range,
numSelectors uint64,
) []gl.QuadraticExtensionVariable {
glApi := gl.NewChip(g.api)
filter := g.computeFilter(row, groupRange, vars.localConstants[selectorIndex], numSelectors > 1)
vars.RemovePrefix(numSelectors)
unfiltered := gate.EvalUnfiltered(g.api, *glApi, vars)
for i := range unfiltered {
unfiltered[i] = glApi.MulExtension(unfiltered[i], filter)
}
return unfiltered
}
func (g *EvaluateGatesChip) EvaluateGateConstraints(vars EvaluationVars) []gl.QuadraticExtensionVariable {
glApi := gl.NewChip(g.api)
constraints := make([]gl.QuadraticExtensionVariable, g.numGateConstraints)
for i := range constraints {
constraints[i] = gl.ZeroExtension()
}
for i, gate := range g.gates {
selectorIndex := g.selectorsInfo.selectorIndices[i]
gateConstraints := g.evalFiltered(
gate,
vars,
uint64(i),
selectorIndex,
g.selectorsInfo.groups[selectorIndex],
g.selectorsInfo.NumSelectors(),
)
for i, constraint := range gateConstraints {
if uint64(i) >= g.numGateConstraints {
panic("num_constraints() gave too low of a number")
}
constraints[i] = glApi.AddExtension(constraints[i], constraint)
}
}
return constraints
}

View File

@@ -0,0 +1,114 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var exponentiationGateRegex = regexp.MustCompile("ExponentiationGate { num_power_bits: (?P<numPowerBits>[0-9]+), _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=(?P<base>[0-9]+)>")
func deserializeExponentiationGate(parameters map[string]string) Gate {
// Has the format "ExponentiationGate { num_power_bits: 67, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>"
numPowerBits, hasNumPowerBits := parameters["numPowerBits"]
if !hasNumPowerBits {
panic("Missing field num_power_bits in ExponentiationGate")
}
numPowerBitsInt, err := strconv.Atoi(numPowerBits)
if err != nil {
panic("Invalid num_power_bits field in ExponentiationGate")
}
return NewExponentiationGate(uint64(numPowerBitsInt))
}
type ExponentiationGate struct {
numPowerBits uint64
}
func NewExponentiationGate(numPowerBits uint64) *ExponentiationGate {
return &ExponentiationGate{
numPowerBits: numPowerBits,
}
}
func (g *ExponentiationGate) Id() string {
return fmt.Sprintf("ExponentiationGate { num_power_bits: %d }", g.numPowerBits)
}
func (g *ExponentiationGate) wireBase() uint64 {
return 0
}
// / The `i`th bit of the exponent, in little-endian order.
func (g *ExponentiationGate) wirePowerBit(i uint64) uint64 {
if i >= g.numPowerBits {
panic("Invalid power bit index")
}
return 1 + i
}
func (g *ExponentiationGate) wireOutput() uint64 {
return 1 + g.numPowerBits
}
func (g *ExponentiationGate) wireIntermediateValue(i uint64) uint64 {
if i >= g.numPowerBits {
panic("Invalid intermediate value index")
}
return 2 + g.numPowerBits + i
}
func (g *ExponentiationGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
base := vars.localWires[g.wireBase()]
var powerBits []gl.QuadraticExtensionVariable
for i := uint64(0); i < g.numPowerBits; i++ {
powerBits = append(powerBits, vars.localWires[g.wirePowerBit(i)])
}
var intermediateValues []gl.QuadraticExtensionVariable
for i := uint64(0); i < g.numPowerBits; i++ {
intermediateValues = append(intermediateValues, vars.localWires[g.wireIntermediateValue(i)])
}
output := vars.localWires[g.wireOutput()]
var constraints []gl.QuadraticExtensionVariable
for i := uint64(0); i < g.numPowerBits; i++ {
var prevIntermediateValue gl.QuadraticExtensionVariable
if i == 0 {
prevIntermediateValue = gl.OneExtension()
} else {
prevIntermediateValue = glApi.MulExtension(intermediateValues[i-1], intermediateValues[i-1])
}
// powerBits is in LE order, but we accumulate in BE order.
curBit := powerBits[g.numPowerBits-i-1]
// Do a polynomial representation of generaized select (where the selector variable doesn't have to be binary)
// if b { x } else { y }
// i.e. `bx - (by-y)`.
tmp := glApi.MulExtension(curBit, gl.OneExtension())
tmp = glApi.SubExtension(tmp, gl.OneExtension())
mulBy := glApi.MulExtension(curBit, base)
mulBy = glApi.SubExtension(mulBy, tmp)
intermediateValueDiff := glApi.MulExtension(prevIntermediateValue, mulBy)
intermediateValueDiff = glApi.SubExtension(intermediateValueDiff, intermediateValues[i])
constraints = append(constraints, intermediateValueDiff)
}
outputDiff := glApi.SubExtension(output, intermediateValues[g.numPowerBits-1])
constraints = append(constraints, outputDiff)
return constraints
}

54
plonk/gates/gates.go Normal file
View File

@@ -0,0 +1,54 @@
package gates
import (
"fmt"
"regexp"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
type Gate interface {
Id() string
EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable
}
var gateRegexHandlers = map[*regexp.Regexp]func(parameters map[string]string) Gate{
aritheticGateRegex: deserializeArithmeticGate,
aritheticExtensionGateRegex: deserializeExtensionArithmeticGate,
baseSumGateRegex: deserializeBaseSumGate,
constantGateRegex: deserializeConstantGate,
cosetInterpolationGateRegex: deserializeCosetInterpolationGate,
exponentiationGateRegex: deserializeExponentiationGate,
mulExtensionGateRegex: deserializeMulExtensionGate,
noopGateRegex: deserializeNoopGate,
poseidonGateRegex: deserializePoseidonGate,
poseidonMdsGateRegex: deserializePoseidonMdsGate,
publicInputGateRegex: deserializePublicInputGate,
randomAccessGateRegex: deserializeRandomAccessGate,
reducingExtensionGateRegex: deserializeReducingExtensionGate,
reducingGateRegex: deserializeReducingGate,
}
func GateInstanceFromId(gateId string) Gate {
for regex, handler := range gateRegexHandlers {
matches := regex.FindStringSubmatch(gateId)
if matches != nil {
parameters := make(map[string]string)
for i, name := range regex.SubexpNames() {
if i != 0 && name != "" {
parameters[name] = matches[i]
}
}
if matches != nil {
return handler(parameters)
}
}
}
panic(fmt.Sprintf("Unknown gate ID %s", gateId))
}

768
plonk/gates/gates_test.go Normal file
View File

@@ -0,0 +1,768 @@
package gates_test
import (
"errors"
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/field/goldilocks"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/test"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
"github.com/succinctlabs/gnark-plonky2-verifier/plonk/gates"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier"
)
// From recursive_step circuit
var localConstants = []gl.QuadraticExtensionVariable{
{gl.NewVariable("4962976205186800892"), gl.NewVariable("6982360466972099197")},
{gl.NewVariable("3587364333101709084"), gl.NewVariable("17496916837371484700")},
{gl.NewVariable("17287374881609559799"), gl.NewVariable("3152841633956965234")},
{gl.NewVariable("8531030241248616826"), gl.NewVariable("7753678118587211959")},
{gl.NewVariable("7622109056373824903"), gl.NewVariable("6523636236475969621")},
}
var localWires = []gl.QuadraticExtensionVariable{
{gl.NewVariable("5101665081776077058"), gl.NewVariable("13601771238484783081")},
{gl.NewVariable("13763997788502656587"), gl.NewVariable("6068443864169526207")},
{gl.NewVariable("10492880302699453810"), gl.NewVariable("11304418575668616669")},
{gl.NewVariable("2175168501339052813"), gl.NewVariable("3658211467579027796")},
{gl.NewVariable("11342710587435471757"), gl.NewVariable("658078906333318768")},
{gl.NewVariable("16590262768413671742"), gl.NewVariable("4678191900868819358")},
{gl.NewVariable("18412513594273328173"), gl.NewVariable("3981245463942959904")},
{gl.NewVariable("18150166316938544267"), gl.NewVariable("6968565044901838140")},
{gl.NewVariable("1048835939602984673"), gl.NewVariable("3511920575130606798")},
{gl.NewVariable("13693300152826538654"), gl.NewVariable("5872314861500881782")},
{gl.NewVariable("6394696263219721312"), gl.NewVariable("92364988976021720")},
{gl.NewVariable("468193345380249942"), gl.NewVariable("4951036536117371576")},
{gl.NewVariable("9660006729985637684"), gl.NewVariable("14762789799642492635")},
{gl.NewVariable("10091149087332313493"), gl.NewVariable("13279468039286967053")},
{gl.NewVariable("12007469191150580744"), gl.NewVariable("2495445179052731885")},
{gl.NewVariable("14225726459587943147"), gl.NewVariable("13484648741862607201")},
{gl.NewVariable("15365400400136175672"), gl.NewVariable("12227857303059870833")},
{gl.NewVariable("1717742269682481687"), gl.NewVariable("14319701537357602192")},
{gl.NewVariable("2130805637557027375"), gl.NewVariable("9674794597783493233")},
{gl.NewVariable("4200526016516623452"), gl.NewVariable("1757832412907480092")},
{gl.NewVariable("4159226258922372229"), gl.NewVariable("2121976810680943769")},
{gl.NewVariable("2887943290582259162"), gl.NewVariable("10337505797799617185")},
{gl.NewVariable("14760843822980496189"), gl.NewVariable("16331301823872182680")},
{gl.NewVariable("14715580754822129725"), gl.NewVariable("13761736659446638375")},
{gl.NewVariable("6925818640561435525"), gl.NewVariable("14142327999826777974")},
{gl.NewVariable("14048060513252076245"), gl.NewVariable("14860933194240516940")},
{gl.NewVariable("3928889853630846436"), gl.NewVariable("16211791673476822740")},
{gl.NewVariable("15980387576926781891"), gl.NewVariable("6238947314711778055")},
{gl.NewVariable("15694939331980119296"), gl.NewVariable("8708301222382733590")},
{gl.NewVariable("192757930858294268"), gl.NewVariable("5400388905722847256")},
{gl.NewVariable("17614358883814855964"), gl.NewVariable("11499208634388453518")},
{gl.NewVariable("9523994443422431577"), gl.NewVariable("6835394446482946098")},
{gl.NewVariable("10096606893378243201"), gl.NewVariable("8982086840326369907")},
{gl.NewVariable("7328922720001507777"), gl.NewVariable("17298728994563323488")},
{gl.NewVariable("7038859554184407337"), gl.NewVariable("6498153778103681368")},
{gl.NewVariable("10610651604960433540"), gl.NewVariable("18240735600936975661")},
{gl.NewVariable("4310901749476028644"), gl.NewVariable("17813866938235850894")},
{gl.NewVariable("12456949458361594924"), gl.NewVariable("16541357680870686003")},
{gl.NewVariable("13986559680062429806"), gl.NewVariable("14210541290696888125")},
{gl.NewVariable("10299578396192380820"), gl.NewVariable("18011235767871391546")},
{gl.NewVariable("747566550336808782"), gl.NewVariable("5892109075601553099")},
{gl.NewVariable("11613383633841665100"), gl.NewVariable("3562006923196410047")},
{gl.NewVariable("14971867523312360339"), gl.NewVariable("9835080574905235511")},
{gl.NewVariable("5487884847548072736"), gl.NewVariable("17112808386797082519")},
{gl.NewVariable("1687420180518659740"), gl.NewVariable("14003627304711288225")},
{gl.NewVariable("6760442482244819429"), gl.NewVariable("15796493945480647537")},
{gl.NewVariable("2639939427088481105"), gl.NewVariable("16213109089273184951")},
{gl.NewVariable("6186345082501710713"), gl.NewVariable("2529053005908871239")},
{gl.NewVariable("16270115914931256348"), gl.NewVariable("2789355919627681645")},
{gl.NewVariable("4586999018177783314"), gl.NewVariable("2427837399215959725")},
{gl.NewVariable("18143358622388343317"), gl.NewVariable("2145167333845152043")},
{gl.NewVariable("20367062449222124"), gl.NewVariable("14939961527015734373")},
{gl.NewVariable("16851694158642043266"), gl.NewVariable("5250789952541240163")},
{gl.NewVariable("273375074794411822"), gl.NewVariable("16211897175907793903")},
{gl.NewVariable("8905927930385832568"), gl.NewVariable("6540262589846603524")},
{gl.NewVariable("9283781971254844102"), gl.NewVariable("15115068064900745758")},
{gl.NewVariable("16002987404851668189"), gl.NewVariable("15226686847545140008")},
{gl.NewVariable("17201679792194997813"), gl.NewVariable("589849108691638964")},
{gl.NewVariable("13270753269614250355"), gl.NewVariable("13858862497673084592")},
{gl.NewVariable("3679908279346826560"), gl.NewVariable("10125726541855725943")},
{gl.NewVariable("9493227554592600240"), gl.NewVariable("13229107531594530196")},
{gl.NewVariable("10072423214517113799"), gl.NewVariable("1877804054697703518")},
{gl.NewVariable("9351494680554520560"), gl.NewVariable("12930187723253788505")},
{gl.NewVariable("9537056082833040850"), gl.NewVariable("3947445714701039423")},
{gl.NewVariable("978662253133020143"), gl.NewVariable("17432233037279205717")},
{gl.NewVariable("13408331971471826902"), gl.NewVariable("8338873650278204671")},
{gl.NewVariable("10455530172494355126"), gl.NewVariable("14614842120953588617")},
{gl.NewVariable("3066054670984065145"), gl.NewVariable("11061840675948823020")},
{gl.NewVariable("1215442291812236170"), gl.NewVariable("6970679356502977963")},
{gl.NewVariable("16254140688845356393"), gl.NewVariable("16413217415268481315")},
{gl.NewVariable("5571707217813279614"), gl.NewVariable("2506082641312169038")},
{gl.NewVariable("18179591596294163519"), gl.NewVariable("16131760445397495720")},
{gl.NewVariable("9500821197677833979"), gl.NewVariable("14137570623214003877")},
{gl.NewVariable("18159279414894480072"), gl.NewVariable("316120438770524969")},
{gl.NewVariable("18164288455905080997"), gl.NewVariable("12889510574086616078")},
{gl.NewVariable("7158952489901063870"), gl.NewVariable("8855957421923524202")},
{gl.NewVariable("11785615172910130564"), gl.NewVariable("13242859272114186921")},
{gl.NewVariable("7978627011292316159"), gl.NewVariable("12030929068833787030")},
{gl.NewVariable("5676253512795062173"), gl.NewVariable("9401396509276686822")},
{gl.NewVariable("13934555872940874542"), gl.NewVariable("12262482935570269103")},
{gl.NewVariable("17018864997992880664"), gl.NewVariable("8399037137658253821")},
{gl.NewVariable("1846702834278938262"), gl.NewVariable("13210394651984411322")},
{gl.NewVariable("18406563809882201846"), gl.NewVariable("15807625126691296911")},
{gl.NewVariable("16192554501791210701"), gl.NewVariable("15105514277710825451")},
{gl.NewVariable("16115514979166385045"), gl.NewVariable("5618092869410987045")},
{gl.NewVariable("9816852940756124129"), gl.NewVariable("1617435612712694609")},
{gl.NewVariable("15012743324956680415"), gl.NewVariable("11098953448520716956")},
{gl.NewVariable("7370750057902285338"), gl.NewVariable("15456123684241865136")},
{gl.NewVariable("14924801177398773859"), gl.NewVariable("1116868612459919368")},
{gl.NewVariable("509701279674911901"), gl.NewVariable("8606220700917290973")},
{gl.NewVariable("256371784527067555"), gl.NewVariable("18023759020251995084")},
{gl.NewVariable("4027645791496469270"), gl.NewVariable("6446906876250510281")},
{gl.NewVariable("8190141658485644545"), gl.NewVariable("3259909135802998300")},
{gl.NewVariable("11270185749533517292"), gl.NewVariable("7032460358965516338")},
{gl.NewVariable("12112891112487601597"), gl.NewVariable("3686732542066412082")},
{gl.NewVariable("18143522178445971138"), gl.NewVariable("6066438010126851248")},
{gl.NewVariable("16109160830754618815"), gl.NewVariable("2728516440557525242")},
{gl.NewVariable("14634072837475699881"), gl.NewVariable("423778353213757146")},
{gl.NewVariable("10421081673554059162"), gl.NewVariable("10142208889746521219")},
{gl.NewVariable("12957639310809930956"), gl.NewVariable("1709286023553869935")},
{gl.NewVariable("16217923109113456531"), gl.NewVariable("3257438610376598615")},
{gl.NewVariable("14024104132094810570"), gl.NewVariable("6065015478137587430")},
{gl.NewVariable("7972303368219061571"), gl.NewVariable("5413678307283424945")},
{gl.NewVariable("10367882107777269226"), gl.NewVariable("9366367173763419226")},
{gl.NewVariable("11506720810821148150"), gl.NewVariable("15210537421649867625")},
{gl.NewVariable("10979917526797364486"), gl.NewVariable("3365843489182711842")},
{gl.NewVariable("9176981360155624350"), gl.NewVariable("7315956459698675112")},
{gl.NewVariable("3964217770504101577"), gl.NewVariable("9088242192411952739")},
{gl.NewVariable("16243289324567090937"), gl.NewVariable("13379263550784156456")},
{gl.NewVariable("18105277122985331384"), gl.NewVariable("13639149553905751132")},
{gl.NewVariable("11145583988660932112"), gl.NewVariable("16125114195985557867")},
{gl.NewVariable("18437667738670181477"), gl.NewVariable("8593343353929068644")},
{gl.NewVariable("15549894364614350199"), gl.NewVariable("6234736889764963090")},
{gl.NewVariable("17753837009416762390"), gl.NewVariable("15297774054893249240")},
{gl.NewVariable("1465043006528110247"), gl.NewVariable("11029942851654974974")},
{gl.NewVariable("14312704742949520917"), gl.NewVariable("17324353686056674958")},
{gl.NewVariable("8078333430227959261"), gl.NewVariable("14797545414164578336")},
{gl.NewVariable("3544997838139687150"), gl.NewVariable("8846840377946705678")},
{gl.NewVariable("9981846866090807073"), gl.NewVariable("18142560414179130259")},
{gl.NewVariable("1256577435119993994"), gl.NewVariable("155745544208227129")},
{gl.NewVariable("6040293874299819317"), gl.NewVariable("10483265617246740662")},
{gl.NewVariable("976159477616343697"), gl.NewVariable("6356544693059700239")},
{gl.NewVariable("4771747444846377672"), gl.NewVariable("2466985401424965488")},
{gl.NewVariable("9549711421417753693"), gl.NewVariable("9543806479040458857")},
{gl.NewVariable("5277199124405775998"), gl.NewVariable("6251037001966593402")},
{gl.NewVariable("13103543598051591262"), gl.NewVariable("2001921170471454234")},
{gl.NewVariable("1254878001165263070"), gl.NewVariable("17587272030879777460")},
{gl.NewVariable("2300344156307624878"), gl.NewVariable("14356513038946626528")},
{gl.NewVariable("2482567400777596327"), gl.NewVariable("3314129985687795881")},
{gl.NewVariable("16492046206730922155"), gl.NewVariable("1312905854247159931")},
{gl.NewVariable("3061501132630116372"), gl.NewVariable("13315665946615810001")},
{gl.NewVariable("16415932954051444990"), gl.NewVariable("925217124969456536")},
{gl.NewVariable("9764657158286137619"), gl.NewVariable("16039332713210679567")},
{gl.NewVariable("14993545086997628961"), gl.NewVariable("18010329211070748489")},
{gl.NewVariable("17327862012036619887"), gl.NewVariable("16962349802452905993")},
{gl.NewVariable("4826313026336060985"), gl.NewVariable("3597777099127511952")},
}
var publicInputsHash = poseidon.GoldilocksHashOut{
gl.Zero(),
gl.Zero(),
gl.Zero(),
gl.Zero(),
}
var publicInputGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("5101665081776077058"), gl.NewVariable("13601771238484783081")},
{gl.NewVariable("13763997788502656587"), gl.NewVariable("6068443864169526207")},
{gl.NewVariable("10492880302699453810"), gl.NewVariable("11304418575668616669")},
{gl.NewVariable("2175168501339052813"), gl.NewVariable("3658211467579027796")},
}
// BaseSumGate { num_limbs: 63 }), (Base: 2)
var baseSumGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("9928715244459351681"), gl.NewVariable("5344081500364361215")},
{gl.NewVariable("10167164649082076581"), gl.NewVariable("15450889555489725096")},
{gl.NewVariable("3546584706462116594"), gl.NewVariable("1476426705388693036")},
{gl.NewVariable("12648634003162244983"), gl.NewVariable("2239452344495239178")},
{gl.NewVariable("2301087631440580451"), gl.NewVariable("11975672920337250307")},
{gl.NewVariable("14001554463269171732"), gl.NewVariable("6953207277617809048")},
{gl.NewVariable("9895590040747031510"), gl.NewVariable("1356956949635190505")},
{gl.NewVariable("14939964178677988571"), gl.NewVariable("454717738260444218")},
{gl.NewVariable("12201660109699192297"), gl.NewVariable("12502457673278583036")},
{gl.NewVariable("1175543972635147885"), gl.NewVariable("11103026408792334489")},
{gl.NewVariable("3384025741923988904"), gl.NewVariable("2656764746353452717")},
{gl.NewVariable("10849522185534943138"), gl.NewVariable("13172212508084788997")},
{gl.NewVariable("10509522572526523739"), gl.NewVariable("2090707475955491976")},
{gl.NewVariable("13692600715410336206"), gl.NewVariable("7227633217973806771")},
{gl.NewVariable("8471053080480597138"), gl.NewVariable("2646922138422495173")},
{gl.NewVariable("555344530120410083"), gl.NewVariable("13860459564781531385")},
{gl.NewVariable("8748801107049442833"), gl.NewVariable("9263752460533085733")},
{gl.NewVariable("13633964398888639692"), gl.NewVariable("10068133633095351031")},
{gl.NewVariable("6911322073377914708"), gl.NewVariable("17978361073083837803")},
{gl.NewVariable("11223090828346729804"), gl.NewVariable("5006610230932979596")},
{gl.NewVariable("11581626217660221266"), gl.NewVariable("16347470001077006094")},
{gl.NewVariable("2924189901864366701"), gl.NewVariable("4309265474738828848")},
{gl.NewVariable("7275314468944461178"), gl.NewVariable("3109308884739285751")},
{gl.NewVariable("12416988612575693809"), gl.NewVariable("13772367397588066248")},
{gl.NewVariable("15438805794425696237"), gl.NewVariable("5809350894111990599")},
{gl.NewVariable("4275145128501503120"), gl.NewVariable("13230668146909969114")},
{gl.NewVariable("15244699495724739585"), gl.NewVariable("7672322205441472064")},
{gl.NewVariable("5429809680618805220"), gl.NewVariable("3153880467220264060")},
{gl.NewVariable("14715345489518514160"), gl.NewVariable("2246036712337629635")},
{gl.NewVariable("9359342125434211935"), gl.NewVariable("7844760208539761732")},
{gl.NewVariable("17550561700498841003"), gl.NewVariable("10851755490050776878")},
{gl.NewVariable("12192385328855013814"), gl.NewVariable("6629056869404844416")},
{gl.NewVariable("3424745785197724925"), gl.NewVariable("9833599393425172230")},
{gl.NewVariable("8602078107149096927"), gl.NewVariable("6592109323720773368")},
{gl.NewVariable("4109716921881297082"), gl.NewVariable("4396469548700606105")},
{gl.NewVariable("10400304110319417426"), gl.NewVariable("1229823145437740976")},
{gl.NewVariable("14853277673343952974"), gl.NewVariable("7653131044140686982")},
{gl.NewVariable("15831955783787857197"), gl.NewVariable("16541106185743830609")},
{gl.NewVariable("16097830673407036871"), gl.NewVariable("917501749911433098")},
{gl.NewVariable("6819428296662518848"), gl.NewVariable("15325182544903569500")},
{gl.NewVariable("3554857310728040215"), gl.NewVariable("17540168721765377170")},
{gl.NewVariable("7246216899469226885"), gl.NewVariable("3184709231158489554")},
{gl.NewVariable("3462793508732024933"), gl.NewVariable("13410498916934897793")},
{gl.NewVariable("784714181705176804"), gl.NewVariable("8079390288171846846")},
{gl.NewVariable("4592501261546923410"), gl.NewVariable("6046244648190342248")},
{gl.NewVariable("14100558314779073910"), gl.NewVariable("9589305391181830029")},
{gl.NewVariable("7208216654581381179"), gl.NewVariable("16662177305876430630")},
{gl.NewVariable("13442246990998561849"), gl.NewVariable("6359024918649040199")},
{gl.NewVariable("16196376030005699590"), gl.NewVariable("5656446490425854681")},
{gl.NewVariable("16279173216505198700"), gl.NewVariable("6278440230935274234")},
{gl.NewVariable("9299204333782277508"), gl.NewVariable("5539548698065086849")},
{gl.NewVariable("531539748103362347"), gl.NewVariable("17008402782657673980")},
{gl.NewVariable("11956287871118080485"), gl.NewVariable("17776888431041950837")},
{gl.NewVariable("16795401491637949606"), gl.NewVariable("12112971435724505573")},
{gl.NewVariable("10141270150228316653"), gl.NewVariable("8738825159351228227")},
{gl.NewVariable("4249416130151320263"), gl.NewVariable("4171109024390883108")},
{gl.NewVariable("13565954345346642147"), gl.NewVariable("11300077318998472624")},
{gl.NewVariable("6006413348327738680"), gl.NewVariable("17429146764001291339")},
{gl.NewVariable("3009379005164242386"), gl.NewVariable("17911649148503516453")},
{gl.NewVariable("4172202865347441020"), gl.NewVariable("6700979848078030374")},
{gl.NewVariable("9692174554453081047"), gl.NewVariable("16461309050820528716")},
{gl.NewVariable("16012555505188709835"), gl.NewVariable("875036531415994728")},
{gl.NewVariable("14527388813134058525"), gl.NewVariable("13371873777459370318")},
{gl.NewVariable("6493493657980111839"), gl.NewVariable("14874520839734823069")},
}
// ArithmeticGate { num_ops: 20 }
var arithmeticGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("8251494922795803874"), gl.NewVariable("7884328911897949424")},
{gl.NewVariable("17545754596575389449"), gl.NewVariable("15111927979676704385")},
{gl.NewVariable("10052040965126353731"), gl.NewVariable("1448153912054014611")},
{gl.NewVariable("3878848318701063854"), gl.NewVariable("15999854355391952993")},
{gl.NewVariable("2194699804496089007"), gl.NewVariable("7489112350095609056")},
{gl.NewVariable("666656317372820215"), gl.NewVariable("8333111246649438880")},
{gl.NewVariable("15500013716804095980"), gl.NewVariable("7739144386812042617")},
{gl.NewVariable("2815612394018416154"), gl.NewVariable("15839168197108305099")},
{gl.NewVariable("12980309813768330187"), gl.NewVariable("12446111953378048591")},
{gl.NewVariable("1389916348936822477"), gl.NewVariable("2080258147396834809")},
{gl.NewVariable("3676770229830052631"), gl.NewVariable("8984521981419906260")},
{gl.NewVariable("4759606161035299488"), gl.NewVariable("18415228017149216426")},
{gl.NewVariable("6849567585629675684"), gl.NewVariable("15231001333591586187")},
{gl.NewVariable("17831496121270832947"), gl.NewVariable("1868580989876710210")},
{gl.NewVariable("12226832860244216901"), gl.NewVariable("12352098694767236965")},
{gl.NewVariable("9795530155924375772"), gl.NewVariable("4833402654226660686")},
{gl.NewVariable("7421277748600887772"), gl.NewVariable("16979590244320625600")},
{gl.NewVariable("4212532134312824848"), gl.NewVariable("7938725153260099101")},
{gl.NewVariable("17718231164451799422"), gl.NewVariable("13363195988334771788")},
{gl.NewVariable("5414385531680474153"), gl.NewVariable("13600409983387272243")},
}
// RandomAccessGate { bits: 4, num_copies: 4, num_extra_constants: 2, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>
var randomAccessGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("18367067186009695282"), gl.NewVariable("6227937229941915629")},
{gl.NewVariable("342627832935644960"), gl.NewVariable("11262336464371657587")},
{gl.NewVariable("7711502047853221895"), gl.NewVariable("9814305320358879113")},
{gl.NewVariable("2436675870898619939"), gl.NewVariable("12171743011114835714")},
{gl.NewVariable("9224796650008092960"), gl.NewVariable("197827193844666436")},
{gl.NewVariable("7661651717350955969"), gl.NewVariable("3929163527437938921")},
{gl.NewVariable("11994613277879586781"), gl.NewVariable("2918199453077793278")},
{gl.NewVariable("2133315582796573410"), gl.NewVariable("9920472598641951727")},
{gl.NewVariable("5763420675219782924"), gl.NewVariable("193200772658790662")},
{gl.NewVariable("14322103909897767697"), gl.NewVariable("2455403487869979318")},
{gl.NewVariable("3583177870835306708"), gl.NewVariable("15956920993825363087")},
{gl.NewVariable("15767764327818217757"), gl.NewVariable("17814936958431909187")},
{gl.NewVariable("7224551806569620055"), gl.NewVariable("1191241782303323453")},
{gl.NewVariable("3994846439282900915"), gl.NewVariable("16007298430807731888")},
{gl.NewVariable("1904864531973789879"), gl.NewVariable("9374437322489636375")},
{gl.NewVariable("17617411600595291430"), gl.NewVariable("11804426503917788826")},
{gl.NewVariable("5010213812557284606"), gl.NewVariable("8276410914978849008")},
{gl.NewVariable("13701536021647106057"), gl.NewVariable("5043776904396037625")},
{gl.NewVariable("4336267979289896624"), gl.NewVariable("8771134635816393433")},
{gl.NewVariable("17885926480537171976"), gl.NewVariable("9644095314646547597")},
{gl.NewVariable("17179233085824331332"), gl.NewVariable("6950525108693323209")},
{gl.NewVariable("9461258042008745175"), gl.NewVariable("6766975264204597922")},
{gl.NewVariable("10838154179711471883"), gl.NewVariable("16554457937262927355")},
{gl.NewVariable("5823858951686479642"), gl.NewVariable("10171201631442530906")},
{gl.NewVariable("17476953112985367168"), gl.NewVariable("12062851564787792403")},
{gl.NewVariable("7909573710893929152"), gl.NewVariable("6207515797705444652")},
}
// PoseidonGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>
var poseidonGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("15438805794425696237"), gl.NewVariable("5809350894111990599")},
{gl.NewVariable("105238306594298866"), gl.NewVariable("6398155585902798861")},
{gl.NewVariable("5256232026568856387"), gl.NewVariable("9253448664982005262")},
{gl.NewVariable("6559974022172208218"), gl.NewVariable("14478753759394222537")},
{gl.NewVariable("7036928093413865537"), gl.NewVariable("895644692646980845")},
{gl.NewVariable("6350074916129003337"), gl.NewVariable("10418298512623677843")},
{gl.NewVariable("6618288817893266284"), gl.NewVariable("17565920952415773065")},
{gl.NewVariable("7214268149308735221"), gl.NewVariable("17797640553663908886")},
{gl.NewVariable("17038147867485750883"), gl.NewVariable("10766691853641769251")},
{gl.NewVariable("1228066111137794024"), gl.NewVariable("1267834319488006514")},
{gl.NewVariable("15317834050441961579"), gl.NewVariable("13280896488837969140")},
{gl.NewVariable("10135227968960430585"), gl.NewVariable("7096433509203324519")},
{gl.NewVariable("10733417635899979276"), gl.NewVariable("16819459255105516700")},
{gl.NewVariable("4231839251429338586"), gl.NewVariable("3213678047797020863")},
{gl.NewVariable("16271445286187692537"), gl.NewVariable("15377656608157234934")},
{gl.NewVariable("9356442829698587975"), gl.NewVariable("14633910545825415036")},
{gl.NewVariable("13952390018297698734"), gl.NewVariable("16325393355066618599")},
{gl.NewVariable("11399251131586292643"), gl.NewVariable("16257107051968717815")},
{gl.NewVariable("4274092107872068929"), gl.NewVariable("15550597684938436610")},
{gl.NewVariable("13076618331457049912"), gl.NewVariable("4958059540220054374")},
{gl.NewVariable("11650097218963026123"), gl.NewVariable("12070947109214611020")},
{gl.NewVariable("2700303408109034014"), gl.NewVariable("5968338348636871194")},
{gl.NewVariable("11508005723655482353"), gl.NewVariable("15224088756564969467")},
{gl.NewVariable("9328231423353697829"), gl.NewVariable("10577349809783627634")},
{gl.NewVariable("556544259468984890"), gl.NewVariable("13376447539117215836")},
{gl.NewVariable("17319865455991589647"), gl.NewVariable("588985536671201497")},
{gl.NewVariable("9528470026616131077"), gl.NewVariable("7257040911301352274")},
{gl.NewVariable("14316182132889623635"), gl.NewVariable("9589165219691594711")},
{gl.NewVariable("10405802815809041956"), gl.NewVariable("13917007789819955074")},
{gl.NewVariable("12560668105252495616"), gl.NewVariable("3591188232548111694")},
{gl.NewVariable("14765117357942682611"), gl.NewVariable("10757853341059462467")},
{gl.NewVariable("6099902163260965551"), gl.NewVariable("11343816861356056114")},
{gl.NewVariable("1083174255539258286"), gl.NewVariable("7587979659522435417")},
{gl.NewVariable("2882552180249608570"), gl.NewVariable("7966658657757662554")},
{gl.NewVariable("13490914415473336227"), gl.NewVariable("63845168436289811")},
{gl.NewVariable("9459794640071212413"), gl.NewVariable("13417331052474309186")},
{gl.NewVariable("18328090807516092318"), gl.NewVariable("11807085063599693782")},
{gl.NewVariable("281059606944328759"), gl.NewVariable("13352248056867426135")},
{gl.NewVariable("10905177588660050370"), gl.NewVariable("6597328385789442670")},
{gl.NewVariable("8426356906491012567"), gl.NewVariable("17214424336396001022")},
{gl.NewVariable("15696035667318839817"), gl.NewVariable("13285870048485492127")},
{gl.NewVariable("6110244444680672193"), gl.NewVariable("17558548349689468031")},
{gl.NewVariable("14614078615782659381"), gl.NewVariable("13184024850613726857")},
{gl.NewVariable("1541592450520953410"), gl.NewVariable("18339388388315914026")},
{gl.NewVariable("8059386643769157052"), gl.NewVariable("10208764910817462305")},
{gl.NewVariable("7612459820354975117"), gl.NewVariable("7582060685277695926")},
{gl.NewVariable("12515587043516861064"), gl.NewVariable("16099239041553682288")},
{gl.NewVariable("14269196473871652102"), gl.NewVariable("1225067220600668761")},
{gl.NewVariable("12691255077510636187"), gl.NewVariable("14147201911063761532")},
{gl.NewVariable("3001134598446056765"), gl.NewVariable("14313090483058155636")},
{gl.NewVariable("13964993951988177315"), gl.NewVariable("17731737838539414275")},
{gl.NewVariable("2686259154263524343"), gl.NewVariable("12198712301337570859")},
{gl.NewVariable("6730431920128908773"), gl.NewVariable("4325394084875720868")},
{gl.NewVariable("988774723104779817"), gl.NewVariable("8388266879854983623")},
{gl.NewVariable("8233087560647959985"), gl.NewVariable("7751837576340060020")},
{gl.NewVariable("9546113779017699592"), gl.NewVariable("4049920632309298778")},
{gl.NewVariable("3283837251411237060"), gl.NewVariable("13560940050752580093")},
{gl.NewVariable("10388838746951897109"), gl.NewVariable("454393475113110282")},
{gl.NewVariable("2208016536897042313"), gl.NewVariable("17105586471193083308")},
{gl.NewVariable("17683990802267567604"), gl.NewVariable("15398473956537380705")},
{gl.NewVariable("70612752050386177"), gl.NewVariable("12349994002954022957")},
{gl.NewVariable("13794244952989612728"), gl.NewVariable("15888581169565306348")},
{gl.NewVariable("8270800566553141412"), gl.NewVariable("1516938823651329185")},
{gl.NewVariable("643507941153616368"), gl.NewVariable("3893451216814345882")},
{gl.NewVariable("16464837166410943694"), gl.NewVariable("11108183142967610977")},
{gl.NewVariable("9748621820629198396"), gl.NewVariable("3766489907402036319")},
{gl.NewVariable("3115179618981245947"), gl.NewVariable("10160994694067456423")},
{gl.NewVariable("4497210741038443097"), gl.NewVariable("6445446770984515259")},
{gl.NewVariable("5470898125882256227"), gl.NewVariable("8249357863801204908")},
{gl.NewVariable("16762380205819269382"), gl.NewVariable("172510727904060494")},
{gl.NewVariable("7920011253931301350"), gl.NewVariable("9681193995678483756")},
{gl.NewVariable("8258951043315574232"), gl.NewVariable("13137471323476190588")},
{gl.NewVariable("4339364527801481944"), gl.NewVariable("16862579756243326257")},
{gl.NewVariable("8980029737458438570"), gl.NewVariable("14651625524257781922")},
{gl.NewVariable("17935993907375677671"), gl.NewVariable("5318319737405476029")},
{gl.NewVariable("716791501623731831"), gl.NewVariable("18425818060734993303")},
{gl.NewVariable("601549076806364660"), gl.NewVariable("12303919727550310013")},
{gl.NewVariable("18026376178895562118"), gl.NewVariable("14687420532194520529")},
{gl.NewVariable("16943892475592026666"), gl.NewVariable("7451688507369746594")},
{gl.NewVariable("8724072308842121373"), gl.NewVariable("11662986251379699921")},
{gl.NewVariable("3201079129905071298"), gl.NewVariable("11542621183935331871")},
{gl.NewVariable("9889739070824270529"), gl.NewVariable("3891825006545095657")},
{gl.NewVariable("15538978715382418651"), gl.NewVariable("2419672705453973015")},
{gl.NewVariable("3001525234835174062"), gl.NewVariable("17115969716224377534")},
{gl.NewVariable("18001237923148428045"), gl.NewVariable("2198015511953873786")},
{gl.NewVariable("14186741561112601666"), gl.NewVariable("13156405199205086627")},
{gl.NewVariable("10166592177477126663"), gl.NewVariable("13586051001537885658")},
{gl.NewVariable("8678352780562557555"), gl.NewVariable("1968366090049630482")},
{gl.NewVariable("5627999915794840395"), gl.NewVariable("13597556392696072088")},
{gl.NewVariable("9291327714650886898"), gl.NewVariable("2411361999629511024")},
{gl.NewVariable("6824943761729555359"), gl.NewVariable("7484507209360908175")},
{gl.NewVariable("6276580084700132178"), gl.NewVariable("6246691657613415035")},
{gl.NewVariable("10736230409698057656"), gl.NewVariable("7306720219045064925")},
{gl.NewVariable("15442170485732017109"), gl.NewVariable("1739984147692575725")},
{gl.NewVariable("4448878124301402845"), gl.NewVariable("18436455114977877323")},
{gl.NewVariable("638012599023653143"), gl.NewVariable("16265955502846626936")},
{gl.NewVariable("6793907577559820653"), gl.NewVariable("15343551069946118619")},
{gl.NewVariable("17903286158968614509"), gl.NewVariable("9559701571149911252")},
{gl.NewVariable("14652006464960400785"), gl.NewVariable("50421020503848143")},
{gl.NewVariable("9452858006432860845"), gl.NewVariable("2625726945677447428")},
{gl.NewVariable("853640589013584892"), gl.NewVariable("14655161412118141649")},
{gl.NewVariable("12863832006745352780"), gl.NewVariable("14564189651136231029")},
{gl.NewVariable("8551517270810530438"), gl.NewVariable("10859465327758962622")},
{gl.NewVariable("10113468436120661191"), gl.NewVariable("16040944006557911589")},
{gl.NewVariable("4921439225277518643"), gl.NewVariable("8399175422965154512")},
{gl.NewVariable("13068240354812957183"), gl.NewVariable("8520393046894990946")},
{gl.NewVariable("1189183420107219532"), gl.NewVariable("18066897627856601789")},
{gl.NewVariable("3997900004790871153"), gl.NewVariable("1269718920871578117")},
{gl.NewVariable("15438784576472256462"), gl.NewVariable("9577304425687441047")},
{gl.NewVariable("17158083218962275971"), gl.NewVariable("17379790274576244684")},
{gl.NewVariable("3470452736936929010"), gl.NewVariable("12769555113044633230")},
{gl.NewVariable("18389243269515626865"), gl.NewVariable("8023737530782576805")},
{gl.NewVariable("3529213023405995549"), gl.NewVariable("8829896701928525938")},
{gl.NewVariable("14072413770981804653"), gl.NewVariable("9660693090213237836")},
{gl.NewVariable("14369435038913678671"), gl.NewVariable("7659129852562422871")},
{gl.NewVariable("6779301728445724040"), gl.NewVariable("18290152515233036523")},
{gl.NewVariable("8113954200727174254"), gl.NewVariable("16490002532983549952")},
{gl.NewVariable("11465655095604389561"), gl.NewVariable("9066100972825318010")},
{gl.NewVariable("15998691377748321442"), gl.NewVariable("16970045124898180365")},
{gl.NewVariable("8424730626816696233"), gl.NewVariable("17168184083072399403")},
{gl.NewVariable("1941959246552302666"), gl.NewVariable("6751013195867127440")},
{gl.NewVariable("1907519456922228224"), gl.NewVariable("689311996911195932")},
{gl.NewVariable("16277197060525435740"), gl.NewVariable("12018417724719716072")},
}
var reducingExtensionGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("12832102811425062912"), gl.NewVariable("2979695993654444095")},
{gl.NewVariable("4822478941232734654"), gl.NewVariable("2600327308894333341")},
{gl.NewVariable("12450653411048814602"), gl.NewVariable("1161667420593062956")},
{gl.NewVariable("3145631295867407955"), gl.NewVariable("1702059944088737075")},
{gl.NewVariable("4597190091407364771"), gl.NewVariable("4257077286672555409")},
{gl.NewVariable("10177664366491925772"), gl.NewVariable("10489575701186298604")},
{gl.NewVariable("2754621968864722399"), gl.NewVariable("12087963411706301871")},
{gl.NewVariable("534408217555793149"), gl.NewVariable("12559345737194357169")},
{gl.NewVariable("9508765820222303634"), gl.NewVariable("14102461861317982082")},
{gl.NewVariable("15070954032232801974"), gl.NewVariable("2078249670161696735")},
{gl.NewVariable("10465809629504954691"), gl.NewVariable("16223748685835312497")},
{gl.NewVariable("10957196413441800202"), gl.NewVariable("3841214025425953691")},
{gl.NewVariable("18438848195188240825"), gl.NewVariable("5697684145424680565")},
{gl.NewVariable("565455534266129104"), gl.NewVariable("12543354947937779806")},
{gl.NewVariable("16376588778962418386"), gl.NewVariable("1273250903423198860")},
{gl.NewVariable("4128104469872810921"), gl.NewVariable("1433037233801071123")},
{gl.NewVariable("6011337242244377340"), gl.NewVariable("16068106780789397185")},
{gl.NewVariable("4741354504248328629"), gl.NewVariable("3000853646720964165")},
{gl.NewVariable("13064594310789140866"), gl.NewVariable("10950406741883971259")},
{gl.NewVariable("17079026691450750925"), gl.NewVariable("6522027970928818261")},
{gl.NewVariable("13158136237489326416"), gl.NewVariable("7677629162183242732")},
{gl.NewVariable("14741398060174921234"), gl.NewVariable("2960243215156352194")},
{gl.NewVariable("9111161782199179468"), gl.NewVariable("8010960876261510099")},
{gl.NewVariable("1404837029582986528"), gl.NewVariable("9377230983302764181")},
{gl.NewVariable("7086781234814455260"), gl.NewVariable("7571558192372650697")},
{gl.NewVariable("5627013434503229817"), gl.NewVariable("14984048934926143304")},
{gl.NewVariable("2115495655441739405"), gl.NewVariable("1656704965110317534")},
{gl.NewVariable("2311846135199651566"), gl.NewVariable("17438437808346967358")},
{gl.NewVariable("8679806319651401773"), gl.NewVariable("3278538718508560579")},
{gl.NewVariable("7897681105604536660"), gl.NewVariable("10966573925848082711")},
{gl.NewVariable("5451958405177630542"), gl.NewVariable("9207735009647199721")},
{gl.NewVariable("8825486358121162697"), gl.NewVariable("15997852519026522914")},
{gl.NewVariable("475225211669491693"), gl.NewVariable("1907827506180042626")},
{gl.NewVariable("16033031089519343732"), gl.NewVariable("15009948832718035672")},
{gl.NewVariable("5048598591200038865"), gl.NewVariable("156574475928756206")},
{gl.NewVariable("3580311624647961767"), gl.NewVariable("6084715537433906996")},
{gl.NewVariable("9121009921295095324"), gl.NewVariable("18407759801432275235")},
{gl.NewVariable("16569013039730214123"), gl.NewVariable("3930908108224055041")},
{gl.NewVariable("13844066138909451365"), gl.NewVariable("6585754647203519368")},
{gl.NewVariable("14133345335167543367"), gl.NewVariable("3946807387480232364")},
{gl.NewVariable("9876285028806980582"), gl.NewVariable("40898067822033734")},
{gl.NewVariable("6293483059765701407"), gl.NewVariable("16009270905706605849")},
{gl.NewVariable("11635947241393753594"), gl.NewVariable("5053395178858294866")},
{gl.NewVariable("16062194595705166277"), gl.NewVariable("752574348595159408")},
{gl.NewVariable("15607597716340375230"), gl.NewVariable("10428583315124220143")},
{gl.NewVariable("6975301479426228318"), gl.NewVariable("16528136630898216147")},
{gl.NewVariable("16312827398430223622"), gl.NewVariable("17909475722464415780")},
{gl.NewVariable("2273087545743905667"), gl.NewVariable("12405446777919046866")},
{gl.NewVariable("14781933506876191161"), gl.NewVariable("4464109151368149713")},
{gl.NewVariable("4226716729950095934"), gl.NewVariable("8908251769229049654")},
{gl.NewVariable("8310476487592089883"), gl.NewVariable("3834672170570438819")},
{gl.NewVariable("4285568636604940795"), gl.NewVariable("7183765355016179794")},
{gl.NewVariable("14300853697824059506"), gl.NewVariable("16287477445929928328")},
{gl.NewVariable("1238186507267033247"), gl.NewVariable("12357102109973664962")},
{gl.NewVariable("15607388919140050768"), gl.NewVariable("15421065238069253306")},
{gl.NewVariable("12418734453826432586"), gl.NewVariable("12072056126139297564")},
{gl.NewVariable("3924467115116313620"), gl.NewVariable("1212362379653628161")},
{gl.NewVariable("8252514850759544679"), gl.NewVariable("7893938436444134034")},
{gl.NewVariable("711675815009325200"), gl.NewVariable("15678724077367989757")},
{gl.NewVariable("10920573406841924033"), gl.NewVariable("8189696933773246220")},
{gl.NewVariable("9737295100232588618"), gl.NewVariable("13383462338120177171")},
{gl.NewVariable("8983013033045953935"), gl.NewVariable("5301160793103788033")},
{gl.NewVariable("2086512740154274197"), gl.NewVariable("9511985884344255651")},
{gl.NewVariable("7404726366142548080"), gl.NewVariable("11257391295697140486")},
{gl.NewVariable("10045968629671906256"), gl.NewVariable("10721172752468420959")},
{gl.NewVariable("9499240237398016191"), gl.NewVariable("17996498955496851489")},
}
// ReducingGate { num_coeffs: 44 }
var reducingGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("4189565386714553574"), gl.NewVariable("14972099283023295929")},
{gl.NewVariable("4811224976739448335"), gl.NewVariable("17901409314576454439")},
{gl.NewVariable("5140059407491502784"), gl.NewVariable("1144330742785924570")},
{gl.NewVariable("7077436393778991453"), gl.NewVariable("13398199711778224412")},
{gl.NewVariable("11213768990622043903"), gl.NewVariable("3886053425349218150")},
{gl.NewVariable("2946099412905029571"), gl.NewVariable("16515307040211357295")},
{gl.NewVariable("11766152895257088950"), gl.NewVariable("12561350435611412995")},
{gl.NewVariable("15559670172179416359"), gl.NewVariable("14246884723129607378")},
{gl.NewVariable("5240707719525548158"), gl.NewVariable("1640773599873992510")},
{gl.NewVariable("14358821079049832289"), gl.NewVariable("2746855687282611080")},
{gl.NewVariable("3214086216088588558"), gl.NewVariable("1520697626094905530")},
{gl.NewVariable("9834748172213967248"), gl.NewVariable("13487010468070558667")},
{gl.NewVariable("1423442768503334248"), gl.NewVariable("10945790255819476518")},
{gl.NewVariable("2308372186436983690"), gl.NewVariable("8803174935784778070")},
{gl.NewVariable("9995833078447025147"), gl.NewVariable("9074310518079663649")},
{gl.NewVariable("14149697874498108875"), gl.NewVariable("15875817120435194028")},
{gl.NewVariable("14564758547073982656"), gl.NewVariable("13386335755835868953")},
{gl.NewVariable("6432745607675418074"), gl.NewVariable("8030247499566565321")},
{gl.NewVariable("17308235779926438117"), gl.NewVariable("16843697410674499818")},
{gl.NewVariable("15507223129386571868"), gl.NewVariable("3935281607585552366")},
{gl.NewVariable("16041402982622709805"), gl.NewVariable("12432717078068957835")},
{gl.NewVariable("6455955094164032063"), gl.NewVariable("2435635342699968412")},
{gl.NewVariable("9814981570869789379"), gl.NewVariable("5009257884262115226")},
{gl.NewVariable("9452031978763862902"), gl.NewVariable("15609083603899848676")},
{gl.NewVariable("13532623109002857304"), gl.NewVariable("7324541443245949391")},
{gl.NewVariable("7899075212455453622"), gl.NewVariable("14276489152002439614")},
{gl.NewVariable("2403019844704266911"), gl.NewVariable("5922544710604013781")},
{gl.NewVariable("9709471021111675830"), gl.NewVariable("5538539165068927028")},
{gl.NewVariable("15700585567216041265"), gl.NewVariable("17893894492159337326")},
{gl.NewVariable("8890003199638063977"), gl.NewVariable("17726621767321974437")},
{gl.NewVariable("389239919653982052"), gl.NewVariable("3497778410650283061")},
{gl.NewVariable("845227572644858827"), gl.NewVariable("7040344997713673855")},
{gl.NewVariable("9861253052349275208"), gl.NewVariable("1880449137233040023")},
{gl.NewVariable("9239454143759318515"), gl.NewVariable("7968256557482935820")},
{gl.NewVariable("12576879243038758854"), gl.NewVariable("9784626207087825707")},
{gl.NewVariable("14811673587164089973"), gl.NewVariable("10785522535030299714")},
{gl.NewVariable("696437091186897361"), gl.NewVariable("13293602092569033065")},
{gl.NewVariable("1240161179290551759"), gl.NewVariable("9542275505416038259")},
{gl.NewVariable("5298553932515957396"), gl.NewVariable("14597738151157731445")},
{gl.NewVariable("8472517818840783225"), gl.NewVariable("7685861056688910111")},
{gl.NewVariable("10067665523858551777"), gl.NewVariable("13019870415534016025")},
{gl.NewVariable("3030966178198674680"), gl.NewVariable("10107838846102885642")},
{gl.NewVariable("6762889891370677550"), gl.NewVariable("16151528872832782368")},
{gl.NewVariable("17207754552662723664"), gl.NewVariable("15168039969859158460")},
{gl.NewVariable("9111161782199179468"), gl.NewVariable("8010960876261510099")},
{gl.NewVariable("1212079098724692260"), gl.NewVariable("3976842077579916925")},
{gl.NewVariable("8111924351272477885"), gl.NewVariable("1472738463707044435")},
{gl.NewVariable("14549763060495382561"), gl.NewVariable("8148654488443197206")},
{gl.NewVariable("9633247645878352168"), gl.NewVariable("4173826759172401145")},
{gl.NewVariable("13429667484612728110"), gl.NewVariable("139708813783643870")},
{gl.NewVariable("11164941208889426013"), gl.NewVariable("3615779386887825309")},
{gl.NewVariable("15733773570058687441"), gl.NewVariable("11172582394325691371")},
{gl.NewVariable("11237663549079845099"), gl.NewVariable("375954911737718734")},
{gl.NewVariable("14815280969174152094"), gl.NewVariable("17903238907570421232")},
{gl.NewVariable("12264332321023153985"), gl.NewVariable("4996015210046477989")},
{gl.NewVariable("5733452693326962912"), gl.NewVariable("15445457134261228447")},
{gl.NewVariable("11339891595047637420"), gl.NewVariable("762619178430884475")},
{gl.NewVariable("10413672060220880988"), gl.NewVariable("2522708614237496949")},
{gl.NewVariable("4759794002943168525"), gl.NewVariable("8366670758049431064")},
{gl.NewVariable("11081128192182141387"), gl.NewVariable("5264843790841556843")},
{gl.NewVariable("16467547707866820269"), gl.NewVariable("10395994280728082037")},
{gl.NewVariable("7372902852922723938"), gl.NewVariable("6597057511414169148")},
{gl.NewVariable("1246550990665510080"), gl.NewVariable("369146659419534786")},
{gl.NewVariable("107137977263990694"), gl.NewVariable("13480217899797734610")},
{gl.NewVariable("9352391006524927052"), gl.NewVariable("16474580549927501346")},
{gl.NewVariable("11475195577527382963"), gl.NewVariable("16771481018793784004")},
{gl.NewVariable("7763817490144412733"), gl.NewVariable("7847907679735875325")},
{gl.NewVariable("6954934416977006194"), gl.NewVariable("1588175103882481774")},
{gl.NewVariable("208699790124989138"), gl.NewVariable("104050776110144395")},
{gl.NewVariable("1999712470949493845"), gl.NewVariable("14640293671425837284")},
{gl.NewVariable("17489389210332023693"), gl.NewVariable("1485853484717956236")},
{gl.NewVariable("13389678828109836153"), gl.NewVariable("12239927773742888217")},
{gl.NewVariable("7279356606052782033"), gl.NewVariable("16889809967345118643")},
{gl.NewVariable("5530632913824527303"), gl.NewVariable("6593916246324540830")},
{gl.NewVariable("6517985275757881887"), gl.NewVariable("1094679265639341934")},
{gl.NewVariable("16005022297334791008"), gl.NewVariable("2231375568117939019")},
{gl.NewVariable("7801581545066110268"), gl.NewVariable("16195585011186011335")},
{gl.NewVariable("2346311239309318787"), gl.NewVariable("10194252071441594046")},
{gl.NewVariable("1333414916806612489"), gl.NewVariable("4078668601880487193")},
{gl.NewVariable("17162202837341088150"), gl.NewVariable("3946492721743094611")},
{gl.NewVariable("2372952988964786162"), gl.NewVariable("14459600129361968991")},
{gl.NewVariable("15958985504784681452"), gl.NewVariable("18297567352909625870")},
{gl.NewVariable("5468110010239944205"), gl.NewVariable("1297673223075459793")},
{gl.NewVariable("5916958362061888790"), gl.NewVariable("12686064186569549334")},
{gl.NewVariable("17141186363273294375"), gl.NewVariable("5330662447468959333")},
{gl.NewVariable("9597329746711776008"), gl.NewVariable("13290917949843243492")},
{gl.NewVariable("9061260430036409956"), gl.NewVariable("10642927510372211646")},
{gl.NewVariable("9766392710518436993"), gl.NewVariable("1864738510099355769")},
}
// ArithmeticExtensionGate { num_ops: 10 }
var arithmeticExtensionGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("14556369430662721230"), gl.NewVariable("4131185000258568561")},
{gl.NewVariable("16378466706564867046"), gl.NewVariable("1439052841211884527")},
{gl.NewVariable("8231479592213172392"), gl.NewVariable("8409169031581010782")},
{gl.NewVariable("5465959779370835700"), gl.NewVariable("17016702720873000919")},
{gl.NewVariable("10611951970626560747"), gl.NewVariable("11015475306668399283")},
{gl.NewVariable("6566683434087540889"), gl.NewVariable("7528162900166069532")},
{gl.NewVariable("13167150559619768862"), gl.NewVariable("15618445283750881414")},
{gl.NewVariable("14768578132422983729"), gl.NewVariable("13938407401080069149")},
{gl.NewVariable("18415232841919605685"), gl.NewVariable("15088528771916927003")},
{gl.NewVariable("1305736199568141897"), gl.NewVariable("16885250849392919438")},
{gl.NewVariable("1425549592953864549"), gl.NewVariable("1074162823816629148")},
{gl.NewVariable("12616210534513128803"), gl.NewVariable("8618852250387339753")},
{gl.NewVariable("16775588216530426832"), gl.NewVariable("16358913853138883160")},
{gl.NewVariable("236831045676808583"), gl.NewVariable("16231688985959438642")},
{gl.NewVariable("264831195814170716"), gl.NewVariable("9852325877887114505")},
{gl.NewVariable("14065541678187010167"), gl.NewVariable("5594602585697559035")},
{gl.NewVariable("2354884863196165822"), gl.NewVariable("12715102096346587892")},
{gl.NewVariable("5881791209743274427"), gl.NewVariable("1913490798645218291")},
{gl.NewVariable("3621056055759314065"), gl.NewVariable("15076066883455218113")},
{gl.NewVariable("15382741815013668685"), gl.NewVariable("5674166256062091576")},
}
// MulExtensionGate { num_ops: 13 }
var mulExtensionGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("14558272317822654580"), gl.NewVariable("833215892324477732")},
{gl.NewVariable("9214806296346539012"), gl.NewVariable("7798842673847612486")},
{gl.NewVariable("4933313819253472884"), gl.NewVariable("17115399133104593821")},
{gl.NewVariable("6382294466663581729"), gl.NewVariable("8863722647290983592")},
{gl.NewVariable("5274430631758054179"), gl.NewVariable("1761561038204031519")},
{gl.NewVariable("6975818216493368257"), gl.NewVariable("3643153118790582585")},
{gl.NewVariable("9382708770545050748"), gl.NewVariable("2040988809014144797")},
{gl.NewVariable("7526300035416853327"), gl.NewVariable("8692405747344509879")},
{gl.NewVariable("6092157877842311771"), gl.NewVariable("5767914690949635280")},
{gl.NewVariable("3636879736078164520"), gl.NewVariable("454792903724498694")},
{gl.NewVariable("5982213211108308130"), gl.NewVariable("3906161453783544349")},
{gl.NewVariable("1353999567434327832"), gl.NewVariable("3912356165392315450")},
{gl.NewVariable("3866250282554618990"), gl.NewVariable("14215790041865539111")},
{gl.NewVariable("16972659905821970574"), gl.NewVariable("2550277288305104044")},
{gl.NewVariable("6739526869755283609"), gl.NewVariable("4676222628249438354")},
{gl.NewVariable("18314541579046409607"), gl.NewVariable("13871312232745645647")},
{gl.NewVariable("13309435341537760906"), gl.NewVariable("10879629980202564460")},
{gl.NewVariable("8149445702527176593"), gl.NewVariable("12079787385488004774")},
{gl.NewVariable("141936326832390573"), gl.NewVariable("9852981409020916366")},
{gl.NewVariable("1174277439708011834"), gl.NewVariable("11084240604056156653")},
{gl.NewVariable("3890191667424476902"), gl.NewVariable("1428130379783403165")},
{gl.NewVariable("18264002552181363059"), gl.NewVariable("17855293364353531924")},
{gl.NewVariable("1657518282890904146"), gl.NewVariable("14874491364689193658")},
{gl.NewVariable("9091236796792826297"), gl.NewVariable("18232800981045995203")},
{gl.NewVariable("7965395014621568897"), gl.NewVariable("15643014489741966811")},
{gl.NewVariable("14048129594584036134"), gl.NewVariable("8880723489474532129")},
}
// CosetInterpolationGate { subgroup_bits: 4, degree: 6, barycentric_weights: [17293822565076172801, 18374686475376656385, 18446744069413535745, 281474976645120, 17592186044416, 18446744069414584577, 18446744000695107601, 18446744065119617025, 1152921504338411520, 72057594037927936, 18446744069415632897, 18446462594437939201, 18446726477228539905, 18446744069414584065, 68719476720, 4294967296], _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>
var cosetInterpolationGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("4489474937116132272"), gl.NewVariable("17966585078409280607")},
{gl.NewVariable("6284821823752419954"), gl.NewVariable("15732864946173560339")},
{gl.NewVariable("12879723719779486283"), gl.NewVariable("983649133858104142")},
{gl.NewVariable("17293136937393925432"), gl.NewVariable("4033193666483141970")},
{gl.NewVariable("10809912963683055710"), gl.NewVariable("3166226310305151244")},
{gl.NewVariable("13051854837169808452"), gl.NewVariable("12636844243964449888")},
{gl.NewVariable("15180422697988222141"), gl.NewVariable("3172471974421734205")},
{gl.NewVariable("7715327263429433235"), gl.NewVariable("14269461688353925342")},
{gl.NewVariable("7348198793616724228"), gl.NewVariable("11426363269581761252")},
{gl.NewVariable("6529761710182712179"), gl.NewVariable("15370899814178958348")},
{gl.NewVariable("1312640305437468539"), gl.NewVariable("7416725026793550034")},
{gl.NewVariable("7435934314089172319"), gl.NewVariable("8931511780309647479")},
}
// PoseidonMdsGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>"
var poseidonMdsGateExpectedConstraints = []gl.QuadraticExtensionVariable{
{gl.NewVariable("7821764612044984890"), gl.NewVariable("11645399715550800761")},
{gl.NewVariable("7054686226368496581"), gl.NewVariable("3456599659382547499")},
{gl.NewVariable("9932401212201586910"), gl.NewVariable("15935184283784595275")},
{gl.NewVariable("14850232436396031573"), gl.NewVariable("10054869170615550942")},
{gl.NewVariable("17859784214232634920"), gl.NewVariable("3141019307077014353")},
{gl.NewVariable("1316926243065869924"), gl.NewVariable("5447399801288094074")},
{gl.NewVariable("12198784876096903918"), gl.NewVariable("10976551553233951532")},
{gl.NewVariable("3280500541526908156"), gl.NewVariable("1813330468204166522")},
{gl.NewVariable("6788483962196012692"), gl.NewVariable("15983747071745976199")},
{gl.NewVariable("3372073447943379816"), gl.NewVariable("9356836818900551936")},
{gl.NewVariable("13834815153351545489"), gl.NewVariable("1073963211629459057")},
{gl.NewVariable("15376716257200419051"), gl.NewVariable("16044430964768811142")},
{gl.NewVariable("16752138206727891451"), gl.NewVariable("6303059651352280564")},
{gl.NewVariable("17195959285241102556"), gl.NewVariable("10990140109461952122")},
{gl.NewVariable("16812594260057394716"), gl.NewVariable("5841834090350584793")},
{gl.NewVariable("17706037262140285164"), gl.NewVariable("8626184557677598926")},
{gl.NewVariable("6826825357492466350"), gl.NewVariable("17865947929743097490")},
{gl.NewVariable("13679887869755160737"), gl.NewVariable("16481628195512675795")},
{gl.NewVariable("7881296289635150478"), gl.NewVariable("15368930380652981390")},
{gl.NewVariable("12075171536836315078"), gl.NewVariable("12900345753644751245")},
{gl.NewVariable("11461113822534614109"), gl.NewVariable("2937306395206947398")},
{gl.NewVariable("18365572828001780476"), gl.NewVariable("4309067613742479326")},
{gl.NewVariable("9460729461000852035"), gl.NewVariable("9232487430983842586")},
{gl.NewVariable("9920817005263779727"), gl.NewVariable("16326126591726196229")},
}
type TestGateCircuit struct {
testGate gates.Gate
ExpectedConstraints []gl.QuadraticExtensionVariable
}
func (circuit *TestGateCircuit) Define(api frontend.API) error {
commonCircuitData := verifier.DeserializeCommonCircuitData("../../data/decode_block/common_circuit_data.json")
numSelectors := commonCircuitData.SelectorsInfo.NumSelectors()
glApi := gl.NewChip(api)
vars := gates.NewEvaluationVars(localConstants[numSelectors:], localWires, publicInputsHash)
constraints := circuit.testGate.EvalUnfiltered(api, *glApi, *vars)
if len(constraints) != len(circuit.ExpectedConstraints) {
return errors.New("gate constraints length mismatch")
}
for i := 0; i < len(constraints); i++ {
glApi.AssertIsEqualExtension(constraints[i], circuit.ExpectedConstraints[i])
}
return nil
}
func TestGates(t *testing.T) {
assert := test.NewAssert(t)
testCase := func(testGate gates.Gate, expectedConstraints []gl.QuadraticExtensionVariable) {
circuit := &TestGateCircuit{testGate: testGate, ExpectedConstraints: expectedConstraints}
witness := &TestGateCircuit{testGate: testGate, ExpectedConstraints: expectedConstraints}
err := test.IsSolved(circuit, witness, ecc.BN254.ScalarField())
assert.NoError(err)
}
type gateTest struct {
testGate gates.Gate
expectedConstraints []gl.QuadraticExtensionVariable
}
gateTests := []gateTest{
{gates.NewPublicInputGate(), publicInputGateExpectedConstraints},
{gates.NewBaseSumGate(63, 2), baseSumGateExpectedConstraints},
{gates.NewArithmeticGate(20), arithmeticGateExpectedConstraints},
{gates.NewRandomAccessGate(4, 4, 2), randomAccessGateExpectedConstraints},
{gates.NewPoseidonGate(), poseidonGateExpectedConstraints},
{gates.NewArithmeticExtensionGate(10), arithmeticExtensionGateExpectedConstraints},
{gates.NewMultiplicationExtensionGate(13), mulExtensionGateExpectedConstraints},
{gates.NewReducingExtensionGate(33), reducingExtensionGateExpectedConstraints},
{gates.NewReducingGate(44), reducingGateExpectedConstraints},
{gates.NewCosetInterpolationGate(
4,
6,
[]goldilocks.Element{
goldilocks.NewElement(17293822565076172801),
goldilocks.NewElement(18374686475376656385),
goldilocks.NewElement(18446744069413535745),
goldilocks.NewElement(281474976645120),
goldilocks.NewElement(17592186044416),
goldilocks.NewElement(18446744069414584577),
goldilocks.NewElement(18446744000695107601),
goldilocks.NewElement(18446744065119617025),
goldilocks.NewElement(1152921504338411520),
goldilocks.NewElement(72057594037927936),
goldilocks.NewElement(18446744069415632897),
goldilocks.NewElement(18446462594437939201),
goldilocks.NewElement(18446726477228539905),
goldilocks.NewElement(18446744069414584065),
goldilocks.NewElement(68719476720),
goldilocks.NewElement(4294967296),
},
), cosetInterpolationGateExpectedConstraints},
{&gates.PoseidonMdsGate{}, poseidonMdsGateExpectedConstraints},
}
for _, test := range gateTests {
testCase(
test.testGate,
test.expectedConstraints,
)
}
}

View File

@@ -0,0 +1,76 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var mulExtensionGateRegex = regexp.MustCompile("MulExtensionGate { num_ops: (?P<numOps>[0-9]+) }")
func deserializeMulExtensionGate(parameters map[string]string) Gate {
// Has the format "MulExtensionGate { num_ops: 13 }"
numOps, hasNumOps := parameters["numOps"]
if !hasNumOps {
panic("Missing field num_ops in MulExtensionGate")
}
numOpsInt, err := strconv.Atoi(numOps)
if err != nil {
panic("Invalid num_ops field in MulExtensionGate")
}
return NewMultiplicationExtensionGate(uint64(numOpsInt))
}
type MultiplicationExtensionGate struct {
numOps uint64
}
func NewMultiplicationExtensionGate(numOps uint64) *MultiplicationExtensionGate {
return &MultiplicationExtensionGate{
numOps: numOps,
}
}
func (g *MultiplicationExtensionGate) Id() string {
return fmt.Sprintf("ArithmeticExtensionGate { num_ops: %d }", g.numOps)
}
func (g *MultiplicationExtensionGate) wiresIthMultiplicand0(i uint64) Range {
return Range{3 * gl.D * i, 3*gl.D*i + gl.D}
}
func (g *MultiplicationExtensionGate) wiresIthMultiplicand1(i uint64) Range {
return Range{3*gl.D*i + gl.D, 3*gl.D*i + 2*gl.D}
}
func (g *MultiplicationExtensionGate) wiresIthOutput(i uint64) Range {
return Range{3*gl.D*i + 2*gl.D, 3*gl.D*i + 3*gl.D}
}
func (g *MultiplicationExtensionGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
const0 := vars.localConstants[0]
constraints := []gl.QuadraticExtensionVariable{}
for i := uint64(0); i < g.numOps; i++ {
multiplicand0 := vars.GetLocalExtAlgebra(g.wiresIthMultiplicand0(i))
multiplicand1 := vars.GetLocalExtAlgebra(g.wiresIthMultiplicand1(i))
output := vars.GetLocalExtAlgebra(g.wiresIthOutput(i))
mul := glApi.MulExtensionAlgebra(multiplicand0, multiplicand1)
computed_output := glApi.ScalarMulExtensionAlgebra(const0, mul)
diff := glApi.SubExtensionAlgebra(output, computed_output)
for j := 0; j < gl.D; j++ {
constraints = append(constraints, diff[j])
}
}
return constraints
}

34
plonk/gates/noop_gate.go Normal file
View File

@@ -0,0 +1,34 @@
package gates
import (
"regexp"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var noopGateRegex = regexp.MustCompile("NoopGate")
func deserializeNoopGate(parameters map[string]string) Gate {
// Has the format "NoopGate"
return NewNoopGate()
}
type NoopGate struct {
}
func NewNoopGate() *NoopGate {
return &NoopGate{}
}
func (g *NoopGate) Id() string {
return "NoopGate"
}
func (g *NoopGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
return []gl.QuadraticExtensionVariable{}
}

View File

@@ -0,0 +1,181 @@
package gates
import (
"regexp"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
)
var poseidonGateRegex = regexp.MustCompile("PoseidonGate.*")
func deserializePoseidonGate(parameters map[string]string) Gate {
// Has the format "PoseidonGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>"
return NewPoseidonGate()
}
type PoseidonGate struct {
}
func NewPoseidonGate() *PoseidonGate {
return &PoseidonGate{}
}
func (g *PoseidonGate) Id() string {
return "PoseidonGate"
}
func (g *PoseidonGate) WireInput(i uint64) uint64 {
return i
}
func (g *PoseidonGate) WireOutput(i uint64) uint64 {
return poseidon.SPONGE_WIDTH + i
}
func (g *PoseidonGate) WireSwap() uint64 {
return 2 * poseidon.SPONGE_WIDTH
}
const START_DELTA = 2*poseidon.SPONGE_WIDTH + 1
func (g *PoseidonGate) WireDelta(i uint64) uint64 {
if i >= 4 {
panic("Delta index out of range")
}
return START_DELTA + i
}
const START_FULL_0 = START_DELTA + 4
func (g *PoseidonGate) WireFullSBox0(round uint64, i uint64) uint64 {
if round == 0 {
panic("First-round S-box inputs are not stored as wires")
}
if round >= poseidon.HALF_N_FULL_ROUNDS {
panic("S-box input round out of range")
}
if i >= poseidon.SPONGE_WIDTH {
panic("S-box input index out of range")
}
return START_FULL_0 + (round-1)*poseidon.SPONGE_WIDTH + i
}
const START_PARTIAL = START_FULL_0 + (poseidon.HALF_N_FULL_ROUNDS-1)*poseidon.SPONGE_WIDTH
func (g *PoseidonGate) WirePartialSBox(round uint64) uint64 {
if round >= poseidon.N_PARTIAL_ROUNDS {
panic("S-box input round out of range")
}
return START_PARTIAL + round
}
const START_FULL_1 = START_PARTIAL + poseidon.N_PARTIAL_ROUNDS
func (g *PoseidonGate) WireFullSBox1(round uint64, i uint64) uint64 {
if round >= poseidon.HALF_N_FULL_ROUNDS {
panic("S-box input round out of range")
}
if i >= poseidon.SPONGE_WIDTH {
panic("S-box input index out of range")
}
return START_FULL_1 + round*poseidon.SPONGE_WIDTH + i
}
func (g *PoseidonGate) WiresEnd() uint64 {
return START_FULL_1 + poseidon.HALF_N_FULL_ROUNDS*poseidon.SPONGE_WIDTH
}
func (g *PoseidonGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
constraints := []gl.QuadraticExtensionVariable{}
poseidonChip := poseidon.NewGoldilocksChip(api)
// Assert that `swap` is binary.
swap := vars.localWires[g.WireSwap()]
swapMinusOne := glApi.SubExtension(swap, gl.OneExtension())
constraints = append(constraints, glApi.MulExtension(swap, swapMinusOne))
// Assert that each delta wire is set properly: `delta_i = swap * (rhs - lhs)`.
for i := uint64(0); i < 4; i++ {
inputLhs := vars.localWires[g.WireInput(i)]
inputRhs := vars.localWires[g.WireInput(i+4)]
deltaI := vars.localWires[g.WireDelta(i)]
diff := glApi.SubExtension(inputRhs, inputLhs)
expectedDeltaI := glApi.MulExtension(swap, diff)
constraints = append(constraints, glApi.SubExtension(expectedDeltaI, deltaI))
}
// Compute the possibly-swapped input layer.
var state [poseidon.SPONGE_WIDTH]gl.QuadraticExtensionVariable
for i := uint64(0); i < 4; i++ {
deltaI := vars.localWires[g.WireDelta(i)]
inputLhs := vars.localWires[g.WireInput(i)]
inputRhs := vars.localWires[g.WireInput(i+4)]
state[i] = glApi.AddExtension(inputLhs, deltaI)
state[i+4] = glApi.SubExtension(inputRhs, deltaI)
}
for i := uint64(8); i < poseidon.SPONGE_WIDTH; i++ {
state[i] = vars.localWires[g.WireInput(i)]
}
roundCounter := 0
// First set of full rounds.
for r := uint64(0); r < poseidon.HALF_N_FULL_ROUNDS; r++ {
state = poseidonChip.ConstantLayerExtension(state, &roundCounter)
if r != 0 {
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
sBoxIn := vars.localWires[g.WireFullSBox0(r, i)]
constraints = append(constraints, glApi.SubExtension(state[i], sBoxIn))
state[i] = sBoxIn
}
}
state = poseidonChip.SBoxLayerExtension(state)
state = poseidonChip.MdsLayerExtension(state)
roundCounter++
}
// Partial rounds.
state = poseidonChip.PartialFirstConstantLayerExtension(state)
state = poseidonChip.MdsPartialLayerInitExtension(state)
for r := uint64(0); r < poseidon.N_PARTIAL_ROUNDS-1; r++ {
sBoxIn := vars.localWires[g.WirePartialSBox(r)]
constraints = append(constraints, glApi.SubExtension(state[0], sBoxIn))
state[0] = poseidonChip.SBoxMonomialExtension(sBoxIn)
state[0] = glApi.AddExtension(state[0], gl.NewQuadraticExtensionVariable(gl.NewVariable(poseidon.FAST_PARTIAL_ROUND_CONSTANTS[r]), gl.Zero()))
state = poseidonChip.MdsPartialLayerFastExtension(state, int(r))
}
sBoxIn := vars.localWires[g.WirePartialSBox(poseidon.N_PARTIAL_ROUNDS-1)]
constraints = append(constraints, glApi.SubExtension(state[0], sBoxIn))
state[0] = poseidonChip.SBoxMonomialExtension(sBoxIn)
state = poseidonChip.MdsPartialLayerFastExtension(state, poseidon.N_PARTIAL_ROUNDS-1)
roundCounter += poseidon.N_PARTIAL_ROUNDS
// Second set of full rounds.
for r := uint64(0); r < poseidon.HALF_N_FULL_ROUNDS; r++ {
state = poseidonChip.ConstantLayerExtension(state, &roundCounter)
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
sBoxIn := vars.localWires[g.WireFullSBox1(r, i)]
constraints = append(constraints, glApi.SubExtension(state[i], sBoxIn))
state[i] = sBoxIn
}
state = poseidonChip.SBoxLayerExtension(state)
state = poseidonChip.MdsLayerExtension(state)
roundCounter++
}
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
constraints = append(constraints, glApi.SubExtension(state[i], vars.localWires[g.WireOutput(i)]))
}
return constraints
}

View File

@@ -0,0 +1,97 @@
package gates
import (
"regexp"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
)
var poseidonMdsGateRegex = regexp.MustCompile("PoseidonMdsGate.*")
func deserializePoseidonMdsGate(parameters map[string]string) Gate {
// Has the format "PoseidonMdsGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>"
return NewPoseidonMdsGate()
}
type PoseidonMdsGate struct {
}
func NewPoseidonMdsGate() *PoseidonMdsGate {
return &PoseidonMdsGate{}
}
func (g *PoseidonMdsGate) Id() string {
return "PoseidonMdsGate"
}
func (g *PoseidonMdsGate) WireInput(i uint64) Range {
if i >= poseidon.SPONGE_WIDTH {
panic("Input less than sponge width")
}
return Range{i * gl.D, (i + 1) * gl.D}
}
func (g *PoseidonMdsGate) WireOutput(i uint64) Range {
if i >= poseidon.SPONGE_WIDTH {
panic("Input less than sponge width")
}
return Range{(poseidon.SPONGE_WIDTH + i) * gl.D, (poseidon.SPONGE_WIDTH + i + 1) * gl.D}
}
func (g *PoseidonMdsGate) mdsRowShfAlgebra(
r uint64,
v [poseidon.SPONGE_WIDTH]gl.QuadraticExtensionAlgebraVariable,
api frontend.API,
) gl.QuadraticExtensionAlgebraVariable {
glApi := gl.NewChip(api)
if r >= poseidon.SPONGE_WIDTH {
panic("MDS row index out of range")
}
res := gl.ZeroExtensionAlgebra()
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
coeff := gl.NewQuadraticExtensionVariable(gl.NewVariable(poseidon.MDS_MATRIX_CIRC[i]), gl.Zero())
res = glApi.AddExtensionAlgebra(res, glApi.ScalarMulExtensionAlgebra(coeff, v[(i+r)%poseidon.SPONGE_WIDTH]))
}
coeff := gl.NewQuadraticExtensionVariable(gl.NewVariable(poseidon.MDS_MATRIX_DIAG[r]), gl.Zero())
res = glApi.AddExtensionAlgebra(res, glApi.ScalarMulExtensionAlgebra(coeff, v[r]))
return res
}
func (g *PoseidonMdsGate) mdsLayerAlgebra(
state [poseidon.SPONGE_WIDTH]gl.QuadraticExtensionAlgebraVariable,
api frontend.API,
) [poseidon.SPONGE_WIDTH]gl.QuadraticExtensionAlgebraVariable {
var result [poseidon.SPONGE_WIDTH]gl.QuadraticExtensionAlgebraVariable
for r := uint64(0); r < poseidon.SPONGE_WIDTH; r++ {
result[r] = g.mdsRowShfAlgebra(r, state, api)
}
return result
}
func (g *PoseidonMdsGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
constraints := []gl.QuadraticExtensionVariable{}
var inputs [poseidon.SPONGE_WIDTH]gl.QuadraticExtensionAlgebraVariable
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
inputs[i] = vars.GetLocalExtAlgebra(g.WireInput(i))
}
computed_outputs := g.mdsLayerAlgebra(inputs, api)
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
output := vars.GetLocalExtAlgebra(g.WireOutput(i))
diff := glApi.SubExtensionAlgebra(output, computed_outputs[i])
constraints = append(constraints, diff[0], diff[1])
}
return constraints
}

View File

@@ -0,0 +1,51 @@
package gates
import (
"regexp"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var publicInputGateRegex = regexp.MustCompile("PublicInputGate")
func deserializePublicInputGate(parameters map[string]string) Gate {
// Has the format "PublicInputGate"
return NewPublicInputGate()
}
type PublicInputGate struct {
}
func NewPublicInputGate() *PublicInputGate {
return &PublicInputGate{}
}
func (g *PublicInputGate) Id() string {
return "PublicInputGate"
}
func (g *PublicInputGate) WiresPublicInputsHash() []uint64 {
return []uint64{0, 1, 2, 3}
}
func (g *PublicInputGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
constraints := []gl.QuadraticExtensionVariable{}
wires := g.WiresPublicInputsHash()
hash_parts := vars.publicInputsHash
for i := 0; i < 4; i++ {
wire := wires[i]
hash_part := hash_parts[i]
tmp := gl.NewQuadraticExtensionVariable(hash_part, gl.Zero())
diff := glApi.SubExtension(vars.localWires[wire], tmp)
constraints = append(constraints, diff)
}
return constraints
}

View File

@@ -0,0 +1,178 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var randomAccessGateRegex = regexp.MustCompile("RandomAccessGate { bits: (?P<bits>[0-9]+), num_copies: (?P<numCopies>[0-9]+), num_extra_constants: (?P<numExtraConstants>[0-9]+), _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=(?P<base>[0-9]+)>")
func deserializeRandomAccessGate(parameters map[string]string) Gate {
// Has the format "RandomAccessGate { bits: 2, num_copies: 13, num_extra_constants: 2, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>"
bits, hasBits := parameters["bits"]
numCopies, hasNumCopies := parameters["numCopies"]
numExtraConstants, hasNumExtraConstants := parameters["numExtraConstants"]
if !hasBits || !hasNumCopies || !hasNumExtraConstants {
panic("missing bits, numCopies, numExtraConstants or base in RandomAccessGate")
}
bitsInt, err := strconv.ParseUint(bits, 10, 64)
if err != nil {
panic("invalid bits in RandomAccessGate")
}
numCopiesInt, err := strconv.ParseUint(numCopies, 10, 64)
if err != nil {
panic("invalid numCopies in RandomAccessGate")
}
numExtraConstantsInt, err := strconv.ParseUint(numExtraConstants, 10, 64)
if err != nil {
panic("invalid numExtraConstants in RandomAccessGate")
}
return NewRandomAccessGate(bitsInt, numCopiesInt, numExtraConstantsInt)
}
type RandomAccessGate struct {
bits uint64
numCopies uint64
numExtraConstants uint64
}
func NewRandomAccessGate(bits uint64, numCopies uint64, numExtraConstants uint64) *RandomAccessGate {
return &RandomAccessGate{
bits: bits,
numCopies: numCopies,
numExtraConstants: numExtraConstants,
}
}
func (g *RandomAccessGate) Id() string {
return fmt.Sprintf("RandomAccessGate { bits: %d, num_copies: %d, num_extra_constants: %d }", g.bits, g.numCopies, g.numExtraConstants)
}
func (g *RandomAccessGate) vecSize() uint64 {
return 1 << g.bits
}
func (g *RandomAccessGate) WireAccessIndex(copy uint64) uint64 {
if copy >= g.numCopies {
panic("RandomAccessGate.WireAccessIndex called with copy >= num_copies")
}
return (2 + g.vecSize()) * copy
}
func (g *RandomAccessGate) WireClaimedElement(copy uint64) uint64 {
if copy >= g.numCopies {
panic("RandomAccessGate.WireClaimedElement called with copy >= num_copies")
}
return (2+g.vecSize())*copy + 1
}
func (g *RandomAccessGate) WireListItem(i uint64, copy uint64) uint64 {
if i >= g.vecSize() {
panic("RandomAccessGate.WireListItem called with i >= vec_size")
}
if copy >= g.numCopies {
panic("RandomAccessGate.WireListItem called with copy >= num_copies")
}
return (2+g.vecSize())*copy + 2 + i
}
func (g *RandomAccessGate) startExtraConstants() uint64 {
return (2 + g.vecSize()) * g.numCopies
}
func (g *RandomAccessGate) wireExtraConstant(i uint64) uint64 {
if i >= g.numExtraConstants {
panic("RandomAccessGate.wireExtraConstant called with i >= num_extra_constants")
}
return g.startExtraConstants() + i
}
func (g *RandomAccessGate) NumRoutedWires() uint64 {
return g.startExtraConstants() + g.numExtraConstants
}
func (g *RandomAccessGate) WireBit(i uint64, copy uint64) uint64 {
if i >= g.bits {
panic("RandomAccessGate.WireBit called with i >= bits")
}
if copy >= g.numCopies {
panic("RandomAccessGate.WireBit called with copy >= num_copies")
}
return g.NumRoutedWires() + copy*g.bits + i
}
func (g *RandomAccessGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
two := gl.NewVariable(2).ToQuadraticExtension()
constraints := []gl.QuadraticExtensionVariable{}
for copy := uint64(0); copy < g.numCopies; copy++ {
accessIndex := vars.localWires[g.WireAccessIndex(copy)]
listItems := []gl.QuadraticExtensionVariable{}
for i := uint64(0); i < g.vecSize(); i++ {
listItems = append(listItems, vars.localWires[g.WireListItem(i, copy)])
}
claimedElement := vars.localWires[g.WireClaimedElement(copy)]
bits := []gl.QuadraticExtensionVariable{}
for i := uint64(0); i < g.bits; i++ {
bits = append(bits, vars.localWires[g.WireBit(i, copy)])
}
// Assert that each bit wire value is indeed boolean.
for _, b := range bits {
bSquared := glApi.MulExtension(b, b)
constraints = append(constraints, glApi.SubExtension(bSquared, b))
}
// Assert that the binary decomposition was correct.
reconstructedIndex := glApi.ReduceWithPowers(bits, two)
constraints = append(constraints, glApi.SubExtension(reconstructedIndex, accessIndex))
for _, b := range bits {
listItemsTmp := []gl.QuadraticExtensionVariable{}
for i := 0; i < len(listItems); i += 2 {
x := listItems[i]
y := listItems[i+1]
// This is computing `if b { x } else { y }`
// i.e. `bx - (by-y)`.
mul1 := glApi.MulExtension(b, x)
sub1 := glApi.SubExtension(mul1, x)
mul2 := glApi.MulExtension(b, y)
sub2 := glApi.SubExtension(mul2, sub1)
listItemsTmp = append(listItemsTmp, sub2)
}
listItems = listItemsTmp
}
if len(listItems) != 1 {
panic("listItems(len) != 1")
}
constraints = append(constraints, glApi.SubExtension(listItems[0], claimedElement))
}
for i := uint64(0); i < g.numExtraConstants; i++ {
constraints = append(constraints, glApi.SubExtension(vars.localConstants[i], vars.localWires[g.wireExtraConstant(i)]))
}
return constraints
}

View File

@@ -0,0 +1,109 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var reducingExtensionGateRegex = regexp.MustCompile("ReducingExtensionGate { num_coeffs: (?P<numCoeffs>[0-9]+) }")
func deserializeReducingExtensionGate(parameters map[string]string) Gate {
// Has the format "ReducingGate { num_coeffs: 33 }"
numCoeffs, hasNumCoeffs := parameters["numCoeffs"]
if !hasNumCoeffs {
panic("Missing field num_coeffs in ReducingExtensionGate")
}
numCoeffsInt, err := strconv.Atoi(numCoeffs)
if err != nil {
panic("Invalid num_coeffs field in ReducingExtensionGate")
}
return NewReducingExtensionGate(uint64(numCoeffsInt))
}
type ReducingExtensionGate struct {
numCoeffs uint64
}
const START_COEFFS_REDUCING_EXTENSION_GATE = 3 * gl.D
func NewReducingExtensionGate(numCoeffs uint64) *ReducingExtensionGate {
return &ReducingExtensionGate{
numCoeffs: numCoeffs,
}
}
func (g *ReducingExtensionGate) Id() string {
return fmt.Sprintf("ReducingExtensionGate { num_ops: %d }", g.numCoeffs)
}
func (g *ReducingExtensionGate) wiresOutput() Range {
return Range{0, gl.D}
}
func (g *ReducingExtensionGate) wiresAlpha() Range {
return Range{gl.D, 2 * gl.D}
}
func (g *ReducingExtensionGate) wiresOldAcc() Range {
return Range{2 * gl.D, 3 * gl.D}
}
func (g *ReducingExtensionGate) wiresCoeff(i uint64) Range {
return Range{START_COEFFS_REDUCING_EXTENSION_GATE + gl.D*i, START_COEFFS_REDUCING_EXTENSION_GATE + gl.D*(i+1)}
}
func (g *ReducingExtensionGate) startAccs() uint64 {
return START_COEFFS_REDUCING_EXTENSION_GATE + g.numCoeffs*gl.D
}
func (g *ReducingExtensionGate) wiresAccs(i uint64) Range {
if i >= g.numCoeffs {
panic("Accumulator index out of bounds")
}
if i == g.numCoeffs-1 {
return g.wiresOutput()
}
return Range{g.startAccs() + gl.D*i, g.startAccs() + gl.D*(i+1)}
}
func (g *ReducingExtensionGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
alpha := vars.GetLocalExtAlgebra(g.wiresAlpha())
oldAcc := vars.GetLocalExtAlgebra(g.wiresOldAcc())
coeffs := []gl.QuadraticExtensionAlgebraVariable{}
for i := uint64(0); i < g.numCoeffs; i++ {
coeffs = append(coeffs, vars.GetLocalExtAlgebra(g.wiresCoeff(i)))
}
accs := []gl.QuadraticExtensionAlgebraVariable{}
for i := uint64(0); i < g.numCoeffs; i++ {
accs = append(accs, vars.GetLocalExtAlgebra(g.wiresAccs(i)))
}
constraints := []gl.QuadraticExtensionVariable{}
acc := oldAcc
for i := uint64(0); i < g.numCoeffs; i++ {
coeff := coeffs[i]
tmp := glApi.MulExtensionAlgebra(acc, alpha)
tmp = glApi.AddExtensionAlgebra(tmp, coeff)
tmp = glApi.SubExtensionAlgebra(tmp, accs[i])
for j := uint64(0); j < gl.D; j++ {
constraints = append(constraints, tmp[j])
}
acc = accs[i]
}
return constraints
}

View File

@@ -0,0 +1,114 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
)
var reducingGateRegex = regexp.MustCompile("ReducingGate { num_coeffs: (?P<numCoeffs>[0-9]+) }")
func deserializeReducingGate(parameters map[string]string) Gate {
// Has the format "ReducingGate { num_coeffs: 33 }"
numCoeffs, hasNumCoeffs := parameters["numCoeffs"]
if !hasNumCoeffs {
panic("Missing field num_coeffs in ReducingGate")
}
numCoeffsInt, err := strconv.Atoi(numCoeffs)
if err != nil {
panic("Invalid num_coeffs field in ReducingGate")
}
return NewReducingGate(uint64(numCoeffsInt))
}
type ReducingGate struct {
numCoeffs uint64
}
const START_COEFFS_REDUCING_GATE = 3 * gl.D
func NewReducingGate(numCoeffs uint64) *ReducingGate {
return &ReducingGate{
numCoeffs: numCoeffs,
}
}
func (g *ReducingGate) Id() string {
return fmt.Sprintf("ReducingExtensionGate { num_ops: %d }", g.numCoeffs)
}
func (g *ReducingGate) wiresOutput() Range {
return Range{0, gl.D}
}
func (g *ReducingGate) wiresAlpha() Range {
return Range{gl.D, 2 * gl.D}
}
func (g *ReducingGate) wiresOldAcc() Range {
return Range{2 * gl.D, 3 * gl.D}
}
func (g *ReducingGate) wiresCoeff() Range {
return Range{START_COEFFS_REDUCING_GATE, START_COEFFS_REDUCING_GATE + g.numCoeffs}
}
func (g *ReducingGate) startAccs() uint64 {
return START_COEFFS_REDUCING_GATE + g.numCoeffs
}
func (g *ReducingGate) wiresAccs(i uint64) Range {
if i >= g.numCoeffs {
panic("Accumulator index out of bounds")
}
if i == g.numCoeffs-1 {
return g.wiresOutput()
}
return Range{g.startAccs() + gl.D*i, g.startAccs() + gl.D*(i+1)}
}
func (g *ReducingGate) EvalUnfiltered(
api frontend.API,
glApi gl.Chip,
vars EvaluationVars,
) []gl.QuadraticExtensionVariable {
alpha := vars.GetLocalExtAlgebra(g.wiresAlpha())
oldAcc := vars.GetLocalExtAlgebra(g.wiresOldAcc())
coeffs := []gl.QuadraticExtensionVariable{}
coeffsRange := g.wiresCoeff()
for i := coeffsRange.start; i < coeffsRange.end; i++ {
coeffs = append(coeffs, vars.localWires[i])
}
accs := []gl.QuadraticExtensionAlgebraVariable{}
for i := uint64(0); i < g.numCoeffs; i++ {
accs = append(accs, vars.GetLocalExtAlgebra(g.wiresAccs(i)))
}
constraints := []gl.QuadraticExtensionVariable{}
acc := oldAcc
for i := uint64(0); i < g.numCoeffs; i++ {
var coeff gl.QuadraticExtensionAlgebraVariable
for j := 0; j < gl.D; j++ {
coeff[j] = gl.ZeroExtension()
}
coeff[0] = coeffs[i]
tmp := glApi.MulExtensionAlgebra(acc, alpha)
tmp = glApi.AddExtensionAlgebra(tmp, coeff)
tmp = glApi.SubExtensionAlgebra(tmp, accs[i])
for j := 0; j < gl.D; j++ {
constraints = append(constraints, tmp[j])
}
acc = accs[i]
}
return constraints
}

36
plonk/gates/selectors.go Normal file
View File

@@ -0,0 +1,36 @@
package gates
const UNUSED_SELECTOR = uint64(^uint32(0)) // max uint32
type Range struct {
start uint64
end uint64
}
type SelectorsInfo struct {
selectorIndices []uint64
groups []Range
}
func NewSelectorsInfo(selectorIndices []uint64, groupStarts []uint64, groupEnds []uint64) *SelectorsInfo {
if len(groupStarts) != len(groupEnds) {
panic("groupStarts and groupEnds must have the same length")
}
groups := []Range{}
for i := range groupStarts {
groups = append(groups, Range{
start: groupStarts[i],
end: groupEnds[i],
})
}
return &SelectorsInfo{
selectorIndices: selectorIndices,
groups: groups,
}
}
func (s *SelectorsInfo) NumSelectors() uint64 {
return uint64(len(s.groups))
}

42
plonk/gates/vars.go Normal file
View File

@@ -0,0 +1,42 @@
package gates
import (
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
)
type EvaluationVars struct {
localConstants []gl.QuadraticExtensionVariable
localWires []gl.QuadraticExtensionVariable
publicInputsHash poseidon.GoldilocksHashOut
}
func NewEvaluationVars(
localConstants []gl.QuadraticExtensionVariable,
localWires []gl.QuadraticExtensionVariable,
publicInputsHash poseidon.GoldilocksHashOut,
) *EvaluationVars {
return &EvaluationVars{
localConstants: localConstants,
localWires: localWires,
publicInputsHash: publicInputsHash,
}
}
func (e *EvaluationVars) RemovePrefix(numSelectors uint64) {
e.localConstants = e.localConstants[numSelectors:]
}
func (e *EvaluationVars) GetLocalExtAlgebra(wireRange Range) gl.QuadraticExtensionAlgebraVariable {
// For now, only support degree 2
if wireRange.end-wireRange.start != gl.D {
panic("Range must be of size D")
}
var ret gl.QuadraticExtensionAlgebraVariable
for i := wireRange.start; i < wireRange.end; i++ {
ret[i-wireRange.start] = e.localWires[i]
}
return ret
}

236
plonk/plonk.go Normal file
View File

@@ -0,0 +1,236 @@
package plonk
import (
"github.com/consensys/gnark/frontend"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
"github.com/succinctlabs/gnark-plonky2-verifier/plonk/gates"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
"github.com/succinctlabs/gnark-plonky2-verifier/types"
)
type PlonkChip struct {
api frontend.API `gnark:"-"`
commonData types.CommonCircuitData `gnark:"-"`
DEGREE gl.Variable `gnark:"-"`
DEGREE_BITS_F gl.Variable `gnark:"-"`
DEGREE_QE gl.QuadraticExtensionVariable `gnark:"-"`
evaluateGatesChip *gates.EvaluateGatesChip
}
func NewPlonkChip(api frontend.API, commonData types.CommonCircuitData) *PlonkChip {
// TODO: Should degreeBits be verified that it fits within the field and that degree is within uint64?
evaluateGatesChip := gates.NewEvaluateGatesChip(
api,
commonData.Gates,
commonData.NumGateConstraints,
commonData.SelectorsInfo,
)
return &PlonkChip{
api: api,
commonData: commonData,
DEGREE: gl.NewVariable(1 << commonData.DegreeBits),
DEGREE_BITS_F: gl.NewVariable(commonData.DegreeBits),
DEGREE_QE: gl.NewVariable(1 << commonData.DegreeBits).ToQuadraticExtension(),
evaluateGatesChip: evaluateGatesChip,
}
}
func (p *PlonkChip) expPowerOf2Extension(x gl.QuadraticExtensionVariable) gl.QuadraticExtensionVariable {
glApi := gl.NewChip(p.api)
for i := uint64(0); i < p.commonData.DegreeBits; i++ {
x = glApi.MulExtension(x, x)
}
return x
}
func (p *PlonkChip) evalL0(x gl.QuadraticExtensionVariable, xPowN gl.QuadraticExtensionVariable) gl.QuadraticExtensionVariable {
// L_0(x) = (x^n - 1) / (n * (x - 1))
glApi := gl.NewChip(p.api)
evalZeroPoly := glApi.SubExtension(
xPowN,
gl.OneExtension(),
)
denominator := glApi.SubExtension(
glApi.ScalarMulExtension(x, p.DEGREE),
p.DEGREE_QE,
)
return glApi.DivExtension(
evalZeroPoly,
denominator,
)
}
func (p *PlonkChip) checkPartialProducts(
numerators []gl.QuadraticExtensionVariable,
denominators []gl.QuadraticExtensionVariable,
challengeNum uint64,
openings types.OpeningSet,
) []gl.QuadraticExtensionVariable {
glApi := gl.NewChip(p.api)
numPartProds := p.commonData.NumPartialProducts
quotDegreeFactor := p.commonData.QuotientDegreeFactor
productAccs := make([]gl.QuadraticExtensionVariable, 0, numPartProds+2)
productAccs = append(productAccs, openings.PlonkZs[challengeNum])
productAccs = append(productAccs, openings.PartialProducts[challengeNum*numPartProds:(challengeNum+1)*numPartProds]...)
productAccs = append(productAccs, openings.PlonkZsNext[challengeNum])
partialProductChecks := make([]gl.QuadraticExtensionVariable, 0, numPartProds)
for i := uint64(0); i <= numPartProds; i += 1 {
ppStartIdx := i * quotDegreeFactor
numeProduct := numerators[ppStartIdx]
denoProduct := denominators[ppStartIdx]
for j := uint64(1); j < quotDegreeFactor; j++ {
numeProduct = glApi.MulExtension(numeProduct, numerators[ppStartIdx+j])
denoProduct = glApi.MulExtension(denoProduct, denominators[ppStartIdx+j])
}
partialProductCheck := glApi.SubExtension(
glApi.MulExtension(productAccs[i], numeProduct),
glApi.MulExtension(productAccs[i+1], denoProduct),
)
partialProductChecks = append(partialProductChecks, partialProductCheck)
}
return partialProductChecks
}
func (p *PlonkChip) evalVanishingPoly(
vars gates.EvaluationVars,
proofChallenges types.ProofChallenges,
openings types.OpeningSet,
zetaPowN gl.QuadraticExtensionVariable,
) []gl.QuadraticExtensionVariable {
glApi := gl.NewChip(p.api)
constraintTerms := p.evaluateGatesChip.EvaluateGateConstraints(vars)
// Calculate the k[i] * x
sIDs := make([]gl.QuadraticExtensionVariable, p.commonData.Config.NumRoutedWires)
for i := uint64(0); i < p.commonData.Config.NumRoutedWires; i++ {
sIDs[i] = glApi.ScalarMulExtension(proofChallenges.PlonkZeta, p.commonData.KIs[i])
}
// Calculate L_0(zeta)
l0Zeta := p.evalL0(proofChallenges.PlonkZeta, zetaPowN)
vanishingZ1Terms := make([]gl.QuadraticExtensionVariable, 0, p.commonData.Config.NumChallenges)
vanishingPartialProductsTerms := make([]gl.QuadraticExtensionVariable, 0, p.commonData.Config.NumChallenges*p.commonData.NumPartialProducts)
for i := uint64(0); i < p.commonData.Config.NumChallenges; i++ {
// L_0(zeta) (Z(zeta) - 1) = 0
z1_term := glApi.MulExtension(
l0Zeta,
glApi.SubExtension(openings.PlonkZs[i], gl.OneExtension()))
vanishingZ1Terms = append(vanishingZ1Terms, z1_term)
numeratorValues := make([]gl.QuadraticExtensionVariable, 0, p.commonData.Config.NumRoutedWires)
denominatorValues := make([]gl.QuadraticExtensionVariable, 0, p.commonData.Config.NumRoutedWires)
for j := uint64(0); j < p.commonData.Config.NumRoutedWires; j++ {
// The numerator is `beta * s_id + wire_value + gamma`, and the denominator is
// `beta * s_sigma + wire_value + gamma`.
wireValuePlusGamma := glApi.AddExtension(
openings.Wires[j],
gl.NewQuadraticExtensionVariable(proofChallenges.PlonkGammas[i], gl.Zero()),
)
numerator := glApi.AddExtension(
glApi.MulExtension(
gl.NewQuadraticExtensionVariable(proofChallenges.PlonkBetas[i], gl.Zero()),
sIDs[j],
),
wireValuePlusGamma,
)
denominator := glApi.AddExtension(
glApi.MulExtension(
gl.NewQuadraticExtensionVariable(proofChallenges.PlonkBetas[i], gl.Zero()),
openings.PlonkSigmas[j],
),
wireValuePlusGamma,
)
numeratorValues = append(numeratorValues, numerator)
denominatorValues = append(denominatorValues, denominator)
}
vanishingPartialProductsTerms = append(
vanishingPartialProductsTerms,
p.checkPartialProducts(numeratorValues, denominatorValues, i, openings)...,
)
}
vanishingTerms := append(vanishingZ1Terms, vanishingPartialProductsTerms...)
vanishingTerms = append(vanishingTerms, constraintTerms...)
reducedValues := make([]gl.QuadraticExtensionVariable, p.commonData.Config.NumChallenges)
for i := uint64(0); i < p.commonData.Config.NumChallenges; i++ {
reducedValues[i] = gl.ZeroExtension()
}
// reverse iterate the vanishingPartialProductsTerms array
for i := len(vanishingTerms) - 1; i >= 0; i-- {
for j := uint64(0); j < p.commonData.Config.NumChallenges; j++ {
reducedValues[j] = glApi.AddExtension(
vanishingTerms[i],
glApi.ScalarMulExtension(
reducedValues[j],
proofChallenges.PlonkAlphas[j],
),
)
}
}
return reducedValues
}
func (p *PlonkChip) Verify(
proofChallenges types.ProofChallenges,
openings types.OpeningSet,
publicInputsHash poseidon.GoldilocksHashOut,
) {
glApi := gl.NewChip(p.api)
// Calculate zeta^n
zetaPowN := p.expPowerOf2Extension(proofChallenges.PlonkZeta)
localConstants := openings.Constants
localWires := openings.Wires
vars := gates.NewEvaluationVars(
localConstants,
localWires,
publicInputsHash,
)
vanishingPolysZeta := p.evalVanishingPoly(*vars, proofChallenges, openings, zetaPowN)
// Calculate Z(H)
zHZeta := glApi.SubExtension(zetaPowN, gl.OneExtension())
// `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)`
// where the "real" quotient polynomial is `t(X) = t_0(X) + t_1(X)*X^n + t_2(X)*X^{2n} + ...`.
// So to reconstruct `t(zeta)` we can compute `reduce_with_powers(chunk, zeta^n)` for each
// `quotient_degree_factor`-sized chunk of the original evaluations.
for i := 0; i < len(vanishingPolysZeta); i++ {
quotientPolysStartIdx := i * int(p.commonData.QuotientDegreeFactor)
quotientPolysEndIdx := quotientPolysStartIdx + int(p.commonData.QuotientDegreeFactor)
prod := glApi.MulExtension(
zHZeta,
glApi.ReduceWithPowers(
openings.QuotientPolys[quotientPolysStartIdx:quotientPolysEndIdx],
zetaPowN,
),
)
glApi.AssertIsEqualExtension(vanishingPolysZeta[i], prod)
}
}

52
plonk/plonk_test.go Normal file
View File

@@ -0,0 +1,52 @@
package plonk_test
import (
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/test"
"github.com/succinctlabs/gnark-plonky2-verifier/plonk"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier"
)
type TestPlonkCircuit struct {
proofWithPIsFilename string `gnark:"-"`
commonCircuitDataFilename string `gnark:"-"`
verifierOnlyCircuitDataFilename string `gnark:"-"`
}
func (circuit *TestPlonkCircuit) Define(api frontend.API) error {
proofWithPis := verifier.DeserializeProofWithPublicInputs(circuit.proofWithPIsFilename)
commonCircuitData := verifier.DeserializeCommonCircuitData(circuit.commonCircuitDataFilename)
verifierOnlyCircuitData := verifier.DeserializeVerifierOnlyCircuitData(circuit.verifierOnlyCircuitDataFilename)
verifierChip := verifier.NewVerifierChip(api, commonCircuitData)
publicInputsHash := verifierChip.GetPublicInputsHash(proofWithPis.PublicInputs)
proofChallenges := verifierChip.GetChallenges(proofWithPis.Proof, publicInputsHash, commonCircuitData, verifierOnlyCircuitData)
plonkChip := plonk.NewPlonkChip(
api,
commonCircuitData,
)
plonkChip.Verify(proofChallenges, proofWithPis.Proof.Openings, publicInputsHash)
return nil
}
func TestPlonkDecodeBlock(t *testing.T) {
assert := test.NewAssert(t)
testCase := func() {
circuit := TestPlonkCircuit{
proofWithPIsFilename: "../../data/decode_block/proof_with_public_inputs.json",
commonCircuitDataFilename: "../../data/decode_block/common_circuit_data.json",
verifierOnlyCircuitDataFilename: "../../data/decode_block/verifier_only_circuit_data.json",
}
witness := TestPlonkCircuit{}
err := test.IsSolved(&circuit, &witness, ecc.BN254.ScalarField())
assert.NoError(err)
}
testCase()
}