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

@@ -1,57 +0,0 @@
package common
import (
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/gates"
)
type VerifierOnlyCircuitData struct {
ConstantSigmasCap MerkleCap
CircuitDigest poseidon.PoseidonBN128HashOut
}
type CircuitConfig struct {
NumWires uint64
NumRoutedWires uint64
NumConstants uint64
UseBaseArithmeticGate bool
SecurityBits uint64
NumChallenges uint64
ZeroKnowledge bool
MaxQuotientDegreeFactor uint64
FriConfig FriConfig
}
type CommonCircuitData struct {
Config CircuitConfig
FriParams FriParams
Gates []gates.Gate
SelectorsInfo gates.SelectorsInfo
DegreeBits uint64
QuotientDegreeFactor uint64
NumGateConstraints uint64
NumConstants uint64
NumPublicInputs uint64
KIs []field.F
NumPartialProducts uint64
}
type FriConfig struct {
RateBits uint64
CapHeight uint64
ProofOfWorkBits uint64
NumQueryRounds uint64
// TODO: add FriReductionStrategy
}
func (fc *FriConfig) Rate() float64 {
return 1.0 / float64((uint64(1) << fc.RateBits))
}
type FriParams struct {
Config FriConfig
Hiding bool
DegreeBits uint64
ReductionArityBits []uint64
}

View File

@@ -1,123 +0,0 @@
package common
import (
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
)
type MerkleCap = []poseidon.PoseidonBN128HashOut
func NewMerkleCap(capHeight uint64) MerkleCap {
return make([]poseidon.PoseidonBN128HashOut, 1<<capHeight)
}
type MerkleProof struct {
Siblings []poseidon.PoseidonBN128HashOut // Length = CircuitConfig.FriConfig.DegreeBits + CircuitConfig.FriConfig.RateBits - CircuitConfig.FriConfig.CapHeight
}
func NewMerkleProof(merkleProofLen uint64) MerkleProof {
return MerkleProof{Siblings: make([]poseidon.PoseidonBN128HashOut, merkleProofLen)}
}
type EvalProof struct {
Elements []field.F // Length = [CommonCircuitData.Constants + CommonCircuitData.NumRoutedWires, CommonCircuitData.NumWires + CommonCircuitData.FriParams.Hiding ? 4 : 0, CommonCircuitData.NumChallenges * (1 + CommonCircuitData.NumPartialProducts) + salt, CommonCircuitData.NumChallenges * CommonCircuitData.QuotientDegreeFactor + salt]
MerkleProof MerkleProof
}
func NewEvalProof(elements []field.F, merkleProof MerkleProof) EvalProof {
return EvalProof{Elements: elements, MerkleProof: merkleProof}
}
type PolynomialCoeffs struct {
Coeffs []field.QuadraticExtension
}
func NewPolynomialCoeffs(numCoeffs uint64) PolynomialCoeffs {
return PolynomialCoeffs{Coeffs: make([]field.QuadraticExtension, numCoeffs)}
}
type OpeningSet struct {
Constants []field.QuadraticExtension // Length = CommonCircuitData.Constants
PlonkSigmas []field.QuadraticExtension // Length = CommonCircuitData.NumRoutedWires
Wires []field.QuadraticExtension // Length = CommonCircuitData.NumWires
PlonkZs []field.QuadraticExtension // Length = CommonCircuitData.NumChallenges
PlonkZsNext []field.QuadraticExtension // Length = CommonCircuitData.NumChallenges
PartialProducts []field.QuadraticExtension // Length = CommonCircuitData.NumChallenges * CommonCircuitData.NumPartialProducts
QuotientPolys []field.QuadraticExtension // Length = CommonCircuitData.NumChallenges * CommonCircuitData.QuotientDegreeFactor
}
func NewOpeningSet(numConstants uint64, numRoutedWires uint64, numWires uint64, numChallenges uint64, numPartialProducts uint64, quotientDegreeFactor uint64) OpeningSet {
return OpeningSet{
Constants: make([]field.QuadraticExtension, numConstants),
PlonkSigmas: make([]field.QuadraticExtension, numRoutedWires),
Wires: make([]field.QuadraticExtension, numWires),
PlonkZs: make([]field.QuadraticExtension, numChallenges),
PlonkZsNext: make([]field.QuadraticExtension, numChallenges),
PartialProducts: make([]field.QuadraticExtension, numChallenges*numPartialProducts),
QuotientPolys: make([]field.QuadraticExtension, numChallenges*quotientDegreeFactor),
}
}
type Proof struct {
WiresCap MerkleCap // length = 2^CircuitConfig.FriConfig.CapHeight
PlonkZsPartialProductsCap MerkleCap // length = 2^CircuitConfig.FriConfig.CapHeight
QuotientPolysCap MerkleCap // length = 2^CircuitConfig.FriConfig.CapHeight
Openings OpeningSet
OpeningProof FriProof
}
type ProofWithPublicInputs struct {
Proof Proof
PublicInputs []field.F // Length = CommonCircuitData.NumPublicInputs
}
type ProofChallenges struct {
PlonkBetas []field.F
PlonkGammas []field.F
PlonkAlphas []field.F
PlonkZeta field.QuadraticExtension
FriChallenges FriChallenges
}
type FriInitialTreeProof struct {
EvalsProofs []EvalProof // Length = 4
}
func NewFriInitialTreeProof(evalsProofs []EvalProof) FriInitialTreeProof {
return FriInitialTreeProof{EvalsProofs: evalsProofs}
}
type FriQueryStep struct {
Evals []field.QuadraticExtension // Length = [2^arityBit for arityBit in CommonCircuitData.FriParams.ReductionArityBits]
MerkleProof MerkleProof // Length = [regularSize - arityBit for arityBit in CommonCircuitData.FriParams.ReductionArityBits]
}
func NewFriQueryStep(arityBit uint64, merkleProofLen uint64) FriQueryStep {
return FriQueryStep{
Evals: make([]field.QuadraticExtension, 1<<arityBit),
MerkleProof: NewMerkleProof(merkleProofLen),
}
}
type FriQueryRound struct {
InitialTreesProof FriInitialTreeProof
Steps []FriQueryStep // Length = Len(CommonCircuitData.FriParams.ReductionArityBits)
}
func NewFriQueryRound(steps []FriQueryStep, initialTreesProof FriInitialTreeProof) FriQueryRound {
return FriQueryRound{InitialTreesProof: initialTreesProof, Steps: steps}
}
type FriProof struct {
CommitPhaseMerkleCaps []MerkleCap // Length = Len(CommonCircuitData.FriParams.ReductionArityBits)
QueryRoundProofs []FriQueryRound // Length = CommonCircuitData.FriConfig.FriParams.NumQueryRounds
FinalPoly PolynomialCoeffs
PowWitness field.F
}
type FriChallenges struct {
FriAlpha field.QuadraticExtension
FriBetas []field.QuadraticExtension
FriPowResponse field.F
FriQueryIndices []field.F
}

View File

