From 6c556bdfe6bd1432868e8e23f51c527667ca62ef Mon Sep 17 00:00:00 2001 From: Roberto Bayardo Date: Sun, 6 Nov 2022 12:39:30 -0800 Subject: [PATCH] remove legacy kzg verification, put all initialization on top (#44) --- crypto/kzg/kzg.go | 113 ++++++++-------------------------------- tests/kzg_bench_test.go | 14 ----- 2 files changed, 23 insertions(+), 104 deletions(-) diff --git a/crypto/kzg/kzg.go b/crypto/kzg/kzg.go index 8116f09721c4..9036fea3f78b 100644 --- a/crypto/kzg/kzg.go +++ b/crypto/kzg/kzg.go @@ -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) @@ -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. @@ -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() -} diff --git a/tests/kzg_bench_test.go b/tests/kzg_bench_test.go index 3295d35fdc83..ecef998dead1 100644 --- a/tests/kzg_bench_test.go +++ b/tests/kzg_bench_test.go @@ -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