diff --git a/common/ssz_test.go b/common/ssz_test.go index d3a680be..7876017a 100644 --- a/common/ssz_test.go +++ b/common/ssz_test.go @@ -3,66 +3,153 @@ package common import ( "bytes" "encoding/json" + "fmt" "os" "testing" builderApiCapella "github.com/attestantio/go-builder-client/api/capella" + builderApiDeneb "github.com/attestantio/go-builder-client/api/deneb" builderSpec "github.com/attestantio/go-builder-client/spec" + "github.com/attestantio/go-eth2-client/spec" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/require" ) func TestSSZBuilderSubmission(t *testing.T) { - // json matches marshalled SSZ - jsonBytes := LoadGzippedBytes(t, "../testdata/submitBlockPayloadCapella_Goerli.json.gz") - - submitBlockData := new(VersionedSubmitBlockRequest) - err := json.Unmarshal(jsonBytes, &submitBlockData) - require.NoError(t, err) - - require.NotNil(t, submitBlockData.Capella) - marshalledSszBytes, err := submitBlockData.Capella.MarshalSSZ() - require.NoError(t, err) - - sszBytes := LoadGzippedBytes(t, "../testdata/submitBlockPayloadCapella_Goerli.ssz.gz") - require.Equal(t, sszBytes, marshalledSszBytes) - - htr, err := submitBlockData.Capella.HashTreeRoot() - require.NoError(t, err) - require.Equal(t, "0x014c218ba41c2ed5388e7f0ed055e109b83692c772de5c2800140a95a4b66d13", hexutil.Encode(htr[:])) - - // marshalled json matches ssz - submitBlockSSZ := new(VersionedSubmitBlockRequest) - err = submitBlockSSZ.UnmarshalSSZ(sszBytes) - require.NoError(t, err) - marshalledJSONBytes, err := json.Marshal(submitBlockSSZ) - require.NoError(t, err) - // trim white space from expected json - buffer := new(bytes.Buffer) - err = json.Compact(buffer, jsonBytes) - require.NoError(t, err) - require.Equal(t, buffer.Bytes(), bytes.ToLower(marshalledJSONBytes)) + testCases := []struct { + name string + filepath string + hashTreeRoot string + }{ + { + name: "Capella", + filepath: "../testdata/submitBlockPayloadCapella_Goerli", + hashTreeRoot: "0x014c218ba41c2ed5388e7f0ed055e109b83692c772de5c2800140a95a4b66d13", + }, + { + name: "Deneb", + filepath: "../testdata/submitBlockPayloadDeneb_Goerli", + hashTreeRoot: "0x258007ab62465df2b5d798571d3ba0554302b7569eb1ca99405485d32723d63f", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + // json matches marshalled SSZ + jsonBytes := LoadGzippedBytes(t, fmt.Sprintf("%s.json.gz", testCase.filepath)) + + submitBlockData := new(VersionedSubmitBlockRequest) + err := json.Unmarshal(jsonBytes, &submitBlockData) + require.NoError(t, err) + + require.False(t, submitBlockData.IsEmpty()) + marshalledSszBytes, err := submitBlockData.MarshalSSZ() + require.NoError(t, err) + + sszBytes := LoadGzippedBytes(t, fmt.Sprintf("%s.ssz.gz", testCase.filepath)) + require.Equal(t, sszBytes, marshalledSszBytes) + + htr, err := submitBlockData.HashTreeRoot() + require.NoError(t, err) + require.Equal(t, testCase.hashTreeRoot, hexutil.Encode(htr[:])) + + // marshalled json matches ssz + submitBlockSSZ := new(VersionedSubmitBlockRequest) + err = submitBlockSSZ.UnmarshalSSZ(sszBytes) + require.NoError(t, err) + marshalledJSONBytes, err := json.Marshal(submitBlockSSZ) + require.NoError(t, err) + // trim white space from expected json + buffer := new(bytes.Buffer) + err = json.Compact(buffer, jsonBytes) + require.NoError(t, err) + require.Equal(t, buffer.Bytes(), marshalledJSONBytes) + }) + } } func TestSSZGetHeaderResponse(t *testing.T) { - payload := new(builderSpec.VersionedSignedBuilderBid) - - byteValue, err := os.ReadFile("../testdata/getHeaderResponseCapella_Mainnet.json") - require.NoError(t, err) - - err = json.Unmarshal(byteValue, &payload) - require.NoError(t, err) - - ssz, err := payload.Capella.MarshalSSZ() - require.NoError(t, err) - - sszExpectedBytes, err := os.ReadFile("../testdata/getHeaderResponseCapella_Mainnet.ssz") - require.NoError(t, err) - require.Equal(t, sszExpectedBytes, ssz) + testCases := []struct { + name string + filepath string + hashTreeRoot string + }{ + { + name: "Capella", + filepath: "../testdata/getHeaderResponseCapella_Mainnet", + hashTreeRoot: "0x74bfedcdd2da65b4fb14800340ce1abbb202a0dee73aed80b1cf18fb5bc88190", + }, + { + name: "Deneb", + filepath: "../testdata/getHeaderResponseDeneb_Goerli", + hashTreeRoot: "0xc55312d9740709036d0f95168d53576a8c578fbab9cf66f147f8aaf1d2ea74da", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + // json -> marshalled ssz -> matches expected ssz + payload := new(builderSpec.VersionedSignedBuilderBid) + + jsonBytes, err := os.ReadFile(fmt.Sprintf("%s.json", testCase.filepath)) + require.NoError(t, err) - htr, err := payload.Capella.HashTreeRoot() - require.NoError(t, err) - require.Equal(t, "0x74bfedcdd2da65b4fb14800340ce1abbb202a0dee73aed80b1cf18fb5bc88190", hexutil.Encode(htr[:])) + err = json.Unmarshal(jsonBytes, &payload) + require.NoError(t, err) + + var ssz []byte + switch payload.Version { //nolint:exhaustive + case spec.DataVersionCapella: + ssz, err = payload.Capella.MarshalSSZ() + require.NoError(t, err) + case spec.DataVersionDeneb: + ssz, err = payload.Deneb.MarshalSSZ() + require.NoError(t, err) + default: + require.Fail(t, "unknown version") + } + + sszExpectedBytes, err := os.ReadFile(fmt.Sprintf("%s.ssz", testCase.filepath)) + require.NoError(t, err) + require.Equal(t, sszExpectedBytes, ssz) + + // check hash tree root + var htr [32]byte + switch payload.Version { //nolint:exhaustive + case spec.DataVersionCapella: + htr, err = payload.Capella.HashTreeRoot() + require.NoError(t, err) + case spec.DataVersionDeneb: + htr, err = payload.Deneb.HashTreeRoot() + require.NoError(t, err) + default: + require.Fail(t, "unknown version") + } + require.NoError(t, err) + require.Equal(t, testCase.hashTreeRoot, hexutil.Encode(htr[:])) + + // ssz -> marshalled json -> matches expected json + switch payload.Version { //nolint:exhaustive + case spec.DataVersionCapella: + payload.Capella = new(builderApiCapella.SignedBuilderBid) + err = payload.Capella.UnmarshalSSZ(sszExpectedBytes) + require.NoError(t, err) + case spec.DataVersionDeneb: + payload.Deneb = new(builderApiDeneb.SignedBuilderBid) + err = payload.Deneb.UnmarshalSSZ(sszExpectedBytes) + require.NoError(t, err) + default: + require.Fail(t, "unknown version") + } + marshalledJSONBytes, err := json.Marshal(payload) + require.NoError(t, err) + // trim white space from expected json + buffer := new(bytes.Buffer) + err = json.Compact(buffer, jsonBytes) + require.NoError(t, err) + require.Equal(t, buffer.Bytes(), marshalledJSONBytes) + }) + } } func BenchmarkDecoding(b *testing.B) { @@ -73,17 +160,37 @@ func BenchmarkDecoding(b *testing.B) { require.NoError(b, err) payload := new(builderSpec.VersionedSignedBuilderBid) - b.Run("json", func(b *testing.B) { + b.Run("capella json", func(b *testing.B) { for i := 0; i < b.N; i++ { err = json.Unmarshal(jsonBytes, &payload) require.NoError(b, err) } }) payload.Capella = new(builderApiCapella.SignedBuilderBid) - b.Run("ssz", func(b *testing.B) { + b.Run("capella ssz", func(b *testing.B) { for i := 0; i < b.N; i++ { err = payload.Capella.UnmarshalSSZ(sszBytes) require.NoError(b, err) } }) + + jsonBytes, err = os.ReadFile("../testdata/getHeaderResponseDeneb_Goerli.json") + require.NoError(b, err) + + sszBytes, err = os.ReadFile("../testdata/getHeaderResponseDeneb_Goerli.ssz") + require.NoError(b, err) + payload = new(builderSpec.VersionedSignedBuilderBid) + b.Run("deneb json", func(b *testing.B) { + for i := 0; i < b.N; i++ { + err = json.Unmarshal(jsonBytes, &payload) + require.NoError(b, err) + } + }) + payload.Deneb = new(builderApiDeneb.SignedBuilderBid) + b.Run("deneb ssz", func(b *testing.B) { + for i := 0; i < b.N; i++ { + err = payload.Deneb.UnmarshalSSZ(sszBytes) + require.NoError(b, err) + } + }) } diff --git a/common/types_spec.go b/common/types_spec.go index 132970f4..eb854954 100644 --- a/common/types_spec.go +++ b/common/types_spec.go @@ -290,6 +290,19 @@ func (r *VersionedSubmitBlockRequest) UnmarshalSSZ(input []byte) error { return errors.Wrap(err, "failed to unmarshal SubmitBlockRequest SSZ") } +func (r *VersionedSubmitBlockRequest) HashTreeRoot() (phase0.Root, error) { + switch r.Version { + case spec.DataVersionCapella: + return r.Capella.HashTreeRoot() + case spec.DataVersionDeneb: + return r.Deneb.HashTreeRoot() + case spec.DataVersionUnknown, spec.DataVersionPhase0, spec.DataVersionAltair, spec.DataVersionBellatrix: + fallthrough + default: + return phase0.Root{}, errors.Wrap(ErrInvalidVersion, fmt.Sprintf("%d is not supported", r.Version)) + } +} + func (r *VersionedSubmitBlockRequest) MarshalJSON() ([]byte, error) { switch r.Version { //nolint:exhaustive case spec.DataVersionCapella: diff --git a/common/types_spec_test.go b/common/types_spec_test.go index bff9c629..411253ae 100644 --- a/common/types_spec_test.go +++ b/common/types_spec_test.go @@ -5,14 +5,7 @@ import ( "encoding/json" "testing" - builderApiDeneb "github.com/attestantio/go-builder-client/api/deneb" - builderApiV1 "github.com/attestantio/go-builder-client/api/v1" - builderSpec "github.com/attestantio/go-builder-client/spec" "github.com/attestantio/go-eth2-client/spec" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/deneb" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/holiman/uint256" "github.com/stretchr/testify/require" ) @@ -30,79 +23,115 @@ func TestSubmitBuilderBlockJSON(t *testing.T) { require.NoError(t, err) expectedJSONBytes := buffer.Bytes() - require.Equal(t, expectedJSONBytes, bytes.ToLower(marshalledJSONBytes)) + require.Equal(t, expectedJSONBytes, marshalledJSONBytes) } func TestSignedBeaconBlockJSON(t *testing.T) { - jsonBytes := LoadGzippedBytes(t, "../testdata/signedBeaconBlock_Goerli.json.gz") - buffer := new(bytes.Buffer) - err := json.Compact(buffer, jsonBytes) - require.NoError(t, err) - expectedJSONBytes := buffer.Bytes() - - blockRequest := new(VersionedSignedProposal) - err = json.Unmarshal(jsonBytes, blockRequest) - require.NoError(t, err) - - marshalledJSONBytes, err := json.Marshal(blockRequest) - require.NoError(t, err) - - require.Equal(t, expectedJSONBytes, bytes.ToLower(marshalledJSONBytes)) + testCases := []struct { + name string + filepath string + }{ + { + name: "Capella", + filepath: "../testdata/signedBeaconBlockCapella_Goerli.json.gz", + }, + { + name: "Deneb", + filepath: "../testdata/signedBeaconBlockContentsDeneb_Goerli.json.gz", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + jsonBytes := LoadGzippedBytes(t, testCase.filepath) + buffer := new(bytes.Buffer) + err := json.Compact(buffer, jsonBytes) + require.NoError(t, err) + expectedJSONBytes := buffer.Bytes() + + blockRequest := new(VersionedSignedProposal) + err = json.Unmarshal(jsonBytes, blockRequest) + require.NoError(t, err) + + marshalledJSONBytes, err := json.Marshal(blockRequest) + require.NoError(t, err) + + require.Equal(t, expectedJSONBytes, marshalledJSONBytes) + }) + } } func TestSignedBlindedBlockJSON(t *testing.T) { - jsonBytes := LoadGzippedBytes(t, "../testdata/signedBlindedBeaconBlock_Goerli.json.gz") - buffer := new(bytes.Buffer) - err := json.Compact(buffer, jsonBytes) - require.NoError(t, err) - expectedJSONBytes := buffer.Bytes() - - blockRequest := new(VersionedSignedBlindedBeaconBlock) - err = json.Unmarshal(jsonBytes, blockRequest) - require.NoError(t, err) - - marshalledJSONBytes, err := json.Marshal(blockRequest) - require.NoError(t, err) - - require.Equal(t, expectedJSONBytes, bytes.ToLower(marshalledJSONBytes)) + testCases := []struct { + name string + filepath string + }{ + { + name: "Capella", + filepath: "../testdata/signedBlindedBeaconBlockCapella_Goerli.json.gz", + }, + { + name: "Deneb", + filepath: "../testdata/signedBlindedBeaconBlockDeneb_Goerli.json.gz", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + jsonBytes := LoadGzippedBytes(t, testCase.filepath) + buffer := new(bytes.Buffer) + err := json.Compact(buffer, jsonBytes) + require.NoError(t, err) + expectedJSONBytes := buffer.Bytes() + + blockRequest := new(VersionedSignedBlindedBeaconBlock) + err = json.Unmarshal(jsonBytes, blockRequest) + require.NoError(t, err) + + marshalledJSONBytes, err := json.Marshal(blockRequest) + require.NoError(t, err) + + require.Equal(t, expectedJSONBytes, marshalledJSONBytes) + }) + } } func TestBuildGetPayloadResponse(t *testing.T) { - t.Run("Capella", func(t *testing.T) { - jsonBytes := LoadGzippedBytes(t, "../testdata/submitBlockPayloadCapella_Goerli.json.gz") - - submitBlockData := new(VersionedSubmitBlockRequest) - err := json.Unmarshal(jsonBytes, &submitBlockData) - require.NoError(t, err) - - resp, err := BuildGetPayloadResponse(submitBlockData) - require.NoError(t, err) - - require.Equal(t, spec.DataVersionCapella, resp.Version) - require.Equal(t, "0x1bafdc454116b605005364976b134d761dd736cb4788d25c835783b46daeb121", resp.Capella.BlockHash.String()) - }) - - t.Run("Deneb", func(t *testing.T) { - // TODO: (deneb) add block request from goerli / devnet - submitBlockData := &VersionedSubmitBlockRequest{ - VersionedSubmitBlockRequest: builderSpec.VersionedSubmitBlockRequest{ - Version: spec.DataVersionDeneb, - Deneb: &builderApiDeneb.SubmitBlockRequest{ - ExecutionPayload: &deneb.ExecutionPayload{ - BaseFeePerGas: uint256.NewInt(123), - BlockHash: phase0.Hash32{0x09}, - Transactions: []bellatrix.Transaction{}, - }, - BlobsBundle: &builderApiDeneb.BlobsBundle{}, - Message: &builderApiV1.BidTrace{}, - }, - }, - } - - resp, err := BuildGetPayloadResponse(submitBlockData) - require.NoError(t, err) - - require.Equal(t, spec.DataVersionDeneb, resp.Version) - require.Equal(t, "0x0900000000000000000000000000000000000000000000000000000000000000", resp.Deneb.ExecutionPayload.BlockHash.String()) - }) + testCases := []struct { + name string + filepath string + version spec.DataVersion + blockHash string + }{ + { + name: "Capella", + filepath: "../testdata/submitBlockPayloadCapella_Goerli.json.gz", + version: spec.DataVersionCapella, + blockHash: "0x1bafdc454116b605005364976b134d761dd736cb4788d25c835783b46daeb121", + }, + { + name: "Deneb", + filepath: "../testdata/submitBlockPayloadDeneb_Goerli.json.gz", + version: spec.DataVersionDeneb, + blockHash: "0x195e2aac0a52cf26428336142e74eafd55d9228f315c2f2fe9253406ef9ef544", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + jsonBytes := LoadGzippedBytes(t, testCase.filepath) + + submitBlockData := new(VersionedSubmitBlockRequest) + err := json.Unmarshal(jsonBytes, &submitBlockData) + require.NoError(t, err) + + resp, err := BuildGetPayloadResponse(submitBlockData) + require.NoError(t, err) + + require.Equal(t, testCase.version, resp.Version) + blockHash, err := resp.BlockHash() + require.NoError(t, err) + require.Equal(t, testCase.blockHash, blockHash.String()) + }) + } } diff --git a/database/typesconv_test.go b/database/typesconv_test.go index 1fe07c71..43e185c6 100644 --- a/database/typesconv_test.go +++ b/database/typesconv_test.go @@ -26,3 +26,23 @@ func TestExecutionPayloadEntryToExecutionPayload(t *testing.T) { require.NoError(t, err) require.Equal(t, "0x1bafdc454116b605005364976b134d761dd736cb4788d25c835783b46daeb121", payload.Capella.BlockHash.String()) } + +func TestExecutionPayloadEntryToExecutionPayloadDeneb(t *testing.T) { + filename := "../testdata/executionPayloadAndBlobsBundleDeneb_Goerli.json.gz" + payloadBytes := common.LoadGzippedBytes(t, filename) + entry := &ExecutionPayloadEntry{ + ID: 123, + Slot: 7432891, + InsertedAt: time.Unix(1685616301, 0), + + ProposerPubkey: "0x8559727ee65c295279332198029c939557f4d2aba0751fc55f71d0733b8aa17cd0301232a7f21a895f81eacf55c97ec4", + BlockHash: "0xbd1ae4f7edb2315d2df70a8d9881fab8d6763fb1c00533ae729050928c38d05a", + Version: common.ForkVersionStringDeneb, + Payload: string(payloadBytes), + } + + payload, err := ExecutionPayloadEntryToExecutionPayload(entry) + require.NoError(t, err) + require.Equal(t, "0xbd1ae4f7edb2315d2df70a8d9881fab8d6763fb1c00533ae729050928c38d05a", payload.Deneb.ExecutionPayload.BlockHash.String()) + require.Equal(t, 1, len(payload.Deneb.BlobsBundle.Blobs)) +} diff --git a/datastore/datastore_test.go b/datastore/datastore_test.go index 02903a62..2336494b 100644 --- a/datastore/datastore_test.go +++ b/datastore/datastore_test.go @@ -1,15 +1,11 @@ package datastore import ( - "encoding/json" "testing" "github.com/alicebob/miniredis/v2" - builderApiDeneb "github.com/attestantio/go-builder-client/api/deneb" - "github.com/attestantio/go-eth2-client/spec/deneb" "github.com/flashbots/mev-boost-relay/common" "github.com/flashbots/mev-boost-relay/database" - "github.com/holiman/uint256" "github.com/stretchr/testify/require" ) @@ -35,45 +31,45 @@ func TestGetPayloadFailure(t *testing.T) { } func TestGetPayloadDatabaseFallback(t *testing.T) { - filename := "../testdata/executionPayloadCapella_Goerli.json.gz" - payloadBytes := common.LoadGzippedBytes(t, filename) - - // prepare mock database with execution payload entry - mockDB := &database.MockDB{ - ExecPayloads: map[string]*database.ExecutionPayloadEntry{ - "1-a-b": { - Version: common.ForkVersionStringCapella, - Payload: string(payloadBytes), - }, + testCases := []struct { + description string + filename string + version string + blockHash string + }{ + { + description: "Good Capella Payload", + filename: "../testdata/executionPayloadCapella_Goerli.json.gz", + version: common.ForkVersionStringCapella, + blockHash: "0x1bafdc454116b605005364976b134d761dd736cb4788d25c835783b46daeb121", + }, + { + description: "Good Deneb Payload", + filename: "../testdata/executionPayloadAndBlobsBundleDeneb_Goerli.json.gz", + version: common.ForkVersionStringDeneb, + blockHash: "0xbd1ae4f7edb2315d2df70a8d9881fab8d6763fb1c00533ae729050928c38d05a", }, } - ds := setupTestDatastore(t, mockDB) - payload, err := ds.GetGetPayloadResponse(common.TestLog, 1, "a", "b") - require.NoError(t, err) - require.Equal(t, "0x1bafdc454116b605005364976b134d761dd736cb4788d25c835783b46daeb121", payload.Capella.BlockHash.String()) -} -func TestGetPayloadDatabaseDeneb(t *testing.T) { - // TODO: (deneb) add execution payload and blobs bundle from goerli / devnet - payloadBytes, err := json.Marshal(&builderApiDeneb.ExecutionPayloadAndBlobsBundle{ - ExecutionPayload: &deneb.ExecutionPayload{ - BaseFeePerGas: uint256.NewInt(5), - }, - BlobsBundle: &builderApiDeneb.BlobsBundle{}, - }) - require.NoError(t, err) + for _, testCase := range testCases { + t.Run(testCase.description, func(t *testing.T) { + payloadBytes := common.LoadGzippedBytes(t, testCase.filename) - // prepare mock database with execution payload entry - mockDB := &database.MockDB{ - ExecPayloads: map[string]*database.ExecutionPayloadEntry{ - "1-a-b": { - Version: common.ForkVersionStringDeneb, - Payload: string(payloadBytes), - }, - }, + // prepare mock database with execution payload entry + mockDB := &database.MockDB{ + ExecPayloads: map[string]*database.ExecutionPayloadEntry{ + "1-a-b": { + Version: testCase.version, + Payload: string(payloadBytes), + }, + }, + } + ds := setupTestDatastore(t, mockDB) + payload, err := ds.GetGetPayloadResponse(common.TestLog, 1, "a", "b") + require.NoError(t, err) + blockHash, err := payload.BlockHash() + require.NoError(t, err) + require.Equal(t, testCase.blockHash, blockHash.String()) + }) } - ds := setupTestDatastore(t, mockDB) - payload, err := ds.GetGetPayloadResponse(common.TestLog, 1, "a", "b") - require.NoError(t, err) - require.Equal(t, "5", payload.Deneb.ExecutionPayload.BaseFeePerGas.String()) } diff --git a/go.mod b/go.mod index 290d7b64..f958a3b4 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/NYTimes/gziphandler v1.1.1 github.com/alicebob/miniredis/v2 v2.31.0 - github.com/attestantio/go-builder-client v0.4.2 + github.com/attestantio/go-builder-client v0.4.3-0.20240124194555-d44db06f45fa github.com/attestantio/go-eth2-client v0.19.9 github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746 github.com/btcsuite/btcd/btcutil v1.1.2 diff --git a/go.sum b/go.sum index 904c6653..050b4519 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/alicebob/miniredis/v2 v2.31.0/go.mod h1:UB/T2Uztp7MlFSDakaX1sTXUv5CAS github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/attestantio/go-builder-client v0.4.2 h1:EycfAFqQV+ooc2z6hmTsbuH4TCLknr0aO0nHLHLMpJM= -github.com/attestantio/go-builder-client v0.4.2/go.mod h1:e02i/WO4fjs3/u9oIZEjiC8CK1Qyxy4cpiMMGKx4VqQ= +github.com/attestantio/go-builder-client v0.4.3-0.20240124194555-d44db06f45fa h1:Kj6d1tXAA+EAi7fK8z8NakBEpY4WYzZMuCmLZjwBpTM= +github.com/attestantio/go-builder-client v0.4.3-0.20240124194555-d44db06f45fa/go.mod h1:e02i/WO4fjs3/u9oIZEjiC8CK1Qyxy4cpiMMGKx4VqQ= github.com/attestantio/go-eth2-client v0.19.9 h1:g5LLX3X7cLC0KS0oai/MtxBOZz3U3QPIX5qryYMxgVE= github.com/attestantio/go-eth2-client v0.19.9/go.mod h1:TTz7YF6w4z6ahvxKiHuGPn6DbQn7gH6HPuWm/DEQeGE= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= diff --git a/services/api/service_test.go b/services/api/service_test.go index 0bb83e3f..4170b513 100644 --- a/services/api/service_test.go +++ b/services/api/service_test.go @@ -336,116 +336,198 @@ func TestDataApiGetDataProposerPayloadDelivered(t *testing.T) { } func TestBuilderSubmitBlockSSZ(t *testing.T) { - requestPayloadJSONBytes := common.LoadGzippedBytes(t, "../../testdata/submitBlockPayloadCapella_Goerli.json.gz") + testCases := []struct { + name string + filepath string + sszLength int + }{ + { + name: "Capella", + filepath: "../../testdata/submitBlockPayloadCapella_Goerli.json.gz", + sszLength: 352239, + }, + { + name: "Deneb", + filepath: "../../testdata/submitBlockPayloadDeneb_Goerli.json.gz", + sszLength: 872081, + }, + } - req := new(common.VersionedSubmitBlockRequest) - req.Capella = new(builderApiCapella.SubmitBlockRequest) - err := json.Unmarshal(requestPayloadJSONBytes, req.Capella) - require.NoError(t, err) + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + requestPayloadJSONBytes := common.LoadGzippedBytes(t, testCase.filepath) - reqSSZ, err := req.Capella.MarshalSSZ() - require.NoError(t, err) - require.Equal(t, 352239, len(reqSSZ)) + req := new(common.VersionedSubmitBlockRequest) + err := json.Unmarshal(requestPayloadJSONBytes, req) + require.NoError(t, err) - test := new(builderApiCapella.SubmitBlockRequest) - err = test.UnmarshalSSZ(reqSSZ) - require.NoError(t, err) + reqSSZ, err := req.MarshalSSZ() + require.NoError(t, err) + require.Equal(t, testCase.sszLength, len(reqSSZ)) + + test := new(common.VersionedSubmitBlockRequest) + err = test.UnmarshalSSZ(reqSSZ) + require.NoError(t, err) + }) + } } func TestBuilderSubmitBlock(t *testing.T) { - path := "/relay/v1/builder/blocks" - backend := newTestBackend(t, 1) - - headSlot := uint64(32) - submissionSlot := headSlot + 1 - submissionTimestamp := 1606824419 + type testHelper struct { + headSlot uint64 + submissionTimestamp int + parentHash string + feeRecipient string + withdrawalRoot string + prevRandao string + jsonReqSize int + sszReqSize int + jsonGzipReqSize int + sszGzipReqSize int + } - // Payload attributes - payloadJSONFilename := "../../testdata/submitBlockPayloadCapella_Goerli.json.gz" - parentHash := "0xbd3291854dc822b7ec585925cda0e18f06af28fa2886e15f52d52dd4b6f94ed6" - feeRec, err := utils.HexToAddress("0x5cc0dde14e7256340cc820415a6022a7d1c93a35") - require.NoError(t, err) - withdrawalsRoot, err := utils.HexToHash("0xb15ed76298ff84a586b1d875df08b6676c98dfe9c7cd73fab88450348d8e70c8") - require.NoError(t, err) - prevRandao := "0x9962816e9d0a39fd4c80935338a741dc916d1545694e41eb5a505e1a3098f9e4" - - // Setup the test relay backend - backend.relay.headSlot.Store(headSlot) - backend.relay.capellaEpoch = 0 - backend.relay.denebEpoch = 2 - backend.relay.proposerDutiesMap = make(map[uint64]*common.BuilderGetValidatorsResponseEntry) - backend.relay.proposerDutiesMap[headSlot+1] = &common.BuilderGetValidatorsResponseEntry{ - Slot: headSlot, - Entry: &builderApiV1.SignedValidatorRegistration{ - Message: &builderApiV1.ValidatorRegistration{ - FeeRecipient: feeRec, + testCases := []struct { + name string + filepath string + data testHelper + }{ + { + name: "Capella", + filepath: "../../testdata/submitBlockPayloadCapella_Goerli.json.gz", + data: testHelper{ + headSlot: 32, + submissionTimestamp: 1606824419, + parentHash: "0xbd3291854dc822b7ec585925cda0e18f06af28fa2886e15f52d52dd4b6f94ed6", + feeRecipient: "0x5cc0dde14e7256340cc820415a6022a7d1c93a35", + withdrawalRoot: "0xb15ed76298ff84a586b1d875df08b6676c98dfe9c7cd73fab88450348d8e70c8", + prevRandao: "0x9962816e9d0a39fd4c80935338a741dc916d1545694e41eb5a505e1a3098f9e4", + jsonReqSize: 704810, + sszReqSize: 352239, + jsonGzipReqSize: 207788, + sszGzipReqSize: 195923, }, }, - } - backend.relay.payloadAttributes = make(map[string]payloadAttributesHelper) - backend.relay.payloadAttributes[parentHash] = payloadAttributesHelper{ - slot: submissionSlot, - parentHash: parentHash, - payloadAttributes: beaconclient.PayloadAttributes{ - PrevRandao: prevRandao, + { + name: "Deneb", + filepath: "../../testdata/submitBlockPayloadDeneb_Goerli.json.gz", + data: testHelper{ + headSlot: 86, + submissionTimestamp: 1606825067, + parentHash: "0xb1bd772f909db1b6cbad8cf31745d3f2d692294998161369a5709c17a71f630f", + feeRecipient: "0x455E5AA18469bC6ccEF49594645666C587A3a71B", + withdrawalRoot: "0x3cb816ccf6bb079b4f462e81db1262064f321a4afa4ff32c1f7e0a1c603836af", + prevRandao: "0x6d414d3ffba7ba51155c3528739102c2889005940913b5d4c8031eed30764d4d", + jsonReqSize: 1744002, + sszReqSize: 872081, + jsonGzipReqSize: 385043, + sszGzipReqSize: 363271, + }, }, - withdrawalsRoot: phase0.Root(withdrawalsRoot), } + path := "/relay/v1/builder/blocks" + backend := newTestBackend(t, 1) - // Prepare the request payload - req := new(common.VersionedSubmitBlockRequest) - req.Capella = new(builderApiCapella.SubmitBlockRequest) - requestPayloadJSONBytes := common.LoadGzippedBytes(t, payloadJSONFilename) - require.NoError(t, err) - err = json.Unmarshal(requestPayloadJSONBytes, req.Capella) - require.NoError(t, err) + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + headSlot := testCase.data.headSlot + submissionSlot := headSlot + 1 + submissionTimestamp := testCase.data.submissionTimestamp - // Update - req.Capella.Message.Slot = submissionSlot - req.Capella.ExecutionPayload.Timestamp = uint64(submissionTimestamp) + // Payload attributes + payloadJSONFilename := testCase.filepath + parentHash := testCase.data.parentHash + feeRec, err := utils.HexToAddress(testCase.data.feeRecipient) + require.NoError(t, err) + withdrawalsRoot, err := utils.HexToHash(testCase.data.withdrawalRoot) + require.NoError(t, err) + prevRandao := testCase.data.prevRandao - // Send JSON encoded request - reqJSONBytes, err := req.Capella.MarshalJSON() - require.NoError(t, err) - require.Equal(t, 704810, len(reqJSONBytes)) - reqJSONBytes2, err := json.Marshal(req.Capella) - require.NoError(t, err) - require.Equal(t, reqJSONBytes, reqJSONBytes2) - rr := backend.requestBytes(http.MethodPost, path, reqJSONBytes, nil) - require.Contains(t, rr.Body.String(), "invalid signature") - require.Equal(t, http.StatusBadRequest, rr.Code) + // Setup the test relay backend + backend.relay.headSlot.Store(headSlot) + backend.relay.capellaEpoch = 0 + backend.relay.denebEpoch = 2 + backend.relay.proposerDutiesMap = make(map[uint64]*common.BuilderGetValidatorsResponseEntry) + backend.relay.proposerDutiesMap[headSlot+1] = &common.BuilderGetValidatorsResponseEntry{ + Slot: headSlot, + Entry: &builderApiV1.SignedValidatorRegistration{ + Message: &builderApiV1.ValidatorRegistration{ + FeeRecipient: feeRec, + }, + }, + } + backend.relay.payloadAttributes = make(map[string]payloadAttributesHelper) + backend.relay.payloadAttributes[parentHash] = payloadAttributesHelper{ + slot: submissionSlot, + parentHash: parentHash, + payloadAttributes: beaconclient.PayloadAttributes{ + PrevRandao: prevRandao, + }, + withdrawalsRoot: phase0.Root(withdrawalsRoot), + } - // Send SSZ encoded request - reqSSZBytes, err := req.Capella.MarshalSSZ() - require.NoError(t, err) - require.Equal(t, 352239, len(reqSSZBytes)) - rr = backend.requestBytes(http.MethodPost, path, reqSSZBytes, map[string]string{ - "Content-Type": "application/octet-stream", - }) - require.Contains(t, rr.Body.String(), "invalid signature") - require.Equal(t, http.StatusBadRequest, rr.Code) + // Prepare the request payload + req := new(common.VersionedSubmitBlockRequest) + requestPayloadJSONBytes := common.LoadGzippedBytes(t, payloadJSONFilename) + require.NoError(t, err) + err = json.Unmarshal(requestPayloadJSONBytes, req) + require.NoError(t, err) - // Send JSON+GZIP encoded request - headers := map[string]string{ - "Content-Encoding": "gzip", - } - jsonGzip := gzipBytes(t, reqJSONBytes) - require.Equal(t, 207788, len(jsonGzip)) - rr = backend.requestBytes(http.MethodPost, path, jsonGzip, headers) - require.Contains(t, rr.Body.String(), "invalid signature") - require.Equal(t, http.StatusBadRequest, rr.Code) - - // Send SSZ+GZIP encoded request - headers = map[string]string{ - "Content-Type": "application/octet-stream", - "Content-Encoding": "gzip", - } + // Update + switch req.Version { //nolint:exhaustive + case spec.DataVersionCapella: + req.Capella.Message.Slot = submissionSlot + req.Capella.ExecutionPayload.Timestamp = uint64(submissionTimestamp) + case spec.DataVersionDeneb: + req.Deneb.Message.Slot = submissionSlot + req.Deneb.ExecutionPayload.Timestamp = uint64(submissionTimestamp) + default: + require.Fail(t, "unknown data version") + } - sszGzip := gzipBytes(t, reqSSZBytes) - require.Equal(t, 195923, len(sszGzip)) - rr = backend.requestBytes(http.MethodPost, path, sszGzip, headers) - require.Contains(t, rr.Body.String(), "invalid signature") - require.Equal(t, http.StatusBadRequest, rr.Code) + // Send JSON encoded request + reqJSONBytes, err := json.Marshal(req) + require.NoError(t, err) + require.Equal(t, testCase.data.jsonReqSize, len(reqJSONBytes)) + reqJSONBytes2, err := json.Marshal(req) + require.NoError(t, err) + require.Equal(t, reqJSONBytes, reqJSONBytes2) + rr := backend.requestBytes(http.MethodPost, path, reqJSONBytes, nil) + require.Contains(t, rr.Body.String(), "invalid signature") + require.Equal(t, http.StatusBadRequest, rr.Code) + + // Send SSZ encoded request + reqSSZBytes, err := req.MarshalSSZ() + require.NoError(t, err) + require.Equal(t, testCase.data.sszReqSize, len(reqSSZBytes)) + rr = backend.requestBytes(http.MethodPost, path, reqSSZBytes, map[string]string{ + "Content-Type": "application/octet-stream", + }) + require.Contains(t, rr.Body.String(), "invalid signature") + require.Equal(t, http.StatusBadRequest, rr.Code) + + // Send JSON+GZIP encoded request + headers := map[string]string{ + "Content-Encoding": "gzip", + } + jsonGzip := gzipBytes(t, reqJSONBytes) + require.Equal(t, testCase.data.jsonGzipReqSize, len(jsonGzip)) + rr = backend.requestBytes(http.MethodPost, path, jsonGzip, headers) + require.Contains(t, rr.Body.String(), "invalid signature") + require.Equal(t, http.StatusBadRequest, rr.Code) + + // Send SSZ+GZIP encoded request + headers = map[string]string{ + "Content-Type": "application/octet-stream", + "Content-Encoding": "gzip", + } + + sszGzip := gzipBytes(t, reqSSZBytes) + require.Equal(t, testCase.data.sszGzipReqSize, len(sszGzip)) + rr = backend.requestBytes(http.MethodPost, path, sszGzip, headers) + require.Contains(t, rr.Body.String(), "invalid signature") + require.Equal(t, http.StatusBadRequest, rr.Code) + }) + } } func TestCheckSubmissionFeeRecipient(t *testing.T) { @@ -1074,7 +1156,7 @@ func TestCheckProposerSignature(t *testing.T) { }) t.Run("Valid Capella Signature", func(t *testing.T) { - jsonBytes := common.LoadGzippedBytes(t, "../../testdata/signedBlindedBeaconBlock_Goerli.json.gz") + jsonBytes := common.LoadGzippedBytes(t, "../../testdata/signedBlindedBeaconBlockCapella_Goerli.json.gz") payload := new(common.VersionedSignedBlindedBeaconBlock) err := json.Unmarshal(jsonBytes, payload) require.NoError(t, err) @@ -1092,7 +1174,7 @@ func TestCheckProposerSignature(t *testing.T) { }) t.Run("Invalid Capella Signature", func(t *testing.T) { - jsonBytes := common.LoadGzippedBytes(t, "../../testdata/signedBlindedBeaconBlock_Goerli.json.gz") + jsonBytes := common.LoadGzippedBytes(t, "../../testdata/signedBlindedBeaconBlockCapella_Goerli.json.gz") payload := new(common.VersionedSignedBlindedBeaconBlock) err := json.Unmarshal(jsonBytes, payload) require.NoError(t, err) @@ -1115,6 +1197,50 @@ func TestCheckProposerSignature(t *testing.T) { require.NoError(t, err) require.False(t, ok) }) + + t.Run("Valid Deneb Signature", func(t *testing.T) { + jsonBytes := common.LoadGzippedBytes(t, "../../testdata/signedBlindedBeaconBlockDeneb_Goerli.json.gz") + payload := new(common.VersionedSignedBlindedBeaconBlock) + err := json.Unmarshal(jsonBytes, payload) + require.NoError(t, err) + // start backend with goerli network + _, _, backend := startTestBackend(t) + goerli, err := common.NewEthNetworkDetails(common.EthNetworkGoerli) + require.NoError(t, err) + backend.relay.opts.EthNetDetails = *goerli + // check signature + t.Log(payload.Deneb.Message.Slot) + pubkey, err := utils.HexToPubkey("0x8322b8af5c6d97e855cc75ad19d59b381a880630cded89268c14acb058cf3c5720ebcde5fa6087dcbb64dbd826936148") + require.NoError(t, err) + ok, err := backend.relay.checkProposerSignature(payload, pubkey[:]) + require.NoError(t, err) + require.True(t, ok) + }) + + t.Run("Invalid Deneb Signature", func(t *testing.T) { + jsonBytes := common.LoadGzippedBytes(t, "../../testdata/signedBlindedBeaconBlockDeneb_Goerli.json.gz") + payload := new(common.VersionedSignedBlindedBeaconBlock) + err := json.Unmarshal(jsonBytes, payload) + require.NoError(t, err) + // change signature + signature, err := utils.HexToSignature( + "0x942d85822e86a182b0a535361b379015a03e5ce4416863d3baa46b42eef06f070462742b79fbc77c0802699ba6d2ab00" + + "11740dad6bfcf05b1f15c5a11687ae2aa6a08c03ad1ff749d7a48e953d13b5d7c2bd1da4cfcf30ba6d918b587d6525f0", + ) + require.NoError(t, err) + payload.Deneb.Signature = signature + // start backend with goerli network + _, _, backend := startTestBackend(t) + goerli, err := common.NewEthNetworkDetails(common.EthNetworkGoerli) + require.NoError(t, err) + backend.relay.opts.EthNetDetails = *goerli + // check signature + pubkey, err := utils.HexToPubkey("0x8322b8af5c6d97e855cc75ad19d59b381a880630cded89268c14acb058cf3c5720ebcde5fa6087dcbb64dbd826936148") + require.NoError(t, err) + ok, err := backend.relay.checkProposerSignature(payload, pubkey[:]) + require.NoError(t, err) + require.False(t, ok) + }) } func gzipBytes(t *testing.T, b []byte) []byte { diff --git a/testdata/executionPayloadAndBlobsBundleDeneb_Goerli.json.gz b/testdata/executionPayloadAndBlobsBundleDeneb_Goerli.json.gz new file mode 100644 index 00000000..69955869 Binary files /dev/null and b/testdata/executionPayloadAndBlobsBundleDeneb_Goerli.json.gz differ diff --git a/testdata/getHeaderResponseCapella_Mainnet.json b/testdata/getHeaderResponseCapella_Mainnet.json index c1ea36b6..cdb6af38 100644 --- a/testdata/getHeaderResponseCapella_Mainnet.json +++ b/testdata/getHeaderResponseCapella_Mainnet.json @@ -4,7 +4,7 @@ "message": { "header": { "parent_hash": "0xfa98f9121134c059d3c180815cb3a0455870a4b8254c729d490970ed9ba6a34e", - "fee_recipient": "0xb636a68f834b4d75af9edc5fb0138bb4758ed293", + "fee_recipient": "0xb636A68F834B4D75aF9EDC5FB0138bB4758eD293", "state_root": "0x2deedbe6351b82bfea1129e9bd26207bca377d0168a4447ce1340690460d3631", "receipts_root": "0xedf52431d776813fb4e7a2f0d250bfd05e3b34bde334e7d258478961f9cc42b4", "logs_bloom": "0xc026020000926000000004d8d01100311060000200001815000e040088010182102c45600001205000300009500400002464000483102a640a000eccc0241c00908040002c49020c121e120a004a0020a88442002048b040013811168814001801084010530200020441118010081c0010210e4201c0650880204210080812007000028288c0202a20010884900100000008541102191808252081d8140201000e08001048240251400001200014c00400894005208622100404c08000b010023020400300402401200229c0840a14485080d04046c82210a0030422000160880050000020000214201a08a22a0000200400c63c6f11205100224000008c0280", diff --git a/testdata/getHeaderResponseDeneb_Goerli.json b/testdata/getHeaderResponseDeneb_Goerli.json new file mode 100644 index 00000000..a89f13f1 --- /dev/null +++ b/testdata/getHeaderResponseDeneb_Goerli.json @@ -0,0 +1,37 @@ +{ + "version": "deneb", + "data": { + "message": { + "header": { + "parent_hash": "0xab0deb2741c1fad04e79b3a46080a65faf9947f19d597ce200067015c6e918da", + "fee_recipient": "0xb636A68F834B4D75aF9EDC5FB0138bB4758eD293", + "state_root": "0xfd956133d063dbd2fc494fa135025411ebf244048b16551ceda91ae72ecf318c", + "receipts_root": "0x1881520b7ccfcf14adc70b5ec3769c855a8b229f199f4bb5bfbb5b9e9c56dd1b", + "logs_bloom": "0x80010013100000200a0c000001010448408808010200404400020002000605004200900604042000500008400000004000c65240243321040018875052640000000a0046a40010080008061de2228001c00000100340209080088004000000a0013200014680400000001880800048520d041c040000000c001000150088080894040a20000008892000028903000041c0010480801410c6807131104440000003089051110000000b0301c08001000983170d03010002c000440224260001204080c00318004040000220164014030824400000008000000000000200042118051003000810804d2802000080800801020010c88200004508080000120e0000", + "prev_randao": "0xbf95f66969756951e11ef4ae6c1b9b57e1f3f0e6c63b3d3efd20135ae27ab0ef", + "block_number": "10402031", + "gas_limit": "30000000", + "gas_used": "21146510", + "timestamp": "1705708476", + "extra_data": "0x496c6c756d696e61746520446d6f63726174697a6520447374726962757465", + "base_fee_per_gas": "296", + "block_hash": "0xc3c5eb1a2725c1065488ba4491f3597b633c945a08301ae9f07603993334a318", + "transactions_root": "0x297d8366756cec251945166e19d1f54e67002a28422558e76ead5db3677798f9", + "withdrawals_root": "0x70ab14824381c971b39cad93b2066b8e9389c89d683ccdb3b56a2ff911b4ff68", + "blob_gas_used": "786432", + "excess_blob_gas": "86769664" + }, + "blob_kzg_commitments": [ + "0x81a51fd61ec96b1aea13f02cd97f1f9fee16c9cde185913753a3f5a5041cee44a15ee8d44ea9dc91721fc7fc660bbdb4", + "0x94b5bad83bfc5ae5497642091c7b7772e3093dde8b08e1f82c9b6038088a8f8c31e5cc4d6e791a2ff1f6d68d69454641", + "0xaa61b98d8d0712768c4cd135592d59ac78c74e0a4af9a6ef15930dfc79956aea82dbe5678076a3864741be4bcd85bac2", + "0x856e43253dab176c81619eb4e559b2f7d609b2fed3cb1d14fe310e9d57fc32b1c155128a328e09b22eaf6599857ce6af", + "0x9314c48e5550108cbb324ad4c977162df4c352ead7f7622ddffdfac2d6ead14c78c5809a6f3e03563e9892c4c7bffdb4", + "0x88d99876da8d398e067c25612b5154deec197b5b88d7f0acee3f977ddc992aa5fdf59e8d126ef4fad8545fbb671aa5d5" + ], + "value": "37851860177112740", + "pubkey": "0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110" + }, + "signature": "0xae22615ca70b0a93b58f43fc36a6fb50226ef510e81332566f430143a8ec5fb05c580cbf4c2e623fdec09878b955ff6709189acd859d15e8656860968bb5c7753936fe45634fd61b18a58bb6a4969aa126437dd19e984e5a726edf1c8f556ba0" + } +} diff --git a/testdata/getHeaderResponseDeneb_Goerli.ssz b/testdata/getHeaderResponseDeneb_Goerli.ssz new file mode 100644 index 00000000..cd2dd69f Binary files /dev/null and b/testdata/getHeaderResponseDeneb_Goerli.ssz differ diff --git a/testdata/signedBeaconBlockCapella_Goerli.json.gz b/testdata/signedBeaconBlockCapella_Goerli.json.gz new file mode 100644 index 00000000..803c58bc Binary files /dev/null and b/testdata/signedBeaconBlockCapella_Goerli.json.gz differ diff --git a/testdata/signedBeaconBlockContentsDeneb_Goerli.json.gz b/testdata/signedBeaconBlockContentsDeneb_Goerli.json.gz new file mode 100644 index 00000000..902bbea6 Binary files /dev/null and b/testdata/signedBeaconBlockContentsDeneb_Goerli.json.gz differ diff --git a/testdata/signedBeaconBlock_Goerli.json.gz b/testdata/signedBeaconBlock_Goerli.json.gz deleted file mode 100644 index 9700c63c..00000000 Binary files a/testdata/signedBeaconBlock_Goerli.json.gz and /dev/null differ diff --git a/testdata/signedBlindedBeaconBlockCapella_Goerli.json.gz b/testdata/signedBlindedBeaconBlockCapella_Goerli.json.gz new file mode 100644 index 00000000..ded4a04e Binary files /dev/null and b/testdata/signedBlindedBeaconBlockCapella_Goerli.json.gz differ diff --git a/testdata/signedBlindedBeaconBlockDeneb_Goerli.json.gz b/testdata/signedBlindedBeaconBlockDeneb_Goerli.json.gz new file mode 100644 index 00000000..75ae8ed0 Binary files /dev/null and b/testdata/signedBlindedBeaconBlockDeneb_Goerli.json.gz differ diff --git a/testdata/signedBlindedBeaconBlock_Goerli.json.gz b/testdata/signedBlindedBeaconBlock_Goerli.json.gz deleted file mode 100644 index 0c2df95f..00000000 Binary files a/testdata/signedBlindedBeaconBlock_Goerli.json.gz and /dev/null differ diff --git a/testdata/submitBlockPayloadCapella_Goerli.json.gz b/testdata/submitBlockPayloadCapella_Goerli.json.gz index 1503a9aa..20be4f0c 100644 Binary files a/testdata/submitBlockPayloadCapella_Goerli.json.gz and b/testdata/submitBlockPayloadCapella_Goerli.json.gz differ diff --git a/testdata/submitBlockPayloadDeneb_Goerli.json.gz b/testdata/submitBlockPayloadDeneb_Goerli.json.gz new file mode 100644 index 00000000..5337ef06 Binary files /dev/null and b/testdata/submitBlockPayloadDeneb_Goerli.json.gz differ diff --git a/testdata/submitBlockPayloadDeneb_Goerli.ssz.gz b/testdata/submitBlockPayloadDeneb_Goerli.ssz.gz new file mode 100644 index 00000000..10b5b6fb Binary files /dev/null and b/testdata/submitBlockPayloadDeneb_Goerli.ssz.gz differ