@@ -1,4 +1,4 @@
package utils
package verifier
import (
"encoding/json"
@@ -7,11 +7,10 @@ import (
"os"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
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/utils"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/gates"
"github.com/succinctlabs/gnark-plonky2-verifier/types"
)
type ProofWithPublicInputsRaw struct {
@@ -147,9 +146,9 @@ type VerifierOnlyCircuitDataRaw struct {
CircuitDigest string `json:"circuit_digest"`
}
func DeserializeMerkleCap(merkleCapRaw []string) common.MerkleCap {
func DeserializeMerkleCap(merkleCapRaw []string) types.FriMerkleCap {
n := len(merkleCapRaw)
merkleCap := make([]poseidon.PoseidonBN128HashOut, n)
merkleCap := make([]poseidon.BN254HashOut, n)
for i := 0; i < n; i++ {
capBigInt, _ := new(big.Int).SetString(merkleCapRaw[i], 10)
merkleCap[i] = frontend.Variable(capBigInt)
@@ -157,13 +156,13 @@ func DeserializeMerkleCap(merkleCapRaw []string) common.MerkleCap {
return merkleCap
}
func DeserializeMerkleProof(merkleProofRaw struct{ Siblings []interface{} }) common.MerkleProof {
func DeserializeMerkleProof(merkleProofRaw struct{ Siblings []interface{} }) types.FriMerkleProof {
n := len(merkleProofRaw.Siblings)
var mp common.MerkleProof
mp.Siblings = make([]poseidon.PoseidonBN128HashOut, n)
var mp types.FriMerkleProof
mp.Siblings = make([]poseidon.BN254HashOut, n)
for i := 0; i < n; i++ {
element := merkleProofRaw.Siblings[i].(struct{ Elements []uint64 })
mp.Siblings[i] = utils.Uint64ArrayToFArray(element.Elements)
mp.Siblings[i] = gl.Uint64ArrayToVariableArray(element.Elements)
}
return mp
}
@@ -176,25 +175,25 @@ func DeserializeOpeningSet(openingSetRaw struct {
PlonkZsNext [][]uint64
PartialProducts [][]uint64
QuotientPolys [][]uint64
}) common.OpeningSet {
return common.OpeningSet{
Constants: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Constants),
PlonkSigmas: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkSigmas),
Wires: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Wires),
PlonkZs: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZs),
PlonkZsNext: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZsNext),
PartialProducts: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PartialProducts),
QuotientPolys: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.QuotientPolys),
}) types.OpeningSet {
return types.OpeningSet{
Constants: gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Constants),
PlonkSigmas: gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkSigmas),
Wires: gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Wires),
PlonkZs: gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZs),
PlonkZsNext: gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZsNext),
PartialProducts: gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PartialProducts),
QuotientPolys: gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.QuotientPolys),
}
}
func StringArrayToHashBN128Array(rawHashes []string) []poseidon.PoseidonBN128HashOut {
hashes := []poseidon.PoseidonBN128HashOut{}
func StringArrayToHashBN254Array(rawHashes []string) []poseidon.BN254HashOut {
hashes := []poseidon.BN254HashOut{}
for i := 0; i < len(rawHashes); i++ {
hashBigInt, _ := new(big.Int).SetString(rawHashes[i], 10)
hashVar := frontend.Variable(hashBigInt)
hashes = append(hashes, poseidon.PoseidonBN128HashOut(hashVar))
hashes = append(hashes, poseidon.BN254HashOut(hashVar))
}
return hashes
@@ -217,39 +216,39 @@ func DeserializeFriProof(openingProofRaw struct {
Coeffs [][]uint64
}
PowWitness uint64
}) common.FriProof {
var openingProof common.FriProof
openingProof.PowWitness = field.NewFieldConst(openingProofRaw.PowWitness)
openingProof.FinalPoly.Coeffs = utils.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.FinalPoly.Coeffs)
}) types.FriProof {
var openingProof types.FriProof
openingProof.PowWitness = gl.NewVariable(openingProofRaw.PowWitness)
openingProof.FinalPoly.Coeffs = gl.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.FinalPoly.Coeffs)
openingProof.CommitPhaseMerkleCaps = make([]common.MerkleCap, len(openingProofRaw.CommitPhaseMerkleCaps))
openingProof.CommitPhaseMerkleCaps = make([]types.FriMerkleCap, len(openingProofRaw.CommitPhaseMerkleCaps))
for i := 0; i < len(openingProofRaw.CommitPhaseMerkleCaps); i++ {
openingProof.CommitPhaseMerkleCaps[i] = StringArrayToHashBN128Array(openingProofRaw.CommitPhaseMerkleCaps[i])
openingProof.CommitPhaseMerkleCaps[i] = StringArrayToHashBN254Array(openingProofRaw.CommitPhaseMerkleCaps[i])
}
numQueryRoundProofs := len(openingProofRaw.QueryRoundProofs)
openingProof.QueryRoundProofs = make([]common.FriQueryRound, numQueryRoundProofs)
openingProof.QueryRoundProofs = make([]types.FriQueryRound, numQueryRoundProofs)
for i := 0; i < numQueryRoundProofs; i++ {
numEvalProofs := len(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs)
openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs = make([]common.EvalProof, numEvalProofs)
openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs = make([]types.FriEvalProof, numEvalProofs)
for j := 0; j < numEvalProofs; j++ {
openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].Elements = utils.Uint64ArrayToFArray(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].LeafElements)
openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].MerkleProof.Siblings = StringArrayToHashBN128Array(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].MerkleProof.Hash)
openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].Elements = gl.Uint64ArrayToVariableArray(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].LeafElements)
openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].MerkleProof.Siblings = StringArrayToHashBN254Array(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].MerkleProof.Hash)
}
numSteps := len(openingProofRaw.QueryRoundProofs[i].Steps)
openingProof.QueryRoundProofs[i].Steps = make([]common.FriQueryStep, numSteps)
openingProof.QueryRoundProofs[i].Steps = make([]types.FriQueryStep, numSteps)
for j := 0; j < numSteps; j++ {
openingProof.QueryRoundProofs[i].Steps[j].Evals = utils.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.QueryRoundProofs[i].Steps[j].Evals)
openingProof.QueryRoundProofs[i].Steps[j].MerkleProof.Siblings = StringArrayToHashBN128Array(openingProofRaw.QueryRoundProofs[i].Steps[j].MerkleProof.Siblings)
openingProof.QueryRoundProofs[i].Steps[j].Evals = gl.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.QueryRoundProofs[i].Steps[j].Evals)
openingProof.QueryRoundProofs[i].Steps[j].MerkleProof.Siblings = StringArrayToHashBN254Array(openingProofRaw.QueryRoundProofs[i].Steps[j].MerkleProof.Siblings)
}
}
return openingProof
}
func DeserializeProofWithPublicInputs(path string) common.ProofWithPublicInputs {
func DeserializeProofWithPublicInputs(path string) types.ProofWithPublicInputs {
jsonFile, err := os.Open(path)
if err != nil {
panic(err)
@@ -264,7 +263,7 @@ func DeserializeProofWithPublicInputs(path string) common.ProofWithPublicInputs
panic(err)
}
var proofWithPis common.ProofWithPublicInputs
var proofWithPis types.ProofWithPublicInputs
proofWithPis.Proof.WiresCap = DeserializeMerkleCap(raw.Proof.WiresCap)
proofWithPis.Proof.PlonkZsPartialProductsCap = DeserializeMerkleCap(raw.Proof.PlonkZsPartialProductsCap)
proofWithPis.Proof.QuotientPolysCap = DeserializeMerkleCap(raw.Proof.QuotientPolysCap)
@@ -293,12 +292,12 @@ func DeserializeProofWithPublicInputs(path string) common.ProofWithPublicInputs
FinalPoly struct{ Coeffs [][]uint64 }
PowWitness uint64
}(raw.Proof.OpeningProof))
proofWithPis.PublicInputs = utils.Uint64ArrayToFArray(raw.PublicInputs)
proofWithPis.PublicInputs = gl.Uint64ArrayToVariableArray(raw.PublicInputs)
return proofWithPis
}
func DeserializeProofChallenges(path string) common.ProofChallenges {
func DeserializeProofChallenges(path string) types.ProofChallenges {
jsonFile, err := os.Open(path)
if err != nil {
panic(err)
@@ -313,15 +312,15 @@ func DeserializeProofChallenges(path string) common.ProofChallenges {
panic(err)
}
var proofChallenges common.ProofChallenges
proofChallenges.PlonkBetas = utils.Uint64ArrayToFArray(raw.PlonkBetas)
proofChallenges.PlonkGammas = utils.Uint64ArrayToFArray(raw.PlonkGammas)
proofChallenges.PlonkAlphas = utils.Uint64ArrayToFArray(raw.PlonkAlphas)
proofChallenges.PlonkZeta = utils.Uint64ArrayToQuadraticExtension(raw.PlonkZeta)
proofChallenges.FriChallenges.FriAlpha = utils.Uint64ArrayToQuadraticExtension(raw.FriChallenges.FriAlpha)
proofChallenges.FriChallenges.FriBetas = utils.Uint64ArrayToQuadraticExtensionArray(raw.FriChallenges.FriBetas)
proofChallenges.FriChallenges.FriPowResponse = field.NewFieldConst(raw.FriChallenges.FriPowResponse)
proofChallenges.FriChallenges.FriQueryIndices = utils.Uint64ArrayToFArray(raw.FriChallenges.FriQueryIndices)
var proofChallenges types.ProofChallenges
proofChallenges.PlonkBetas = gl.Uint64ArrayToVariableArray(raw.PlonkBetas)
proofChallenges.PlonkGammas = gl.Uint64ArrayToVariableArray(raw.PlonkGammas)
proofChallenges.PlonkAlphas = gl.Uint64ArrayToVariableArray(raw.PlonkAlphas)
proofChallenges.PlonkZeta = gl.Uint64ArrayToQuadraticExtension(raw.PlonkZeta)
proofChallenges.FriChallenges.FriAlpha = gl.Uint64ArrayToQuadraticExtension(raw.FriChallenges.FriAlpha)
proofChallenges.FriChallenges.FriBetas = gl.Uint64ArrayToQuadraticExtensionArray(raw.FriChallenges.FriBetas)
proofChallenges.FriChallenges.FriPowResponse = gl.NewVariable(raw.FriChallenges.FriPowResponse)
proofChallenges.FriChallenges.FriQueryIndices = gl.Uint64ArrayToVariableArray(raw.FriChallenges.FriQueryIndices)
return proofChallenges
}
@@ -346,7 +345,7 @@ func ReductionArityBits(
return returnArr
}
func DeserializeCommonCircuitData(path string) common.CommonCircuitData {
func DeserializeCommonCircuitData(path string) types.CommonCircuitData {
jsonFile, err := os.Open(path)
if err != nil {
panic(err)
@@ -361,7 +360,7 @@ func DeserializeCommonCircuitData(path string) common.CommonCircuitData {
panic(err)
}
var commonCircuitData common.CommonCircuitData
var commonCircuitData types.CommonCircuitData
commonCircuitData.Config.NumWires = raw.Config.NumWires
commonCircuitData.Config.NumRoutedWires = raw.Config.NumRoutedWires
commonCircuitData.Config.NumConstants = raw.Config.NumConstants
@@ -406,13 +405,13 @@ func DeserializeCommonCircuitData(path string) common.CommonCircuitData {
commonCircuitData.NumGateConstraints = raw.NumGateConstraints
commonCircuitData.NumConstants = raw.NumConstants
commonCircuitData.NumPublicInputs = raw.NumPublicInputs
commonCircuitData.KIs = utils.Uint64ArrayToFArray(raw.KIs)
commonCircuitData.KIs = gl.Uint64ArrayToVariableArray(raw.KIs)
commonCircuitData.NumPartialProducts = raw.NumPartialProducts
return commonCircuitData
}
func DeserializeVerifierOnlyCircuitData(path string) common.VerifierOnlyCircuitData {
func DeserializeVerifierOnlyCircuitData(path string) types.VerifierOnlyCircuitData {
jsonFile, err := os.Open(path)
if err != nil {
panic(err)
@@ -427,10 +426,10 @@ func DeserializeVerifierOnlyCircuitData(path string) common.VerifierOnlyCircuitD
panic(err)
}
var verifierOnlyCircuitData common.VerifierOnlyCircuitData
var verifierOnlyCircuitData types.VerifierOnlyCircuitData
verifierOnlyCircuitData.ConstantSigmasCap = DeserializeMerkleCap(raw.ConstantsSigmasCap)
circuitDigestBigInt, _ := new(big.Int).SetString(raw.CircuitDigest, 10)
circuitDigestVar := frontend.Variable(circuitDigestBigInt)
verifierOnlyCircuitData.CircuitDigest = poseidon.PoseidonBN128HashOut(circuitDigestVar)
verifierOnlyCircuitData.CircuitDigest = poseidon.BN254HashOut(circuitDigestVar)
return verifierOnlyCircuitData
}

View File

@@ -1,4 +1,4 @@
package utils
package verifier
import (
"fmt"

View File

@@ -1,519 +0,0 @@
package fri
import (
"fmt"
"math"
"math/big"
"math/bits"
"github.com/consensys/gnark-crypto/field/goldilocks"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
)
type FriChip struct {
api frontend.API `gnark:"-"`
fieldAPI field.FieldAPI `gnark:"-"`
qeAPI *field.QuadraticExtensionAPI `gnark:"-"`
poseidonBN128Chip *poseidon.PoseidonBN128Chip
friParams *common.FriParams `gnark:"-"`
}
func NewFriChip(
api frontend.API,
fieldAPI field.FieldAPI,
qeAPI *field.QuadraticExtensionAPI,
poseidonBN128Chip *poseidon.PoseidonBN128Chip,
friParams *common.FriParams,
) *FriChip {
return &FriChip{
api: api,
fieldAPI: fieldAPI,
qeAPI: qeAPI,
poseidonBN128Chip: poseidonBN128Chip,
friParams: friParams,
}
}
func (f *FriChip) assertLeadingZeros(powWitness field.F, friConfig common.FriConfig) {
// Asserts that powWitness'es big-endian bit representation has at least `leading_zeros` leading zeros.
// Note that this is assuming that the Goldilocks field is being used. Specfically that the
// field is 64 bits long
maxPowWitness := uint64(math.Pow(2, float64(64-friConfig.ProofOfWorkBits))) - 1
reducedPOWWitness := f.fieldAPI.Reduce(powWitness)
f.fieldAPI.AssertIsLessOrEqual(reducedPOWWitness, field.NewFieldConst(maxPowWitness))
}
func (f *FriChip) fromOpeningsAndAlpha(openings *FriOpenings, alpha field.QuadraticExtension) []field.QuadraticExtension {
// One reduced opening for all openings evaluated at point Zeta.
// Another one for all openings evaluated at point Zeta * Omega (which is only PlonkZsNext polynomial)
reducedOpenings := make([]field.QuadraticExtension, 0, 2)
for _, batch := range openings.Batches {
reducedOpenings = append(reducedOpenings, f.qeAPI.ReduceWithPowers(batch.Values, alpha))
}
return reducedOpenings
}
func (f *FriChip) verifyMerkleProofToCapWithCapIndex(leafData []field.F, leafIndexBits []frontend.Variable, capIndexBits []frontend.Variable, merkleCap common.MerkleCap, proof *common.MerkleProof) {
currentDigest := f.poseidonBN128Chip.HashOrNoop(leafData)
for i, sibling := range proof.Siblings {
bit := leafIndexBits[i]
// TODO: Don't need to do two hashes by using a trick that the plonky2 verifier circuit does
// https://github.com/mir-protocol/plonky2/blob/973624f12d2d12d74422b3ea051358b9eaacb050/plonky2/src/gates/poseidon.rs#L298
leftHash := f.poseidonBN128Chip.TwoToOne(sibling, currentDigest)
rightHash := f.poseidonBN128Chip.TwoToOne(currentDigest, sibling)
currentDigest = f.api.Select(bit, leftHash, rightHash)
}
// We assume that the cap_height is 4. Create two levels of the Lookup2 circuit
if len(capIndexBits) != 4 || len(merkleCap) != 16 {
errorMsg, _ := fmt.Printf(
"capIndexBits length should be 4 and the merkleCap length should be 16. Actual values (capIndexBits: %d, merkleCap: %d)\n",
len(capIndexBits),
len(merkleCap),
)
panic(errorMsg)
}
const NUM_LEAF_LOOKUPS = 4
var leafLookups [NUM_LEAF_LOOKUPS]poseidon.PoseidonBN128HashOut
// First create the "leaf" lookup2 circuits
// The will use the least significant bits of the capIndexBits array
for i := 0; i < NUM_LEAF_LOOKUPS; i++ {
leafLookups[i] = f.api.Lookup2(
capIndexBits[0], capIndexBits[1],
merkleCap[i*NUM_LEAF_LOOKUPS], merkleCap[i*NUM_LEAF_LOOKUPS+1], merkleCap[i*NUM_LEAF_LOOKUPS+2], merkleCap[i*NUM_LEAF_LOOKUPS+3],
)
}
// Use the most 2 significant bits of the capIndexBits array for the "root" lookup
merkleCapEntry := f.api.Lookup2(capIndexBits[2], capIndexBits[3], leafLookups[0], leafLookups[1], leafLookups[2], leafLookups[3])
f.api.AssertIsEqual(currentDigest, merkleCapEntry)
}
func (f *FriChip) verifyInitialProof(xIndexBits []frontend.Variable, proof *common.FriInitialTreeProof, initialMerkleCaps []common.MerkleCap, capIndexBits []frontend.Variable) {
if len(proof.EvalsProofs) != len(initialMerkleCaps) {
panic("length of eval proofs in fri proof should equal length of initial merkle caps")
}
for i := 0; i < len(initialMerkleCaps); i++ {
evals := proof.EvalsProofs[i].Elements
merkleProof := proof.EvalsProofs[i].MerkleProof
cap := initialMerkleCaps[i]
f.verifyMerkleProofToCapWithCapIndex(evals, xIndexBits, capIndexBits, cap, &merkleProof)
}
}
// / We decompose FRI query indices into bits without verifying that the decomposition given by
// / the prover is the canonical one. In particular, if `x_index < 2^field_bits - p`, then the
// / prover could supply the binary encoding of either `x_index` or `x_index + p`, since they are
// / congruent mod `p`. However, this only occurs with probability
// / p_ambiguous = (2^field_bits - p) / p
// / which is small for the field that we use in practice.
// /
// / In particular, the soundness error of one FRI query is roughly the codeword rate, which
// / is much larger than this ambiguous-element probability given any reasonable parameters.
// / Thus ambiguous elements contribute a negligible amount to soundness error.
// /
// / Here we compare the probabilities as a sanity check, to verify the claim above.
func (f *FriChip) assertNoncanonicalIndicesOK() {
numAmbiguousElems := uint64(math.MaxUint64) - goldilocks.Modulus().Uint64() + 1
queryError := f.friParams.Config.Rate()
pAmbiguous := float64(numAmbiguousElems) / float64(goldilocks.Modulus().Uint64())
// TODO: Check that pAmbiguous value is the same as the one in plonky2 verifier
if pAmbiguous >= queryError*1e-5 {
panic("A non-negligible portion of field elements are in the range that permits non-canonical encodings. Need to do more analysis or enforce canonical encodings.")
}
}
func (f *FriChip) expFromBitsConstBase(
base goldilocks.Element,
exponentBits []frontend.Variable,
) field.F {
product := field.ONE_F
for i, bit := range exponentBits {
pow := int64(1 << i)
// If the bit is on, we multiply product by base^pow.
// We can arithmetize this as:
// product *= 1 + bit (base^pow - 1)
// product = (base^pow - 1) product bit + product
basePow := goldilocks.NewElement(0)
basePow.Exp(base, big.NewInt(pow))
basePowElement := field.NewFieldConst(basePow.Uint64() - 1)
product = f.fieldAPI.Add(
f.fieldAPI.Mul(
f.fieldAPI.Mul(
basePowElement,
product),
f.fieldAPI.NewElement(bit)),
product,
)
}
return product
}
func (f *FriChip) calculateSubgroupX(
xIndexBits []frontend.Variable,
nLog uint64,
) field.F {
// Compute x from its index
// `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain.
// TODO - Make these as global values
g := field.NewFieldConst(field.GOLDILOCKS_MULTIPLICATIVE_GROUP_GENERATOR.Uint64())
base := field.GoldilocksPrimitiveRootOfUnity(nLog)
// Create a reverse list of xIndexBits
xIndexBitsRev := make([]frontend.Variable, 0)
for i := len(xIndexBits) - 1; i >= 0; i-- {
xIndexBitsRev = append(xIndexBitsRev, xIndexBits[i])
}
product := f.expFromBitsConstBase(base, xIndexBitsRev)
return f.fieldAPI.Mul(g, product)
}
func (f *FriChip) friCombineInitial(
instance FriInstanceInfo,
proof common.FriInitialTreeProof,
friAlpha field.QuadraticExtension,
subgroupX_QE field.QuadraticExtension,
precomputedReducedEval []field.QuadraticExtension,
) field.QuadraticExtension {
sum := f.qeAPI.ZERO_QE
if len(instance.Batches) != len(precomputedReducedEval) {
panic("len(openings) != len(precomputedReducedEval)")
}
for i := 0; i < len(instance.Batches); i++ {
batch := instance.Batches[i]
reducedOpenings := precomputedReducedEval[i]
point := batch.Point
evals := make([]field.QuadraticExtension, 0)
for _, polynomial := range batch.Polynomials {
evals = append(
evals,
field.QuadraticExtension{proof.EvalsProofs[polynomial.OracleIndex].Elements[polynomial.PolynomialInfo], field.ZERO_F},
)
}
reducedEvals := f.qeAPI.ReduceWithPowers(evals, friAlpha)
numerator := f.qeAPI.SubExtension(reducedEvals, reducedOpenings)
denominator := f.qeAPI.SubExtension(subgroupX_QE, point)
sum = f.qeAPI.MulExtension(f.qeAPI.ExpU64Extension(friAlpha, uint64(len(evals))), sum)
sum = f.qeAPI.AddExtension(
f.qeAPI.DivExtension(
numerator,
denominator,
),
sum,
)
}
return sum
}
func (f *FriChip) finalPolyEval(finalPoly common.PolynomialCoeffs, point field.QuadraticExtension) field.QuadraticExtension {
ret := f.qeAPI.ZERO_QE
for i := len(finalPoly.Coeffs) - 1; i >= 0; i-- {
ret = f.qeAPI.AddExtension(
f.qeAPI.MulExtension(
ret,
point,
),
finalPoly.Coeffs[i],
)
}
return ret
}
func (f *FriChip) interpolate(x field.QuadraticExtension, xPoints []field.QuadraticExtension, yPoints []field.QuadraticExtension, barycentricWeights []field.QuadraticExtension) field.QuadraticExtension {
if len(xPoints) != len(yPoints) || len(xPoints) != len(barycentricWeights) {
panic("length of xPoints, yPoints, and barycentricWeights are inconsistent")
}
lX := f.qeAPI.ONE_QE
for i := 0; i < len(xPoints); i++ {
lX = f.qeAPI.MulExtension(
lX,
f.qeAPI.SubExtension(
x,
xPoints[i],
),
)
}
sum := f.qeAPI.ZERO_QE
for i := 0; i < len(xPoints); i++ {
sum = f.qeAPI.AddExtension(
f.qeAPI.MulExtension(
f.qeAPI.DivExtension(
barycentricWeights[i],
f.qeAPI.SubExtension(
x,
xPoints[i],
),
),
yPoints[i],
),
sum,
)
}
interpolation := f.qeAPI.MulExtension(lX, sum)
returnField := interpolation
// Now check if x is already within the xPoints
for i := 0; i < len(xPoints); i++ {
returnField = f.qeAPI.Select(
f.qeAPI.IsZero(f.qeAPI.SubExtension(x, xPoints[i])),
yPoints[i],
returnField,
)
}
return returnField
}
func (f *FriChip) computeEvaluation(
x field.F,
xIndexWithinCosetBits []frontend.Variable,
arityBits uint64,
evals []field.QuadraticExtension,
beta field.QuadraticExtension,
) field.QuadraticExtension {
arity := 1 << arityBits
if (len(evals)) != arity {
panic("len(evals) ! arity")
}
if arityBits > 8 {
panic("currently assuming that arityBits is <= 8")
}
g := field.GoldilocksPrimitiveRootOfUnity(arityBits)
gInv := goldilocks.NewElement(0)
gInv.Exp(g, big.NewInt(int64(arity-1)))
// The evaluation vector needs to be reordered first. Permute the evals array such that each
// element's new index is the bit reverse of it's original index.
// TODO: Optimization - Since the size of the evals array should be constant (e.g. 2^arityBits),
// we can just hard code the permutation.
permutedEvals := make([]field.QuadraticExtension, len(evals))
for i := uint8(0); i < uint8(len(evals)); i++ {
newIndex := bits.Reverse8(i) >> arityBits
permutedEvals[newIndex] = evals[i]
}
// Want `g^(arity - rev_x_index_within_coset)` as in the out-of-circuit version. Compute it
// as `(g^-1)^rev_x_index_within_coset`.
revXIndexWithinCosetBits := make([]frontend.Variable, len(xIndexWithinCosetBits))
for i := 0; i < len(xIndexWithinCosetBits); i++ {
revXIndexWithinCosetBits[len(xIndexWithinCosetBits)-1-i] = xIndexWithinCosetBits[i]
}
start := f.expFromBitsConstBase(gInv, revXIndexWithinCosetBits)
cosetStart := f.fieldAPI.Mul(start, x)
xPoints := make([]field.QuadraticExtension, len(evals))
yPoints := permutedEvals
// TODO: Make g_F a constant
g_F := f.qeAPI.FieldToQE(field.NewFieldConst(g.Uint64()))
xPoints[0] = f.qeAPI.FieldToQE(cosetStart)
for i := 1; i < len(evals); i++ {
xPoints[i] = f.qeAPI.MulExtension(xPoints[i-1], g_F)
}
// TODO: This is n^2. Is there a way to do this better?
// Compute the barycentric weights
barycentricWeights := make([]field.QuadraticExtension, len(xPoints))
for i := 0; i < len(xPoints); i++ {
barycentricWeights[i] = f.qeAPI.ONE_QE
for j := 0; j < len(xPoints); j++ {
if i != j {
barycentricWeights[i] = f.qeAPI.MulExtension(
f.qeAPI.SubExtension(xPoints[i], xPoints[j]),
barycentricWeights[i],
)
}
}
// Take the inverse of the barycentric weights
// TODO: Can provide a witness to this value
barycentricWeights[i] = f.qeAPI.InverseExtension(barycentricWeights[i])
}
return f.interpolate(beta, xPoints, yPoints, barycentricWeights)
}
func (f *FriChip) verifyQueryRound(
instance FriInstanceInfo,
challenges *common.FriChallenges,
precomputedReducedEval []field.QuadraticExtension,
initialMerkleCaps []common.MerkleCap,
proof *common.FriProof,
xIndex field.F,
n uint64,
nLog uint64,
roundProof *common.FriQueryRound,
) {
f.assertNoncanonicalIndicesOK()
xIndex = f.fieldAPI.Reduce(xIndex)
xIndexBits := f.fieldAPI.ToBits(xIndex)[0 : f.friParams.DegreeBits+f.friParams.Config.RateBits]
capIndexBits := xIndexBits[len(xIndexBits)-int(f.friParams.Config.CapHeight):]
f.verifyInitialProof(xIndexBits, &roundProof.InitialTreesProof, initialMerkleCaps, capIndexBits)
subgroupX := f.calculateSubgroupX(
xIndexBits,
nLog,
)
subgroupX_QE := field.QuadraticExtension{subgroupX, field.ZERO_F}
oldEval := f.friCombineInitial(
instance,
roundProof.InitialTreesProof,
challenges.FriAlpha,
subgroupX_QE,
precomputedReducedEval,
)
for i, arityBits := range f.friParams.ReductionArityBits {
evals := roundProof.Steps[i].Evals
cosetIndexBits := xIndexBits[arityBits:]
xIndexWithinCosetBits := xIndexBits[:arityBits]
// Assumes that the arity bits will be 4. That means that the range of
// xIndexWithCoset is [0,2^4-1]. This is based on plonky2's circuit recursive
// config: https://github.com/mir-protocol/plonky2/blob/main/plonky2/src/plonk/circuit_data.rs#L63
// Will use a two levels tree of 4-selector gadgets.
if arityBits != 4 {
panic("assuming arity bits is 4")
}
const NUM_LEAF_LOOKUPS = 4
var leafLookups [NUM_LEAF_LOOKUPS]field.QuadraticExtension
// First create the "leaf" lookup2 circuits
// The will use the least significant bits of the xIndexWithCosetBits array
for i := 0; i < NUM_LEAF_LOOKUPS; i++ {
leafLookups[i] = f.qeAPI.Lookup2(
xIndexWithinCosetBits[0],
xIndexWithinCosetBits[1],
evals[i*NUM_LEAF_LOOKUPS],
evals[i*NUM_LEAF_LOOKUPS+1],
evals[i*NUM_LEAF_LOOKUPS+2],
evals[i*NUM_LEAF_LOOKUPS+3],
)
}
// Use the most 2 significant bits of the xIndexWithCosetBits array for the "root" lookup
newEval := f.qeAPI.Lookup2(
xIndexWithinCosetBits[2],
xIndexWithinCosetBits[3],
leafLookups[0],
leafLookups[1],
leafLookups[2],
leafLookups[3],
)
f.qeAPI.AssertIsEqual(newEval, oldEval)
oldEval = f.computeEvaluation(
subgroupX,
xIndexWithinCosetBits,
arityBits,
evals,
challenges.FriBetas[i],
)
// Convert evals (array of QE) to fields by taking their 0th degree coefficients
fieldEvals := make([]field.F, 0, 2*len(evals))
for j := 0; j < len(evals); j++ {
fieldEvals = append(fieldEvals, evals[j][0])
fieldEvals = append(fieldEvals, evals[j][1])
}
f.verifyMerkleProofToCapWithCapIndex(
fieldEvals,
cosetIndexBits,
capIndexBits,
proof.CommitPhaseMerkleCaps[i],
&roundProof.Steps[i].MerkleProof,
)
// Update the point x to x^arity.
for j := uint64(0); j < arityBits; j++ {
subgroupX = f.fieldAPI.Mul(subgroupX, subgroupX)
}
xIndexBits = cosetIndexBits
}
subgroupX_QE = f.qeAPI.FieldToQE(subgroupX)
finalPolyEval := f.finalPolyEval(proof.FinalPoly, subgroupX_QE)
f.qeAPI.AssertIsEqual(oldEval, finalPolyEval)
}
func (f *FriChip) VerifyFriProof(
instance FriInstanceInfo,
openings FriOpenings,
friChallenges *common.FriChallenges,
initialMerkleCaps []common.MerkleCap,
friProof *common.FriProof,
) {
// TODO: Check fri config
/* if let Some(max_arity_bits) = params.max_arity_bits() {
self.check_recursion_config::<C>(max_arity_bits);
}
debug_assert_eq!(
params.final_poly_len(),
proof.final_poly.len(),
"Final polynomial has wrong degree."
); */
// Check POW
f.assertLeadingZeros(friChallenges.FriPowResponse, f.friParams.Config)
precomputedReducedEvals := f.fromOpeningsAndAlpha(&openings, friChallenges.FriAlpha)
// Size of the LDE domain.
nLog := f.friParams.DegreeBits + f.friParams.Config.RateBits
n := uint64(math.Pow(2, float64(nLog)))
if len(friChallenges.FriQueryIndices) != len(friProof.QueryRoundProofs) {
panic(fmt.Sprintf(
"Number of query indices (%d) should equal number of query round proofs (%d)",
len(friChallenges.FriQueryIndices),
len(friProof.QueryRoundProofs),
))
}
for idx, xIndex := range friChallenges.FriQueryIndices {
roundProof := friProof.QueryRoundProofs[idx]
f.verifyQueryRound(
instance,
friChallenges,
precomputedReducedEvals,
initialMerkleCaps,
friProof,
xIndex,
n,
nLog,
&roundProof,
)
}
}

View File

@@ -1,124 +0,0 @@
package fri_test
import (
"testing"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/test"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/fri"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/plonk"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils"
)
type TestFriCircuit struct {
proofWithPIsFilename string `gnark:"-"`
commonCircuitDataFilename string `gnark:"-"`
verifierOnlyCircuitDataFilename string `gnark:"-"`
}
func (circuit *TestFriCircuit) Define(api frontend.API) error {
proofWithPis := utils.DeserializeProofWithPublicInputs(circuit.proofWithPIsFilename)
commonCircuitData := utils.DeserializeCommonCircuitData(circuit.commonCircuitDataFilename)
verifierOnlyCircuitData := utils.DeserializeVerifierOnlyCircuitData(circuit.verifierOnlyCircuitDataFilename)
fieldAPI := field.NewFieldAPI(api)
qeAPI := field.NewQuadraticExtensionAPI(api, fieldAPI)
poseidonChip := poseidon.NewPoseidonChip(api, fieldAPI, qeAPI)
poseidonBN128Chip := poseidon.NewPoseidonBN128Chip(api, fieldAPI)
friChip := fri.NewFriChip(api, fieldAPI, qeAPI, poseidonBN128Chip, &commonCircuitData.FriParams)
challengerChip := plonk.NewChallengerChip(api, fieldAPI, poseidonChip, poseidonBN128Chip)
challengerChip.ObserveBN128Hash(verifierOnlyCircuitData.CircuitDigest)
challengerChip.ObserveHash(poseidonChip.HashNoPad(proofWithPis.PublicInputs))
challengerChip.ObserveCap(proofWithPis.Proof.WiresCap)
plonkBetas := challengerChip.GetNChallenges(commonCircuitData.Config.NumChallenges) // For plonk betas
fieldAPI.AssertIsEqual(plonkBetas[0], field.NewFieldConst(17615363392879944733))
plonkGammas := challengerChip.GetNChallenges(commonCircuitData.Config.NumChallenges) // For plonk gammas
fieldAPI.AssertIsEqual(plonkGammas[0], field.NewFieldConst(15174493176564484303))
challengerChip.ObserveCap(proofWithPis.Proof.PlonkZsPartialProductsCap)
plonkAlphas := challengerChip.GetNChallenges(commonCircuitData.Config.NumChallenges) // For plonk alphas
fieldAPI.AssertIsEqual(plonkAlphas[0], field.NewFieldConst(9276470834414745550))
challengerChip.ObserveCap(proofWithPis.Proof.QuotientPolysCap)
plonkZeta := challengerChip.GetExtensionChallenge()
fieldAPI.AssertIsEqual(plonkZeta[0], field.NewFieldConst(3892795992421241388))
challengerChip.ObserveOpenings(fri.ToFriOpenings(proofWithPis.Proof.Openings))
friChallenges := challengerChip.GetFriChallenges(
proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
proofWithPis.Proof.OpeningProof.FinalPoly,
proofWithPis.Proof.OpeningProof.PowWitness,
commonCircuitData.DegreeBits,
commonCircuitData.Config.FriConfig,
)
fieldAPI.AssertIsEqual(friChallenges.FriAlpha[0], field.NewFieldConst(885535811531859621))
fieldAPI.AssertIsEqual(friChallenges.FriBetas[0][0], field.NewFieldConst(5231781384587895507))
fieldAPI.AssertIsEqual(friChallenges.FriPowResponse, field.NewFieldConst(70715523064019))
fieldAPI.AssertIsEqual(friChallenges.FriQueryIndices[0], field.NewFieldConst(11890500485816111017))
initialMerkleCaps := []common.MerkleCap{
verifierOnlyCircuitData.ConstantSigmasCap,
proofWithPis.Proof.WiresCap,
proofWithPis.Proof.PlonkZsPartialProductsCap,
proofWithPis.Proof.QuotientPolysCap,
}
// Seems like there is a bug in the emulated field code.
// Add ZERO to all of the fri challenges values to reduce them.
plonkZeta[0] = fieldAPI.Add(plonkZeta[0], field.ZERO_F)
plonkZeta[1] = fieldAPI.Add(plonkZeta[1], field.ZERO_F)
friChallenges.FriAlpha[0] = fieldAPI.Add(friChallenges.FriAlpha[0], field.ZERO_F)
friChallenges.FriAlpha[1] = fieldAPI.Add(friChallenges.FriAlpha[1], field.ZERO_F)
for i := 0; i < len(friChallenges.FriBetas); i++ {
friChallenges.FriBetas[i][0] = fieldAPI.Add(friChallenges.FriBetas[i][0], field.ZERO_F)
friChallenges.FriBetas[i][1] = fieldAPI.Add(friChallenges.FriBetas[i][1], field.ZERO_F)
}
friChallenges.FriPowResponse = fieldAPI.Add(friChallenges.FriPowResponse, field.ZERO_F)
for i := 0; i < len(friChallenges.FriQueryIndices); i++ {
friChallenges.FriQueryIndices[i] = fieldAPI.Add(friChallenges.FriQueryIndices[i], field.ZERO_F)
}
friChip.VerifyFriProof(
fri.GetFriInstance(&commonCircuitData, qeAPI, plonkZeta, commonCircuitData.DegreeBits),
fri.ToFriOpenings(proofWithPis.Proof.Openings),
&friChallenges,
initialMerkleCaps,
&proofWithPis.Proof.OpeningProof,
)
return nil
}
func TestDecodeBlockFriVerification(t *testing.T) {
assert := test.NewAssert(t)
testCase := func() {
circuit := TestFriCircuit{
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 := TestFriCircuit{
proofWithPIsFilename: "../../data/dummy_2^14_gates/proof_with_public_inputs.json",
commonCircuitDataFilename: "../../data/dummy_2^14_gates/common_circuit_data.json",
verifierOnlyCircuitDataFilename: ".../../data/dummy_2^14_gates/verifier_only_circuit_data.json",
}
err := test.IsSolved(&circuit, &witness, field.TEST_CURVE.ScalarField())
assert.NoError(err)
}
testCase()
}

View File

@@ -1,199 +0,0 @@
package fri
import (
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
)
type FriOpeningBatch struct {
Values []field.QuadraticExtension
}
type FriOpenings struct {
Batches []FriOpeningBatch
}
func ToFriOpenings(c common.OpeningSet) FriOpenings {
values := c.Constants // num_constants + 1
values = append(values, c.PlonkSigmas...) // num_routed_wires
values = append(values, c.Wires...) // num_wires
values = append(values, c.PlonkZs...) // num_challenges
values = append(values, c.PartialProducts...) // num_challenges * num_partial_products
values = append(values, c.QuotientPolys...) // num_challenges * quotient_degree_factor
zetaBatch := FriOpeningBatch{Values: values}
zetaNextBatch := FriOpeningBatch{Values: c.PlonkZsNext}
return FriOpenings{Batches: []FriOpeningBatch{zetaBatch, zetaNextBatch}}
}
type FriPolynomialInfo struct {
OracleIndex uint64
PolynomialInfo uint64
}
type FriOracleInfo struct {
NumPolys uint64
Blinding bool
}
type FriBatchInfo struct {
Point field.QuadraticExtension
Polynomials []FriPolynomialInfo
}
type FriInstanceInfo struct {
Oracles []FriOracleInfo
Batches []FriBatchInfo
}
type PlonkOracle struct {
index uint64
blinding bool
}
var CONSTANTS_SIGMAS = PlonkOracle{
index: 0,
blinding: false,
}
var WIRES = PlonkOracle{
index: 1,
blinding: true,
}
var ZS_PARTIAL_PRODUCTS = PlonkOracle{
index: 2,
blinding: true,
}
var QUOTIENT = PlonkOracle{
index: 3,
blinding: true,
}
func polynomialInfoFromRange(c *common.CommonCircuitData, oracleIdx uint64, startPolyIdx uint64, endPolyIdx uint64) []FriPolynomialInfo {
returnArr := make([]FriPolynomialInfo, 0)
for i := startPolyIdx; i < endPolyIdx; i++ {
returnArr = append(returnArr,
FriPolynomialInfo{
OracleIndex: oracleIdx,
PolynomialInfo: i,
})
}
return returnArr
}
// Range of the sigma polynomials in the `constants_sigmas_commitment`.
func sigmasRange(c *common.CommonCircuitData) []uint64 {
returnArr := make([]uint64, 0)
for i := c.NumConstants; i <= c.NumConstants+c.Config.NumRoutedWires; i++ {
returnArr = append(returnArr, i)
}
return returnArr
}
func numPreprocessedPolys(c *common.CommonCircuitData) uint64 {
sigmasRange := sigmasRange(c)
return sigmasRange[len(sigmasRange)-1]
}
func numZSPartialProductsPolys(c *common.CommonCircuitData) uint64 {
return c.Config.NumChallenges * (1 + c.NumPartialProducts)
}
func numQuotientPolys(c *common.CommonCircuitData) uint64 {
return c.Config.NumChallenges * c.QuotientDegreeFactor
}
func friPreprocessedPolys(c *common.CommonCircuitData) []FriPolynomialInfo {
return polynomialInfoFromRange(
c,
CONSTANTS_SIGMAS.index,
0,
numPreprocessedPolys(c),
)
}
func friWirePolys(c *common.CommonCircuitData) []FriPolynomialInfo {
numWirePolys := c.Config.NumWires
return polynomialInfoFromRange(c, WIRES.index, 0, numWirePolys)
}
func friZSPartialProductsPolys(c *common.CommonCircuitData) []FriPolynomialInfo {
return polynomialInfoFromRange(
c,
ZS_PARTIAL_PRODUCTS.index,
0,
numZSPartialProductsPolys(c),
)
}
func friQuotientPolys(c *common.CommonCircuitData) []FriPolynomialInfo {
return polynomialInfoFromRange(
c,
QUOTIENT.index,
0,
numQuotientPolys(c),
)
}
func friZSPolys(c *common.CommonCircuitData) []FriPolynomialInfo {
return polynomialInfoFromRange(
c,
ZS_PARTIAL_PRODUCTS.index,
0,
c.Config.NumChallenges,
)
}
func friOracles(c *common.CommonCircuitData) []FriOracleInfo {
return []FriOracleInfo{
{
NumPolys: numPreprocessedPolys(c),
Blinding: CONSTANTS_SIGMAS.blinding,
},
{
NumPolys: c.Config.NumWires,
Blinding: WIRES.blinding,
},
{
NumPolys: numZSPartialProductsPolys(c),
Blinding: ZS_PARTIAL_PRODUCTS.blinding,
},
{
NumPolys: numQuotientPolys(c),
Blinding: QUOTIENT.blinding,
},
}
}
func friAllPolys(c *common.CommonCircuitData) []FriPolynomialInfo {
returnArr := make([]FriPolynomialInfo, 0)
returnArr = append(returnArr, friPreprocessedPolys(c)...)
returnArr = append(returnArr, friWirePolys(c)...)
returnArr = append(returnArr, friZSPartialProductsPolys(c)...)
returnArr = append(returnArr, friQuotientPolys(c)...)
return returnArr
}
func GetFriInstance(c *common.CommonCircuitData, qeAPI *field.QuadraticExtensionAPI, zeta field.QuadraticExtension, degreeBits uint64) FriInstanceInfo {
zetaBatch := FriBatchInfo{
Point: zeta,
Polynomials: friAllPolys(c),
}
g := field.GoldilocksPrimitiveRootOfUnity(degreeBits)
zetaNext := qeAPI.MulExtension(qeAPI.FieldToQE(field.NewFieldConst(g.Uint64())), zeta)
zetaNextBath := FriBatchInfo{
Point: zetaNext,
Polynomials: friZSPolys(c),
}
return FriInstanceInfo{
Oracles: friOracles(c),
Batches: []FriBatchInfo{zetaBatch, zetaNextBath},
}
}

View File

@@ -1,82 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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 * field.D * i, 4*field.D*i + field.D}
}
func (g *ArithmeticExtensionGate) wiresIthMultiplicand1(i uint64) Range {
return Range{4*field.D*i + field.D, 4*field.D*i + 2*field.D}
}
func (g *ArithmeticExtensionGate) wiresIthAddend(i uint64) Range {
return Range{4*field.D*i + 2*field.D, 4*field.D*i + 3*field.D}
}
func (g *ArithmeticExtensionGate) wiresIthOutput(i uint64) Range {
return Range{4*field.D*i + 3*field.D, 4*field.D*i + 4*field.D}
}
func (g *ArithmeticExtensionGate) EvalUnfiltered(api frontend.API, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
const0 := vars.localConstants[0]
const1 := vars.localConstants[1]
constraints := []field.QuadraticExtension{}
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 := qeAPI.MulExtensionAlgebra(multiplicand0, multiplicand1)
scaled_mul := qeAPI.ScalarMulExtensionAlgebra(const0, mul)
computed_output := qeAPI.ScalarMulExtensionAlgebra(const1, addend)
computed_output = qeAPI.AddExtensionAlgebra(computed_output, scaled_mul)
diff := qeAPI.SubExtensionAlgebra(output, computed_output)
for j := 0; j < field.D; j++ {
constraints = append(constraints, diff[j])
}
}
return constraints
}

View File

@@ -1,80 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
const0 := vars.localConstants[0]
const1 := vars.localConstants[1]
constraints := []field.QuadraticExtension{}
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 := qeAPI.AddExtension(
qeAPI.MulExtension(qeAPI.MulExtension(multiplicand0, multiplicand1), const0),
qeAPI.MulExtension(addend, const1),
)
constraints = append(constraints, qeAPI.SubExtension(output, computedOutput))
}
return constraints
}

View File

@@ -1,92 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
sum := vars.localWires[BASESUM_GATE_WIRE_SUM]
limbs := make([]field.QuadraticExtension, g.numLimbs)
limbIndices := g.limbs()
for i, limbIdx := range limbIndices {
limbs[i] = vars.localWires[limbIdx]
}
base_qe := qeAPI.FieldToQE(field.NewFieldConst(g.base))
computedSum := qeAPI.ReduceWithPowers(
limbs,
base_qe,
)
var constraints []field.QuadraticExtension
constraints = append(constraints, qeAPI.SubExtension(computedSum, sum))
for _, limb := range limbs {
acc := qeAPI.ONE_QE
for i := uint64(0); i < g.base; i++ {
difference := qeAPI.SubExtension(limb, qeAPI.FieldToQE(field.NewFieldConst(i)))
acc = qeAPI.MulExtension(acc, difference)
}
constraints = append(constraints, acc)
}
return constraints
}

View File

@@ -1,65 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
constraints := []field.QuadraticExtension{}
for i := uint64(0); i < g.numConsts; i++ {
constraints = append(constraints, qeAPI.SubExtension(vars.localConstants[g.ConstInput(i)], vars.localWires[g.WireOutput(i)]))
}
return constraints
}

View File

@@ -1,215 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"strings"
"github.com/consensys/gnark-crypto/field/goldilocks"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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*field.D
return Range{start, start + field.D}
}
func (g *CosetInterpolationGate) startEvaluationPoint() uint64 {
return g.startValues() + g.numPoints()*field.D
}
// Wire indices of the point to evaluate the interpolant at.
func (g *CosetInterpolationGate) wiresEvaluationPoint() Range {
start := g.startEvaluationPoint()
return Range{start, start + field.D}
}
func (g *CosetInterpolationGate) startEvaluationValue() uint64 {
return g.startEvaluationPoint() + field.D
}
// Wire indices of the interpolated value.
func (g *CosetInterpolationGate) wiresEvaluationValue() Range {
start := g.startEvaluationValue()
return Range{start, start + field.D}
}
func (g *CosetInterpolationGate) startIntermediates() uint64 {
return g.startEvaluationValue() + field.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() + field.D*i
return Range{start, start + field.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() + field.D*(g.numIntermediates()+i)
return Range{start, start + field.D}
}
// Wire indices of the shifted point to evaluate the interpolant at.
func (g *CosetInterpolationGate) wiresShiftedEvaluationPoint() Range {
start := g.startIntermediates() + field.D*2*g.numIntermediates()
return Range{start, start + field.D}
}
func (g *CosetInterpolationGate) EvalUnfiltered(api frontend.API, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
constraints := []field.QuadraticExtension{}
shift := vars.localWires[g.wireShift()]
evaluationPoint := vars.GetLocalExtAlgebra(g.wiresEvaluationPoint())
shiftedEvaluationPoint := vars.GetLocalExtAlgebra(g.wiresShiftedEvaluationPoint())
negShift := qeAPI.ScalarMulExtension(shift, field.NEG_ONE_F)
tmp := qeAPI.ScalarMulExtensionAlgebra(negShift, shiftedEvaluationPoint)
tmp = qeAPI.AddExtensionAlgebra(tmp, evaluationPoint)
for i := 0; i < field.D; i++ {
constraints = append(constraints, tmp[i])
}
domain := field.TwoAdicSubgroup(g.subgroupBits)
values := []field.QEAlgebra{}
for i := uint64(0); i < g.numPoints(); i++ {
values = append(values, vars.GetLocalExtAlgebra(g.wiresValue(i)))
}
weights := g.barycentricWeights
initialEval := qeAPI.ZERO_QE_ALGEBRA
initialProd := field.QEAlgebra{qeAPI.ONE_QE, qeAPI.ZERO_QE}
computedEval, computedProd := qeAPI.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 := qeAPI.SubExtensionAlgebra(intermediateEval, computedEval)
for j := 0; j < field.D; j++ {
constraints = append(constraints, evalDiff[j])
}
prodDiff := qeAPI.SubExtensionAlgebra(intermediateProd, computedProd)
for j := 0; j < field.D; j++ {
constraints = append(constraints, prodDiff[j])
}
startIndex := 1 + (g.degree-1)*(i+1)
endIndex := startIndex + g.degree - 1
computedEval, computedProd = qeAPI.PartialInterpolateExtAlgebra(
domain[startIndex:endIndex],
values[startIndex:endIndex],
weights[startIndex:endIndex],
shiftedEvaluationPoint,
intermediateEval,
intermediateProd,
)
}
evaluationValue := vars.GetLocalExtAlgebra(g.wiresEvaluationValue())
evalDiff := qeAPI.SubExtensionAlgebra(evaluationValue, computedEval)
for j := 0; j < field.D; j++ {
constraints = append(constraints, evalDiff[j])
}
return constraints
}

