-
Notifications
You must be signed in to change notification settings - Fork 193
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create util to verify KZG commitment by generation and comparison (#1042
) Signed-off-by: litt3 <[email protected]>
- Loading branch information
Showing
2 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |