Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove legacy kzg verification, put all initialization on top #44

Merged
merged 1 commit into from
Nov 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 23 additions & 90 deletions crypto/kzg/kzg.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,29 @@ var kzgSetupLagrange []bls.G1Point
// KZG CRS for G1 (only used in tests (for proof creation))
var KzgSetupG1 []bls.G1Point

type JSONTrustedSetup struct {
SetupG1 []bls.G1Point
SetupG2 []bls.G2Point
SetupLagrange []bls.G1Point
}

// Initialize KZG subsystem (load the trusted setup data)
func init() {
var parsedSetup = JSONTrustedSetup{}

// TODO: This is dirty. KZG setup should be loaded using an actual config file directive
err := json.Unmarshal([]byte(KZGSetupStr), &parsedSetup)
if err != nil {
panic(err)
}

kzgSetupG2 = parsedSetup.SetupG2
kzgSetupLagrange = bitReversalPermutation(parsedSetup.SetupLagrange)
KzgSetupG1 = parsedSetup.SetupG1

initDomain()
}

// Convert polynomial in evaluation form to KZG commitment
func BlobToKzg(eval []bls.Fr) *bls.G1Point {
return bls.LinCombG1(kzgSetupLagrange, eval)
Expand Down Expand Up @@ -99,73 +122,6 @@ func (batch *BlobsBatch) Verify() error {
return nil
}

// Verify that the list of `commitments` maps to the list of `blobs`
//
// This is an optimization over the naive approach (found in the EIP) of iteratively checking each blob against each
// commitment. The naive approach requires n*l scalar multiplications where `n` is the number of blobs and `l` is
// FIELD_ELEMENTS_PER_BLOB to compute the commitments for all blobs.
//
// A more efficient approach is to build a linear combination of all blobs and commitments and check all of them in a
// single multi-scalar multiplication.
//
// The MSM would look like this (for three blobs with two field elements each):
// r_0(b0_0*L_0 + b0_1*L_1) + r_1(b1_0*L_0 + b1_1*L_1) + r_2(b2_0*L_0 + b2_1*L_1)
// which we would need to check against the linear combination of commitments: r_0*C_0 + r_1*C_1 + r_2*C_2
// In the above, `r` are the random scalars of the linear combination, `b0` is the zero blob, `L` are the elements
// of the KZG_SETUP_LAGRANGE and `C` are the commitments provided.
//
// By regrouping the above equation around the `L` points we can reduce the length of the MSM further
// (down to just `n` scalar multiplications) by making it look like this:
// (r_0*b0_0 + r_1*b1_0 + r_2*b2_0) * L_0 + (r_0*b0_1 + r_1*b1_1 + r_2*b2_1) * L_1
func VerifyBlobsLegacy(commitments []*bls.G1Point, blobs [][]bls.Fr) error {
// Prepare objects to hold our two MSMs
lPoints := make([]bls.G1Point, params.FieldElementsPerBlob)
lScalars := make([]bls.Fr, params.FieldElementsPerBlob)
rPoints := make([]bls.G1Point, len(commitments))
rScalars := make([]bls.Fr, len(commitments))

// Generate list of random scalars for lincomb
rList := make([]bls.Fr, len(blobs))
for i := 0; i < len(blobs); i++ {
bls.CopyFr(&rList[i], bls.RandomFr())
}

// Build left-side MSM:
// (r_0*b0_0 + r_1*b1_0 + r_2*b2_0) * L_0 + (r_0*b0_1 + r_1*b1_1 + r_2*b2_1) * L_1
for c := 0; c < params.FieldElementsPerBlob; c++ {
var sum bls.Fr
for i := 0; i < len(blobs); i++ {
var tmp bls.Fr

r := rList[i]
blob := blobs[i]

bls.MulModFr(&tmp, &r, &blob[c])
bls.AddModFr(&sum, &sum, &tmp)
}
lScalars[c] = sum
lPoints[c] = kzgSetupLagrange[c]
}

// Build right-side MSM: r_0 * C_0 + r_1 * C_1 + r_2 * C_2 + ...
for i, commitment := range commitments {
rScalars[i] = rList[i]
rPoints[i] = *commitment
}

// Compute both MSMs and check equality
lResult := bls.LinCombG1(lPoints, lScalars)
rResult := bls.LinCombG1(rPoints, rScalars)
if !bls.EqualG1(lResult, rResult) {
return errors.New("VerifyBlobs failed")
}

// TODO: Potential improvement is to unify both MSMs into a single MSM, but you would need to batch-invert the `r`s
// of the right-side MSM to effectively pull them to the left side.

return nil
}

// Bit-reversal permutation helper functions

// Check if `value` is a power of two integer.
Expand Down Expand Up @@ -239,26 +195,3 @@ func ComputeProof(eval []bls.Fr, z *bls.Fr) (*bls.G1Point, error) {
}
return bls.LinCombG1(kzgSetupLagrange, quotientPoly[:]), nil
}

type JSONTrustedSetup struct {
SetupG1 []bls.G1Point
SetupG2 []bls.G2Point
SetupLagrange []bls.G1Point
}

// Initialize KZG subsystem (load the trusted setup data)
func init() {
var parsedSetup = JSONTrustedSetup{}

// TODO: This is dirty. KZG setup should be loaded using an actual config file directive
err := json.Unmarshal([]byte(KZGSetupStr), &parsedSetup)
if err != nil {
panic(err)
}

kzgSetupG2 = parsedSetup.SetupG2
kzgSetupLagrange = bitReversalPermutation(parsedSetup.SetupLagrange)
KzgSetupG1 = parsedSetup.SetupG1

initDomain()
}
14 changes: 0 additions & 14 deletions tests/kzg_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,6 @@ func BenchmarkBlobToKzg(b *testing.B) {
}
}

func BenchmarkVerifyBlobsWithoutKZGProof(b *testing.B) {
var blobs [][]bls.Fr
var commitments []*bls.G1Point
for i := 0; i < 16; i++ {
blob := randomBlob()
blobs = append(blobs, blob)
commitments = append(commitments, kzg.BlobToKzg(blob))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
kzg.VerifyBlobsLegacy(commitments, blobs)
}
}

func BenchmarkVerifyBlobs(b *testing.B) {
blobs := make([]types.Blob, params.MaxBlobsPerBlock)
var commitments []types.KZGCommitment
Expand Down