View File

@@ -1,104 +0,0 @@
package gates
import (
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
type EvaluateGatesChip struct {
api frontend.API
qeAPI *field.QuadraticExtensionAPI
gates []Gate
numGateConstraints uint64
selectorsInfo SelectorsInfo
}
func NewEvaluateGatesChip(
api frontend.API,
qeAPI *field.QuadraticExtensionAPI,
gates []Gate,
numGateConstraints uint64,
selectorsInfo SelectorsInfo,
) *EvaluateGatesChip {
return &EvaluateGatesChip{
api: api,
qeAPI: qeAPI,
gates: gates,
numGateConstraints: numGateConstraints,
selectorsInfo: selectorsInfo,
}
}
func (g *EvaluateGatesChip) computeFilter(
row uint64,
groupRange Range,
s field.QuadraticExtension,
manySelector bool,
) field.QuadraticExtension {
product := g.qeAPI.ONE_QE
for i := groupRange.start; i < groupRange.end; i++ {
if i == uint64(row) {
continue
}
product = g.qeAPI.MulExtension(product, g.qeAPI.SubExtension(g.qeAPI.FieldToQE(field.NewFieldConst(i)), s))
}
if manySelector {
product = g.qeAPI.MulExtension(product, g.qeAPI.SubExtension(g.qeAPI.FieldToQE(field.NewFieldConst(UNUSED_SELECTOR)), s))
}
return product
}
func (g *EvaluateGatesChip) evalFiltered(
gate Gate,
vars EvaluationVars,
row uint64,
selectorIndex uint64,
groupRange Range,
numSelectors uint64,
) []field.QuadraticExtension {
filter := g.computeFilter(row, groupRange, vars.localConstants[selectorIndex], numSelectors > 1)
vars.RemovePrefix(numSelectors)
unfiltered := gate.EvalUnfiltered(g.api, g.qeAPI, vars)
for i := range unfiltered {
unfiltered[i] = g.qeAPI.MulExtension(unfiltered[i], filter)
}
return unfiltered
}
func (g *EvaluateGatesChip) EvaluateGateConstraints(vars EvaluationVars) []field.QuadraticExtension {
constraints := make([]field.QuadraticExtension, g.numGateConstraints)
for i := range constraints {
constraints[i] = g.qeAPI.ZERO_QE
}
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] = g.qeAPI.AddExtension(constraints[i], constraint)
}
}
return constraints
}

