From 17f9d23aa5f2a39d2be7b3c5fcf6fbe4508d7e61 Mon Sep 17 00:00:00 2001 From: Ian Shim Date: Wed, 4 Dec 2024 21:33:03 -0800 Subject: [PATCH] update blob header hasher --- core/chainio.go | 4 +- core/eth/reader.go | 8 +- core/mock/writer.go | 6 +- core/v2/serialization.go | 205 ++++++++++++++-------------- core/v2/serialization_test.go | 11 +- core/v2/types.go | 2 +- disperser/dataapi/server_v2_test.go | 2 +- relay/relay_test_utils.go | 2 +- 8 files changed, 124 insertions(+), 116 deletions(-) diff --git a/core/chainio.go b/core/chainio.go index 121aacdee..6ced6ed4c 100644 --- a/core/chainio.go +++ b/core/chainio.go @@ -107,10 +107,10 @@ type Reader interface { GetNumBlobVersions(ctx context.Context) (uint16, error) // GetVersionedBlobParams returns the blob version parameters for the given block number and blob version. - GetVersionedBlobParams(ctx context.Context, blobVersion uint8) (*BlobVersionParameters, error) + GetVersionedBlobParams(ctx context.Context, blobVersion uint16) (*BlobVersionParameters, error) // GetAllVersionedBlobParams returns the blob version parameters for all blob versions at the given block number. - GetAllVersionedBlobParams(ctx context.Context) (map[uint8]*BlobVersionParameters, error) + GetAllVersionedBlobParams(ctx context.Context) (map[uint16]*BlobVersionParameters, error) // GetActiveReservations returns active reservations (end timestamp > current timestamp) GetActiveReservations(ctx context.Context, accountIDs []gethcommon.Address) (map[gethcommon.Address]*ActiveReservation, error) diff --git a/core/eth/reader.go b/core/eth/reader.go index af13ae441..b2e59dfb4 100644 --- a/core/eth/reader.go +++ b/core/eth/reader.go @@ -647,7 +647,7 @@ func (t *Reader) GetNumBlobVersions(ctx context.Context) (uint16, error) { }) } -func (t *Reader) GetVersionedBlobParams(ctx context.Context, blobVersion uint8) (*core.BlobVersionParameters, error) { +func (t *Reader) GetVersionedBlobParams(ctx context.Context, blobVersion uint16) (*core.BlobVersionParameters, error) { params, err := t.bindings.EigenDAServiceManager.GetBlobParams(&bind.CallOpts{ Context: ctx, }, uint16(blobVersion)) @@ -661,7 +661,7 @@ func (t *Reader) GetVersionedBlobParams(ctx context.Context, blobVersion uint8) }, nil } -func (t *Reader) GetAllVersionedBlobParams(ctx context.Context) (map[uint8]*core.BlobVersionParameters, error) { +func (t *Reader) GetAllVersionedBlobParams(ctx context.Context) (map[uint16]*core.BlobVersionParameters, error) { if t.bindings.ThresholdRegistry == nil { return nil, errors.New("threshold registry not deployed") } @@ -671,8 +671,8 @@ func (t *Reader) GetAllVersionedBlobParams(ctx context.Context) (map[uint8]*core return nil, err } - res := make(map[uint8]*core.BlobVersionParameters) - for version := uint8(0); version < uint8(numBlobVersions); version++ { + res := make(map[uint16]*core.BlobVersionParameters) + for version := uint16(0); version < uint16(numBlobVersions); version++ { params, err := t.GetVersionedBlobParams(ctx, version) if err != nil && strings.Contains(err.Error(), "execution reverted") { break diff --git a/core/mock/writer.go b/core/mock/writer.go index a6939554e..87384401b 100644 --- a/core/mock/writer.go +++ b/core/mock/writer.go @@ -203,7 +203,7 @@ func (t *MockWriter) GetNumBlobVersions(ctx context.Context) (uint16, error) { return result.(uint16), args.Error(1) } -func (t *MockWriter) GetVersionedBlobParams(ctx context.Context, blobVersion uint8) (*core.BlobVersionParameters, error) { +func (t *MockWriter) GetVersionedBlobParams(ctx context.Context, blobVersion uint16) (*core.BlobVersionParameters, error) { args := t.Called() if args.Get(0) == nil { return nil, args.Error(1) @@ -212,13 +212,13 @@ func (t *MockWriter) GetVersionedBlobParams(ctx context.Context, blobVersion uin return result.(*core.BlobVersionParameters), args.Error(1) } -func (t *MockWriter) GetAllVersionedBlobParams(ctx context.Context) (map[uint8]*core.BlobVersionParameters, error) { +func (t *MockWriter) GetAllVersionedBlobParams(ctx context.Context) (map[uint16]*core.BlobVersionParameters, error) { args := t.Called() result := args.Get(0) if result == nil { return nil, args.Error(1) } - return result.(map[uint8]*core.BlobVersionParameters), args.Error(1) + return result.(map[uint16]*core.BlobVersionParameters), args.Error(1) } func (t *MockWriter) PubkeyHashToOperator(ctx context.Context, operatorId core.OperatorID) (gethcommon.Address, error) { diff --git a/core/v2/serialization.go b/core/v2/serialization.go index 5acff9115..fa36850b1 100644 --- a/core/v2/serialization.go +++ b/core/v2/serialization.go @@ -24,92 +24,85 @@ type abiBlobCommitments struct { Commitment abiG1Commit LengthCommitment abiG2Commit LengthProof abiG2Commit - Length uint32 -} -type abiBlobHeader struct { - BlobVersion uint8 - BlobCommitments abiBlobCommitments - QuorumNumbers []byte - PaymentMetadataHash [32]byte + DataLength uint32 } -func blobHeaderArgMarshaling() []abi.ArgumentMarshaling { - return []abi.ArgumentMarshaling{ +func (b *BlobHeader) BlobKey() (BlobKey, error) { + versionType, err := abi.NewType("uint16", "", nil) + if err != nil { + return [32]byte{}, err + } + quorumNumbersType, err := abi.NewType("bytes", "", nil) + if err != nil { + return [32]byte{}, err + } + commitmentType, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ { - Name: "blobVersion", - Type: "uint8", + Name: "commitment", + Type: "tuple", + Components: []abi.ArgumentMarshaling{ + { + Name: "X", + Type: "uint256", + }, + { + Name: "Y", + Type: "uint256", + }, + }, }, { - Name: "blobCommitments", + Name: "lengthCommitment", Type: "tuple", Components: []abi.ArgumentMarshaling{ { - Name: "commitment", - Type: "tuple", - Components: []abi.ArgumentMarshaling{ - { - Name: "X", - Type: "uint256", - }, - { - Name: "Y", - Type: "uint256", - }, - }, + Name: "X", + Type: "uint256[2]", }, { - Name: "lengthCommitment", - Type: "tuple", - Components: []abi.ArgumentMarshaling{ - { - Name: "X", - Type: "uint256[2]", - }, - { - Name: "Y", - Type: "uint256[2]", - }, - }, + Name: "Y", + Type: "uint256[2]", }, + }, + }, + { + Name: "lengthProof", + Type: "tuple", + Components: []abi.ArgumentMarshaling{ { - Name: "lengthProof", - Type: "tuple", - Components: []abi.ArgumentMarshaling{ - { - Name: "X", - Type: "uint256[2]", - }, - { - Name: "Y", - Type: "uint256[2]", - }, - }, + Name: "X", + Type: "uint256[2]", }, { - Name: "length", - Type: "uint32", + Name: "Y", + Type: "uint256[2]", }, }, }, { - Name: "quorumNumbers", - Type: "bytes", + Name: "dataLength", + Type: "uint32", + }, + }) + if err != nil { + return [32]byte{}, err + } + arguments := abi.Arguments{ + { + Type: versionType, }, { - Name: "paymentMetadataHash", - Type: "bytes32", + Type: quorumNumbersType, + }, + { + Type: commitmentType, }, } -} -func (b *BlobHeader) toABIStruct() (abiBlobHeader, error) { - paymentHash, err := b.PaymentMetadata.Hash() - if err != nil { - return abiBlobHeader{}, err - } - return abiBlobHeader{ - BlobVersion: uint8(b.BlobVersion), - BlobCommitments: abiBlobCommitments{ + packedBytes, err := arguments.Pack( + b.BlobVersion, + b.QuorumNumbers, + abiBlobCommitments{ Commitment: abiG1Commit{ X: b.BlobCommitments.Commitment.X.BigInt(new(big.Int)), Y: b.BlobCommitments.Commitment.Y.BigInt(new(big.Int)), @@ -134,41 +127,62 @@ func (b *BlobHeader) toABIStruct() (abiBlobHeader, error) { b.BlobCommitments.LengthProof.Y.A1.BigInt(new(big.Int)), }, }, - Length: uint32(b.BlobCommitments.Length), + DataLength: uint32(b.BlobCommitments.Length), }, - QuorumNumbers: b.QuorumNumbers, - PaymentMetadataHash: paymentHash, - }, nil -} + ) + if err != nil { + return [32]byte{}, err + } -func (b *BlobHeader) BlobKey() (BlobKey, error) { - blobHeaderType, err := abi.NewType("tuple", "", blobHeaderArgMarshaling()) + var headerHash [32]byte + hasher := sha3.NewLegacyKeccak256() + hasher.Write(packedBytes) + copy(headerHash[:], hasher.Sum(nil)[:32]) + + blobKeyType, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ + { + Name: "blobHeaderHash", + Type: "bytes32", + }, + { + Name: "paymentMetadataHash", + Type: "bytes32", + }, + }) if err != nil { return [32]byte{}, err } - arguments := abi.Arguments{ + arguments = abi.Arguments{ { - Type: blobHeaderType, + Type: blobKeyType, }, } - s, err := b.toABIStruct() + paymentMetadataHash, err := b.PaymentMetadata.Hash() if err != nil { return [32]byte{}, err } - bytes, err := arguments.Pack(s) + s2 := struct { + BlobHeaderHash [32]byte + PaymentMetadataHash [32]byte + }{ + BlobHeaderHash: headerHash, + PaymentMetadataHash: paymentMetadataHash, + } + + packedBytes, err = arguments.Pack(s2) if err != nil { return [32]byte{}, err } - var headerHash [32]byte - hasher := sha3.NewLegacyKeccak256() - hasher.Write(bytes) - copy(headerHash[:], hasher.Sum(nil)[:32]) + var blobKey [32]byte + hasher = sha3.NewLegacyKeccak256() + hasher.Write(packedBytes) + copy(blobKey[:], hasher.Sum(nil)[:32]) - return headerHash, nil + return blobKey, nil } func (c *BlobCertificate) Hash() ([32]byte, error) { @@ -176,40 +190,31 @@ func (c *BlobCertificate) Hash() ([32]byte, error) { return [32]byte{}, fmt.Errorf("blob header is nil") } - blobCertType, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ - { - Name: "blobHeader", - Type: "tuple", - Components: blobHeaderArgMarshaling(), - }, - { - Name: "relayKeys", - Type: "uint32[]", - }, - }) + blobKeyType, err := abi.NewType("bytes32", "", nil) + if err != nil { + return [32]byte{}, err + } + + relayKeysType, err := abi.NewType("uint32[]", "", nil) if err != nil { return [32]byte{}, err } arguments := abi.Arguments{ { - Type: blobCertType, + Type: blobKeyType, + }, + { + Type: relayKeysType, }, } - bh, err := c.BlobHeader.toABIStruct() + blobKey, err := c.BlobHeader.BlobKey() if err != nil { return [32]byte{}, err } - s := struct { - BlobHeader abiBlobHeader - RelayKeys []RelayKey - }{ - BlobHeader: bh, - RelayKeys: c.RelayKeys, - } - bytes, err := arguments.Pack(s) + bytes, err := arguments.Pack(blobKey, c.RelayKeys) if err != nil { return [32]byte{}, err } diff --git a/core/v2/serialization_test.go b/core/v2/serialization_test.go index 78e97d190..4f77438ad 100644 --- a/core/v2/serialization_test.go +++ b/core/v2/serialization_test.go @@ -48,13 +48,14 @@ func TestBlobKeyFromHeader(t *testing.T) { AccountID: "0x123", ReservationPeriod: 5, CumulativePayment: big.NewInt(100), + Salt: 42, }, Signature: []byte{1, 2, 3}, } blobKey, err := bh.BlobKey() assert.NoError(t, err) - // 0x1354b29d9dd9a332959795d17f456c219566417fdbf1a7b4f5d118f5c2a36bbd verified in solidity - assert.Equal(t, "1354b29d9dd9a332959795d17f456c219566417fdbf1a7b4f5d118f5c2a36bbd", blobKey.Hex()) + // 0x22c9e31c3d79c7c4085b564113f488019cbae18198c9a4fc4ecd70a5742e8638 verified in solidity + assert.Equal(t, "22c9e31c3d79c7c4085b564113f488019cbae18198c9a4fc4ecd70a5742e8638", blobKey.Hex()) } func TestBatchHeaderHash(t *testing.T) { @@ -102,6 +103,7 @@ func TestBlobCertHash(t *testing.T) { AccountID: "0x123", ReservationPeriod: 5, CumulativePayment: big.NewInt(100), + Salt: 42, }, Signature: []byte{1, 2, 3}, }, @@ -110,8 +112,8 @@ func TestBlobCertHash(t *testing.T) { hash, err := blobCert.Hash() assert.NoError(t, err) - // 0xad938e477d0bc1f9f4e8de7c5cd837560bdbb2dc7094207a7ad53e7442611a43 verified in solidity - assert.Equal(t, "ad938e477d0bc1f9f4e8de7c5cd837560bdbb2dc7094207a7ad53e7442611a43", hex.EncodeToString(hash[:])) + // 0x182087a394c8aab23e8da107c820679333c1efee66fd4380ba283c0e4c09efd6 verified in solidity + assert.Equal(t, "182087a394c8aab23e8da107c820679333c1efee66fd4380ba283c0e4c09efd6", hex.EncodeToString(hash[:])) } func TestBlobCertSerialization(t *testing.T) { @@ -130,6 +132,7 @@ func TestBlobCertSerialization(t *testing.T) { AccountID: "0x123", ReservationPeriod: 5, CumulativePayment: big.NewInt(100), + Salt: 42, }, Signature: []byte{1, 2, 3}, }, diff --git a/core/v2/types.go b/core/v2/types.go index 90cb5524a..f1c129a8d 100644 --- a/core/v2/types.go +++ b/core/v2/types.go @@ -14,7 +14,7 @@ import ( gethcommon "github.com/ethereum/go-ethereum/common" ) -type BlobVersion = uint8 +type BlobVersion = uint16 // Assignment contains information about the set of chunks that a specific node will receive type Assignment struct { diff --git a/disperser/dataapi/server_v2_test.go b/disperser/dataapi/server_v2_test.go index 1e1da4114..2fe042058 100644 --- a/disperser/dataapi/server_v2_test.go +++ b/disperser/dataapi/server_v2_test.go @@ -190,7 +190,7 @@ func TestFetchBlobHandlerV2(t *testing.T) { assert.Equal(t, http.StatusOK, res.StatusCode) assert.Equal(t, "Queued", response.Status) - assert.Equal(t, uint8(0), response.BlobHeader.BlobVersion) + assert.Equal(t, uint16(0), response.BlobHeader.BlobVersion) assert.Equal(t, blobHeader.Signature, response.BlobHeader.Signature) assert.Equal(t, blobHeader.PaymentMetadata.AccountID, response.BlobHeader.PaymentMetadata.AccountID) assert.Equal(t, blobHeader.PaymentMetadata.ReservationPeriod, response.BlobHeader.PaymentMetadata.ReservationPeriod) diff --git a/relay/relay_test_utils.go b/relay/relay_test_utils.go index 375e823b6..efaca396c 100644 --- a/relay/relay_test_utils.go +++ b/relay/relay_test_utils.go @@ -183,7 +183,7 @@ func newMockChainReader() *coremock.MockWriter { return w } -func mockBlobParamsMap() map[uint8]*core.BlobVersionParameters { +func mockBlobParamsMap() map[v2.BlobVersion]*core.BlobVersionParameters { blobParams := &core.BlobVersionParameters{ NumChunks: 8192, CodingRate: 8,