Skip to content

Commit

Permalink
Create util to verify KZG commitment by generation and comparison (#1042
Browse files Browse the repository at this point in the history
)

Signed-off-by: litt3 <[email protected]>
  • Loading branch information
litt3 authored Dec 20, 2024
1 parent 6059c6a commit 290bc67
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 0 deletions.
59 changes: 59 additions & 0 deletions api/clients/v2/verification/verification_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package verification

import (
"fmt"
"github.com/Layr-Labs/eigenda/encoding"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/ecc/bn254"

"github.com/Layr-Labs/eigenda/encoding/kzg/verifier"
"github.com/Layr-Labs/eigenda/encoding/rs"
)

// GenerateBlobCommitment computes a kzg-bn254 commitment of blob data using SRS
func GenerateBlobCommitment(
kzgVerifier *verifier.Verifier,
blob []byte) (*encoding.G1Commitment, error) {

inputFr, err := rs.ToFrArray(blob)
if err != nil {
return nil, fmt.Errorf("convert bytes to field elements, %w", err)
}

if len(kzgVerifier.Srs.G1) < len(inputFr) {
return nil, fmt.Errorf(
"insufficient SRS in memory: have %v, need %v",
len(kzgVerifier.Srs.G1),
len(inputFr))
}

var commitment bn254.G1Affine
_, err = commitment.MultiExp(kzgVerifier.Srs.G1[:len(inputFr)], inputFr, ecc.MultiExpConfig{})
if err != nil {
return nil, fmt.Errorf("MultiExp: %w", err)
}

return &encoding.G1Commitment{X: commitment.X, Y: commitment.Y}, nil
}

// GenerateAndCompareBlobCommitment generates the kzg-bn254 commitment of the blob, and compares it with a claimed
// commitment. An error is returned if there is a problem generating the commitment, or if the comparison fails.
func GenerateAndCompareBlobCommitment(
kzgVerifier *verifier.Verifier,
claimedCommitment *encoding.G1Commitment,
blobBytes []byte) error {

computedCommitment, err := GenerateBlobCommitment(kzgVerifier, blobBytes)
if err != nil {
return fmt.Errorf("compute commitment: %w", err)
}

if claimedCommitment.X.Equal(&computedCommitment.X) &&
claimedCommitment.Y.Equal(&computedCommitment.Y) {
return nil
}

return fmt.Errorf(
"commitment field elements do not match. computed commitment: (x: %x, y: %x), claimed commitment (x: %x, y: %x)",
computedCommitment.X, computedCommitment.Y, claimedCommitment.X, claimedCommitment.Y)
}
125 changes: 125 additions & 0 deletions api/clients/v2/verification/verification_utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package verification

import (
"github.com/Layr-Labs/eigenda/common/testutils/random"
"github.com/Layr-Labs/eigenda/encoding/kzg"
"github.com/Layr-Labs/eigenda/encoding/kzg/verifier"
"github.com/Layr-Labs/eigenda/encoding/utils/codec"
"github.com/stretchr/testify/require"
"runtime"
"testing"
)

func getKzgConfig() *kzg.KzgConfig {
return &kzg.KzgConfig{
G1Path: "../../../../inabox/resources/kzg/g1.point",
G2Path: "../../../../inabox/resources/kzg/g2.point",
G2PowerOf2Path: "../../../../inabox/resources/kzg/g2.point.powerOf2",
CacheDir: "../../../../inabox/resources/kzg/SRSTables",
SRSOrder: 3000,
SRSNumberToLoad: 2900,
NumWorker: uint64(runtime.GOMAXPROCS(0)),
LoadG2Points: false,
}
}

// randomlyModifyBytes picks a random byte from the input array, and increments it
func randomlyModifyBytes(testRandom *random.TestRandom, inputBytes []byte) {
indexToModify := testRandom.Intn(len(inputBytes))
inputBytes[indexToModify] = inputBytes[indexToModify] + 1
}

func getRandomPaddedBytes(testRandom *random.TestRandom, count int) []byte {
return codec.ConvertByPaddingEmptyByte(testRandom.Bytes(count))
}

func TestComputeAndCompareKzgCommitmentSuccess(t *testing.T) {
testRandom := random.NewTestRandom(t)
randomBytes := getRandomPaddedBytes(testRandom, 1000)

kzgVerifier, err := verifier.NewVerifier(getKzgConfig(), nil)
require.NotNil(t, kzgVerifier)
require.NoError(t, err)

commitment, err := GenerateBlobCommitment(kzgVerifier, randomBytes)
require.NotNil(t, commitment)
require.NoError(t, err)

// make sure the commitment verifies correctly
err = GenerateAndCompareBlobCommitment(
kzgVerifier,
commitment,
randomBytes)
require.NoError(t, err)
}

func TestComputeAndCompareKzgCommitmentFailure(t *testing.T) {
testRandom := random.NewTestRandom(t)
randomBytes := getRandomPaddedBytes(testRandom, 1000)

kzgVerifier, err := verifier.NewVerifier(getKzgConfig(), nil)
require.NotNil(t, kzgVerifier)
require.NoError(t, err)

commitment, err := GenerateBlobCommitment(kzgVerifier, randomBytes)
require.NotNil(t, commitment)
require.NoError(t, err)

// randomly modify the bytes, and make sure the commitment verification fails
randomlyModifyBytes(testRandom, randomBytes)
err = GenerateAndCompareBlobCommitment(
kzgVerifier,
commitment,
randomBytes)
require.NotNil(t, err)
}

func TestGenerateBlobCommitmentEquality(t *testing.T) {
testRandom := random.NewTestRandom(t)
randomBytes := getRandomPaddedBytes(testRandom, 1000)

kzgVerifier, err := verifier.NewVerifier(getKzgConfig(), nil)
require.NotNil(t, kzgVerifier)
require.NoError(t, err)

// generate two identical commitments
commitment1, err := GenerateBlobCommitment(kzgVerifier, randomBytes)
require.NotNil(t, commitment1)
require.NoError(t, err)
commitment2, err := GenerateBlobCommitment(kzgVerifier, randomBytes)
require.NotNil(t, commitment2)
require.NoError(t, err)

// commitments to identical bytes should be equal
require.Equal(t, commitment1, commitment2)

// randomly modify a byte
randomlyModifyBytes(testRandom, randomBytes)
commitmentA, err := GenerateBlobCommitment(kzgVerifier, randomBytes)
require.NotNil(t, commitmentA)
require.NoError(t, err)

// commitments to non-identical bytes should not be equal
require.NotEqual(t, commitment1, commitmentA)
}

func TestGenerateBlobCommitmentTooLong(t *testing.T) {
kzgVerifier, err := verifier.NewVerifier(getKzgConfig(), nil)
require.NotNil(t, kzgVerifier)
require.NoError(t, err)

// this is the absolute maximum number of bytes we can handle, given how the verifier was configured
almostTooLongByteCount := 2900 * 32

// an array of exactly this size should be fine
almostTooLongBytes := make([]byte, almostTooLongByteCount)
commitment1, err := GenerateBlobCommitment(kzgVerifier, almostTooLongBytes)
require.NotNil(t, commitment1)
require.NoError(t, err)

// but 1 more byte is more than we can handle
tooLongBytes := make([]byte, almostTooLongByteCount+1)
commitment2, err := GenerateBlobCommitment(kzgVerifier, tooLongBytes)
require.Nil(t, commitment2)
require.NotNil(t, err)
}

0 comments on commit 290bc67

Please sign in to comment.