View File

@@ -1,110 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
base := vars.localWires[g.wireBase()]
var powerBits []field.QuadraticExtension
for i := uint64(0); i < g.numPowerBits; i++ {
powerBits = append(powerBits, vars.localWires[g.wirePowerBit(i)])
}
var intermediateValues []field.QuadraticExtension
for i := uint64(0); i < g.numPowerBits; i++ {
intermediateValues = append(intermediateValues, vars.localWires[g.wireIntermediateValue(i)])
}
output := vars.localWires[g.wireOutput()]
var constraints []field.QuadraticExtension
for i := uint64(0); i < g.numPowerBits; i++ {
var prevIntermediateValue field.QuadraticExtension
if i == 0 {
prevIntermediateValue = qeAPI.ONE_QE
} else {
prevIntermediateValue = qeAPI.SquareExtension(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 := qeAPI.MulExtension(curBit, qeAPI.ONE_QE)
tmp = qeAPI.SubExtension(tmp, qeAPI.ONE_QE)
mulBy := qeAPI.MulExtension(curBit, base)
mulBy = qeAPI.SubExtension(mulBy, tmp)
intermediateValueDiff := qeAPI.MulExtension(prevIntermediateValue, mulBy)
intermediateValueDiff = qeAPI.SubExtension(intermediateValueDiff, intermediateValues[i])
constraints = append(constraints, intermediateValueDiff)
}
outputDiff := qeAPI.SubExtension(output, intermediateValues[g.numPowerBits-1])
constraints = append(constraints, outputDiff)
return constraints
}

View File

@@ -1,50 +0,0 @@
package gates
import (
"fmt"
"regexp"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
type Gate interface {
Id() string
EvalUnfiltered(api frontend.API, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension
}
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))
}

