diff --git a/CHANGELOG.md b/CHANGELOG.md index 91bc8dfb5847..56e2af19020c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve - Add ability to rollback node's internal state during processing. - Change how unsafe protobuf state is created to prevent unnecessary copies. - Added benchmarks for process slots for Capella, Deneb, Electra +- Validator REST mode Electra support ### Changed @@ -48,6 +49,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve - Capella blocks are execution. - Fixed panic when http request to subscribe to event stream fails. - Return early for blob reconstructor during capella fork +- Updated block endpoint from V1 to V2 ### Deprecated diff --git a/validator/client/beacon-api/BUILD.bazel b/validator/client/beacon-api/BUILD.bazel index 442352b88496..e03b86e8517e 100644 --- a/validator/client/beacon-api/BUILD.bazel +++ b/validator/client/beacon-api/BUILD.bazel @@ -97,8 +97,10 @@ go_test( "propose_beacon_block_blinded_bellatrix_test.go", "propose_beacon_block_blinded_capella_test.go", "propose_beacon_block_blinded_deneb_test.go", + "propose_beacon_block_blinded_electra_test.go", "propose_beacon_block_capella_test.go", "propose_beacon_block_deneb_test.go", + "propose_beacon_block_electra_test.go", "propose_beacon_block_phase0_test.go", "propose_beacon_block_test.go", "propose_exit_test.go", diff --git a/validator/client/beacon-api/beacon_api_validator_client_test.go b/validator/client/beacon-api/beacon_api_validator_client_test.go index 63599d9f2f82..5e8521a68163 100644 --- a/validator/client/beacon-api/beacon_api_validator_client_test.go +++ b/validator/client/beacon-api/beacon_api_validator_client_test.go @@ -139,7 +139,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockValid(t *testing.T) { jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", map[string]string{"Eth-Consensus-Version": "phase0"}, gomock.Any(), nil, @@ -175,7 +175,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockError(t *testing.T) { jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", map[string]string{"Eth-Consensus-Version": "phase0"}, gomock.Any(), nil, diff --git a/validator/client/beacon-api/get_beacon_block.go b/validator/client/beacon-api/get_beacon_block.go index 16de0e5b9598..3c6a108a662f 100644 --- a/validator/client/beacon-api/get_beacon_block.go +++ b/validator/client/beacon-api/get_beacon_block.go @@ -69,8 +69,14 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti blinded = produceBlockV3ResponseJson.ExecutionPayloadBlinded decoder = json.NewDecoder(bytes.NewReader(produceBlockV3ResponseJson.Data)) } + return processBlockResponse(ver, blinded, decoder) +} +func processBlockResponse(ver string, isBlinded bool, decoder *json.Decoder) (*ethpb.GenericBeaconBlock, error) { var response *ethpb.GenericBeaconBlock + if decoder == nil { + return nil, errors.New("no produce block json decoder found") + } switch ver { case version.String(version.Phase0): jsonPhase0Block := structs.BeaconBlock{} @@ -93,7 +99,7 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti } response = genericBlock case version.String(version.Bellatrix): - if blinded { + if isBlinded { jsonBellatrixBlock := structs.BlindedBeaconBlockBellatrix{} if err := decoder.Decode(&jsonBellatrixBlock); err != nil { return nil, errors.Wrap(err, "failed to decode blinded bellatrix block response json") @@ -115,7 +121,7 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti response = genericBlock } case version.String(version.Capella): - if blinded { + if isBlinded { jsonCapellaBlock := structs.BlindedBeaconBlockCapella{} if err := decoder.Decode(&jsonCapellaBlock); err != nil { return nil, errors.Wrap(err, "failed to decode blinded capella block response json") @@ -137,7 +143,7 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti response = genericBlock } case version.String(version.Deneb): - if blinded { + if isBlinded { jsonDenebBlock := structs.BlindedBeaconBlockDeneb{} if err := decoder.Decode(&jsonDenebBlock); err != nil { return nil, errors.Wrap(err, "failed to decode blinded deneb block response json") @@ -158,6 +164,28 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti } response = genericBlock } + case version.String(version.Electra): + if isBlinded { + jsonElectraBlock := structs.BlindedBeaconBlockElectra{} + if err := decoder.Decode(&jsonElectraBlock); err != nil { + return nil, errors.Wrap(err, "failed to decode blinded electra block response json") + } + genericBlock, err := jsonElectraBlock.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get blinded electra block") + } + response = genericBlock + } else { + jsonElectraBlockContents := structs.BeaconBlockContentsElectra{} + if err := decoder.Decode(&jsonElectraBlockContents); err != nil { + return nil, errors.Wrap(err, "failed to decode electra block response json") + } + genericBlock, err := jsonElectraBlockContents.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get electra block") + } + response = genericBlock + } default: return nil, errors.Errorf("unsupported consensus version `%s`", ver) } diff --git a/validator/client/beacon-api/get_beacon_block_test.go b/validator/client/beacon-api/get_beacon_block_test.go index 68efd0196d89..2e31fee13b61 100644 --- a/validator/client/beacon-api/get_beacon_block_test.go +++ b/validator/client/beacon-api/get_beacon_block_test.go @@ -500,6 +500,96 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) { assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) } +func TestGetBeaconBlock_ElectraValid(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + proto := testhelpers.GenerateProtoElectraBeaconBlockContents() + block := testhelpers.GenerateJsonElectraBeaconBlockContents() + bytes, err := json.Marshal(block) + require.NoError(t, err) + + const slot = primitives.Slot(1) + randaoReveal := []byte{2} + graffiti := []byte{3} + + ctx := context.Background() + + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + jsonRestHandler.EXPECT().Get( + gomock.Any(), + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &structs.ProduceBlockV3Response{}, + ).SetArg( + 2, + structs.ProduceBlockV3Response{ + Version: "electra", + ExecutionPayloadBlinded: false, + Data: bytes, + }, + ).Return( + nil, + ).Times(1) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti) + require.NoError(t, err) + + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_Electra{ + Electra: proto, + }, + IsBlinded: false, + } + + assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) +} + +func TestGetBeaconBlock_BlindedElectraValid(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + proto := testhelpers.GenerateProtoBlindedElectraBeaconBlock() + block := testhelpers.GenerateJsonBlindedElectraBeaconBlock() + bytes, err := json.Marshal(block) + require.NoError(t, err) + + const slot = primitives.Slot(1) + randaoReveal := []byte{2} + graffiti := []byte{3} + + ctx := context.Background() + + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + jsonRestHandler.EXPECT().Get( + gomock.Any(), + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &structs.ProduceBlockV3Response{}, + ).SetArg( + 2, + structs.ProduceBlockV3Response{ + Version: "electra", + ExecutionPayloadBlinded: true, + Data: bytes, + }, + ).Return( + nil, + ).Times(1) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti) + require.NoError(t, err) + + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_BlindedElectra{ + BlindedElectra: proto, + }, + IsBlinded: true, + } + + assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) +} + func TestGetBeaconBlock_FallbackToBlindedBlock(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() diff --git a/validator/client/beacon-api/propose_beacon_block.go b/validator/client/beacon-api/propose_beacon_block.go index b6d91a447e49..52e7a1e91944 100644 --- a/validator/client/beacon-api/propose_beacon_block.go +++ b/validator/client/beacon-api/propose_beacon_block.go @@ -120,6 +120,35 @@ func (c *beaconApiValidatorClient) proposeBeaconBlock(ctx context.Context, in *e if err != nil { return nil, errors.Wrap(err, "failed to marshal blinded deneb beacon block contents") } + case *ethpb.GenericSignedBeaconBlock_Electra: + consensusVersion = "electra" + beaconBlockRoot, err = blockType.Electra.Block.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "failed to compute block root for electra beacon block") + } + signedBlock, err := structs.SignedBeaconBlockContentsElectraFromConsensus(blockType.Electra) + if err != nil { + return nil, errors.Wrap(err, "failed to convert electra beacon block contents") + } + marshalledSignedBeaconBlockJson, err = json.Marshal(signedBlock) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal electra beacon block contents") + } + case *ethpb.GenericSignedBeaconBlock_BlindedElectra: + blinded = true + consensusVersion = "electra" + beaconBlockRoot, err = blockType.BlindedElectra.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "failed to compute block root for blinded electra beacon block") + } + signedBlock, err := structs.SignedBlindedBeaconBlockElectraFromConsensus(blockType.BlindedElectra) + if err != nil { + return nil, errors.Wrap(err, "failed to convert blinded electra beacon block contents") + } + marshalledSignedBeaconBlockJson, err = json.Marshal(signedBlock) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal blinded electra beacon block contents") + } default: return nil, errors.Errorf("unsupported block type %T", in.Block) } @@ -127,9 +156,9 @@ func (c *beaconApiValidatorClient) proposeBeaconBlock(ctx context.Context, in *e var endpoint string if blinded { - endpoint = "/eth/v1/beacon/blinded_blocks" + endpoint = "/eth/v2/beacon/blinded_blocks" } else { - endpoint = "/eth/v1/beacon/blocks" + endpoint = "/eth/v2/beacon/blocks" } headers := map[string]string{"Eth-Consensus-Version": consensusVersion} diff --git a/validator/client/beacon-api/propose_beacon_block_altair_test.go b/validator/client/beacon-api/propose_beacon_block_altair_test.go index 540fc2435bc3..46fb29baba3b 100644 --- a/validator/client/beacon-api/propose_beacon_block_altair_test.go +++ b/validator/client/beacon-api/propose_beacon_block_altair_test.go @@ -59,7 +59,7 @@ func TestProposeBeaconBlock_Altair(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "altair"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_bellatrix_test.go b/validator/client/beacon-api/propose_beacon_block_bellatrix_test.go index a154b25e74e6..8bb5c773dbb0 100644 --- a/validator/client/beacon-api/propose_beacon_block_bellatrix_test.go +++ b/validator/client/beacon-api/propose_beacon_block_bellatrix_test.go @@ -76,7 +76,7 @@ func TestProposeBeaconBlock_Bellatrix(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "bellatrix"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_blinded_bellatrix_test.go b/validator/client/beacon-api/propose_beacon_block_blinded_bellatrix_test.go index 7f32a5b39ba3..12bf428ea270 100644 --- a/validator/client/beacon-api/propose_beacon_block_blinded_bellatrix_test.go +++ b/validator/client/beacon-api/propose_beacon_block_blinded_bellatrix_test.go @@ -77,7 +77,7 @@ func TestProposeBeaconBlock_BlindedBellatrix(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "bellatrix"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blinded_blocks", + "/eth/v2/beacon/blinded_blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_blinded_capella_test.go b/validator/client/beacon-api/propose_beacon_block_blinded_capella_test.go index f858bdacaaf1..9ea5144bb6f7 100644 --- a/validator/client/beacon-api/propose_beacon_block_blinded_capella_test.go +++ b/validator/client/beacon-api/propose_beacon_block_blinded_capella_test.go @@ -79,7 +79,7 @@ func TestProposeBeaconBlock_BlindedCapella(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "capella"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blinded_blocks", + "/eth/v2/beacon/blinded_blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_blinded_deneb_test.go b/validator/client/beacon-api/propose_beacon_block_blinded_deneb_test.go index 06601363a7f9..c5da35c264d5 100644 --- a/validator/client/beacon-api/propose_beacon_block_blinded_deneb_test.go +++ b/validator/client/beacon-api/propose_beacon_block_blinded_deneb_test.go @@ -15,7 +15,6 @@ import ( ) func TestProposeBeaconBlock_BlindedDeneb(t *testing.T) { - t.Skip("TODO: Fix this in the beacon-API PR") ctrl := gomock.NewController(t) defer ctrl.Finish() jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) @@ -32,7 +31,7 @@ func TestProposeBeaconBlock_BlindedDeneb(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "deneb"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blinded_blocks", + "/eth/v2/beacon/blinded_blocks", headers, bytes.NewBuffer(denebBytes), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_blinded_electra_test.go b/validator/client/beacon-api/propose_beacon_block_blinded_electra_test.go new file mode 100644 index 000000000000..00ac93e2362a --- /dev/null +++ b/validator/client/beacon-api/propose_beacon_block_blinded_electra_test.go @@ -0,0 +1,50 @@ +package beacon_api + +import ( + "bytes" + "context" + "encoding/json" + "testing" + + "github.com/prysmaticlabs/prysm/v5/api/server/structs" + rpctesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared/testing" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock" + "go.uber.org/mock/gomock" +) + +func TestProposeBeaconBlock_BlindedElectra(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + var block structs.SignedBlindedBeaconBlockElectra + err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block) + require.NoError(t, err) + genericSignedBlock, err := block.ToGeneric() + require.NoError(t, err) + + electraBytes, err := json.Marshal(block) + require.NoError(t, err) + // Make sure that what we send in the POST body is the marshalled version of the protobuf block + headers := map[string]string{"Eth-Consensus-Version": "electra"} + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/beacon/blinded_blocks", + headers, + bytes.NewBuffer(electraBytes), + nil, + ) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + proposeResponse, err := validatorClient.proposeBeaconBlock(context.Background(), genericSignedBlock) + assert.NoError(t, err) + require.NotNil(t, proposeResponse) + + expectedBlockRoot, err := genericSignedBlock.GetBlindedElectra().HashTreeRoot() + require.NoError(t, err) + + // Make sure that the block root is set + assert.DeepEqual(t, expectedBlockRoot[:], proposeResponse.BlockRoot) +} diff --git a/validator/client/beacon-api/propose_beacon_block_capella_test.go b/validator/client/beacon-api/propose_beacon_block_capella_test.go index 733edfd5cceb..acc57e28bacd 100644 --- a/validator/client/beacon-api/propose_beacon_block_capella_test.go +++ b/validator/client/beacon-api/propose_beacon_block_capella_test.go @@ -76,7 +76,7 @@ func TestProposeBeaconBlock_Capella(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "capella"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_deneb_test.go b/validator/client/beacon-api/propose_beacon_block_deneb_test.go index 1caf7504fa21..31128aa82bc1 100644 --- a/validator/client/beacon-api/propose_beacon_block_deneb_test.go +++ b/validator/client/beacon-api/propose_beacon_block_deneb_test.go @@ -15,8 +15,6 @@ import ( ) func TestProposeBeaconBlock_Deneb(t *testing.T) { - t.Skip("TODO: Fix this in the beacon-API PR") - ctrl := gomock.NewController(t) defer ctrl.Finish() jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) @@ -33,7 +31,7 @@ func TestProposeBeaconBlock_Deneb(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "deneb"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(denebBytes), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_electra_test.go b/validator/client/beacon-api/propose_beacon_block_electra_test.go new file mode 100644 index 000000000000..d7d2a949d7e3 --- /dev/null +++ b/validator/client/beacon-api/propose_beacon_block_electra_test.go @@ -0,0 +1,50 @@ +package beacon_api + +import ( + "bytes" + "context" + "encoding/json" + "testing" + + "github.com/prysmaticlabs/prysm/v5/api/server/structs" + rpctesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared/testing" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock" + "go.uber.org/mock/gomock" +) + +func TestProposeBeaconBlock_Electra(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + var blockContents structs.SignedBeaconBlockContentsElectra + err := json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &blockContents) + require.NoError(t, err) + genericSignedBlock, err := blockContents.ToGeneric() + require.NoError(t, err) + + electraBytes, err := json.Marshal(blockContents) + require.NoError(t, err) + // Make sure that what we send in the POST body is the marshalled version of the protobuf block + headers := map[string]string{"Eth-Consensus-Version": "electra"} + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/beacon/blocks", + headers, + bytes.NewBuffer(electraBytes), + nil, + ) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + proposeResponse, err := validatorClient.proposeBeaconBlock(context.Background(), genericSignedBlock) + assert.NoError(t, err) + require.NotNil(t, proposeResponse) + + expectedBlockRoot, err := genericSignedBlock.GetElectra().Block.HashTreeRoot() + require.NoError(t, err) + + // Make sure that the block root is set + assert.DeepEqual(t, expectedBlockRoot[:], proposeResponse.BlockRoot) +} diff --git a/validator/client/beacon-api/propose_beacon_block_phase0_test.go b/validator/client/beacon-api/propose_beacon_block_phase0_test.go index aa63c28d1159..140461f40015 100644 --- a/validator/client/beacon-api/propose_beacon_block_phase0_test.go +++ b/validator/client/beacon-api/propose_beacon_block_phase0_test.go @@ -55,7 +55,7 @@ func TestProposeBeaconBlock_Phase0(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "phase0"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_test.go b/validator/client/beacon-api/propose_beacon_block_test.go index 33e165748ff1..23c37e8c0e25 100644 --- a/validator/client/beacon-api/propose_beacon_block_test.go +++ b/validator/client/beacon-api/propose_beacon_block_test.go @@ -51,7 +51,7 @@ func TestProposeBeaconBlock_Error(t *testing.T) { { name: "phase0", consensusVersion: "phase0", - endpoint: "/eth/v1/beacon/blocks", + endpoint: "/eth/v2/beacon/blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedPhase0Block(), }, @@ -59,7 +59,7 @@ func TestProposeBeaconBlock_Error(t *testing.T) { { name: "altair", consensusVersion: "altair", - endpoint: "/eth/v1/beacon/blocks", + endpoint: "/eth/v2/beacon/blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedAltairBlock(), }, @@ -67,7 +67,7 @@ func TestProposeBeaconBlock_Error(t *testing.T) { { name: "bellatrix", consensusVersion: "bellatrix", - endpoint: "/eth/v1/beacon/blocks", + endpoint: "/eth/v2/beacon/blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedBellatrixBlock(), }, @@ -75,15 +75,23 @@ func TestProposeBeaconBlock_Error(t *testing.T) { { name: "blinded bellatrix", consensusVersion: "bellatrix", - endpoint: "/eth/v1/beacon/blinded_blocks", + endpoint: "/eth/v2/beacon/blinded_blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedBlindedBellatrixBlock(), }, }, + { + name: "capella", + consensusVersion: "capella", + endpoint: "/eth/v2/beacon/blocks", + block: ðpb.GenericSignedBeaconBlock{ + Block: generateSignedCapellaBlock(), + }, + }, { name: "blinded capella", consensusVersion: "capella", - endpoint: "/eth/v1/beacon/blinded_blocks", + endpoint: "/eth/v2/beacon/blinded_blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedBlindedCapellaBlock(), }, diff --git a/validator/client/beacon-api/test-helpers/BUILD.bazel b/validator/client/beacon-api/test-helpers/BUILD.bazel index 725b3f5907b6..e8527eed9dcf 100644 --- a/validator/client/beacon-api/test-helpers/BUILD.bazel +++ b/validator/client/beacon-api/test-helpers/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "bellatrix_beacon_block_test_helpers.go", "capella_beacon_block_test_helpers.go", "deneb_beacon_block_test_helpers.go", + "electra_beacon_block_test_helpers.go", "phase0_beacon_block_test_helpers.go", "test_helpers.go", ], diff --git a/validator/client/beacon-api/test-helpers/electra_beacon_block_test_helpers.go b/validator/client/beacon-api/test-helpers/electra_beacon_block_test_helpers.go new file mode 100644 index 000000000000..829d201318f3 --- /dev/null +++ b/validator/client/beacon-api/test-helpers/electra_beacon_block_test_helpers.go @@ -0,0 +1,1156 @@ +package test_helpers + +import ( + "github.com/prysmaticlabs/prysm/v5/api/server/structs" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" +) + +func GenerateProtoElectraBeaconBlockContents() *ethpb.BeaconBlockContentsElectra { + return ðpb.BeaconBlockContentsElectra{ + Block: ðpb.BeaconBlockElectra{ + Slot: 1, + ProposerIndex: 2, + ParentRoot: FillByteSlice(32, 3), + StateRoot: FillByteSlice(32, 4), + Body: ðpb.BeaconBlockBodyElectra{ + RandaoReveal: FillByteSlice(96, 5), + Eth1Data: ðpb.Eth1Data{ + DepositRoot: FillByteSlice(32, 6), + DepositCount: 7, + BlockHash: FillByteSlice(32, 8), + }, + Graffiti: FillByteSlice(32, 9), + ProposerSlashings: []*ethpb.ProposerSlashing{ + { + Header_1: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 10, + ProposerIndex: 11, + ParentRoot: FillByteSlice(32, 12), + StateRoot: FillByteSlice(32, 13), + BodyRoot: FillByteSlice(32, 14), + }, + Signature: FillByteSlice(96, 15), + }, + Header_2: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 16, + ProposerIndex: 17, + ParentRoot: FillByteSlice(32, 18), + StateRoot: FillByteSlice(32, 19), + BodyRoot: FillByteSlice(32, 20), + }, + Signature: FillByteSlice(96, 21), + }, + }, + { + Header_1: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 22, + ProposerIndex: 23, + ParentRoot: FillByteSlice(32, 24), + StateRoot: FillByteSlice(32, 25), + BodyRoot: FillByteSlice(32, 26), + }, + Signature: FillByteSlice(96, 27), + }, + Header_2: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 28, + ProposerIndex: 29, + ParentRoot: FillByteSlice(32, 30), + StateRoot: FillByteSlice(32, 31), + BodyRoot: FillByteSlice(32, 32), + }, + Signature: FillByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*ethpb.AttesterSlashingElectra{ + { + Attestation_1: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{34, 35}, + Data: ðpb.AttestationData{ + Slot: 36, + CommitteeIndex: 37, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 39, + Root: FillByteSlice(32, 40), + }, + Target: ðpb.Checkpoint{ + Epoch: 41, + Root: FillByteSlice(32, 42), + }, + }, + Signature: FillByteSlice(96, 43), + }, + Attestation_2: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{44, 45}, + Data: ðpb.AttestationData{ + Slot: 46, + CommitteeIndex: 47, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 49, + Root: FillByteSlice(32, 50), + }, + Target: ðpb.Checkpoint{ + Epoch: 51, + Root: FillByteSlice(32, 52), + }, + }, + Signature: FillByteSlice(96, 53), + }, + }, + { + Attestation_1: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{54, 55}, + Data: ðpb.AttestationData{ + Slot: 56, + CommitteeIndex: 57, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 59, + Root: FillByteSlice(32, 60), + }, + Target: ðpb.Checkpoint{ + Epoch: 61, + Root: FillByteSlice(32, 62), + }, + }, + Signature: FillByteSlice(96, 63), + }, + Attestation_2: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{64, 65}, + Data: ðpb.AttestationData{ + Slot: 66, + CommitteeIndex: 67, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 69, + Root: FillByteSlice(32, 70), + }, + Target: ðpb.Checkpoint{ + Epoch: 71, + Root: FillByteSlice(32, 72), + }, + }, + Signature: FillByteSlice(96, 73), + }, + }, + }, + Attestations: []*ethpb.AttestationElectra{ + { + AggregationBits: FillByteSlice(4, 74), + Data: ðpb.AttestationData{ + Slot: 75, + CommitteeIndex: 76, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 78, + Root: FillByteSlice(32, 79), + }, + Target: ðpb.Checkpoint{ + Epoch: 80, + Root: FillByteSlice(32, 81), + }, + }, + Signature: FillByteSlice(96, 82), + CommitteeBits: FillByteSlice(8, 82), + }, + { + AggregationBits: FillByteSlice(4, 83), + Data: ðpb.AttestationData{ + Slot: 84, + CommitteeIndex: 85, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 87, + Root: FillByteSlice(32, 88), + }, + Target: ðpb.Checkpoint{ + Epoch: 89, + Root: FillByteSlice(32, 90), + }, + }, + Signature: FillByteSlice(96, 91), + CommitteeBits: FillByteSlice(8, 91), + }, + }, + Deposits: []*ethpb.Deposit{ + { + Proof: FillByteArraySlice(33, FillByteSlice(32, 92)), + Data: ðpb.Deposit_Data{ + PublicKey: FillByteSlice(48, 94), + WithdrawalCredentials: FillByteSlice(32, 95), + Amount: 96, + Signature: FillByteSlice(96, 97), + }, + }, + { + Proof: FillByteArraySlice(33, FillByteSlice(32, 98)), + Data: ðpb.Deposit_Data{ + PublicKey: FillByteSlice(48, 100), + WithdrawalCredentials: FillByteSlice(32, 101), + Amount: 102, + Signature: FillByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*ethpb.SignedVoluntaryExit{ + { + Exit: ðpb.VoluntaryExit{ + Epoch: 104, + ValidatorIndex: 105, + }, + Signature: FillByteSlice(96, 106), + }, + { + Exit: ðpb.VoluntaryExit{ + Epoch: 107, + ValidatorIndex: 108, + }, + Signature: FillByteSlice(96, 109), + }, + }, + SyncAggregate: ðpb.SyncAggregate{ + SyncCommitteeBits: FillByteSlice(64, 110), + SyncCommitteeSignature: FillByteSlice(96, 111), + }, + ExecutionPayload: &enginev1.ExecutionPayloadDeneb{ + ParentHash: FillByteSlice(32, 112), + FeeRecipient: FillByteSlice(20, 113), + StateRoot: FillByteSlice(32, 114), + ReceiptsRoot: FillByteSlice(32, 115), + LogsBloom: FillByteSlice(256, 116), + PrevRandao: FillByteSlice(32, 117), + BlockNumber: 118, + GasLimit: 119, + GasUsed: 120, + Timestamp: 121, + ExtraData: FillByteSlice(32, 122), + BaseFeePerGas: FillByteSlice(32, 123), + BlockHash: FillByteSlice(32, 124), + Transactions: [][]byte{ + FillByteSlice(32, 125), + FillByteSlice(32, 126), + }, + Withdrawals: []*enginev1.Withdrawal{ + { + Index: 127, + ValidatorIndex: 128, + Address: FillByteSlice(20, 129), + Amount: 130, + }, + { + Index: 131, + ValidatorIndex: 132, + Address: FillByteSlice(20, 133), + Amount: 134, + }, + }, + BlobGasUsed: 135, + ExcessBlobGas: 136, + }, + BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{ + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 137, + FromBlsPubkey: FillByteSlice(48, 138), + ToExecutionAddress: FillByteSlice(20, 139), + }, + Signature: FillByteSlice(96, 140), + }, + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 141, + FromBlsPubkey: FillByteSlice(48, 142), + ToExecutionAddress: FillByteSlice(20, 143), + }, + Signature: FillByteSlice(96, 144), + }, + }, + BlobKzgCommitments: [][]byte{FillByteSlice(48, 145), FillByteSlice(48, 146)}, + ExecutionRequests: &enginev1.ExecutionRequests{ + Deposits: []*enginev1.DepositRequest{{ + Pubkey: FillByteSlice(48, 147), + WithdrawalCredentials: FillByteSlice(32, 148), + Amount: 149, + Signature: FillByteSlice(96, 150), + Index: 151, + }}, + Withdrawals: []*enginev1.WithdrawalRequest{ + { + SourceAddress: FillByteSlice(20, 152), + ValidatorPubkey: FillByteSlice(48, 153), + Amount: 154, + }, + }, + Consolidations: []*enginev1.ConsolidationRequest{ + { + SourceAddress: FillByteSlice(20, 155), + SourcePubkey: FillByteSlice(48, 156), + TargetPubkey: FillByteSlice(48, 157), + }, + }, + }, + }, + }, + KzgProofs: [][]byte{FillByteSlice(48, 158)}, + Blobs: [][]byte{FillByteSlice(131072, 159)}, + } +} + +func GenerateProtoBlindedElectraBeaconBlock() *ethpb.BlindedBeaconBlockElectra { + return ðpb.BlindedBeaconBlockElectra{ + Slot: 1, + ProposerIndex: 2, + ParentRoot: FillByteSlice(32, 3), + StateRoot: FillByteSlice(32, 4), + Body: ðpb.BlindedBeaconBlockBodyElectra{ + RandaoReveal: FillByteSlice(96, 5), + Eth1Data: ðpb.Eth1Data{ + DepositRoot: FillByteSlice(32, 6), + DepositCount: 7, + BlockHash: FillByteSlice(32, 8), + }, + Graffiti: FillByteSlice(32, 9), + ProposerSlashings: []*ethpb.ProposerSlashing{ + { + Header_1: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 10, + ProposerIndex: 11, + ParentRoot: FillByteSlice(32, 12), + StateRoot: FillByteSlice(32, 13), + BodyRoot: FillByteSlice(32, 14), + }, + Signature: FillByteSlice(96, 15), + }, + Header_2: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 16, + ProposerIndex: 17, + ParentRoot: FillByteSlice(32, 18), + StateRoot: FillByteSlice(32, 19), + BodyRoot: FillByteSlice(32, 20), + }, + Signature: FillByteSlice(96, 21), + }, + }, + { + Header_1: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 22, + ProposerIndex: 23, + ParentRoot: FillByteSlice(32, 24), + StateRoot: FillByteSlice(32, 25), + BodyRoot: FillByteSlice(32, 26), + }, + Signature: FillByteSlice(96, 27), + }, + Header_2: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 28, + ProposerIndex: 29, + ParentRoot: FillByteSlice(32, 30), + StateRoot: FillByteSlice(32, 31), + BodyRoot: FillByteSlice(32, 32), + }, + Signature: FillByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*ethpb.AttesterSlashingElectra{ + { + Attestation_1: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{34, 35}, + Data: ðpb.AttestationData{ + Slot: 36, + CommitteeIndex: 37, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 39, + Root: FillByteSlice(32, 40), + }, + Target: ðpb.Checkpoint{ + Epoch: 41, + Root: FillByteSlice(32, 42), + }, + }, + Signature: FillByteSlice(96, 43), + }, + Attestation_2: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{44, 45}, + Data: ðpb.AttestationData{ + Slot: 46, + CommitteeIndex: 47, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 49, + Root: FillByteSlice(32, 50), + }, + Target: ðpb.Checkpoint{ + Epoch: 51, + Root: FillByteSlice(32, 52), + }, + }, + Signature: FillByteSlice(96, 53), + }, + }, + { + Attestation_1: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{54, 55}, + Data: ðpb.AttestationData{ + Slot: 56, + CommitteeIndex: 57, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 59, + Root: FillByteSlice(32, 60), + }, + Target: ðpb.Checkpoint{ + Epoch: 61, + Root: FillByteSlice(32, 62), + }, + }, + Signature: FillByteSlice(96, 63), + }, + Attestation_2: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{64, 65}, + Data: ðpb.AttestationData{ + Slot: 66, + CommitteeIndex: 67, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 69, + Root: FillByteSlice(32, 70), + }, + Target: ðpb.Checkpoint{ + Epoch: 71, + Root: FillByteSlice(32, 72), + }, + }, + Signature: FillByteSlice(96, 73), + }, + }, + }, + Attestations: []*ethpb.AttestationElectra{ + { + AggregationBits: FillByteSlice(4, 74), + Data: ðpb.AttestationData{ + Slot: 75, + CommitteeIndex: 76, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 78, + Root: FillByteSlice(32, 79), + }, + Target: ðpb.Checkpoint{ + Epoch: 80, + Root: FillByteSlice(32, 81), + }, + }, + Signature: FillByteSlice(96, 82), + CommitteeBits: FillByteSlice(8, 82), + }, + { + AggregationBits: FillByteSlice(4, 83), + Data: ðpb.AttestationData{ + Slot: 84, + CommitteeIndex: 85, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 87, + Root: FillByteSlice(32, 88), + }, + Target: ðpb.Checkpoint{ + Epoch: 89, + Root: FillByteSlice(32, 90), + }, + }, + Signature: FillByteSlice(96, 91), + CommitteeBits: FillByteSlice(8, 91), + }, + }, + Deposits: []*ethpb.Deposit{ + { + Proof: FillByteArraySlice(33, FillByteSlice(32, 92)), + Data: ðpb.Deposit_Data{ + PublicKey: FillByteSlice(48, 94), + WithdrawalCredentials: FillByteSlice(32, 95), + Amount: 96, + Signature: FillByteSlice(96, 97), + }, + }, + { + Proof: FillByteArraySlice(33, FillByteSlice(32, 98)), + Data: ðpb.Deposit_Data{ + PublicKey: FillByteSlice(48, 100), + WithdrawalCredentials: FillByteSlice(32, 101), + Amount: 102, + Signature: FillByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*ethpb.SignedVoluntaryExit{ + { + Exit: ðpb.VoluntaryExit{ + Epoch: 104, + ValidatorIndex: 105, + }, + Signature: FillByteSlice(96, 106), + }, + { + Exit: ðpb.VoluntaryExit{ + Epoch: 107, + ValidatorIndex: 108, + }, + Signature: FillByteSlice(96, 109), + }, + }, + SyncAggregate: ðpb.SyncAggregate{ + SyncCommitteeBits: FillByteSlice(64, 110), + SyncCommitteeSignature: FillByteSlice(96, 111), + }, + ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: FillByteSlice(32, 112), + FeeRecipient: FillByteSlice(20, 113), + StateRoot: FillByteSlice(32, 114), + ReceiptsRoot: FillByteSlice(32, 115), + LogsBloom: FillByteSlice(256, 116), + PrevRandao: FillByteSlice(32, 117), + BlockNumber: 118, + GasLimit: 119, + GasUsed: 120, + Timestamp: 121, + ExtraData: FillByteSlice(32, 122), + BaseFeePerGas: FillByteSlice(32, 123), + BlockHash: FillByteSlice(32, 124), + TransactionsRoot: FillByteSlice(32, 125), + WithdrawalsRoot: FillByteSlice(32, 126), + BlobGasUsed: 127, + ExcessBlobGas: 128, + }, + BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{ + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 129, + FromBlsPubkey: FillByteSlice(48, 130), + ToExecutionAddress: FillByteSlice(20, 131), + }, + Signature: FillByteSlice(96, 132), + }, + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 133, + FromBlsPubkey: FillByteSlice(48, 134), + ToExecutionAddress: FillByteSlice(20, 135), + }, + Signature: FillByteSlice(96, 136), + }, + }, + BlobKzgCommitments: [][]byte{FillByteSlice(48, 137), FillByteSlice(48, 138)}, + ExecutionRequests: &enginev1.ExecutionRequests{ + Deposits: []*enginev1.DepositRequest{{ + Pubkey: FillByteSlice(48, 139), + WithdrawalCredentials: FillByteSlice(32, 140), + Amount: 141, + Signature: FillByteSlice(96, 142), + Index: 143, + }}, + Withdrawals: []*enginev1.WithdrawalRequest{ + { + SourceAddress: FillByteSlice(20, 144), + ValidatorPubkey: FillByteSlice(48, 145), + Amount: 146, + }, + }, + Consolidations: []*enginev1.ConsolidationRequest{ + { + SourceAddress: FillByteSlice(20, 147), + SourcePubkey: FillByteSlice(48, 148), + TargetPubkey: FillByteSlice(48, 149), + }, + }, + }, + }, + } +} + +func GenerateJsonElectraBeaconBlockContents() *structs.BeaconBlockContentsElectra { + return &structs.BeaconBlockContentsElectra{ + Block: &structs.BeaconBlockElectra{ + Slot: "1", + ProposerIndex: "2", + ParentRoot: FillEncodedByteSlice(32, 3), + StateRoot: FillEncodedByteSlice(32, 4), + Body: &structs.BeaconBlockBodyElectra{ + RandaoReveal: FillEncodedByteSlice(96, 5), + Eth1Data: &structs.Eth1Data{ + DepositRoot: FillEncodedByteSlice(32, 6), + DepositCount: "7", + BlockHash: FillEncodedByteSlice(32, 8), + }, + Graffiti: FillEncodedByteSlice(32, 9), + ProposerSlashings: []*structs.ProposerSlashing{ + { + SignedHeader1: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "10", + ProposerIndex: "11", + ParentRoot: FillEncodedByteSlice(32, 12), + StateRoot: FillEncodedByteSlice(32, 13), + BodyRoot: FillEncodedByteSlice(32, 14), + }, + Signature: FillEncodedByteSlice(96, 15), + }, + SignedHeader2: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "16", + ProposerIndex: "17", + ParentRoot: FillEncodedByteSlice(32, 18), + StateRoot: FillEncodedByteSlice(32, 19), + BodyRoot: FillEncodedByteSlice(32, 20), + }, + Signature: FillEncodedByteSlice(96, 21), + }, + }, + { + SignedHeader1: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "22", + ProposerIndex: "23", + ParentRoot: FillEncodedByteSlice(32, 24), + StateRoot: FillEncodedByteSlice(32, 25), + BodyRoot: FillEncodedByteSlice(32, 26), + }, + Signature: FillEncodedByteSlice(96, 27), + }, + SignedHeader2: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "28", + ProposerIndex: "29", + ParentRoot: FillEncodedByteSlice(32, 30), + StateRoot: FillEncodedByteSlice(32, 31), + BodyRoot: FillEncodedByteSlice(32, 32), + }, + Signature: FillEncodedByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*structs.AttesterSlashingElectra{ + { + Attestation1: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"34", "35"}, + Data: &structs.AttestationData{ + Slot: "36", + CommitteeIndex: "37", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "39", + Root: FillEncodedByteSlice(32, 40), + }, + Target: &structs.Checkpoint{ + Epoch: "41", + Root: FillEncodedByteSlice(32, 42), + }, + }, + Signature: FillEncodedByteSlice(96, 43), + }, + Attestation2: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"44", "45"}, + Data: &structs.AttestationData{ + Slot: "46", + CommitteeIndex: "47", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "49", + Root: FillEncodedByteSlice(32, 50), + }, + Target: &structs.Checkpoint{ + Epoch: "51", + Root: FillEncodedByteSlice(32, 52), + }, + }, + Signature: FillEncodedByteSlice(96, 53), + }, + }, + { + Attestation1: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"54", "55"}, + Data: &structs.AttestationData{ + Slot: "56", + CommitteeIndex: "57", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "59", + Root: FillEncodedByteSlice(32, 60), + }, + Target: &structs.Checkpoint{ + Epoch: "61", + Root: FillEncodedByteSlice(32, 62), + }, + }, + Signature: FillEncodedByteSlice(96, 63), + }, + Attestation2: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"64", "65"}, + Data: &structs.AttestationData{ + Slot: "66", + CommitteeIndex: "67", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "69", + Root: FillEncodedByteSlice(32, 70), + }, + Target: &structs.Checkpoint{ + Epoch: "71", + Root: FillEncodedByteSlice(32, 72), + }, + }, + Signature: FillEncodedByteSlice(96, 73), + }, + }, + }, + Attestations: []*structs.AttestationElectra{ + { + AggregationBits: FillEncodedByteSlice(4, 74), + Data: &structs.AttestationData{ + Slot: "75", + CommitteeIndex: "76", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "78", + Root: FillEncodedByteSlice(32, 79), + }, + Target: &structs.Checkpoint{ + Epoch: "80", + Root: FillEncodedByteSlice(32, 81), + }, + }, + Signature: FillEncodedByteSlice(96, 82), + CommitteeBits: FillEncodedByteSlice(8, 82), + }, + { + AggregationBits: FillEncodedByteSlice(4, 83), + Data: &structs.AttestationData{ + Slot: "84", + CommitteeIndex: "85", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "87", + Root: FillEncodedByteSlice(32, 88), + }, + Target: &structs.Checkpoint{ + Epoch: "89", + Root: FillEncodedByteSlice(32, 90), + }, + }, + Signature: FillEncodedByteSlice(96, 91), + CommitteeBits: FillEncodedByteSlice(8, 91), + }, + }, + Deposits: []*structs.Deposit{ + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 92)), + Data: &structs.DepositData{ + Pubkey: FillEncodedByteSlice(48, 94), + WithdrawalCredentials: FillEncodedByteSlice(32, 95), + Amount: "96", + Signature: FillEncodedByteSlice(96, 97), + }, + }, + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 98)), + Data: &structs.DepositData{ + Pubkey: FillEncodedByteSlice(48, 100), + WithdrawalCredentials: FillEncodedByteSlice(32, 101), + Amount: "102", + Signature: FillEncodedByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*structs.SignedVoluntaryExit{ + { + Message: &structs.VoluntaryExit{ + Epoch: "104", + ValidatorIndex: "105", + }, + Signature: FillEncodedByteSlice(96, 106), + }, + { + Message: &structs.VoluntaryExit{ + Epoch: "107", + ValidatorIndex: "108", + }, + Signature: FillEncodedByteSlice(96, 109), + }, + }, + SyncAggregate: &structs.SyncAggregate{ + SyncCommitteeBits: FillEncodedByteSlice(64, 110), + SyncCommitteeSignature: FillEncodedByteSlice(96, 111), + }, + ExecutionPayload: &structs.ExecutionPayloadDeneb{ + ParentHash: FillEncodedByteSlice(32, 112), + FeeRecipient: FillEncodedByteSlice(20, 113), + StateRoot: FillEncodedByteSlice(32, 114), + ReceiptsRoot: FillEncodedByteSlice(32, 115), + LogsBloom: FillEncodedByteSlice(256, 116), + PrevRandao: FillEncodedByteSlice(32, 117), + BlockNumber: "118", + GasLimit: "119", + GasUsed: "120", + Timestamp: "121", + ExtraData: FillEncodedByteSlice(32, 122), + BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(FillByteSlice(32, 123)).String(), + BlockHash: FillEncodedByteSlice(32, 124), + Transactions: []string{ + FillEncodedByteSlice(32, 125), + FillEncodedByteSlice(32, 126), + }, + Withdrawals: []*structs.Withdrawal{ + { + WithdrawalIndex: "127", + ValidatorIndex: "128", + ExecutionAddress: FillEncodedByteSlice(20, 129), + Amount: "130", + }, + { + WithdrawalIndex: "131", + ValidatorIndex: "132", + ExecutionAddress: FillEncodedByteSlice(20, 133), + Amount: "134", + }, + }, + BlobGasUsed: "135", + ExcessBlobGas: "136", + }, + BLSToExecutionChanges: []*structs.SignedBLSToExecutionChange{ + { + Message: &structs.BLSToExecutionChange{ + ValidatorIndex: "137", + FromBLSPubkey: FillEncodedByteSlice(48, 138), + ToExecutionAddress: FillEncodedByteSlice(20, 139), + }, + Signature: FillEncodedByteSlice(96, 140), + }, + { + Message: &structs.BLSToExecutionChange{ + ValidatorIndex: "141", + FromBLSPubkey: FillEncodedByteSlice(48, 142), + ToExecutionAddress: FillEncodedByteSlice(20, 143), + }, + Signature: FillEncodedByteSlice(96, 144), + }, + }, + BlobKzgCommitments: []string{FillEncodedByteSlice(48, 145), FillEncodedByteSlice(48, 146)}, + ExecutionRequests: &structs.ExecutionRequests{ + Deposits: []*structs.DepositRequest{{ + Pubkey: FillEncodedByteSlice(48, 147), + WithdrawalCredentials: FillEncodedByteSlice(32, 148), + Amount: "149", + Signature: FillEncodedByteSlice(96, 150), + Index: "151", + }}, + Withdrawals: []*structs.WithdrawalRequest{ + { + SourceAddress: FillEncodedByteSlice(20, 152), + ValidatorPubkey: FillEncodedByteSlice(48, 153), + Amount: "154", + }, + }, + Consolidations: []*structs.ConsolidationRequest{ + { + SourceAddress: FillEncodedByteSlice(20, 155), + SourcePubkey: FillEncodedByteSlice(48, 156), + TargetPubkey: FillEncodedByteSlice(48, 157), + }, + }, + }, + }, + }, + KzgProofs: []string{FillEncodedByteSlice(48, 158)}, + Blobs: []string{FillEncodedByteSlice(131072, 159)}, + } +} + +func GenerateJsonBlindedElectraBeaconBlock() *structs.BlindedBeaconBlockElectra { + return &structs.BlindedBeaconBlockElectra{ + Slot: "1", + ProposerIndex: "2", + ParentRoot: FillEncodedByteSlice(32, 3), + StateRoot: FillEncodedByteSlice(32, 4), + Body: &structs.BlindedBeaconBlockBodyElectra{ + RandaoReveal: FillEncodedByteSlice(96, 5), + Eth1Data: &structs.Eth1Data{ + DepositRoot: FillEncodedByteSlice(32, 6), + DepositCount: "7", + BlockHash: FillEncodedByteSlice(32, 8), + }, + Graffiti: FillEncodedByteSlice(32, 9), + ProposerSlashings: []*structs.ProposerSlashing{ + { + SignedHeader1: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "10", + ProposerIndex: "11", + ParentRoot: FillEncodedByteSlice(32, 12), + StateRoot: FillEncodedByteSlice(32, 13), + BodyRoot: FillEncodedByteSlice(32, 14), + }, + Signature: FillEncodedByteSlice(96, 15), + }, + SignedHeader2: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "16", + ProposerIndex: "17", + ParentRoot: FillEncodedByteSlice(32, 18), + StateRoot: FillEncodedByteSlice(32, 19), + BodyRoot: FillEncodedByteSlice(32, 20), + }, + Signature: FillEncodedByteSlice(96, 21), + }, + }, + { + SignedHeader1: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "22", + ProposerIndex: "23", + ParentRoot: FillEncodedByteSlice(32, 24), + StateRoot: FillEncodedByteSlice(32, 25), + BodyRoot: FillEncodedByteSlice(32, 26), + }, + Signature: FillEncodedByteSlice(96, 27), + }, + SignedHeader2: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "28", + ProposerIndex: "29", + ParentRoot: FillEncodedByteSlice(32, 30), + StateRoot: FillEncodedByteSlice(32, 31), + BodyRoot: FillEncodedByteSlice(32, 32), + }, + Signature: FillEncodedByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*structs.AttesterSlashingElectra{ + { + Attestation1: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"34", "35"}, + Data: &structs.AttestationData{ + Slot: "36", + CommitteeIndex: "37", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "39", + Root: FillEncodedByteSlice(32, 40), + }, + Target: &structs.Checkpoint{ + Epoch: "41", + Root: FillEncodedByteSlice(32, 42), + }, + }, + Signature: FillEncodedByteSlice(96, 43), + }, + Attestation2: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"44", "45"}, + Data: &structs.AttestationData{ + Slot: "46", + CommitteeIndex: "47", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "49", + Root: FillEncodedByteSlice(32, 50), + }, + Target: &structs.Checkpoint{ + Epoch: "51", + Root: FillEncodedByteSlice(32, 52), + }, + }, + Signature: FillEncodedByteSlice(96, 53), + }, + }, + { + Attestation1: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"54", "55"}, + Data: &structs.AttestationData{ + Slot: "56", + CommitteeIndex: "57", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "59", + Root: FillEncodedByteSlice(32, 60), + }, + Target: &structs.Checkpoint{ + Epoch: "61", + Root: FillEncodedByteSlice(32, 62), + }, + }, + Signature: FillEncodedByteSlice(96, 63), + }, + Attestation2: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"64", "65"}, + Data: &structs.AttestationData{ + Slot: "66", + CommitteeIndex: "67", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "69", + Root: FillEncodedByteSlice(32, 70), + }, + Target: &structs.Checkpoint{ + Epoch: "71", + Root: FillEncodedByteSlice(32, 72), + }, + }, + Signature: FillEncodedByteSlice(96, 73), + }, + }, + }, + Attestations: []*structs.AttestationElectra{ + { + AggregationBits: FillEncodedByteSlice(4, 74), + Data: &structs.AttestationData{ + Slot: "75", + CommitteeIndex: "76", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "78", + Root: FillEncodedByteSlice(32, 79), + }, + Target: &structs.Checkpoint{ + Epoch: "80", + Root: FillEncodedByteSlice(32, 81), + }, + }, + Signature: FillEncodedByteSlice(96, 82), + CommitteeBits: FillEncodedByteSlice(8, 82), + }, + { + AggregationBits: FillEncodedByteSlice(4, 83), + Data: &structs.AttestationData{ + Slot: "84", + CommitteeIndex: "85", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "87", + Root: FillEncodedByteSlice(32, 88), + }, + Target: &structs.Checkpoint{ + Epoch: "89", + Root: FillEncodedByteSlice(32, 90), + }, + }, + Signature: FillEncodedByteSlice(96, 91), + CommitteeBits: FillEncodedByteSlice(8, 91), + }, + }, + Deposits: []*structs.Deposit{ + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 92)), + Data: &structs.DepositData{ + Pubkey: FillEncodedByteSlice(48, 94), + WithdrawalCredentials: FillEncodedByteSlice(32, 95), + Amount: "96", + Signature: FillEncodedByteSlice(96, 97), + }, + }, + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 98)), + Data: &structs.DepositData{ + Pubkey: FillEncodedByteSlice(48, 100), + WithdrawalCredentials: FillEncodedByteSlice(32, 101), + Amount: "102", + Signature: FillEncodedByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*structs.SignedVoluntaryExit{ + { + Message: &structs.VoluntaryExit{ + Epoch: "104", + ValidatorIndex: "105", + }, + Signature: FillEncodedByteSlice(96, 106), + }, + { + Message: &structs.VoluntaryExit{ + Epoch: "107", + ValidatorIndex: "108", + }, + Signature: FillEncodedByteSlice(96, 109), + }, + }, + SyncAggregate: &structs.SyncAggregate{ + SyncCommitteeBits: FillEncodedByteSlice(64, 110), + SyncCommitteeSignature: FillEncodedByteSlice(96, 111), + }, + ExecutionPayloadHeader: &structs.ExecutionPayloadHeaderDeneb{ + ParentHash: FillEncodedByteSlice(32, 112), + FeeRecipient: FillEncodedByteSlice(20, 113), + StateRoot: FillEncodedByteSlice(32, 114), + ReceiptsRoot: FillEncodedByteSlice(32, 115), + LogsBloom: FillEncodedByteSlice(256, 116), + PrevRandao: FillEncodedByteSlice(32, 117), + BlockNumber: "118", + GasLimit: "119", + GasUsed: "120", + Timestamp: "121", + ExtraData: FillEncodedByteSlice(32, 122), + BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(FillByteSlice(32, 123)).String(), + BlockHash: FillEncodedByteSlice(32, 124), + TransactionsRoot: FillEncodedByteSlice(32, 125), + WithdrawalsRoot: FillEncodedByteSlice(32, 126), + BlobGasUsed: "127", + ExcessBlobGas: "128", + }, + BLSToExecutionChanges: []*structs.SignedBLSToExecutionChange{ + { + Message: &structs.BLSToExecutionChange{ + ValidatorIndex: "129", + FromBLSPubkey: FillEncodedByteSlice(48, 130), + ToExecutionAddress: FillEncodedByteSlice(20, 131), + }, + Signature: FillEncodedByteSlice(96, 132), + }, + { + Message: &structs.BLSToExecutionChange{ + ValidatorIndex: "133", + FromBLSPubkey: FillEncodedByteSlice(48, 134), + ToExecutionAddress: FillEncodedByteSlice(20, 135), + }, + Signature: FillEncodedByteSlice(96, 136), + }, + }, + BlobKzgCommitments: []string{FillEncodedByteSlice(48, 137), FillEncodedByteSlice(48, 138)}, + ExecutionRequests: &structs.ExecutionRequests{ + Deposits: []*structs.DepositRequest{{ + Pubkey: FillEncodedByteSlice(48, 139), + WithdrawalCredentials: FillEncodedByteSlice(32, 140), + Amount: "141", + Signature: FillEncodedByteSlice(96, 142), + Index: "143", + }}, + Withdrawals: []*structs.WithdrawalRequest{ + { + SourceAddress: FillEncodedByteSlice(20, 144), + ValidatorPubkey: FillEncodedByteSlice(48, 145), + Amount: "146", + }, + }, + Consolidations: []*structs.ConsolidationRequest{ + { + SourceAddress: FillEncodedByteSlice(20, 147), + SourcePubkey: FillEncodedByteSlice(48, 148), + TargetPubkey: FillEncodedByteSlice(48, 149), + }, + }, + }, + }, + } +}