mirror of
https://github.com/arnaucube/gnark-plonky2-verifier.git
synced 2026-01-12 09:01:32 +01:00
Merge pull request #42 from succinctlabs/kevjue/audit_fixes
fix: Veridise audit fixes
This commit is contained in:
@@ -10,7 +10,7 @@ Besides the verifier, there are some Gnark implementation of circuits in this re
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- [Go (1.20.1+)](https://go.dev/doc/install)
|
- [Go (1.19+)](https://go.dev/doc/install)
|
||||||
|
|
||||||
## Benchmark
|
## Benchmark
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ type Chip struct {
|
|||||||
api frontend.API `gnark:"-"`
|
api frontend.API `gnark:"-"`
|
||||||
poseidonChip *poseidon.GoldilocksChip
|
poseidonChip *poseidon.GoldilocksChip
|
||||||
poseidonBN254Chip *poseidon.BN254Chip
|
poseidonBN254Chip *poseidon.BN254Chip
|
||||||
spongeState [poseidon.SPONGE_WIDTH]gl.Variable
|
spongeState poseidon.GoldilocksState
|
||||||
inputBuffer []gl.Variable
|
inputBuffer []gl.Variable
|
||||||
outputBuffer []gl.Variable
|
outputBuffer []gl.Variable
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChip(api frontend.API) *Chip {
|
func NewChip(api frontend.API) *Chip {
|
||||||
var spongeState [poseidon.SPONGE_WIDTH]gl.Variable
|
var spongeState poseidon.GoldilocksState
|
||||||
var inputBuffer []gl.Variable
|
var inputBuffer []gl.Variable
|
||||||
var outputBuffer []gl.Variable
|
var outputBuffer []gl.Variable
|
||||||
for i := 0; i < poseidon.SPONGE_WIDTH; i++ {
|
for i := 0; i < poseidon.SPONGE_WIDTH; i++ {
|
||||||
@@ -40,7 +40,8 @@ func NewChip(api frontend.API) *Chip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chip) ObserveElement(element gl.Variable) {
|
func (c *Chip) ObserveElement(element gl.Variable) {
|
||||||
c.outputBuffer = clearBuffer(c.outputBuffer)
|
// Clear the output buffer
|
||||||
|
c.outputBuffer = make([]gl.Variable, 0)
|
||||||
c.inputBuffer = append(c.inputBuffer, element)
|
c.inputBuffer = append(c.inputBuffer, element)
|
||||||
if len(c.inputBuffer) == poseidon.SPONGE_RATE {
|
if len(c.inputBuffer) == poseidon.SPONGE_RATE {
|
||||||
c.duplexing()
|
c.duplexing()
|
||||||
@@ -110,14 +111,13 @@ func (c *Chip) GetExtensionChallenge() gl.QuadraticExtensionVariable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chip) GetHash() poseidon.GoldilocksHashOut {
|
func (c *Chip) GetHash() poseidon.GoldilocksHashOut {
|
||||||
return [4]gl.Variable{c.GetChallenge(), c.GetChallenge(), c.GetChallenge(), c.GetChallenge()}
|
return [poseidon.POSEIDON_GL_HASH_SIZE]gl.Variable{c.GetChallenge(), c.GetChallenge(), c.GetChallenge(), c.GetChallenge()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chip) GetFriChallenges(
|
func (c *Chip) GetFriChallenges(
|
||||||
commitPhaseMerkleCaps []variables.FriMerkleCap,
|
commitPhaseMerkleCaps []variables.FriMerkleCap,
|
||||||
finalPoly variables.PolynomialCoeffs,
|
finalPoly variables.PolynomialCoeffs,
|
||||||
powWitness gl.Variable,
|
powWitness gl.Variable,
|
||||||
degreeBits uint64,
|
|
||||||
config types.FriConfig,
|
config types.FriConfig,
|
||||||
) variables.FriChallenges {
|
) variables.FriChallenges {
|
||||||
numFriQueries := config.NumQueryRounds
|
numFriQueries := config.NumQueryRounds
|
||||||
@@ -143,10 +143,6 @@ func (c *Chip) GetFriChallenges(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearBuffer(buffer []gl.Variable) []gl.Variable {
|
|
||||||
return make([]gl.Variable, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Chip) duplexing() {
|
func (c *Chip) duplexing() {
|
||||||
if len(c.inputBuffer) > poseidon.SPONGE_RATE {
|
if len(c.inputBuffer) > poseidon.SPONGE_RATE {
|
||||||
fmt.Println(len(c.inputBuffer))
|
fmt.Println(len(c.inputBuffer))
|
||||||
@@ -158,9 +154,12 @@ func (c *Chip) duplexing() {
|
|||||||
for i := 0; i < len(c.inputBuffer); i++ {
|
for i := 0; i < len(c.inputBuffer); i++ {
|
||||||
c.spongeState[i] = glApi.Reduce(c.inputBuffer[i])
|
c.spongeState[i] = glApi.Reduce(c.inputBuffer[i])
|
||||||
}
|
}
|
||||||
c.inputBuffer = clearBuffer(c.inputBuffer)
|
// Clear the input buffer
|
||||||
|
c.inputBuffer = make([]gl.Variable, 0)
|
||||||
c.spongeState = c.poseidonChip.Poseidon(c.spongeState)
|
c.spongeState = c.poseidonChip.Poseidon(c.spongeState)
|
||||||
clearBuffer(c.outputBuffer)
|
|
||||||
|
// Clear the output buffer
|
||||||
|
c.outputBuffer = make([]gl.Variable, 0)
|
||||||
for i := 0; i < poseidon.SPONGE_RATE; i++ {
|
for i := 0; i < poseidon.SPONGE_RATE; i++ {
|
||||||
c.outputBuffer = append(c.outputBuffer, c.spongeState[i])
|
c.outputBuffer = append(c.outputBuffer, c.spongeState[i])
|
||||||
}
|
}
|
||||||
|
|||||||
56
fri/fri.go
56
fri/fri.go
@@ -49,14 +49,14 @@ func (f *Chip) GetInstance(zeta gl.QuadraticExtensionVariable) InstanceInfo {
|
|||||||
zeta,
|
zeta,
|
||||||
)
|
)
|
||||||
|
|
||||||
zetaNextBath := BatchInfo{
|
zetaNextBatch := BatchInfo{
|
||||||
Point: zetaNext,
|
Point: zetaNext,
|
||||||
Polynomials: friZSPolys(f.commonData),
|
Polynomials: friZSPolys(f.commonData),
|
||||||
}
|
}
|
||||||
|
|
||||||
return InstanceInfo{
|
return InstanceInfo{
|
||||||
Oracles: friOracles(f.commonData),
|
Oracles: friOracles(f.commonData),
|
||||||
Batches: []BatchInfo{zetaBatch, zetaNextBath},
|
Batches: []BatchInfo{zetaBatch, zetaNextBatch},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,12 +73,10 @@ func (f *Chip) ToOpenings(c variables.OpeningSet) Openings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Chip) assertLeadingZeros(powWitness gl.Variable, friConfig types.FriConfig) {
|
func (f *Chip) assertLeadingZeros(powWitness gl.Variable, friConfig types.FriConfig) {
|
||||||
// Asserts that powWitness'es big-endian bit representation has at least `leading_zeros` leading zeros.
|
// Asserts that powWitness'es big-endian bit representation has at least friConfig.ProofOfWorkBits leading zeros.
|
||||||
// Note that this is assuming that the Goldilocks field is being used. Specfically that the
|
// Note that this is assuming that the Goldilocks field is being used. Specfically that the
|
||||||
// field is 64 bits long
|
// field is 64 bits long.
|
||||||
maxPowWitness := uint64(math.Pow(2, float64(64-friConfig.ProofOfWorkBits))) - 1
|
f.gl.RangeCheckWithMaxBits(powWitness, 64-friConfig.ProofOfWorkBits)
|
||||||
reducedPowWitness := f.gl.Reduce(powWitness)
|
|
||||||
f.api.AssertIsLessOrEqual(reducedPowWitness.Limb, frontend.Variable(maxPowWitness))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Chip) fromOpeningsAndAlpha(
|
func (f *Chip) fromOpeningsAndAlpha(
|
||||||
@@ -128,13 +126,15 @@ func (f *Chip) verifyMerkleProofToCapWithCapIndex(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const NUM_LEAF_LOOKUPS = 4
|
const NUM_LEAF_LOOKUPS = 4
|
||||||
|
// Each lookup gadget will connect to 4 merkleCap entries
|
||||||
|
const STRIDE_LENGTH = 4
|
||||||
var leafLookups [NUM_LEAF_LOOKUPS]poseidon.BN254HashOut
|
var leafLookups [NUM_LEAF_LOOKUPS]poseidon.BN254HashOut
|
||||||
// First create the "leaf" lookup2 circuits
|
// First create the "leaf" lookup2 circuits
|
||||||
// The will use the least significant bits of the capIndexBits array
|
// This will use the least significant bits of the capIndexBits array
|
||||||
for i := 0; i < NUM_LEAF_LOOKUPS; i++ {
|
for i := 0; i < NUM_LEAF_LOOKUPS; i++ {
|
||||||
leafLookups[i] = f.api.Lookup2(
|
leafLookups[i] = f.api.Lookup2(
|
||||||
capIndexBits[0], capIndexBits[1],
|
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],
|
merkleCap[i*STRIDE_LENGTH], merkleCap[i*STRIDE_LENGTH+1], merkleCap[i*STRIDE_LENGTH+2], merkleCap[i*STRIDE_LENGTH+3],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ func (f *Chip) expFromBitsConstBase(
|
|||||||
) gl.Variable {
|
) gl.Variable {
|
||||||
product := gl.One()
|
product := gl.One()
|
||||||
for i, bit := range exponentBits {
|
for i, bit := range exponentBits {
|
||||||
// If the bit is on, we multiply product by base^pow.
|
// If the bit is 1, we multiply product by base^pow.
|
||||||
// We can arithmetize this as:
|
// We can arithmetize this as:
|
||||||
// product *= 1 + bit (base^pow - 1)
|
// product *= 1 + bit (base^pow - 1)
|
||||||
// product = (base^pow - 1) product bit + product
|
// product = (base^pow - 1) product bit + product
|
||||||
@@ -238,9 +238,11 @@ func (f *Chip) friCombineInitial(
|
|||||||
numerator := f.gl.SubExtensionNoReduce(reducedEvals, reducedOpenings)
|
numerator := f.gl.SubExtensionNoReduce(reducedEvals, reducedOpenings)
|
||||||
denominator := f.gl.SubExtension(subgroupX_QE, point)
|
denominator := f.gl.SubExtension(subgroupX_QE, point)
|
||||||
sum = f.gl.MulExtension(f.gl.ExpExtension(friAlpha, uint64(len(evals))), sum)
|
sum = f.gl.MulExtension(f.gl.ExpExtension(friAlpha, uint64(len(evals))), sum)
|
||||||
|
inv, hasInv := f.gl.InverseExtension(denominator)
|
||||||
|
f.api.AssertIsEqual(hasInv, frontend.Variable(1))
|
||||||
sum = f.gl.MulAddExtension(
|
sum = f.gl.MulAddExtension(
|
||||||
numerator,
|
numerator,
|
||||||
f.gl.InverseExtension(denominator),
|
inv,
|
||||||
sum,
|
sum,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -272,17 +274,23 @@ func (f *Chip) interpolate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
sum := gl.ZeroExtension()
|
sum := gl.ZeroExtension()
|
||||||
|
|
||||||
|
lookupFromPoints := frontend.Variable(1)
|
||||||
for i := 0; i < len(xPoints); i++ {
|
for i := 0; i < len(xPoints); i++ {
|
||||||
sum = f.gl.AddExtension(
|
quotient, hasQuotient := f.gl.DivExtension(
|
||||||
f.gl.MulExtension(
|
|
||||||
f.gl.DivExtension(
|
|
||||||
barycentricWeights[i],
|
barycentricWeights[i],
|
||||||
f.gl.SubExtension(
|
f.gl.SubExtension(
|
||||||
x,
|
x,
|
||||||
xPoints[i],
|
xPoints[i],
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
|
|
||||||
|
lookupFromPoints = f.api.Mul(hasQuotient, lookupFromPoints)
|
||||||
|
|
||||||
|
sum = f.gl.AddExtension(
|
||||||
|
f.gl.MulExtension(
|
||||||
yPoints[i],
|
yPoints[i],
|
||||||
|
quotient,
|
||||||
),
|
),
|
||||||
sum,
|
sum,
|
||||||
)
|
)
|
||||||
@@ -290,17 +298,17 @@ func (f *Chip) interpolate(
|
|||||||
|
|
||||||
interpolation := f.gl.MulExtension(lX, sum)
|
interpolation := f.gl.MulExtension(lX, sum)
|
||||||
|
|
||||||
returnField := interpolation
|
lookupVal := gl.ZeroExtension()
|
||||||
// Now check if x is already within the xPoints
|
// Now check if x is already within the xPoints
|
||||||
for i := 0; i < len(xPoints); i++ {
|
for i := 0; i < len(xPoints); i++ {
|
||||||
returnField = f.gl.Lookup(
|
lookupVal = f.gl.Lookup(
|
||||||
f.gl.IsZero(f.gl.SubExtension(x, xPoints[i])),
|
f.gl.IsZero(f.gl.SubExtension(x, xPoints[i])),
|
||||||
returnField,
|
lookupVal,
|
||||||
yPoints[i],
|
yPoints[i],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnField
|
return f.gl.Lookup(lookupFromPoints, lookupVal, interpolation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Chip) computeEvaluation(
|
func (f *Chip) computeEvaluation(
|
||||||
@@ -312,7 +320,7 @@ func (f *Chip) computeEvaluation(
|
|||||||
) gl.QuadraticExtensionVariable {
|
) gl.QuadraticExtensionVariable {
|
||||||
arity := 1 << arityBits
|
arity := 1 << arityBits
|
||||||
if (len(evals)) != arity {
|
if (len(evals)) != arity {
|
||||||
panic("len(evals) ! arity")
|
panic("len(evals) != arity")
|
||||||
}
|
}
|
||||||
if arityBits > 8 {
|
if arityBits > 8 {
|
||||||
panic("currently assuming that arityBits is <= 8")
|
panic("currently assuming that arityBits is <= 8")
|
||||||
@@ -327,8 +335,8 @@ func (f *Chip) computeEvaluation(
|
|||||||
// OPTIMIZE - Since the size of the evals array should be constant (e.g. 2^arityBits),
|
// OPTIMIZE - Since the size of the evals array should be constant (e.g. 2^arityBits),
|
||||||
// we can just hard code the permutation.
|
// we can just hard code the permutation.
|
||||||
permutedEvals := make([]gl.QuadraticExtensionVariable, len(evals))
|
permutedEvals := make([]gl.QuadraticExtensionVariable, len(evals))
|
||||||
for i := uint8(0); i < uint8(len(evals)); i++ {
|
for i := uint8(0); i <= uint8(len(evals)-1); i++ {
|
||||||
newIndex := bits.Reverse8(i) >> arityBits
|
newIndex := bits.Reverse8(i) >> (8 - arityBits)
|
||||||
permutedEvals[newIndex] = evals[i]
|
permutedEvals[newIndex] = evals[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +375,9 @@ func (f *Chip) computeEvaluation(
|
|||||||
}
|
}
|
||||||
// Take the inverse of the barycentric weights
|
// Take the inverse of the barycentric weights
|
||||||
// OPTIMIZE: Can provide a witness to this value
|
// OPTIMIZE: Can provide a witness to this value
|
||||||
barycentricWeights[i] = f.gl.InverseExtension(barycentricWeights[i])
|
inv, hasInv := f.gl.InverseExtension(barycentricWeights[i])
|
||||||
|
f.api.AssertIsEqual(hasInv, frontend.Variable(1))
|
||||||
|
barycentricWeights[i] = inv
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.interpolate(beta, xPoints, yPoints, barycentricWeights)
|
return f.interpolate(beta, xPoints, yPoints, barycentricWeights)
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ func (circuit *TestFriCircuit) Define(api frontend.API) error {
|
|||||||
proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
|
proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
|
||||||
proofWithPis.Proof.OpeningProof.FinalPoly,
|
proofWithPis.Proof.OpeningProof.FinalPoly,
|
||||||
proofWithPis.Proof.OpeningProof.PowWitness,
|
proofWithPis.Proof.OpeningProof.PowWitness,
|
||||||
commonCircuitData.DegreeBits,
|
|
||||||
commonCircuitData.Config.FriConfig,
|
commonCircuitData.Config.FriConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ var POWER_OF_TWO_GENERATOR goldilocks.Element = goldilocks.NewElement(1753635133
|
|||||||
// The modulus of the field.
|
// The modulus of the field.
|
||||||
var MODULUS *big.Int = emulated.Goldilocks{}.Modulus()
|
var MODULUS *big.Int = emulated.Goldilocks{}.Modulus()
|
||||||
|
|
||||||
// The threshold maximum number of bits at which we must reduce the element.
|
|
||||||
var REDUCE_NB_BITS_THRESHOLD uint8 = 254 - 64
|
|
||||||
|
|
||||||
// The number of bits to use for range checks on inner products of field elements.
|
// The number of bits to use for range checks on inner products of field elements.
|
||||||
var RANGE_CHECK_NB_BITS int = 140
|
var RANGE_CHECK_NB_BITS int = 140
|
||||||
|
|
||||||
@@ -90,38 +87,41 @@ func New(api frontend.API) *Chip {
|
|||||||
return &Chip{api: api, rangeChecker: rangeChecker}
|
return &Chip{api: api, rangeChecker: rangeChecker}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds two field elements such that x + y = z within the Golidlocks field.
|
// Adds two goldilocks field elements and returns a value within the goldilocks field.
|
||||||
func (p *Chip) Add(a Variable, b Variable) Variable {
|
func (p *Chip) Add(a Variable, b Variable) Variable {
|
||||||
return p.MulAdd(a, NewVariable(1), b)
|
return p.MulAdd(a, NewVariable(1), b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds two field elements such that x + y = z within the Golidlocks field without reducing.
|
// Adds two goldilocks field elements and returns a value that may not be within the goldilocks field
|
||||||
|
// (e.g. the sum is not reduced).
|
||||||
func (p *Chip) AddNoReduce(a Variable, b Variable) Variable {
|
func (p *Chip) AddNoReduce(a Variable, b Variable) Variable {
|
||||||
return NewVariable(p.api.Add(a.Limb, b.Limb))
|
return NewVariable(p.api.Add(a.Limb, b.Limb))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subtracts two field elements such that x + y = z within the Golidlocks field.
|
// Subracts two goldilocks field elements and returns a value within the goldilocks field.
|
||||||
func (p *Chip) Sub(a Variable, b Variable) Variable {
|
func (p *Chip) Sub(a Variable, b Variable) Variable {
|
||||||
return p.MulAdd(b, NewVariable(MODULUS.Uint64()-1), a)
|
return p.MulAdd(b, NegOne(), a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subtracts two field elements such that x + y = z within the Golidlocks field without reducing.
|
// Subracts two goldilocks field elements and returns a value that may not be within the goldilocks field
|
||||||
|
// (e.g. the difference is not reduced).
|
||||||
func (p *Chip) SubNoReduce(a Variable, b Variable) Variable {
|
func (p *Chip) SubNoReduce(a Variable, b Variable) Variable {
|
||||||
return NewVariable(p.api.Add(a.Limb, p.api.Mul(b.Limb, MODULUS.Uint64()-1)))
|
return NewVariable(p.api.Add(a.Limb, p.api.Mul(b.Limb, NegOne().Limb)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies two field elements such that x * y = z within the Golidlocks field.
|
// Multiplies two goldilocks field elements and returns a value within the goldilocks field.
|
||||||
func (p *Chip) Mul(a Variable, b Variable) Variable {
|
func (p *Chip) Mul(a Variable, b Variable) Variable {
|
||||||
return p.MulAdd(a, b, Zero())
|
return p.MulAdd(a, b, Zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies two field elements such that x * y = z within the Golidlocks field without reducing.
|
// Multiplies two goldilocks field elements and returns a value that may not be within the goldilocks field
|
||||||
|
// (e.g. the product is not reduced).
|
||||||
func (p *Chip) MulNoReduce(a Variable, b Variable) Variable {
|
func (p *Chip) MulNoReduce(a Variable, b Variable) Variable {
|
||||||
return NewVariable(p.api.Mul(a.Limb, b.Limb))
|
return NewVariable(p.api.Mul(a.Limb, b.Limb))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies two field elements and adds a field element such that x * y + z = c within the
|
// Multiplies two field elements and adds a field element (e.g. computes a * b + c). The returned value
|
||||||
// Golidlocks field.
|
// will be within the goldilocks field.
|
||||||
func (p *Chip) MulAdd(a Variable, b Variable, c Variable) Variable {
|
func (p *Chip) MulAdd(a Variable, b Variable, c Variable) Variable {
|
||||||
result, err := p.api.Compiler().NewHint(MulAddHint, 2, a.Limb, b.Limb, c.Limb)
|
result, err := p.api.Compiler().NewHint(MulAddHint, 2, a.Limb, b.Limb, c.Limb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -131,7 +131,8 @@ func (p *Chip) MulAdd(a Variable, b Variable, c Variable) Variable {
|
|||||||
quotient := NewVariable(result[0])
|
quotient := NewVariable(result[0])
|
||||||
remainder := NewVariable(result[1])
|
remainder := NewVariable(result[1])
|
||||||
|
|
||||||
lhs := p.api.MulAcc(c.Limb, a.Limb, b.Limb)
|
cLimbCopy := p.api.Mul(c.Limb, 1)
|
||||||
|
lhs := p.api.MulAcc(cLimbCopy, a.Limb, b.Limb)
|
||||||
rhs := p.api.MulAcc(remainder.Limb, MODULUS, quotient.Limb)
|
rhs := p.api.MulAcc(remainder.Limb, MODULUS, quotient.Limb)
|
||||||
p.api.AssertIsEqual(lhs, rhs)
|
p.api.AssertIsEqual(lhs, rhs)
|
||||||
|
|
||||||
@@ -140,10 +141,11 @@ func (p *Chip) MulAdd(a Variable, b Variable, c Variable) Variable {
|
|||||||
return remainder
|
return remainder
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies two field elements and adds a field element such that x * y + z = c within the
|
// Multiplies two field elements and adds a field element (e.g. computes a * b + c). The returned value
|
||||||
// Golidlocks field without reducing.
|
// may no be within the goldilocks field (e.g. the result is not reduced).
|
||||||
func (p *Chip) MulAddNoReduce(a Variable, b Variable, c Variable) Variable {
|
func (p *Chip) MulAddNoReduce(a Variable, b Variable, c Variable) Variable {
|
||||||
return NewVariable(p.api.MulAcc(c.Limb, a.Limb, b.Limb))
|
cLimbCopy := p.api.Mul(c.Limb, 1)
|
||||||
|
return NewVariable(p.api.MulAcc(cLimbCopy, a.Limb, b.Limb))
|
||||||
}
|
}
|
||||||
|
|
||||||
// The hint used to compute MulAdd.
|
// The hint used to compute MulAdd.
|
||||||
@@ -179,18 +181,7 @@ func (p *Chip) Reduce(x Variable) Variable {
|
|||||||
// that this computation does not overflow. We use 2^RANGE_CHECK_NB_BITS to reduce the cost of the range check
|
// that this computation does not overflow. We use 2^RANGE_CHECK_NB_BITS to reduce the cost of the range check
|
||||||
//
|
//
|
||||||
// In other words, we assume that we at most compute a a dot product with dimension at most RANGE_CHECK_NB_BITS - 128.
|
// In other words, we assume that we at most compute a a dot product with dimension at most RANGE_CHECK_NB_BITS - 128.
|
||||||
|
return p.ReduceWithMaxBits(x, uint64(RANGE_CHECK_NB_BITS))
|
||||||
result, err := p.api.Compiler().NewHint(ReduceHint, 2, x.Limb)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
quotient := result[0]
|
|
||||||
p.rangeChecker.Check(quotient, RANGE_CHECK_NB_BITS)
|
|
||||||
|
|
||||||
remainder := NewVariable(result[1])
|
|
||||||
p.RangeCheck(remainder)
|
|
||||||
return remainder
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduces a field element x such that x % MODULUS = y.
|
// Reduces a field element x such that x % MODULUS = y.
|
||||||
@@ -212,6 +203,9 @@ func (p *Chip) ReduceWithMaxBits(x Variable, maxNbBits uint64) Variable {
|
|||||||
|
|
||||||
remainder := NewVariable(result[1])
|
remainder := NewVariable(result[1])
|
||||||
p.RangeCheck(remainder)
|
p.RangeCheck(remainder)
|
||||||
|
|
||||||
|
p.api.AssertIsEqual(x.Limb, p.api.Add(p.api.Mul(quotient, MODULUS), remainder.Limb))
|
||||||
|
|
||||||
return remainder
|
return remainder
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,16 +223,22 @@ func ReduceHint(_ *big.Int, inputs []*big.Int, results []*big.Int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Computes the inverse of a field element x such that x * x^-1 = 1.
|
// Computes the inverse of a field element x such that x * x^-1 = 1.
|
||||||
func (p *Chip) Inverse(x Variable) Variable {
|
func (p *Chip) Inverse(x Variable) (Variable, frontend.Variable) {
|
||||||
result, err := p.api.Compiler().NewHint(InverseHint, 1, x.Limb)
|
result, err := p.api.Compiler().NewHint(InverseHint, 1, x.Limb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
inverse := NewVariable(result[0])
|
inverse := NewVariable(result[0])
|
||||||
|
isZero := p.api.IsZero(x.Limb)
|
||||||
|
hasInv := p.api.Sub(1, isZero)
|
||||||
|
p.RangeCheck(inverse)
|
||||||
|
|
||||||
product := p.Mul(inverse, x)
|
product := p.Mul(inverse, x)
|
||||||
p.api.AssertIsEqual(product.Limb, frontend.Variable(1))
|
productToCheck := p.api.Select(hasInv, product.Limb, frontend.Variable(1))
|
||||||
return inverse
|
p.api.AssertIsEqual(productToCheck, frontend.Variable(1))
|
||||||
|
|
||||||
|
return inverse, hasInv
|
||||||
}
|
}
|
||||||
|
|
||||||
// The hint used to compute Inverse.
|
// The hint used to compute Inverse.
|
||||||
@@ -254,6 +254,8 @@ func InverseHint(_ *big.Int, inputs []*big.Int, results []*big.Int) error {
|
|||||||
|
|
||||||
inputGl := goldilocks.NewElement(input.Uint64())
|
inputGl := goldilocks.NewElement(input.Uint64())
|
||||||
resultGl := goldilocks.NewElement(0)
|
resultGl := goldilocks.NewElement(0)
|
||||||
|
|
||||||
|
// Will set resultGL if inputGL == 0
|
||||||
resultGl.Inverse(&inputGl)
|
resultGl.Inverse(&inputGl)
|
||||||
|
|
||||||
result := big.NewInt(0)
|
result := big.NewInt(0)
|
||||||
@@ -262,28 +264,6 @@ func InverseHint(_ *big.Int, inputs []*big.Int, results []*big.Int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes a field element raised to some power.
|
|
||||||
func (p *Chip) Exp(x Variable, k *big.Int) Variable {
|
|
||||||
if k.IsUint64() && k.Uint64() == 0 {
|
|
||||||
return One()
|
|
||||||
}
|
|
||||||
|
|
||||||
e := k
|
|
||||||
if k.Sign() == -1 {
|
|
||||||
panic("Unsupported negative exponent. Need to implement inversion.")
|
|
||||||
}
|
|
||||||
|
|
||||||
z := x
|
|
||||||
for i := e.BitLen() - 2; i >= 0; i-- {
|
|
||||||
z = p.Mul(z, z)
|
|
||||||
if e.Bit(i) == 1 {
|
|
||||||
z = p.Mul(z, x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return z
|
|
||||||
}
|
|
||||||
|
|
||||||
// The hint used to split a GoldilocksVariable into 2 32 bit limbs.
|
// The hint used to split a GoldilocksVariable into 2 32 bit limbs.
|
||||||
func SplitLimbsHint(_ *big.Int, inputs []*big.Int, results []*big.Int) error {
|
func SplitLimbsHint(_ *big.Int, inputs []*big.Int, results []*big.Int) error {
|
||||||
if len(inputs) != 1 {
|
if len(inputs) != 1 {
|
||||||
@@ -348,6 +328,11 @@ func (p *Chip) RangeCheck(x Variable) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function will assert that the field element x is less than 2^maxNbBits.
|
||||||
|
func (p *Chip) RangeCheckWithMaxBits(x Variable, maxNbBits uint64) {
|
||||||
|
p.rangeChecker.Check(x.Limb, int(maxNbBits))
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Chip) AssertIsEqual(x, y Variable) {
|
func (p *Chip) AssertIsEqual(x, y Variable) {
|
||||||
p.api.AssertIsEqual(x.Limb, y.Limb)
|
p.api.AssertIsEqual(x.Limb, y.Limb)
|
||||||
}
|
}
|
||||||
@@ -373,7 +358,7 @@ func TwoAdicSubgroup(nLog uint64) []goldilocks.Element {
|
|||||||
rootOfUnity := PrimitiveRootOfUnity(nLog)
|
rootOfUnity := PrimitiveRootOfUnity(nLog)
|
||||||
res = append(res, goldilocks.NewElement(1))
|
res = append(res, goldilocks.NewElement(1))
|
||||||
|
|
||||||
for i := 0; i < (1 << nLog); i++ {
|
for i := 0; i < (1<<nLog)-1; i++ {
|
||||||
lastElement := res[len(res)-1]
|
lastElement := res[len(res)-1]
|
||||||
res = append(res, *lastElement.Mul(&lastElement, &rootOfUnity))
|
res = append(res, *lastElement.Mul(&lastElement, &rootOfUnity))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,15 +58,13 @@ func (p *Chip) SubExtensionNoReduce(a, b QuadraticExtensionVariable) QuadraticEx
|
|||||||
// Multiplies quadratic extension variable in the Goldilocks field.
|
// Multiplies quadratic extension variable in the Goldilocks field.
|
||||||
func (p *Chip) MulExtension(a, b QuadraticExtensionVariable) QuadraticExtensionVariable {
|
func (p *Chip) MulExtension(a, b QuadraticExtensionVariable) QuadraticExtensionVariable {
|
||||||
product := p.MulExtensionNoReduce(a, b)
|
product := p.MulExtensionNoReduce(a, b)
|
||||||
product[0] = p.Reduce(product[0])
|
return p.ReduceExtension(product)
|
||||||
product[1] = p.Reduce(product[1])
|
|
||||||
return product
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies quadratic extension variable in the Goldilocks field without reducing.
|
// Multiplies quadratic extension variable in the Goldilocks field without reducing.
|
||||||
func (p *Chip) MulExtensionNoReduce(a, b QuadraticExtensionVariable) QuadraticExtensionVariable {
|
func (p *Chip) MulExtensionNoReduce(a, b QuadraticExtensionVariable) QuadraticExtensionVariable {
|
||||||
c0o0 := p.MulNoReduce(a[0], b[0])
|
c0o0 := p.MulNoReduce(a[0], b[0])
|
||||||
c0o1 := p.MulNoReduce(p.MulNoReduce(NewVariable(7), a[1]), b[1])
|
c0o1 := p.MulNoReduce(p.MulNoReduce(NewVariable(W), a[1]), b[1])
|
||||||
c0 := p.AddNoReduce(c0o0, c0o1)
|
c0 := p.AddNoReduce(c0o0, c0o1)
|
||||||
c1 := p.AddNoReduce(p.MulNoReduce(a[0], b[1]), p.MulNoReduce(a[1], b[0]))
|
c1 := p.AddNoReduce(p.MulNoReduce(a[0], b[1]), p.MulNoReduce(a[1], b[0]))
|
||||||
return NewQuadraticExtensionVariable(c0, c1)
|
return NewQuadraticExtensionVariable(c0, c1)
|
||||||
@@ -77,9 +75,7 @@ func (p *Chip) MulExtensionNoReduce(a, b QuadraticExtensionVariable) QuadraticEx
|
|||||||
func (p *Chip) MulAddExtension(a, b, c QuadraticExtensionVariable) QuadraticExtensionVariable {
|
func (p *Chip) MulAddExtension(a, b, c QuadraticExtensionVariable) QuadraticExtensionVariable {
|
||||||
product := p.MulExtensionNoReduce(a, b)
|
product := p.MulExtensionNoReduce(a, b)
|
||||||
sum := p.AddExtensionNoReduce(product, c)
|
sum := p.AddExtensionNoReduce(product, c)
|
||||||
sum[0] = p.Reduce(sum[0])
|
return p.ReduceExtension(sum)
|
||||||
sum[1] = p.Reduce(sum[1])
|
|
||||||
return sum
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Chip) MulAddExtensionNoReduce(a, b, c QuadraticExtensionVariable) QuadraticExtensionVariable {
|
func (p *Chip) MulAddExtensionNoReduce(a, b, c QuadraticExtensionVariable) QuadraticExtensionVariable {
|
||||||
@@ -88,14 +84,12 @@ func (p *Chip) MulAddExtensionNoReduce(a, b, c QuadraticExtensionVariable) Quadr
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies two operands a and b and subtracts to c in the Goldilocks extension field. a * b - c must
|
// Subtracts two operands a and b and multiplies the diff by c in the Goldilocks extension field. (a - b) * c must
|
||||||
// be less than RANGE_CHECK_NB_BITS bits.
|
// be less than RANGE_CHECK_NB_BITS bits.
|
||||||
func (p *Chip) SubMulExtension(a, b, c QuadraticExtensionVariable) QuadraticExtensionVariable {
|
func (p *Chip) SubMulExtension(a, b, c QuadraticExtensionVariable) QuadraticExtensionVariable {
|
||||||
difference := p.SubExtensionNoReduce(a, b)
|
difference := p.SubExtensionNoReduce(a, b)
|
||||||
product := p.MulExtensionNoReduce(difference, c)
|
product := p.MulExtensionNoReduce(difference, c)
|
||||||
product[0] = p.Reduce(product[0])
|
return p.ReduceExtension(product)
|
||||||
product[1] = p.Reduce(product[1])
|
|
||||||
return product
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies quadratic extension variable in the Goldilocks field by a scalar.
|
// Multiplies quadratic extension variable in the Goldilocks field by a scalar.
|
||||||
@@ -126,21 +120,23 @@ func (p *Chip) InnerProductExtension(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Computes the inverse of a quadratic extension variable in the Goldilocks field.
|
// Computes the inverse of a quadratic extension variable in the Goldilocks field.
|
||||||
func (p *Chip) InverseExtension(a QuadraticExtensionVariable) QuadraticExtensionVariable {
|
func (p *Chip) InverseExtension(a QuadraticExtensionVariable) (QuadraticExtensionVariable, frontend.Variable) {
|
||||||
a0IsZero := p.api.IsZero(a[0].Limb)
|
aIsZero := p.IsZero(a)
|
||||||
a1IsZero := p.api.IsZero(a[1].Limb)
|
p.api.AssertIsEqual(aIsZero, frontend.Variable(0))
|
||||||
p.api.AssertIsEqual(p.api.Mul(a0IsZero, a1IsZero), frontend.Variable(0))
|
|
||||||
aPowRMinus1 := QuadraticExtensionVariable{
|
aPowRMinus1 := QuadraticExtensionVariable{
|
||||||
a[0],
|
a[0],
|
||||||
p.Mul(a[1], NewVariable(DTH_ROOT)),
|
p.Mul(a[1], NewVariable(DTH_ROOT)),
|
||||||
}
|
}
|
||||||
aPowR := p.MulExtension(aPowRMinus1, a)
|
aPowR := p.MulExtension(aPowRMinus1, a)
|
||||||
return p.ScalarMulExtension(aPowRMinus1, p.Inverse(aPowR[0]))
|
|
||||||
|
aPowRInv, hasInv := p.Inverse(aPowR[0])
|
||||||
|
return p.ScalarMulExtension(aPowRMinus1, aPowRInv), hasInv
|
||||||
}
|
}
|
||||||
|
|
||||||
// Divides two quadratic extension variables in the Goldilocks field.
|
// Divides two quadratic extension variables in the Goldilocks field.
|
||||||
func (p *Chip) DivExtension(a, b QuadraticExtensionVariable) QuadraticExtensionVariable {
|
func (p *Chip) DivExtension(a, b QuadraticExtensionVariable) (QuadraticExtensionVariable, frontend.Variable) {
|
||||||
return p.MulExtension(a, p.InverseExtension(b))
|
bInv, hasInv := p.InverseExtension(b)
|
||||||
|
return p.MulExtension(a, bInv), hasInv
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exponentiates a quadratic extension variable to some exponent in the Golidlocks field.
|
// Exponentiates a quadratic extension variable to some exponent in the Golidlocks field.
|
||||||
@@ -213,7 +209,7 @@ func (p *Chip) Lookup(
|
|||||||
return NewQuadraticExtensionVariable(NewVariable(c0), NewVariable(c1))
|
return NewQuadraticExtensionVariable(NewVariable(c0), NewVariable(c1))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup2 is similar to select2, but returns the first variable if the bit is zero and vice-versa.
|
// Lookup2 is similar to Lookup2. It returns the ith qe value (0 indexed) where i is bit decomposed to b0,b1 (little endian).
|
||||||
func (p *Chip) Lookup2(
|
func (p *Chip) Lookup2(
|
||||||
b0 frontend.Variable,
|
b0 frontend.Variable,
|
||||||
b1 frontend.Variable,
|
b1 frontend.Variable,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func NewQuadraticExtensionAlgebraVariable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p QuadraticExtensionVariable) ToQuadraticExtensionAlgebra() QuadraticExtensionAlgebraVariable {
|
func (p QuadraticExtensionVariable) ToQuadraticExtensionAlgebra() QuadraticExtensionAlgebraVariable {
|
||||||
return [2]QuadraticExtensionVariable{p, ZeroExtension()}
|
return [D]QuadraticExtensionVariable{p, ZeroExtension()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ZeroExtensionAlgebra() QuadraticExtensionAlgebraVariable {
|
func ZeroExtensionAlgebra() QuadraticExtensionAlgebraVariable {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ type TestQuadraticExtensionDivCircuit struct {
|
|||||||
|
|
||||||
func (c *TestQuadraticExtensionDivCircuit) Define(api frontend.API) error {
|
func (c *TestQuadraticExtensionDivCircuit) Define(api frontend.API) error {
|
||||||
glAPI := New(api)
|
glAPI := New(api)
|
||||||
actualRes := glAPI.DivExtension(c.Operand1, c.Operand2)
|
actualRes, _ := glAPI.DivExtension(c.Operand1, c.Operand2)
|
||||||
glAPI.AssertIsEqual(actualRes[0], c.ExpectedResult[0])
|
glAPI.AssertIsEqual(actualRes[0], c.ExpectedResult[0])
|
||||||
glAPI.AssertIsEqual(actualRes[1], c.ExpectedResult[1])
|
glAPI.AssertIsEqual(actualRes[1], c.ExpectedResult[1])
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
|
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
var aritheticExtensionGateRegex = regexp.MustCompile("ArithmeticExtensionGate { num_ops: (?P<numOps>[0-9]+) }")
|
var arithmeticExtensionGateRegex = regexp.MustCompile("ArithmeticExtensionGate { num_ops: (?P<numOps>[0-9]+) }")
|
||||||
|
|
||||||
func deserializeExtensionArithmeticGate(parameters map[string]string) Gate {
|
func deserializeExtensionArithmeticGate(parameters map[string]string) Gate {
|
||||||
// Has the format "ArithmeticExtensionGate { num_ops: 10 }"
|
// Has the format "ArithmeticExtensionGate { num_ops: 10 }"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
|
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
var aritheticGateRegex = regexp.MustCompile("ArithmeticGate { num_ops: (?P<numOps>[0-9]+) }")
|
var arithmeticGateRegex = regexp.MustCompile("ArithmeticGate { num_ops: (?P<numOps>[0-9]+) }")
|
||||||
|
|
||||||
func deserializeArithmeticGate(parameters map[string]string) Gate {
|
func deserializeArithmeticGate(parameters map[string]string) Gate {
|
||||||
// Has the format "ArithmeticGate { num_ops: 10 }"
|
// Has the format "ArithmeticGate { num_ops: 10 }"
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func NewBaseSumGate(numLimbs uint64, base uint64) *BaseSumGate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *BaseSumGate) Id() string {
|
func (g *BaseSumGate) Id() string {
|
||||||
return fmt.Sprintf("BaseSumGate { num_ops: %d } + Base: %d", g.numLimbs, g.base)
|
return fmt.Sprintf("BaseSumGate { num_limbs: %d } + Base: %d", g.numLimbs, g.base)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *BaseSumGate) limbs() []uint64 {
|
func (g *BaseSumGate) limbs() []uint64 {
|
||||||
|
|||||||
@@ -41,14 +41,14 @@ func (g *ConstantGate) Id() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *ConstantGate) ConstInput(i uint64) uint64 {
|
func (g *ConstantGate) ConstInput(i uint64) uint64 {
|
||||||
if i > g.numConsts {
|
if i >= g.numConsts {
|
||||||
panic("Invalid constant index")
|
panic("Invalid constant index")
|
||||||
}
|
}
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *ConstantGate) WireOutput(i uint64) uint64 {
|
func (g *ConstantGate) WireOutput(i uint64) uint64 {
|
||||||
if i > g.numConsts {
|
if i >= g.numConsts {
|
||||||
panic("Invalid wire index")
|
panic("Invalid wire index")
|
||||||
}
|
}
|
||||||
return i
|
return i
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ func deserializeCosetInterpolationGate(parameters map[string]string) Gate {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic("invalid degree in CosetInterpolationGate")
|
panic("invalid degree in CosetInterpolationGate")
|
||||||
}
|
}
|
||||||
|
if degreeInt < 2 {
|
||||||
|
panic("degree must be at least 2 in CosetInterpolationGate")
|
||||||
|
}
|
||||||
|
|
||||||
barycentricWeightsStr := strings.Split(barycentricWeights, ",")
|
barycentricWeightsStr := strings.Split(barycentricWeights, ",")
|
||||||
barycentricWeightsInt := make([]goldilocks.Element, len(barycentricWeightsStr))
|
barycentricWeightsInt := make([]goldilocks.Element, len(barycentricWeightsStr))
|
||||||
@@ -199,6 +202,10 @@ func (g *CosetInterpolationGate) EvalUnfiltered(
|
|||||||
|
|
||||||
startIndex := 1 + (g.degree-1)*(i+1)
|
startIndex := 1 + (g.degree-1)*(i+1)
|
||||||
endIndex := startIndex + g.degree - 1
|
endIndex := startIndex + g.degree - 1
|
||||||
|
if endIndex > g.numPoints() {
|
||||||
|
endIndex = g.numPoints()
|
||||||
|
}
|
||||||
|
|
||||||
computedEval, computedProd = glApi.PartialInterpolateExtAlgebra(
|
computedEval, computedProd = glApi.PartialInterpolateExtAlgebra(
|
||||||
domain[startIndex:endIndex],
|
domain[startIndex:endIndex],
|
||||||
values[startIndex:endIndex],
|
values[startIndex:endIndex],
|
||||||
|
|||||||
@@ -23,6 +23,20 @@ func deserializeExponentiationGate(parameters map[string]string) Gate {
|
|||||||
panic("Invalid num_power_bits field in ExponentiationGate")
|
panic("Invalid num_power_bits field in ExponentiationGate")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base, hasBase := parameters["base"]
|
||||||
|
if !hasBase {
|
||||||
|
panic("Missing field base in ExponentiationGate")
|
||||||
|
}
|
||||||
|
|
||||||
|
baseInt, err := strconv.Atoi(base)
|
||||||
|
if err != nil {
|
||||||
|
panic("Invalid base field in ExponentiationGate")
|
||||||
|
}
|
||||||
|
|
||||||
|
if baseInt != gl.D {
|
||||||
|
panic("Expected base field in ExponentiationGate to equal gl.D")
|
||||||
|
}
|
||||||
|
|
||||||
return NewExponentiationGate(uint64(numPowerBitsInt))
|
return NewExponentiationGate(uint64(numPowerBitsInt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ type Gate interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var gateRegexHandlers = map[*regexp.Regexp]func(parameters map[string]string) Gate{
|
var gateRegexHandlers = map[*regexp.Regexp]func(parameters map[string]string) Gate{
|
||||||
aritheticGateRegex: deserializeArithmeticGate,
|
arithmeticGateRegex: deserializeArithmeticGate,
|
||||||
aritheticExtensionGateRegex: deserializeExtensionArithmeticGate,
|
arithmeticExtensionGateRegex: deserializeExtensionArithmeticGate,
|
||||||
baseSumGateRegex: deserializeBaseSumGate,
|
baseSumGateRegex: deserializeBaseSumGate,
|
||||||
constantGateRegex: deserializeConstantGate,
|
constantGateRegex: deserializeConstantGate,
|
||||||
cosetInterpolationGateRegex: deserializeCosetInterpolationGate,
|
cosetInterpolationGateRegex: deserializeCosetInterpolationGate,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func NewMultiplicationExtensionGate(numOps uint64) *MultiplicationExtensionGate
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *MultiplicationExtensionGate) Id() string {
|
func (g *MultiplicationExtensionGate) Id() string {
|
||||||
return fmt.Sprintf("ArithmeticExtensionGate { num_ops: %d }", g.numOps)
|
return fmt.Sprintf("MulExtensionGate { num_ops: %d }", g.numOps)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *MultiplicationExtensionGate) wiresIthMultiplicand0(i uint64) Range {
|
func (g *MultiplicationExtensionGate) wiresIthMultiplicand0(i uint64) Range {
|
||||||
|
|||||||
@@ -90,7 +90,9 @@ func (g *PoseidonMdsGate) EvalUnfiltered(
|
|||||||
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
|
for i := uint64(0); i < poseidon.SPONGE_WIDTH; i++ {
|
||||||
output := vars.GetLocalExtAlgebra(g.WireOutput(i))
|
output := vars.GetLocalExtAlgebra(g.WireOutput(i))
|
||||||
diff := glApi.SubExtensionAlgebra(output, computed_outputs[i])
|
diff := glApi.SubExtensionAlgebra(output, computed_outputs[i])
|
||||||
constraints = append(constraints, diff[0], diff[1])
|
for i := 0; i < gl.D; i++ {
|
||||||
|
constraints = append(constraints, diff[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return constraints
|
return constraints
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func (g *PublicInputGate) EvalUnfiltered(
|
|||||||
|
|
||||||
wires := g.WiresPublicInputsHash()
|
wires := g.WiresPublicInputsHash()
|
||||||
hash_parts := vars.publicInputsHash
|
hash_parts := vars.publicInputsHash
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < len(wires); i++ {
|
||||||
wire := wires[i]
|
wire := wires[i]
|
||||||
hash_part := hash_parts[i]
|
hash_part := hash_parts[i]
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,20 @@ func deserializeRandomAccessGate(parameters map[string]string) Gate {
|
|||||||
panic("invalid numExtraConstants in RandomAccessGate")
|
panic("invalid numExtraConstants in RandomAccessGate")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base, hasBase := parameters["base"]
|
||||||
|
if !hasBase {
|
||||||
|
panic("Missing field base in RandomAccessGate")
|
||||||
|
}
|
||||||
|
|
||||||
|
baseInt, err := strconv.Atoi(base)
|
||||||
|
if err != nil {
|
||||||
|
panic("Invalid base field in RandomAccessGate")
|
||||||
|
}
|
||||||
|
|
||||||
|
if baseInt != gl.D {
|
||||||
|
panic("Expected base field in RandomAccessGate to equal gl.D")
|
||||||
|
}
|
||||||
|
|
||||||
return NewRandomAccessGate(bitsInt, numCopiesInt, numExtraConstantsInt)
|
return NewRandomAccessGate(bitsInt, numCopiesInt, numExtraConstantsInt)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,14 +165,12 @@ func (g *RandomAccessGate) EvalUnfiltered(
|
|||||||
y := listItems[i+1]
|
y := listItems[i+1]
|
||||||
|
|
||||||
// This is computing `if b { x } else { y }`
|
// This is computing `if b { x } else { y }`
|
||||||
// i.e. `bx - (by-y)`.
|
// i.e. `x + b(y - x)`.
|
||||||
mul1 := glApi.MulExtension(b, x)
|
diff := glApi.SubExtension(y, x)
|
||||||
sub1 := glApi.SubExtension(mul1, x)
|
mul := glApi.MulExtension(b, diff)
|
||||||
|
add := glApi.AddExtension(x, mul)
|
||||||
|
|
||||||
mul2 := glApi.MulExtension(b, y)
|
listItemsTmp = append(listItemsTmp, add)
|
||||||
sub2 := glApi.SubExtension(mul2, sub1)
|
|
||||||
|
|
||||||
listItemsTmp = append(listItemsTmp, sub2)
|
|
||||||
}
|
}
|
||||||
listItems = listItemsTmp
|
listItems = listItemsTmp
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
var reducingExtensionGateRegex = regexp.MustCompile("ReducingExtensionGate { num_coeffs: (?P<numCoeffs>[0-9]+) }")
|
var reducingExtensionGateRegex = regexp.MustCompile("ReducingExtensionGate { num_coeffs: (?P<numCoeffs>[0-9]+) }")
|
||||||
|
|
||||||
func deserializeReducingExtensionGate(parameters map[string]string) Gate {
|
func deserializeReducingExtensionGate(parameters map[string]string) Gate {
|
||||||
// Has the format "ReducingGate { num_coeffs: 33 }"
|
// Has the format "ReducingExtensionGate { num_coeffs: 33 }"
|
||||||
numCoeffs, hasNumCoeffs := parameters["numCoeffs"]
|
numCoeffs, hasNumCoeffs := parameters["numCoeffs"]
|
||||||
if !hasNumCoeffs {
|
if !hasNumCoeffs {
|
||||||
panic("Missing field num_coeffs in ReducingExtensionGate")
|
panic("Missing field num_coeffs in ReducingExtensionGate")
|
||||||
@@ -39,7 +39,7 @@ func NewReducingExtensionGate(numCoeffs uint64) *ReducingExtensionGate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *ReducingExtensionGate) Id() string {
|
func (g *ReducingExtensionGate) Id() string {
|
||||||
return fmt.Sprintf("ReducingExtensionGate { num_ops: %d }", g.numCoeffs)
|
return fmt.Sprintf("ReducingExtensionGate { num_coeffs: %d }", g.numCoeffs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *ReducingExtensionGate) wiresOutput() Range {
|
func (g *ReducingExtensionGate) wiresOutput() Range {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func NewReducingGate(numCoeffs uint64) *ReducingGate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *ReducingGate) Id() string {
|
func (g *ReducingGate) Id() string {
|
||||||
return fmt.Sprintf("ReducingExtensionGate { num_ops: %d }", g.numCoeffs)
|
return fmt.Sprintf("ReducingGate { num_coeffs: %d }", g.numCoeffs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *ReducingGate) wiresOutput() Range {
|
func (g *ReducingGate) wiresOutput() Range {
|
||||||
@@ -96,11 +96,7 @@ func (g *ReducingGate) EvalUnfiltered(
|
|||||||
constraints := []gl.QuadraticExtensionVariable{}
|
constraints := []gl.QuadraticExtensionVariable{}
|
||||||
acc := oldAcc
|
acc := oldAcc
|
||||||
for i := uint64(0); i < g.numCoeffs; i++ {
|
for i := uint64(0); i < g.numCoeffs; i++ {
|
||||||
var coeff gl.QuadraticExtensionAlgebraVariable
|
coeff := coeffs[i].ToQuadraticExtensionAlgebra()
|
||||||
for j := 0; j < gl.D; j++ {
|
|
||||||
coeff[j] = gl.ZeroExtension()
|
|
||||||
}
|
|
||||||
coeff[0] = coeffs[i]
|
|
||||||
tmp := glApi.MulExtensionAlgebra(acc, alpha)
|
tmp := glApi.MulExtensionAlgebra(acc, alpha)
|
||||||
tmp = glApi.AddExtensionAlgebra(tmp, coeff)
|
tmp = glApi.AddExtensionAlgebra(tmp, coeff)
|
||||||
tmp = glApi.SubExtensionAlgebra(tmp, accs[i])
|
tmp = glApi.SubExtensionAlgebra(tmp, accs[i])
|
||||||
|
|||||||
@@ -71,10 +71,15 @@ func (p *PlonkChip) evalL0(x gl.QuadraticExtensionVariable, xPowN gl.QuadraticEx
|
|||||||
glApi.ScalarMulExtension(x, p.DEGREE),
|
glApi.ScalarMulExtension(x, p.DEGREE),
|
||||||
p.DEGREE_QE,
|
p.DEGREE_QE,
|
||||||
)
|
)
|
||||||
return glApi.DivExtension(
|
|
||||||
|
quotient, hasQuotient := glApi.DivExtension(
|
||||||
evalZeroPoly,
|
evalZeroPoly,
|
||||||
denominator,
|
denominator,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
p.api.AssertIsEqual(hasQuotient, frontend.Variable(1))
|
||||||
|
|
||||||
|
return quotient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PlonkChip) checkPartialProducts(
|
func (p *PlonkChip) checkPartialProducts(
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ package poseidon
|
|||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/consensys/gnark-crypto/ecc/bn254"
|
||||||
"github.com/consensys/gnark/frontend"
|
"github.com/consensys/gnark/frontend"
|
||||||
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
|
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
|
||||||
)
|
)
|
||||||
@@ -28,6 +29,10 @@ type BN254State = [BN254_SPONGE_WIDTH]frontend.Variable
|
|||||||
type BN254HashOut = frontend.Variable
|
type BN254HashOut = frontend.Variable
|
||||||
|
|
||||||
func NewBN254Chip(api frontend.API) *BN254Chip {
|
func NewBN254Chip(api frontend.API) *BN254Chip {
|
||||||
|
if api.Compiler().Field().Cmp(bn254.ID.ScalarField()) != 0 {
|
||||||
|
panic("Gnark compiler not set to BN254 scalar field")
|
||||||
|
}
|
||||||
|
|
||||||
return &BN254Chip{api: api, gl: *gl.New(api)}
|
return &BN254Chip{api: api, gl: *gl.New(api)}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,8 +81,10 @@ func (c *BN254Chip) HashOrNoop(input []gl.Variable) BN254HashOut {
|
|||||||
returnVal := frontend.Variable(0)
|
returnVal := frontend.Variable(0)
|
||||||
|
|
||||||
alpha := new(big.Int).SetInt64(1 << 32)
|
alpha := new(big.Int).SetInt64(1 << 32)
|
||||||
|
alpha = new(big.Int).Mul(alpha, alpha)
|
||||||
for i, inputElement := range input {
|
for i, inputElement := range input {
|
||||||
returnVal = c.api.MulAcc(returnVal, inputElement, alpha.Exp(alpha, big.NewInt(int64(i)), nil))
|
mulFactor := new(big.Int).Exp(alpha, big.NewInt(int64(i)), nil)
|
||||||
|
returnVal = c.api.MulAcc(returnVal, inputElement.Limb, mulFactor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return BN254HashOut(returnVal)
|
return BN254HashOut(returnVal)
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import (
|
|||||||
|
|
||||||
const HALF_N_FULL_ROUNDS = 4
|
const HALF_N_FULL_ROUNDS = 4
|
||||||
const N_PARTIAL_ROUNDS = 22
|
const N_PARTIAL_ROUNDS = 22
|
||||||
const MAX_WIDTH = 12
|
|
||||||
const SPONGE_WIDTH = 12
|
const SPONGE_WIDTH = 12
|
||||||
const SPONGE_RATE = 8
|
const SPONGE_RATE = 8
|
||||||
|
const POSEIDON_GL_HASH_SIZE = 4
|
||||||
|
|
||||||
type GoldilocksState = [SPONGE_WIDTH]gl.Variable
|
type GoldilocksState = [SPONGE_WIDTH]gl.Variable
|
||||||
type GoldilocksStateExtension = [SPONGE_WIDTH]gl.QuadraticExtensionVariable
|
type GoldilocksStateExtension = [SPONGE_WIDTH]gl.QuadraticExtensionVariable
|
||||||
type GoldilocksHashOut = [4]gl.Variable
|
type GoldilocksHashOut = [POSEIDON_GL_HASH_SIZE]gl.Variable
|
||||||
|
|
||||||
type GoldilocksChip struct {
|
type GoldilocksChip struct {
|
||||||
api frontend.API `gnark:"-"`
|
api frontend.API `gnark:"-"`
|
||||||
@@ -77,8 +77,8 @@ func (c *GoldilocksChip) HashNoPad(input []gl.Variable) GoldilocksHashOut {
|
|||||||
inputVars = append(inputVars, c.gl.Reduce(input[i]))
|
inputVars = append(inputVars, c.gl.Reduce(input[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
outputVars := c.HashNToMNoPad(inputVars, 4)
|
outputVars := c.HashNToMNoPad(inputVars, len(hash))
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < len(hash); i++ {
|
||||||
hash[i] = outputVars[i]
|
hash[i] = outputVars[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ func (c *GoldilocksChip) constantLayer(state GoldilocksState, roundCounter *int)
|
|||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
if i < SPONGE_WIDTH {
|
if i < SPONGE_WIDTH {
|
||||||
roundConstant := ALL_ROUND_CONSTANTS[i+SPONGE_WIDTH*(*roundCounter)]
|
roundConstant := ALL_ROUND_CONSTANTS[i+SPONGE_WIDTH*(*roundCounter)]
|
||||||
state[i] = c.gl.MulAdd(state[i], gl.NewVariable(1), gl.NewVariable(roundConstant))
|
state[i] = c.gl.Add(state[i], gl.NewVariable(roundConstant))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
@@ -169,7 +169,7 @@ func (c *GoldilocksChip) SBoxLayerExtension(state GoldilocksStateExtension) Gold
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GoldilocksChip) mdsRowShf(r int, v [SPONGE_WIDTH]gl.Variable) gl.Variable {
|
func (c *GoldilocksChip) mdsRowShf(r int, v GoldilocksState) gl.Variable {
|
||||||
res := gl.Zero()
|
res := gl.Zero()
|
||||||
|
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
@@ -182,7 +182,7 @@ func (c *GoldilocksChip) mdsRowShf(r int, v [SPONGE_WIDTH]gl.Variable) gl.Variab
|
|||||||
return c.gl.Reduce(res)
|
return c.gl.Reduce(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GoldilocksChip) MdsRowShfExtension(r int, v [SPONGE_WIDTH]gl.QuadraticExtensionVariable) gl.QuadraticExtensionVariable {
|
func (c *GoldilocksChip) MdsRowShfExtension(r int, v GoldilocksStateExtension) gl.QuadraticExtensionVariable {
|
||||||
res := gl.ZeroExtension()
|
res := gl.ZeroExtension()
|
||||||
|
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
@@ -251,7 +251,7 @@ func (c *GoldilocksChip) PartialFirstConstantLayerExtension(state GoldilocksStat
|
|||||||
func (c *GoldilocksChip) mdsPartialLayerInit(state GoldilocksState) GoldilocksState {
|
func (c *GoldilocksChip) mdsPartialLayerInit(state GoldilocksState) GoldilocksState {
|
||||||
var result GoldilocksState
|
var result GoldilocksState
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
result[i] = gl.NewVariable(0)
|
result[i] = gl.Zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
result[0] = state[0]
|
result[0] = state[0]
|
||||||
|
|||||||
@@ -118,5 +118,10 @@ func ReadCommonCircuitData(path string) CommonCircuitData {
|
|||||||
commonCircuitData.KIs = raw.KIs
|
commonCircuitData.KIs = raw.KIs
|
||||||
commonCircuitData.NumPartialProducts = raw.NumPartialProducts
|
commonCircuitData.NumPartialProducts = raw.NumPartialProducts
|
||||||
|
|
||||||
|
// Don't support circuits that have hiding enabled
|
||||||
|
if raw.FriParams.Hiding {
|
||||||
|
panic("Circuit has hiding enabled, which is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
return commonCircuitData
|
return commonCircuitData
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
func ReductionArityBits(
|
|
||||||
arityBits uint64,
|
|
||||||
finalPolyBits uint64,
|
|
||||||
degreeBits uint64,
|
|
||||||
rateBits uint64,
|
|
||||||
capHeight uint64,
|
|
||||||
) []uint64 {
|
|
||||||
returnArr := make([]uint64, 0)
|
|
||||||
|
|
||||||
for degreeBits > finalPolyBits && degreeBits+rateBits-arityBits >= capHeight {
|
|
||||||
returnArr = append(returnArr, arityBits)
|
|
||||||
if degreeBits < arityBits {
|
|
||||||
panic("degreeBits < arityBits")
|
|
||||||
}
|
|
||||||
degreeBits -= arityBits
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnArr
|
|
||||||
}
|
|
||||||
@@ -12,18 +12,6 @@ type OpeningSet struct {
|
|||||||
QuotientPolys []gl.QuadraticExtensionVariable // Length = CommonCircuitData.NumChallenges * CommonCircuitData.QuotientDegreeFactor
|
QuotientPolys []gl.QuadraticExtensionVariable // Length = CommonCircuitData.NumChallenges * CommonCircuitData.QuotientDegreeFactor
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOpeningSet(numConstants uint64, numRoutedWires uint64, numWires uint64, numChallenges uint64, numPartialProducts uint64, quotientDegreeFactor uint64) OpeningSet {
|
|
||||||
return OpeningSet{
|
|
||||||
Constants: make([]gl.QuadraticExtensionVariable, numConstants),
|
|
||||||
PlonkSigmas: make([]gl.QuadraticExtensionVariable, numRoutedWires),
|
|
||||||
Wires: make([]gl.QuadraticExtensionVariable, numWires),
|
|
||||||
PlonkZs: make([]gl.QuadraticExtensionVariable, numChallenges),
|
|
||||||
PlonkZsNext: make([]gl.QuadraticExtensionVariable, numChallenges),
|
|
||||||
PartialProducts: make([]gl.QuadraticExtensionVariable, numChallenges*numPartialProducts),
|
|
||||||
QuotientPolys: make([]gl.QuadraticExtensionVariable, numChallenges*quotientDegreeFactor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProofChallenges struct {
|
type ProofChallenges struct {
|
||||||
PlonkBetas []gl.Variable
|
PlonkBetas []gl.Variable
|
||||||
PlonkGammas []gl.Variable
|
PlonkGammas []gl.Variable
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ func (c *VerifierChip) GetChallenges(
|
|||||||
proof.OpeningProof.CommitPhaseMerkleCaps,
|
proof.OpeningProof.CommitPhaseMerkleCaps,
|
||||||
proof.OpeningProof.FinalPoly,
|
proof.OpeningProof.FinalPoly,
|
||||||
proof.OpeningProof.PowWitness,
|
proof.OpeningProof.PowWitness,
|
||||||
c.commonData.DegreeBits,
|
|
||||||
config.FriConfig,
|
config.FriConfig,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -119,8 +118,10 @@ func (c *VerifierChip) rangeCheckProof(proof variables.Proof) {
|
|||||||
|
|
||||||
// Range check the openings proof.
|
// Range check the openings proof.
|
||||||
for _, queryRound := range proof.OpeningProof.QueryRoundProofs {
|
for _, queryRound := range proof.OpeningProof.QueryRoundProofs {
|
||||||
for _, initialTreesElement := range queryRound.InitialTreesProof.EvalsProofs[0].Elements {
|
for _, evalsProof := range queryRound.InitialTreesProof.EvalsProofs {
|
||||||
c.glChip.RangeCheck(initialTreesElement)
|
for _, evalsProofElement := range evalsProof.Elements {
|
||||||
|
c.glChip.RangeCheck(evalsProofElement)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, queryStep := range queryRound.Steps {
|
for _, queryStep := range queryRound.Steps {
|
||||||
|
|||||||
Reference in New Issue
Block a user