View File

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

@@ -1,74 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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 * field.D * i, 3*field.D*i + field.D}
}
func (g *MultiplicationExtensionGate) wiresIthMultiplicand1(i uint64) Range {
return Range{3*field.D*i + field.D, 3*field.D*i + 2*field.D}
}
func (g *MultiplicationExtensionGate) wiresIthOutput(i uint64) Range {
return Range{3*field.D*i + 2*field.D, 3*field.D*i + 3*field.D}
}
func (g *MultiplicationExtensionGate) EvalUnfiltered(api frontend.API, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
const0 := vars.localConstants[0]
constraints := []field.QuadraticExtension{}
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 := qeAPI.MulExtensionAlgebra(multiplicand0, multiplicand1)
computed_output := qeAPI.ScalarMulExtensionAlgebra(const0, mul)
diff := qeAPI.SubExtensionAlgebra(output, computed_output)
for j := 0; j < field.D; j++ {
constraints = append(constraints, diff[j])
}
}
return constraints
}

View File

@@ -1,30 +0,0 @@
package gates
import (
"regexp"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
return []field.QuadraticExtension{}
}

View File

@@ -1,177 +0,0 @@
package gates
import (
"regexp"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"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, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
constraints := []field.QuadraticExtension{}
poseidonChip := poseidon.NewPoseidonChip(api, field.NewFieldAPI(api), qeAPI)
// Assert that `swap` is binary.
swap := vars.localWires[g.WireSwap()]
swapMinusOne := qeAPI.SubExtension(swap, qeAPI.FieldToQE(field.ONE_F))
constraints = append(constraints, qeAPI.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 := qeAPI.SubExtension(inputRhs, inputLhs)
expectedDeltaI := qeAPI.MulExtension(swap, diff)
constraints = append(constraints, qeAPI.SubExtension(expectedDeltaI, deltaI))
}
// Compute the possibly-swapped input layer.
var state [poseidon.SPONGE_WIDTH]field.QuadraticExtension
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] = qeAPI.AddExtension(inputLhs, deltaI)
state[i+4] = qeAPI.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, qeAPI.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, qeAPI.SubExtension(state[0], sBoxIn))
state[0] = poseidonChip.SBoxMonomialExtension(sBoxIn)
state[0] = qeAPI.AddExtension(state[0], qeAPI.VarToQE(poseidon.FAST_PARTIAL_ROUND_CONSTANTS[r]))
state = poseidonChip.MdsPartialLayerFastExtension(state, int(r))
}
sBoxIn := vars.localWires[g.WirePartialSBox(poseidon.N_PARTIAL_ROUNDS-1)]
constraints = append(constraints, qeAPI.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, qeAPI.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, qeAPI.SubExtension(state[i], vars.localWires[g.WireOutput(i)]))
}
return constraints
}

View File

@@ -1,86 +0,0 @@
package gates
import (
"regexp"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"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 * field.D, (i + 1) * field.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) * field.D, (poseidon.SPONGE_WIDTH + i + 1) * field.D}
}
func (g *PoseidonMdsGate) mdsRowShfAlgebra(r uint64, v [poseidon.SPONGE_WIDTH]field.QEAlgebra, qeAPI *field.QuadraticExtensionAPI) field.QEAlgebra {
if r >= poseidon.SPONGE_WIDTH {
panic("MDS row index out of range")
}
res := qeAPI.ZERO_QE_ALGEBRA
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
coeff := qeAPI.VarToQE(poseidon.MDS_MATRIX_CIRC[i])
res = qeAPI.AddExtensionAlgebra(res, qeAPI.ScalarMulExtensionAlgebra(coeff, v[(i+r)%poseidon.SPONGE_WIDTH]))
}
coeff := qeAPI.VarToQE(poseidon.MDS_MATRIX_DIAG[r])
res = qeAPI.AddExtensionAlgebra(res, qeAPI.ScalarMulExtensionAlgebra(coeff, v[r]))
return res
}
func (g *PoseidonMdsGate) mdsLayerAlgebra(state [poseidon.SPONGE_WIDTH]field.QEAlgebra, qeAPI *field.QuadraticExtensionAPI) [poseidon.SPONGE_WIDTH]field.QEAlgebra {
var result [poseidon.SPONGE_WIDTH]field.QEAlgebra
for r := uint64(0); r < poseidon.SPONGE_WIDTH; r++ {
result[r] = g.mdsRowShfAlgebra(r, state, qeAPI)
}
return result
}
func (g *PoseidonMdsGate) EvalUnfiltered(api frontend.API, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
constraints := []field.QuadraticExtension{}
var inputs [poseidon.SPONGE_WIDTH]field.QEAlgebra
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
inputs[i] = vars.GetLocalExtAlgebra(g.WireInput(i))
}
computed_outputs := g.mdsLayerAlgebra(inputs, qeAPI)
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
output := vars.GetLocalExtAlgebra(g.WireOutput(i))
diff := qeAPI.SubExtensionAlgebra(output, computed_outputs[i])
constraints = append(constraints, diff[0], diff[1])
}
return constraints
}

View File

@@ -1,46 +0,0 @@
package gates
import (
"regexp"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
constraints := []field.QuadraticExtension{}
wires := g.WiresPublicInputsHash()
hash_parts := vars.publicInputsHash
for i := 0; i < 4; i++ {
wire := wires[i]
hash_part := hash_parts[i]
diff := qeAPI.SubExtension(vars.localWires[wire], qeAPI.FieldToQE(hash_part))
constraints = append(constraints, diff)
}
return constraints
}

