mirror of
https://github.com/logos-storage/gnark-plonky2-verifier.git
synced 2026-01-03 21:53:10 +00:00
calculated subgroupX
This commit is contained in:
parent
21157cf4af
commit
8e9591c964
@ -1,10 +1,8 @@
|
||||
package field
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc"
|
||||
"github.com/consensys/gnark-crypto/field/goldilocks"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/std/math/emulated"
|
||||
)
|
||||
@ -32,15 +30,22 @@ func NewFieldAPI(api frontend.API) frontend.API {
|
||||
return field
|
||||
}
|
||||
|
||||
var r EmulatedField
|
||||
var ONE_F = NewFieldElement(1)
|
||||
var ZERO_F = NewFieldElement(0)
|
||||
|
||||
func EmulatedFieldModulus() *big.Int {
|
||||
return r.Modulus()
|
||||
}
|
||||
var GOLDILOCKS_MULTIPLICATIVE_GROUP_GENERATOR = goldilocks.NewElement(7)
|
||||
var GOLDILOCKS_TWO_ADICITY = uint64(32)
|
||||
var GOLDILOCKS_POWER_OF_TWO_GENERATOR = goldilocks.NewElement(1753635133440165772)
|
||||
|
||||
func PrintHash(f frontend.API, h Hash) {
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Println("Hash Limb", i)
|
||||
f.Println(h[i])
|
||||
func GoldilocksPrimitiveRootOfUnity(nLog uint64) goldilocks.Element {
|
||||
if nLog > GOLDILOCKS_TWO_ADICITY {
|
||||
panic("nLog is greater than GOLDILOCKS_TWO_ADICITY")
|
||||
}
|
||||
|
||||
res := goldilocks.NewElement(GOLDILOCKS_POWER_OF_TWO_GENERATOR.Uint64())
|
||||
for i := 0; i < int(GOLDILOCKS_TWO_ADICITY-nLog); i++ {
|
||||
res.Square(&res)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@ -6,7 +6,9 @@ import (
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-ed25519/poseidon"
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
"github.com/consensys/gnark-crypto/field/goldilocks"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
)
|
||||
|
||||
@ -31,9 +33,9 @@ func (c *OpeningSet) ToFriOpenings() FriOpenings {
|
||||
}
|
||||
|
||||
type FriChip struct {
|
||||
api frontend.API
|
||||
field frontend.API
|
||||
qe *QuadraticExtensionAPI
|
||||
api frontend.API
|
||||
fieldAPI frontend.API
|
||||
qeAPI *QuadraticExtensionAPI
|
||||
|
||||
poseidonChip *poseidon.PoseidonChip
|
||||
|
||||
@ -41,11 +43,11 @@ type FriChip struct {
|
||||
verifierOnlyCircuitData *VerifierOnlyCircuitData
|
||||
}
|
||||
|
||||
func NewFriChip(api frontend.API, field frontend.API, qe *QuadraticExtensionAPI, poseidonChip *poseidon.PoseidonChip, friParams *FriParams) *FriChip {
|
||||
func NewFriChip(api frontend.API, fieldAPI frontend.API, qeAPI *QuadraticExtensionAPI, poseidonChip *poseidon.PoseidonChip, friParams *FriParams) *FriChip {
|
||||
return &FriChip{
|
||||
api: api,
|
||||
field: field,
|
||||
qe: qe,
|
||||
fieldAPI: fieldAPI,
|
||||
qeAPI: qeAPI,
|
||||
poseidonChip: poseidonChip,
|
||||
friParams: friParams,
|
||||
}
|
||||
@ -56,7 +58,7 @@ func (f *FriChip) assertLeadingZeros(powWitness F, friConfig FriConfig) {
|
||||
// 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
|
||||
f.field.AssertIsLessOrEqual(powWitness, field.NewFieldElement(maxPowWitness))
|
||||
f.fieldAPI.AssertIsLessOrEqual(powWitness, field.NewFieldElement(maxPowWitness))
|
||||
}
|
||||
|
||||
func (f *FriChip) fromOpeningsAndAlpha(openings *FriOpenings, alpha QuadraticExtension) []QuadraticExtension {
|
||||
@ -65,7 +67,7 @@ func (f *FriChip) fromOpeningsAndAlpha(openings *FriOpenings, alpha QuadraticExt
|
||||
|
||||
reducedOpenings := make([]QuadraticExtension, 0, 2)
|
||||
for _, batch := range openings.Batches {
|
||||
reducedOpenings = append(reducedOpenings, reduceWithPowers(f.qe, batch.values, alpha))
|
||||
reducedOpenings = append(reducedOpenings, reduceWithPowers(f.qeAPI, batch.values, alpha))
|
||||
}
|
||||
|
||||
return reducedOpenings
|
||||
@ -79,7 +81,7 @@ func (f *FriChip) hashOrNoop(data []F) Hash {
|
||||
elements[i] = inputElement
|
||||
}
|
||||
for i := len(data); i < 4; i++ {
|
||||
elements[i] = f.qe.ZERO_F
|
||||
elements[i] = field.ZERO_F
|
||||
}
|
||||
|
||||
return elements
|
||||
@ -100,7 +102,7 @@ func (f *FriChip) hashOrNoop(data []F) Hash {
|
||||
|
||||
func (f *FriChip) verifyMerkleProofToCapWithCapIndex(leafData []F, leafIndexBits []frontend.Variable, capIndexBits []frontend.Variable, merkleCap MerkleCap, proof *MerkleProof) {
|
||||
currentDigest := f.hashOrNoop(leafData)
|
||||
fourZeros := [4]F{f.qe.ZERO_F, f.qe.ZERO_F, f.qe.ZERO_F, f.qe.ZERO_F}
|
||||
fourZeros := [4]F{field.ZERO_F, field.ZERO_F, field.ZERO_F, field.ZERO_F}
|
||||
for i, sibling := range proof.Siblings {
|
||||
bit := leafIndexBits[i]
|
||||
|
||||
@ -128,7 +130,7 @@ func (f *FriChip) verifyMerkleProofToCapWithCapIndex(leafData []F, leafIndexBits
|
||||
rightHashCompress[2] = rightHash[2]
|
||||
rightHashCompress[3] = rightHash[3]
|
||||
|
||||
currentDigest = SelectHash(f.field, bit, leftHashCompress, rightHashCompress)
|
||||
currentDigest = SelectHash(f.fieldAPI, bit, leftHashCompress, rightHashCompress)
|
||||
}
|
||||
|
||||
// We assume that the cap_height is 4. Create two levels of the Lookup2 circuit
|
||||
@ -142,14 +144,14 @@ func (f *FriChip) verifyMerkleProofToCapWithCapIndex(leafData []F, leafIndexBits
|
||||
// The will use the least significant bits of the capIndexBits array
|
||||
for i := 0; i < NUM_LEAF_LOOKUPS; i++ {
|
||||
leafLookups[i] = Lookup2Hash(
|
||||
f.field, capIndexBits[0], capIndexBits[1],
|
||||
f.fieldAPI, 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 := Lookup2Hash(f.field, capIndexBits[2], capIndexBits[3], leafLookups[0], leafLookups[1], leafLookups[2], leafLookups[3])
|
||||
AssertIsEqualHash(f.field, currentDigest, merkleCapEntry)
|
||||
merkleCapEntry := Lookup2Hash(f.fieldAPI, capIndexBits[2], capIndexBits[3], leafLookups[0], leafLookups[1], leafLookups[2], leafLookups[3])
|
||||
AssertIsEqualHash(f.fieldAPI, currentDigest, merkleCapEntry)
|
||||
}
|
||||
|
||||
func (f *FriChip) verifyInitialProof(xIndexBits []frontend.Variable, proof *FriInitialTreeProof, initialMerkleCaps []MerkleCap, capIndexBits []frontend.Variable) {
|
||||
@ -178,9 +180,9 @@ func (f *FriChip) verifyInitialProof(xIndexBits []frontend.Variable, proof *FriI
|
||||
// /
|
||||
// / Here we compare the probabilities as a sanity check, to verify the claim above.
|
||||
func (f *FriChip) assertNoncanonicalIndicesOK() {
|
||||
numAmbiguousElems := uint64(math.MaxUint64) - EmulatedFieldModulus().Uint64() + 1
|
||||
numAmbiguousElems := uint64(math.MaxUint64) - goldilocks.Modulus().Uint64() + 1
|
||||
queryError := f.friParams.Config.rate()
|
||||
pAmbiguous := float64(numAmbiguousElems) / float64(EmulatedFieldModulus().Uint64())
|
||||
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 {
|
||||
@ -199,10 +201,46 @@ func (f *FriChip) verifyQueryRound(
|
||||
roundProof *FriQueryRound,
|
||||
) {
|
||||
f.assertNoncanonicalIndicesOK()
|
||||
xIndexBits := f.qe.field.ToBinary(xIndex, int(nLog))
|
||||
xIndexBits := f.fieldAPI.ToBinary(xIndex, int(nLog))
|
||||
capIndexBits := xIndexBits[len(xIndexBits)-int(f.friParams.Config.CapHeight):]
|
||||
|
||||
f.verifyInitialProof(xIndexBits, &roundProof.InitialTreesProof, initialMerkleCaps, capIndexBits)
|
||||
|
||||
// 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.NewFieldElement(field.GOLDILOCKS_MULTIPLICATIVE_GROUP_GENERATOR.Uint64())
|
||||
base := field.GoldilocksPrimitiveRootOfUnity(nLog)
|
||||
|
||||
product := ONE_F
|
||||
// Create a reverse list of xIndexBits
|
||||
xIndexBitsRev := make([]frontend.Variable, 0)
|
||||
for i := len(xIndexBits) - 1; i >= 0; i-- {
|
||||
xIndexBitsRev = append(xIndexBitsRev, xIndexBits[i])
|
||||
}
|
||||
|
||||
for i, bit := range xIndexBitsRev {
|
||||
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 := NewFieldElement(basePow.Uint64() - 1)
|
||||
|
||||
product = f.fieldAPI.Add(
|
||||
f.fieldAPI.Mul(
|
||||
basePowElement,
|
||||
product,
|
||||
bit,
|
||||
),
|
||||
product,
|
||||
).(F)
|
||||
}
|
||||
|
||||
subgroupX := f.fieldAPI.Mul(g, product).(F)
|
||||
}
|
||||
|
||||
func (f *FriChip) VerifyFriProof(
|
||||
|
||||
@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
type QuadraticExtensionAPI struct {
|
||||
field frontend.API
|
||||
fieldAPI frontend.API
|
||||
|
||||
W F
|
||||
DTH_ROOT F
|
||||
@ -18,18 +18,17 @@ type QuadraticExtensionAPI struct {
|
||||
ZERO_QE QuadraticExtension
|
||||
}
|
||||
|
||||
func NewQuadraticExtensionAPI(field frontend.API, degreeBits uint64) *QuadraticExtensionAPI {
|
||||
func NewQuadraticExtensionAPI(fieldAPI frontend.API, degreeBits uint64) *QuadraticExtensionAPI {
|
||||
// TODO: Should degreeBits be verified that it fits within the field and that degree is within uint64?
|
||||
|
||||
return &QuadraticExtensionAPI{
|
||||
field: field,
|
||||
fieldAPI: fieldAPI,
|
||||
|
||||
W: NewFieldElement(7),
|
||||
DTH_ROOT: NewFieldElement(18446744069414584320),
|
||||
ZERO_F: NewFieldElement(0),
|
||||
|
||||
ONE: QuadraticExtension{NewFieldElement(1), NewFieldElement(0)},
|
||||
ZERO_QE: QuadraticExtension{NewFieldElement(0), NewFieldElement(0)},
|
||||
ONE: QuadraticExtension{ONE_F, ZERO_F},
|
||||
ZERO_QE: QuadraticExtension{ZERO_F, ZERO_F},
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,20 +37,20 @@ func (c *QuadraticExtensionAPI) SquareExtension(a QuadraticExtension) QuadraticE
|
||||
}
|
||||
|
||||
func (c *QuadraticExtensionAPI) MulExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
|
||||
c_0 := c.field.Add(c.field.Mul(a[0], b[0]).(F), c.field.Mul(c.W, a[1], b[1])).(F)
|
||||
c_1 := c.field.Add(c.field.Mul(a[0], b[1]).(F), c.field.Mul(a[1], b[0])).(F)
|
||||
c_0 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[0]).(F), c.fieldAPI.Mul(c.W, a[1], b[1])).(F)
|
||||
c_1 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[1]).(F), c.fieldAPI.Mul(a[1], b[0])).(F)
|
||||
return QuadraticExtension{c_0, c_1}
|
||||
}
|
||||
|
||||
func (c *QuadraticExtensionAPI) AddExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
|
||||
c_0 := c.field.Add(a[0], b[0]).(F)
|
||||
c_1 := c.field.Add(a[1], b[1]).(F)
|
||||
c_0 := c.fieldAPI.Add(a[0], b[0]).(F)
|
||||
c_1 := c.fieldAPI.Add(a[1], b[1]).(F)
|
||||
return QuadraticExtension{c_0, c_1}
|
||||
}
|
||||
|
||||
func (c *QuadraticExtensionAPI) SubExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
|
||||
c_0 := c.field.Sub(a[0], b[0]).(F)
|
||||
c_1 := c.field.Sub(a[1], b[1]).(F)
|
||||
c_0 := c.fieldAPI.Sub(a[0], b[0]).(F)
|
||||
c_1 := c.fieldAPI.Sub(a[1], b[1]).(F)
|
||||
return QuadraticExtension{c_0, c_1}
|
||||
}
|
||||
|
||||
@ -63,19 +62,19 @@ func (c *QuadraticExtensionAPI) DivExtension(a QuadraticExtension, b QuadraticEx
|
||||
// inverse and assert that a_inverse * a = 1. Should reduce # of constraints.
|
||||
func (c *QuadraticExtensionAPI) InverseExtension(a QuadraticExtension) QuadraticExtension {
|
||||
// First assert that a doesn't have 0 value coefficients
|
||||
a0_is_zero := c.field.IsZero(a[0])
|
||||
a1_is_zero := c.field.IsZero(a[1])
|
||||
a0_is_zero := c.fieldAPI.IsZero(a[0])
|
||||
a1_is_zero := c.fieldAPI.IsZero(a[1])
|
||||
|
||||
// assert that a0_is_zero OR a1_is_zero == false
|
||||
c.field.AssertIsEqual(c.field.Mul(a0_is_zero, a1_is_zero).(F), c.ZERO_F)
|
||||
c.fieldAPI.AssertIsEqual(c.fieldAPI.Mul(a0_is_zero, a1_is_zero).(F), c.ZERO_F)
|
||||
|
||||
a_pow_r_minus_1 := QuadraticExtension{a[0], c.field.Mul(a[1], c.DTH_ROOT).(F)}
|
||||
a_pow_r_minus_1 := QuadraticExtension{a[0], c.fieldAPI.Mul(a[1], c.DTH_ROOT).(F)}
|
||||
a_pow_r := c.MulExtension(a_pow_r_minus_1, a)
|
||||
return c.ScalarMulExtension(a_pow_r_minus_1, c.field.Inverse(a_pow_r[0]).(F))
|
||||
return c.ScalarMulExtension(a_pow_r_minus_1, c.fieldAPI.Inverse(a_pow_r[0]).(F))
|
||||
}
|
||||
|
||||
func (c *QuadraticExtensionAPI) ScalarMulExtension(a QuadraticExtension, scalar F) QuadraticExtension {
|
||||
return QuadraticExtension{c.field.Mul(a[0], scalar).(F), c.field.Mul(a[1], scalar).(F)}
|
||||
return QuadraticExtension{c.fieldAPI.Mul(a[0], scalar).(F), c.fieldAPI.Mul(a[1], scalar).(F)}
|
||||
}
|
||||
|
||||
func (c *QuadraticExtensionAPI) FieldToQE(a F) QuadraticExtension {
|
||||
@ -84,8 +83,8 @@ func (c *QuadraticExtensionAPI) FieldToQE(a F) QuadraticExtension {
|
||||
|
||||
func (c *QuadraticExtensionAPI) Println(a QuadraticExtension) {
|
||||
fmt.Print("Degree 0 coefficient")
|
||||
c.field.Println(a[0])
|
||||
c.fieldAPI.Println(a[0])
|
||||
|
||||
fmt.Print("Degree 1 coefficient")
|
||||
c.field.Println(a[1])
|
||||
c.fieldAPI.Println(a[1])
|
||||
}
|
||||
|
||||
@ -57,3 +57,10 @@ func AssertIsEqualHash(fieldAPI frontend.API, h1, h2 Hash) {
|
||||
fieldAPI.AssertIsEqual(h1[0], h2[0])
|
||||
}
|
||||
}
|
||||
|
||||
func PrintHash(f frontend.API, h Hash) {
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Println("Hash Limb", i)
|
||||
f.Println(h[i])
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user