View File

@@ -1,174 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
two := field.QuadraticExtension{field.NewFieldConst(2), field.NewFieldConst(0)}
constraints := []field.QuadraticExtension{}
for copy := uint64(0); copy < g.numCopies; copy++ {
accessIndex := vars.localWires[g.WireAccessIndex(copy)]
listItems := []field.QuadraticExtension{}
for i := uint64(0); i < g.vecSize(); i++ {
listItems = append(listItems, vars.localWires[g.WireListItem(i, copy)])
}
claimedElement := vars.localWires[g.WireClaimedElement(copy)]
bits := []field.QuadraticExtension{}
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 := qeAPI.MulExtension(b, b)
constraints = append(constraints, qeAPI.SubExtension(bSquared, b))
}
// Assert that the binary decomposition was correct.
reconstructedIndex := qeAPI.ReduceWithPowers(bits, two)
constraints = append(constraints, qeAPI.SubExtension(reconstructedIndex, accessIndex))
for _, b := range bits {
listItemsTmp := []field.QuadraticExtension{}
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 := qeAPI.MulExtension(b, x)
sub1 := qeAPI.SubExtension(mul1, x)
mul2 := qeAPI.MulExtension(b, y)
sub2 := qeAPI.SubExtension(mul2, sub1)
listItemsTmp = append(listItemsTmp, sub2)
}
listItems = listItemsTmp
}
if len(listItems) != 1 {
panic("listItems(len) != 1")
}
constraints = append(constraints, qeAPI.SubExtension(listItems[0], claimedElement))
}
for i := uint64(0); i < g.numExtraConstants; i++ {
constraints = append(constraints, qeAPI.SubExtension(vars.localConstants[i], vars.localWires[g.wireExtraConstant(i)]))
}
return constraints
}

View File

@@ -1,105 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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 * field.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, field.D}
}
func (g *ReducingExtensionGate) wiresAlpha() Range {
return Range{field.D, 2 * field.D}
}
func (g *ReducingExtensionGate) wiresOldAcc() Range {
return Range{2 * field.D, 3 * field.D}
}
func (g *ReducingExtensionGate) wiresCoeff(i uint64) Range {
return Range{START_COEFFS_REDUCING_EXTENSION_GATE + field.D*i, START_COEFFS_REDUCING_EXTENSION_GATE + field.D*(i+1)}
}
func (g *ReducingExtensionGate) startAccs() uint64 {
return START_COEFFS_REDUCING_EXTENSION_GATE + g.numCoeffs*field.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() + field.D*i, g.startAccs() + field.D*(i+1)}
}
func (g *ReducingExtensionGate) EvalUnfiltered(api frontend.API, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
alpha := vars.GetLocalExtAlgebra(g.wiresAlpha())
oldAcc := vars.GetLocalExtAlgebra(g.wiresOldAcc())
coeffs := []field.QEAlgebra{}
for i := uint64(0); i < g.numCoeffs; i++ {
coeffs = append(coeffs, vars.GetLocalExtAlgebra(g.wiresCoeff(i)))
}
accs := []field.QEAlgebra{}
for i := uint64(0); i < g.numCoeffs; i++ {
accs = append(accs, vars.GetLocalExtAlgebra(g.wiresAccs(i)))
}
constraints := []field.QuadraticExtension{}
acc := oldAcc
for i := uint64(0); i < g.numCoeffs; i++ {
coeff := coeffs[i]
tmp := qeAPI.MulExtensionAlgebra(acc, alpha)
tmp = qeAPI.AddExtensionAlgebra(tmp, coeff)
tmp = qeAPI.SubExtensionAlgebra(tmp, accs[i])
for j := uint64(0); j < field.D; j++ {
constraints = append(constraints, tmp[j])
}
acc = accs[i]
}
return constraints
}

View File

@@ -1,110 +0,0 @@
package gates
import (
"fmt"
"regexp"
"strconv"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
)
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 * field.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, field.D}
}
func (g *ReducingGate) wiresAlpha() Range {
return Range{field.D, 2 * field.D}
}
func (g *ReducingGate) wiresOldAcc() Range {
return Range{2 * field.D, 3 * field.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() + field.D*i, g.startAccs() + field.D*(i+1)}
}
func (g *ReducingGate) EvalUnfiltered(api frontend.API, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
alpha := vars.GetLocalExtAlgebra(g.wiresAlpha())
oldAcc := vars.GetLocalExtAlgebra(g.wiresOldAcc())
coeffs := []field.QuadraticExtension{}
coeffsRange := g.wiresCoeff()
for i := coeffsRange.start; i < coeffsRange.end; i++ {
coeffs = append(coeffs, vars.localWires[i])
}
accs := []field.QEAlgebra{}
for i := uint64(0); i < g.numCoeffs; i++ {
accs = append(accs, vars.GetLocalExtAlgebra(g.wiresAccs(i)))
}
constraints := []field.QuadraticExtension{}
acc := oldAcc
for i := uint64(0); i < g.numCoeffs; i++ {
var coeff field.QEAlgebra
for j := 0; j < field.D; j++ {
coeff[j] = qeAPI.ZERO_QE
}
coeff[0] = coeffs[i]
tmp := qeAPI.MulExtensionAlgebra(acc, alpha)
tmp = qeAPI.AddExtensionAlgebra(tmp, coeff)
tmp = qeAPI.SubExtensionAlgebra(tmp, accs[i])
for j := 0; j < field.D; j++ {
constraints = append(constraints, tmp[j])
}
acc = accs[i]
}
return constraints
}

View File

@@ -1,36 +0,0 @@
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))
}

View File

@@ -1,42 +0,0 @@
package gates
import (
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
)
type EvaluationVars struct {
localConstants []field.QuadraticExtension
localWires []field.QuadraticExtension
publicInputsHash poseidon.PoseidonHashOut
}
func NewEvaluationVars(
localConstants []field.QuadraticExtension,
localWires []field.QuadraticExtension,
publicInputsHash poseidon.PoseidonHashOut,
) *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) field.QEAlgebra {
// For now, only support degree 2
if wireRange.end-wireRange.start != field.D {
panic("Range must be of size D")
}
var ret field.QEAlgebra
for i := wireRange.start; i < wireRange.end; i++ {
ret[i-wireRange.start] = e.localWires[i]
}
return ret
}

View File

@@ -1,160 +0,0 @@
package plonk
import (
"fmt"
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/fri"
)
type ChallengerChip struct {
api frontend.API `gnark:"-"`
field field.FieldAPI `gnark:"-"`
poseidonChip *poseidon.PoseidonChip
poseidonBN128Chip *poseidon.PoseidonBN128Chip
spongeState [poseidon.SPONGE_WIDTH]frontend.Variable
inputBuffer []field.F
outputBuffer []field.F
}
func NewChallengerChip(api frontend.API, fieldAPI field.FieldAPI, poseidonChip *poseidon.PoseidonChip, poseidonBN128Chip *poseidon.PoseidonBN128Chip) *ChallengerChip {
var spongeState [poseidon.SPONGE_WIDTH]frontend.Variable
var inputBuffer []field.F
var outputBuffer []field.F
for i := 0; i < poseidon.SPONGE_WIDTH; i++ {
spongeState[i] = frontend.Variable(0)
}
return &ChallengerChip{
api: api,
field: fieldAPI,
poseidonChip: poseidonChip,
poseidonBN128Chip: poseidonBN128Chip,
spongeState: spongeState,
inputBuffer: inputBuffer,
outputBuffer: outputBuffer,
}
}
func (c *ChallengerChip) ObserveElement(element field.F) {
c.outputBuffer = clearBuffer(c.outputBuffer)
c.inputBuffer = append(c.inputBuffer, element)
if len(c.inputBuffer) == poseidon.SPONGE_RATE {
c.duplexing()
}
}
func (c *ChallengerChip) ObserveElements(elements []field.F) {
for i := 0; i < len(elements); i++ {
c.ObserveElement(elements[i])
}
}
func (c *ChallengerChip) ObserveHash(hash poseidon.PoseidonHashOut) {
elements := c.poseidonChip.ToVec(hash)
c.ObserveElements(elements)
}
func (c *ChallengerChip) ObserveBN128Hash(hash poseidon.PoseidonBN128HashOut) {
elements := c.poseidonBN128Chip.ToVec(hash)
c.ObserveElements(elements)
}
func (c *ChallengerChip) ObserveCap(cap []poseidon.PoseidonBN128HashOut) {
for i := 0; i < len(cap); i++ {
c.ObserveBN128Hash(cap[i])
}
}
func (c *ChallengerChip) ObserveExtensionElement(element field.QuadraticExtension) {
c.ObserveElements(element[:])
}
func (c *ChallengerChip) ObserveExtensionElements(elements []field.QuadraticExtension) {
for i := 0; i < len(elements); i++ {
c.ObserveExtensionElement(elements[i])
}
}
func (c *ChallengerChip) ObserveOpenings(openings fri.FriOpenings) {
for i := 0; i < len(openings.Batches); i++ {
c.ObserveExtensionElements(openings.Batches[i].Values)
}
}
func (c *ChallengerChip) GetChallenge() field.F {
if len(c.inputBuffer) != 0 || len(c.outputBuffer) == 0 {
c.duplexing()
}
challenge := c.outputBuffer[len(c.outputBuffer)-1]
c.outputBuffer = c.outputBuffer[:len(c.outputBuffer)-1]
return challenge
}
func (c *ChallengerChip) GetNChallenges(n uint64) []field.F {
challenges := make([]field.F, n)
for i := uint64(0); i < n; i++ {
challenges[i] = c.GetChallenge()
}
return challenges
}
func (c *ChallengerChip) GetExtensionChallenge() field.QuadraticExtension {
values := c.GetNChallenges(2)
return field.QuadraticExtension{values[0], values[1]}
}
func (c *ChallengerChip) GetHash() poseidon.PoseidonHashOut {
return [4]field.F{c.GetChallenge(), c.GetChallenge(), c.GetChallenge(), c.GetChallenge()}
}
func (c *ChallengerChip) GetFriChallenges(commitPhaseMerkleCaps []common.MerkleCap, finalPoly common.PolynomialCoeffs, powWitness field.F, degreeBits uint64, config common.FriConfig) common.FriChallenges {
numFriQueries := config.NumQueryRounds
friAlpha := c.GetExtensionChallenge()
var friBetas []field.QuadraticExtension
for i := 0; i < len(commitPhaseMerkleCaps); i++ {
c.ObserveCap(commitPhaseMerkleCaps[i])
friBetas = append(friBetas, c.GetExtensionChallenge())
}
c.ObserveExtensionElements(finalPoly.Coeffs)
c.ObserveElement(powWitness)
friPowResponse := c.GetChallenge()
friQueryIndices := c.GetNChallenges(numFriQueries)
return common.FriChallenges{
FriAlpha: friAlpha,
FriBetas: friBetas,
FriPowResponse: friPowResponse,
FriQueryIndices: friQueryIndices,
}
}
func clearBuffer(buffer []field.F) []field.F {
return make([]field.F, 0)
}
func (c *ChallengerChip) duplexing() {
if len(c.inputBuffer) > poseidon.SPONGE_RATE {
fmt.Println(len(c.inputBuffer))
panic("something went wrong")
}
for i := 0; i < len(c.inputBuffer); i++ {
c.spongeState[i] = c.field.Reduce(c.inputBuffer[i]).Limbs[0]
}
c.inputBuffer = clearBuffer(c.inputBuffer)
c.spongeState = c.poseidonChip.Poseidon(c.spongeState)
clearBuffer(c.outputBuffer)
for i := 0; i < poseidon.SPONGE_RATE; i++ {
c.outputBuffer = append(c.outputBuffer, c.field.NewElement(c.spongeState[i]))
}
}

View File

@@ -1,227 +0,0 @@
package plonk
import (
"math/big"
"testing"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/cs/r1cs"
"github.com/consensys/gnark/test"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/fri"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils"
)
type TestChallengerCircuit struct {
commonCircuitDataFilename string `gnark:"-"`
CircuitDigest frontend.Variable `gnark:",public"`
PublicInputs []field.F `gnark:",public"`
WiresCap []frontend.Variable
PlonkZsPartialProductsCap []frontend.Variable
QuotientPolysCap []frontend.Variable
FriOpenings fri.FriOpenings
CommitPhaseMerkleCaps [][]frontend.Variable
FinalPoly common.PolynomialCoeffs
PowWitness field.F
}
func (circuit *TestChallengerCircuit) Define(api frontend.API) error {
commonCircuitData := utils.DeserializeCommonCircuitData(circuit.commonCircuitDataFilename)
config := commonCircuitData.Config
numChallenges := config.NumChallenges
fieldAPI := field.NewFieldAPI(api)
qeAPI := field.NewQuadraticExtensionAPI(api, fieldAPI)
poseidonChip := poseidon.NewPoseidonChip(api, fieldAPI, qeAPI)
poseidonBN128Chip := poseidon.NewPoseidonBN128Chip(api, fieldAPI)
challenger := NewChallengerChip(api, fieldAPI, poseidonChip, poseidonBN128Chip)
challenger.ObserveBN128Hash(circuit.CircuitDigest)
challenger.ObserveHash(poseidonChip.HashNoPad(circuit.PublicInputs))
challenger.ObserveCap(circuit.WiresCap)
plonkBetas := challenger.GetNChallenges(numChallenges)
plonkGammas := challenger.GetNChallenges(numChallenges)
challenger.ObserveCap(circuit.PlonkZsPartialProductsCap)
plonkAlphas := challenger.GetNChallenges(numChallenges)
challenger.ObserveCap(circuit.QuotientPolysCap)
plonkZeta := challenger.GetExtensionChallenge()
challenger.ObserveOpenings(circuit.FriOpenings)
friChallenges := challenger.GetFriChallenges(
circuit.CommitPhaseMerkleCaps,
circuit.FinalPoly,
circuit.PowWitness,
commonCircuitData.DegreeBits,
config.FriConfig,
)
expectedPlonkBetas := [2]field.F{
field.NewFieldConstFromString("17615363392879944733"),
field.NewFieldConstFromString("9422446877322953047"),
}
expectedPlonkGammas := [2]field.F{
field.NewFieldConstFromString("15174493176564484303"),
field.NewFieldConstFromString("6175150444166239851"),
}
for i := 0; i < 2; i++ {
fieldAPI.AssertIsEqual(plonkBetas[i], expectedPlonkBetas[i])
fieldAPI.AssertIsEqual(plonkGammas[i], expectedPlonkGammas[i])
}
expectedPlonkAlphas := [2]field.F{
field.NewFieldConstFromString("9276470834414745550"),
field.NewFieldConstFromString("5302812342351431915"),
}
for i := 0; i < 2; i++ {
fieldAPI.AssertIsEqual(plonkAlphas[i], expectedPlonkAlphas[i])
}
expectedPlonkZeta := field.QuadraticExtension{
field.NewFieldConstFromString("3892795992421241388"),
field.NewFieldConstFromString("15786647757418200302"),
}
for i := 0; i < 2; i++ {
fieldAPI.AssertIsEqual(plonkZeta[i], expectedPlonkZeta[i])
}
fieldAPI.AssertIsEqual(friChallenges.FriAlpha[0], field.NewFieldConst(885535811531859621))
fieldAPI.AssertIsEqual(friChallenges.FriBetas[0][0], field.NewFieldConst(5231781384587895507))
fieldAPI.AssertIsEqual(friChallenges.FriPowResponse, field.NewFieldConst(70715523064019))
fieldAPI.AssertIsEqual(friChallenges.FriQueryIndices[0], field.NewFieldConst(11890500485816111017))
return nil
}
func StringToBN128Hash(hashStr string) poseidon.PoseidonBN128HashOut {
hashBigInt, ok := new(big.Int).SetString(hashStr, 10)
if !(ok) {
panic("Invalid hash: " + hashStr)
}
hashVar := frontend.Variable(*hashBigInt)
return poseidon.PoseidonBN128HashOut(hashVar)
}
func TestChallengerWitness(t *testing.T) {
assert := test.NewAssert(t)
testCase := func() {
proofWithPis := utils.DeserializeProofWithPublicInputs("../../data/decode_block/proof_with_public_inputs.json")
verifierData := utils.DeserializeVerifierOnlyCircuitData("../../data/decode_block/verifier_only_circuit_data.json")
circuit := TestChallengerCircuit{
commonCircuitDataFilename: "../../data/decode_block/common_circuit_data.json",
CircuitDigest: verifierData.CircuitDigest,
PublicInputs: proofWithPis.PublicInputs,
WiresCap: proofWithPis.Proof.WiresCap,
PlonkZsPartialProductsCap: proofWithPis.Proof.PlonkZsPartialProductsCap,
QuotientPolysCap: proofWithPis.Proof.QuotientPolysCap,
FriOpenings: fri.ToFriOpenings(proofWithPis.Proof.Openings),
CommitPhaseMerkleCaps: proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
FinalPoly: proofWithPis.Proof.OpeningProof.FinalPoly,
PowWitness: proofWithPis.Proof.OpeningProof.PowWitness,
}
witness := TestChallengerCircuit{
CircuitDigest: verifierData.CircuitDigest,
PublicInputs: proofWithPis.PublicInputs,
WiresCap: proofWithPis.Proof.WiresCap,
PlonkZsPartialProductsCap: proofWithPis.Proof.PlonkZsPartialProductsCap,
QuotientPolysCap: proofWithPis.Proof.QuotientPolysCap,
FriOpenings: fri.ToFriOpenings(proofWithPis.Proof.Openings),
CommitPhaseMerkleCaps: proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
FinalPoly: proofWithPis.Proof.OpeningProof.FinalPoly,
PowWitness: proofWithPis.Proof.OpeningProof.PowWitness,
}
err := test.IsSolved(&circuit, &witness, field.TEST_CURVE.ScalarField())
assert.NoError(err)
}
testCase()
}
func TestChallengerProver(t *testing.T) {
proofWithPis := utils.DeserializeProofWithPublicInputs("../../data/decode_block/proof_with_public_inputs.json")
verifierData := utils.DeserializeVerifierOnlyCircuitData("../../data/decode_block/verifier_only_circuit_data.json")
circuit := TestChallengerCircuit{
commonCircuitDataFilename: "../../data/decode_block/common_circuit_data.json",
CircuitDigest: verifierData.CircuitDigest,
PublicInputs: proofWithPis.PublicInputs,
WiresCap: proofWithPis.Proof.WiresCap,
PlonkZsPartialProductsCap: proofWithPis.Proof.PlonkZsPartialProductsCap,
QuotientPolysCap: proofWithPis.Proof.QuotientPolysCap,
FriOpenings: fri.ToFriOpenings(proofWithPis.Proof.Openings),
CommitPhaseMerkleCaps: proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
FinalPoly: proofWithPis.Proof.OpeningProof.FinalPoly,
PowWitness: proofWithPis.Proof.OpeningProof.PowWitness,
}
proofWithPis = utils.DeserializeProofWithPublicInputs("../../data/decode_block/proof_with_public_inputs.json")
verifierData = utils.DeserializeVerifierOnlyCircuitData("../../data/decode_block/verifier_only_circuit_data.json")
assignment := TestChallengerCircuit{
commonCircuitDataFilename: "../../data/decode_block/common_circuit_data.json",
CircuitDigest: verifierData.CircuitDigest,
PublicInputs: proofWithPis.PublicInputs,
WiresCap: proofWithPis.Proof.WiresCap,
PlonkZsPartialProductsCap: proofWithPis.Proof.PlonkZsPartialProductsCap,
QuotientPolysCap: proofWithPis.Proof.QuotientPolysCap,
FriOpenings: fri.ToFriOpenings(proofWithPis.Proof.Openings),
CommitPhaseMerkleCaps: proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
FinalPoly: proofWithPis.Proof.OpeningProof.FinalPoly,
PowWitness: proofWithPis.Proof.OpeningProof.PowWitness,
}
r1cs, err := frontend.Compile(field.TEST_CURVE.ScalarField(), r1cs.NewBuilder, &circuit)
if err != nil {
panic(err)
}
println("num constraints is ", r1cs.GetNbConstraints())
assert := test.NewAssert(t)
err = test.IsSolved(&circuit, &assignment, field.TEST_CURVE.ScalarField())
assert.NoError(err)
witness, err := frontend.NewWitness(&assignment, field.TEST_CURVE.ScalarField())
if err != nil {
panic(err)
}
pk, vk, err := groth16.Setup(r1cs)
if err != nil {
panic(err)
}
proof, err := groth16.Prove(r1cs, pk, witness)
if err != nil {
panic(err)
}
publicWitness, err := witness.Public()
if err != nil {
panic(err)
}
err = groth16.Verify(proof, vk, publicWitness)
if err != nil {
panic(err)
}
}

View File

@@ -1,225 +0,0 @@
package plonk
import (
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/gates"
)
type PlonkChip struct {
api frontend.API `gnark:"-"`
qeAPI *field.QuadraticExtensionAPI `gnark:"-"`
commonData common.CommonCircuitData `gnark:"-"`
DEGREE field.F `gnark:"-"`
DEGREE_BITS_F field.F `gnark:"-"`
DEGREE_QE field.QuadraticExtension `gnark:"-"`
evaluateGatesChip *gates.EvaluateGatesChip
}
func NewPlonkChip(api frontend.API, qeAPI *field.QuadraticExtensionAPI, commonData common.CommonCircuitData) *PlonkChip {
// TODO: Should degreeBits be verified that it fits within the field and that degree is within uint64?
evaluateGatesChip := gates.NewEvaluateGatesChip(
api,
qeAPI,
commonData.Gates,
commonData.NumGateConstraints,
commonData.SelectorsInfo,
)
return &PlonkChip{
api: api,
qeAPI: qeAPI,
commonData: commonData,
DEGREE: field.NewFieldConst(1 << commonData.DegreeBits),
DEGREE_BITS_F: field.NewFieldConst(commonData.DegreeBits),
DEGREE_QE: field.QuadraticExtension{field.NewFieldConst(1 << commonData.DegreeBits), field.ZERO_F},
evaluateGatesChip: evaluateGatesChip,
}
}
func (p *PlonkChip) expPowerOf2Extension(x field.QuadraticExtension) field.QuadraticExtension {
for i := uint64(0); i < p.commonData.DegreeBits; i++ {
x = p.qeAPI.SquareExtension(x)
}
return x
}
func (p *PlonkChip) evalL0(x field.QuadraticExtension, xPowN field.QuadraticExtension) field.QuadraticExtension {
// L_0(x) = (x^n - 1) / (n * (x - 1))
evalZeroPoly := p.qeAPI.SubExtension(
xPowN,
p.qeAPI.ONE_QE,
)
denominator := p.qeAPI.SubExtension(
p.qeAPI.ScalarMulExtension(x, p.DEGREE),
p.DEGREE_QE,
)
return p.qeAPI.DivExtension(
evalZeroPoly,
denominator,
)
}
func (p *PlonkChip) checkPartialProducts(
numerators []field.QuadraticExtension,
denominators []field.QuadraticExtension,
challengeNum uint64,
openings common.OpeningSet,
) []field.QuadraticExtension {
numPartProds := p.commonData.NumPartialProducts
quotDegreeFactor := p.commonData.QuotientDegreeFactor
productAccs := make([]field.QuadraticExtension, 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([]field.QuadraticExtension, 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 = p.qeAPI.MulExtension(numeProduct, numerators[ppStartIdx+j])
denoProduct = p.qeAPI.MulExtension(denoProduct, denominators[ppStartIdx+j])
}
partialProductCheck := p.qeAPI.SubExtension(
p.qeAPI.MulExtension(productAccs[i], numeProduct),
p.qeAPI.MulExtension(productAccs[i+1], denoProduct),
)
partialProductChecks = append(partialProductChecks, partialProductCheck)
}
return partialProductChecks
}
func (p *PlonkChip) evalVanishingPoly(vars gates.EvaluationVars, proofChallenges common.ProofChallenges, openings common.OpeningSet, zetaPowN field.QuadraticExtension) []field.QuadraticExtension {
constraintTerms := p.evaluateGatesChip.EvaluateGateConstraints(vars)
// Calculate the k[i] * x
sIDs := make([]field.QuadraticExtension, p.commonData.Config.NumRoutedWires)
for i := uint64(0); i < p.commonData.Config.NumRoutedWires; i++ {
sIDs[i] = p.qeAPI.ScalarMulExtension(proofChallenges.PlonkZeta, p.commonData.KIs[i])
}
// Calculate L_0(zeta)
l0Zeta := p.evalL0(proofChallenges.PlonkZeta, zetaPowN)
vanishingZ1Terms := make([]field.QuadraticExtension, 0, p.commonData.Config.NumChallenges)
vanishingPartialProductsTerms := make([]field.QuadraticExtension, 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 := p.qeAPI.MulExtension(
l0Zeta,
p.qeAPI.SubExtension(openings.PlonkZs[i], p.qeAPI.ONE_QE))
vanishingZ1Terms = append(vanishingZ1Terms, z1_term)
numeratorValues := make([]field.QuadraticExtension, 0, p.commonData.Config.NumRoutedWires)
denominatorValues := make([]field.QuadraticExtension, 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 := p.qeAPI.AddExtension(
openings.Wires[j],
p.qeAPI.FieldToQE(proofChallenges.PlonkGammas[i]),
)
numerator := p.qeAPI.AddExtension(
p.qeAPI.MulExtension(
p.qeAPI.FieldToQE(proofChallenges.PlonkBetas[i]),
sIDs[j],
),
wireValuePlusGamma,
)
denominator := p.qeAPI.AddExtension(
p.qeAPI.MulExtension(
p.qeAPI.FieldToQE(proofChallenges.PlonkBetas[i]),
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([]field.QuadraticExtension, p.commonData.Config.NumChallenges)
for i := uint64(0); i < p.commonData.Config.NumChallenges; i++ {
reducedValues[i] = p.qeAPI.ZERO_QE
}
// 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] = p.qeAPI.AddExtension(
vanishingTerms[i],
p.qeAPI.ScalarMulExtension(
reducedValues[j],
proofChallenges.PlonkAlphas[j],
),
)
}
}
return reducedValues
}
func (p *PlonkChip) Verify(proofChallenges common.ProofChallenges, openings common.OpeningSet, publicInputsHash poseidon.PoseidonHashOut) {
// 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 := p.qeAPI.SubExtension(zetaPowN, p.qeAPI.ONE_QE)
// `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 := p.qeAPI.MulExtension(
zHZeta,
p.qeAPI.ReduceWithPowers(
openings.QuotientPolys[quotientPolysStartIdx:quotientPolysEndIdx],
zetaPowN,
),
)
p.qeAPI.AssertIsEqual(vanishingPolysZeta[i], prod)
}
}

View File

@@ -1,56 +0,0 @@
package plonk_test
import (
"testing"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/test"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/plonk"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils"
)
type TestPlonkCircuit struct {
proofWithPIsFilename string `gnark:"-"`
commonCircuitDataFilename string `gnark:"-"`
verifierOnlyCircuitDataFilename string `gnark:"-"`
}
func (circuit *TestPlonkCircuit) Define(api frontend.API) error {
proofWithPis := utils.DeserializeProofWithPublicInputs(circuit.proofWithPIsFilename)
commonCircuitData := utils.DeserializeCommonCircuitData(circuit.commonCircuitDataFilename)
verifierOnlyCircuitData := utils.DeserializeVerifierOnlyCircuitData(circuit.verifierOnlyCircuitDataFilename)
verifierChip := verifier.NewVerifierChip(api, commonCircuitData)
publicInputsHash := verifierChip.GetPublicInputsHash(proofWithPis.PublicInputs)
proofChallenges := verifierChip.GetChallenges(proofWithPis.Proof, publicInputsHash, commonCircuitData, verifierOnlyCircuitData)
fieldAPI := field.NewFieldAPI(api)
qeAPI := field.NewQuadraticExtensionAPI(api, fieldAPI)
plonkChip := plonk.NewPlonkChip(
api,
qeAPI,
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, field.TEST_CURVE.ScalarField())
assert.NoError(err)
}
testCase()
}

View File

@@ -1,13 +0,0 @@
package plonk
import "github.com/succinctlabs/gnark-plonky2-verifier/field"
type OpeningSet struct {
Constants []field.QuadraticExtension
PlonkSigmas []field.QuadraticExtension
Wires []field.QuadraticExtension
PlonkZs []field.QuadraticExtension
PlonkZsNext []field.QuadraticExtension
PartialProducts []field.QuadraticExtension
QuotientPolys []field.QuadraticExtension
}

View File

@@ -1,28 +0,0 @@
package verifier
import (
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/plonk"
)
type Proof struct {
WiresCap common.MerkleCap
PlonkZsPartialProductsCap common.MerkleCap
QuotientPolysCap common.MerkleCap
Openings plonk.OpeningSet
OpeningProof common.FriProof
}
type ProofWithPublicInputs struct {
Proof Proof
PublicInputs []field.F
}
type ProofChallenges struct {
PlonkBetas []field.F
PlonkGammas []field.F
PlonkAlphas []field.F
PlonkZeta field.QuadraticExtension
FriChallenges common.FriChallenges
}

View File

@@ -2,63 +2,53 @@ package verifier
import (
"github.com/consensys/gnark/frontend"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/challenger"
"github.com/succinctlabs/gnark-plonky2-verifier/fri"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
"github.com/succinctlabs/gnark-plonky2-verifier/plonk"
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/fri"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/plonk"
"github.com/succinctlabs/gnark-plonky2-verifier/types"
)
type VerifierChip struct {
api frontend.API `gnark:"-"`
fieldAPI field.FieldAPI `gnark:"-"`
qeAPI *field.QuadraticExtensionAPI `gnark:"-"`
poseidonChip *poseidon.PoseidonChip
poseidonBN128Chip *poseidon.PoseidonBN128Chip
api frontend.API `gnark:"-"`
poseidonGlChip *poseidon.GoldilocksChip
poseidonBN254Chip *poseidon.BN254Chip
plonkChip *plonk.PlonkChip
friChip *fri.FriChip
friChip *fri.Chip
}
func NewVerifierChip(api frontend.API, commonCircuitData common.CommonCircuitData) *VerifierChip {
fieldAPI := field.NewFieldAPI(api)
qeAPI := field.NewQuadraticExtensionAPI(api, fieldAPI)
poseidonBN128Chip := poseidon.NewPoseidonBN128Chip(api, fieldAPI)
friChip := fri.NewFriChip(api, fieldAPI, qeAPI, poseidonBN128Chip, &commonCircuitData.FriParams)
plonkChip := plonk.NewPlonkChip(api, qeAPI, commonCircuitData)
// We are using goldilocks poseidon for the challenge computation
poseidonChip := poseidon.NewPoseidonChip(api, fieldAPI, qeAPI)
func NewVerifierChip(api frontend.API, commonCircuitData types.CommonCircuitData) *VerifierChip {
friChip := fri.NewChip(api, &commonCircuitData.FriParams)
plonkChip := plonk.NewPlonkChip(api, commonCircuitData)
poseidonGlChip := poseidon.NewGoldilocksChip(api)
poseidonBN254Chip := poseidon.NewBN254Chip(api)
return &VerifierChip{
api: api,
fieldAPI: fieldAPI,
qeAPI: qeAPI,
poseidonChip: poseidonChip,
poseidonBN128Chip: poseidonBN128Chip,
poseidonGlChip: poseidonGlChip,
poseidonBN254Chip: poseidonBN254Chip,
plonkChip: plonkChip,
friChip: friChip,
}
}
func (c *VerifierChip) GetPublicInputsHash(publicInputs []field.F) poseidon.PoseidonHashOut {
return c.poseidonChip.HashNoPad(publicInputs)
func (c *VerifierChip) GetPublicInputsHash(publicInputs []gl.Variable) poseidon.GoldilocksHashOut {
return c.poseidonGlChip.HashNoPad(publicInputs)
}
func (c *VerifierChip) GetChallenges(
proof common.Proof,
publicInputsHash poseidon.PoseidonHashOut,
commonData common.CommonCircuitData,
verifierData common.VerifierOnlyCircuitData,
) common.ProofChallenges {
proof types.Proof,
publicInputsHash poseidon.GoldilocksHashOut,
commonData types.CommonCircuitData,
verifierData types.VerifierOnlyCircuitData,
) types.ProofChallenges {
config := commonData.Config
numChallenges := config.NumChallenges
challenger := plonk.NewChallengerChip(c.api, c.fieldAPI, c.poseidonChip, c.poseidonBN128Chip)
challenger := challenger.NewChip(c.api)
var circuitDigest = verifierData.CircuitDigest
challenger.ObserveBN128Hash(circuitDigest)
challenger.ObserveBN254Hash(circuitDigest)
challenger.ObserveHash(publicInputsHash)
challenger.ObserveCap(proof.WiresCap)
plonkBetas := challenger.GetNChallenges(numChallenges)
@@ -70,9 +60,9 @@ func (c *VerifierChip) GetChallenges(
challenger.ObserveCap(proof.QuotientPolysCap)
plonkZeta := challenger.GetExtensionChallenge()
challenger.ObserveOpenings(fri.ToFriOpenings(proof.Openings))
challenger.ObserveOpenings(fri.ToOpenings(proof.Openings))
return common.ProofChallenges{
return types.ProofChallenges{
PlonkBetas: plonkBetas,
PlonkGammas: plonkGammas,
PlonkAlphas: plonkAlphas,
@@ -154,7 +144,13 @@ func (c *VerifierChip) generateProofInput(commonData common.CommonCircuitData) c
}
*/
func (c *VerifierChip) Verify(proof common.Proof, publicInputs []field.F, verifierData common.VerifierOnlyCircuitData, commonData common.CommonCircuitData) {
func (c *VerifierChip) Verify(
proof types.Proof,
publicInputs []gl.Variable,
verifierData types.VerifierOnlyCircuitData,
commonData types.CommonCircuitData,
) {
glApi := gl.NewChip(c.api)
// TODO: Need to range check all the proof and public input elements to make sure they are within goldilocks field
// Generate the parts of the witness that is for the plonky2 proof input
@@ -163,7 +159,7 @@ func (c *VerifierChip) Verify(proof common.Proof, publicInputs []field.F, verifi
c.plonkChip.Verify(proofChallenges, proof.Openings, publicInputsHash)
initialMerkleCaps := []common.MerkleCap{
initialMerkleCaps := []types.FriMerkleCap{
verifierData.ConstantSigmasCap,
proof.WiresCap,
proof.PlonkZsPartialProductsCap,
@@ -172,26 +168,26 @@ func (c *VerifierChip) Verify(proof common.Proof, publicInputs []field.F, verifi
// Seems like there is a bug in the emulated field code.
// Add ZERO to all of the fri challenges values to reduce them.
proofChallenges.PlonkZeta[0] = c.fieldAPI.Add(proofChallenges.PlonkZeta[0], field.ZERO_F)
proofChallenges.PlonkZeta[1] = c.fieldAPI.Add(proofChallenges.PlonkZeta[1], field.ZERO_F)
proofChallenges.PlonkZeta[0] = glApi.Add(proofChallenges.PlonkZeta[0], gl.Zero())
proofChallenges.PlonkZeta[1] = glApi.Add(proofChallenges.PlonkZeta[1], gl.Zero())
proofChallenges.FriChallenges.FriAlpha[0] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriAlpha[0], field.ZERO_F)
proofChallenges.FriChallenges.FriAlpha[1] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriAlpha[1], field.ZERO_F)
proofChallenges.FriChallenges.FriAlpha[0] = glApi.Add(proofChallenges.FriChallenges.FriAlpha[0], gl.Zero())
proofChallenges.FriChallenges.FriAlpha[1] = glApi.Add(proofChallenges.FriChallenges.FriAlpha[1], gl.Zero())
for i := 0; i < len(proofChallenges.FriChallenges.FriBetas); i++ {
proofChallenges.FriChallenges.FriBetas[i][0] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriBetas[i][0], field.ZERO_F)
proofChallenges.FriChallenges.FriBetas[i][1] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriBetas[i][1], field.ZERO_F)
proofChallenges.FriChallenges.FriBetas[i][0] = glApi.Add(proofChallenges.FriChallenges.FriBetas[i][0], gl.Zero())
proofChallenges.FriChallenges.FriBetas[i][1] = glApi.Add(proofChallenges.FriChallenges.FriBetas[i][1], gl.Zero())
}
proofChallenges.FriChallenges.FriPowResponse = c.fieldAPI.Add(proofChallenges.FriChallenges.FriPowResponse, field.ZERO_F)
proofChallenges.FriChallenges.FriPowResponse = glApi.Add(proofChallenges.FriChallenges.FriPowResponse, gl.Zero())
for i := 0; i < len(proofChallenges.FriChallenges.FriQueryIndices); i++ {
proofChallenges.FriChallenges.FriQueryIndices[i] = c.fieldAPI.Add(proofChallenges.FriChallenges.FriQueryIndices[i], field.ZERO_F)
proofChallenges.FriChallenges.FriQueryIndices[i] = glApi.Add(proofChallenges.FriChallenges.FriQueryIndices[i], gl.Zero())
}
c.friChip.VerifyFriProof(
fri.GetFriInstance(&commonData, c.qeAPI, proofChallenges.PlonkZeta, commonData.DegreeBits),
fri.ToFriOpenings(proof.Openings),
fri.GetInstance(&commonData, glApi, proofChallenges.PlonkZeta, commonData.DegreeBits),
fri.ToOpenings(proof.Openings),
&proofChallenges.FriChallenges,
initialMerkleCaps,
&proof.OpeningProof,

View File

@@ -8,15 +8,14 @@ import (
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/math/emulated"
"github.com/consensys/gnark/test"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
"github.com/succinctlabs/gnark-plonky2-verifier/types"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils"
)
type TestVerifierCircuit struct {
Proof common.Proof
PublicInputs []field.F `gnark:",public"`
Proof types.Proof
PublicInputs []gl.Variable `gnark:",public"`
verifierChip *verifier.VerifierChip `gnark:"-"`
plonky2CircuitName string `gnark:"-"`
@@ -24,8 +23,8 @@ type TestVerifierCircuit struct {
func (c *TestVerifierCircuit) Define(api frontend.API) error {
circuitDirname := "./data/" + c.plonky2CircuitName + "/"
commonCircuitData := utils.DeserializeCommonCircuitData(circuitDirname + "common_circuit_data.json")
verifierOnlyCircuitData := utils.DeserializeVerifierOnlyCircuitData(circuitDirname + "verifier_only_circuit_data.json")
commonCircuitData := verifier.DeserializeCommonCircuitData(circuitDirname + "common_circuit_data.json")
verifierOnlyCircuitData := verifier.DeserializeVerifierOnlyCircuitData(circuitDirname + "verifier_only_circuit_data.json")
c.verifierChip = verifier.NewVerifierChip(api, commonCircuitData)
@@ -39,21 +38,21 @@ func TestStepVerifier(t *testing.T) {
testCase := func() {
plonky2Circuit := "step"
proofWithPis := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
proofWithPis := verifier.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
circuit := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis.Proof,
PublicInputs: proofWithPis.PublicInputs,
}
proofWithPis2 := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
proofWithPis2 := verifier.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
witness := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis2.Proof,
PublicInputs: proofWithPis2.PublicInputs,
}
err := test.IsSolved(&circuit, &witness, field.TEST_CURVE.ScalarField())
err := test.IsSolved(&circuit, &witness, ecc.BN254.ScalarField())
assert.NoError(err)
}
testCase()
@@ -63,14 +62,14 @@ func TestStepVerifier2(t *testing.T) {
assert := test.NewAssert(t)
plonky2Circuit := "step"
proofWithPis := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
proofWithPis := verifier.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
circuit := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis.Proof,
PublicInputs: proofWithPis.PublicInputs,
}
proofWithPis2 := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
proofWithPis2 := verifier.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
witness := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis2.Proof,