diff --git a/testing/endtoend/minimal_builder_e2e_test.go b/testing/endtoend/minimal_builder_e2e_test.go index a94e144088b7..038864ee4847 100644 --- a/testing/endtoend/minimal_builder_e2e_test.go +++ b/testing/endtoend/minimal_builder_e2e_test.go @@ -11,3 +11,8 @@ func TestEndToEnd_MinimalConfig_WithBuilder(t *testing.T) { r := e2eMinimal(t, version.Phase0, types.WithCheckpointSync(), types.WithBuilder()) r.run() } + +func TestEndToEnd_MinimalConfig_WithBuilder_ValidatorRESTApi(t *testing.T) { + r := e2eMinimal(t, version.Phase0, types.WithCheckpointSync(), types.WithBuilder(), types.WithValidatorRESTApi()) + r.run() +} diff --git a/validator/client/beacon-api/get_beacon_block.go b/validator/client/beacon-api/get_beacon_block.go index df5d31ac4957..e94abd24337a 100644 --- a/validator/client/beacon-api/get_beacon_block.go +++ b/validator/client/beacon-api/get_beacon_block.go @@ -5,111 +5,160 @@ import ( "context" "encoding/json" "fmt" + "net/http" neturl "net/url" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/validator" "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v4/runtime/version" ) type abstractProduceBlockResponseJson struct { - Version string `json:"version" enum:"true"` + Version string `json:"version"` Data json.RawMessage `json:"data"` } func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primitives.Slot, randaoReveal []byte, graffiti []byte) (*ethpb.GenericBeaconBlock, error) { queryParams := neturl.Values{} queryParams.Add("randao_reveal", hexutil.Encode(randaoReveal)) - if len(graffiti) > 0 { queryParams.Add("graffiti", hexutil.Encode(graffiti)) } - queryUrl := buildURL(fmt.Sprintf("/eth/v2/validator/blocks/%d", slot), queryParams) - - // Since we don't know yet what the json looks like, we unmarshal into an abstract structure that has only a version - // and a blob of data - produceBlockResponseJson := abstractProduceBlockResponseJson{} - if _, err := c.jsonRestHandler.GetRestJsonResponse(ctx, queryUrl, &produceBlockResponseJson); err != nil { + var ver string + var blinded bool + var decoder *json.Decoder + + // Try v3 endpoint first. If it's not supported, then we fall back to older endpoints. + // We try the blinded block endpoint first. If it fails, we assume that we got a full block and try the full block endpoint. + queryUrl := buildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams) + produceBlockV3ResponseJson := validator.ProduceBlockV3Response{} + errJson, err := c.jsonRestHandler.GetRestJsonResponse(ctx, queryUrl, &produceBlockV3ResponseJson) + if err == nil { + ver = produceBlockV3ResponseJson.Version + blinded = produceBlockV3ResponseJson.ExecutionPayloadBlinded + decoder = json.NewDecoder(bytes.NewReader(produceBlockV3ResponseJson.Data)) + } else if errJson == nil { return nil, errors.Wrap(err, "failed to query GET REST endpoint") + } else if errJson.Code == http.StatusNotFound { + log.Debug("Endpoint /eth/v3/validator/blocks is not supported, falling back to older endpoints for block proposal.") + produceBlindedBlockResponseJson := abstractProduceBlockResponseJson{} + queryUrl = buildURL(fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d", slot), queryParams) + errJson, err = c.jsonRestHandler.GetRestJsonResponse(ctx, queryUrl, &produceBlindedBlockResponseJson) + if err == nil { + ver = produceBlindedBlockResponseJson.Version + blinded = true + decoder = json.NewDecoder(bytes.NewReader(produceBlindedBlockResponseJson.Data)) + } else { + log.Debug("Endpoint /eth/v1/validator/blinded_blocks failed to produce a blinded block, trying /eth/v2/validator/blocks.") + produceBlockResponseJson := abstractProduceBlockResponseJson{} + queryUrl = buildURL(fmt.Sprintf("/eth/v2/validator/blocks/%d", slot), queryParams) + errJson, err = c.jsonRestHandler.GetRestJsonResponse(ctx, queryUrl, &produceBlockResponseJson) + if err != nil { + return nil, errors.Wrap(err, "failed to query GET REST endpoint") + } + ver = produceBlockResponseJson.Version + blinded = false + decoder = json.NewDecoder(bytes.NewReader(produceBlockResponseJson.Data)) + } + } else { + return nil, fmt.Errorf("failed to query GET REST endpoint: %s (status code %d)", errJson.Message, errJson.Code) } - // Once we know what the consensus version is, we can go ahead and unmarshal into the specific structs unique to each version - decoder := json.NewDecoder(bytes.NewReader(produceBlockResponseJson.Data)) - - response := ðpb.GenericBeaconBlock{} - - switch produceBlockResponseJson.Version { - case "phase0": - jsonPhase0Block := apimiddleware.BeaconBlockJson{} + var response *ethpb.GenericBeaconBlock + switch ver { + case version.String(version.Phase0): + jsonPhase0Block := shared.BeaconBlock{} if err := decoder.Decode(&jsonPhase0Block); err != nil { return nil, errors.Wrap(err, "failed to decode phase0 block response json") } - - phase0Block, err := c.beaconBlockConverter.ConvertRESTPhase0BlockToProto(&jsonPhase0Block) + genericBlock, err := jsonPhase0Block.ToGeneric() if err != nil { return nil, errors.Wrap(err, "failed to get phase0 block") } - response.Block = ðpb.GenericBeaconBlock_Phase0{ - Phase0: phase0Block, - } - - case "altair": - jsonAltairBlock := apimiddleware.BeaconBlockAltairJson{} + response = genericBlock + case version.String(version.Altair): + jsonAltairBlock := shared.BeaconBlockAltair{} if err := decoder.Decode(&jsonAltairBlock); err != nil { return nil, errors.Wrap(err, "failed to decode altair block response json") } - - altairBlock, err := c.beaconBlockConverter.ConvertRESTAltairBlockToProto(&jsonAltairBlock) + genericBlock, err := jsonAltairBlock.ToGeneric() if err != nil { return nil, errors.Wrap(err, "failed to get altair block") } - response.Block = ðpb.GenericBeaconBlock_Altair{ - Altair: altairBlock, - } - - case "bellatrix": - jsonBellatrixBlock := apimiddleware.BeaconBlockBellatrixJson{} - if err := decoder.Decode(&jsonBellatrixBlock); err != nil { - return nil, errors.Wrap(err, "failed to decode bellatrix block response json") - } - - bellatrixBlock, err := c.beaconBlockConverter.ConvertRESTBellatrixBlockToProto(&jsonBellatrixBlock) - if err != nil { - return nil, errors.Wrap(err, "failed to get bellatrix block") - } - response.Block = ðpb.GenericBeaconBlock_Bellatrix{ - Bellatrix: bellatrixBlock, - } - - case "capella": - jsonCapellaBlock := apimiddleware.BeaconBlockCapellaJson{} - if err := decoder.Decode(&jsonCapellaBlock); err != nil { - return nil, errors.Wrap(err, "failed to decode capella block response json") - } - - capellaBlock, err := c.beaconBlockConverter.ConvertRESTCapellaBlockToProto(&jsonCapellaBlock) - if err != nil { - return nil, errors.Wrap(err, "failed to get capella block") - } - response.Block = ðpb.GenericBeaconBlock_Capella{ - Capella: capellaBlock, + response = genericBlock + case version.String(version.Bellatrix): + if blinded { + jsonBellatrixBlock := shared.BlindedBeaconBlockBellatrix{} + if err := decoder.Decode(&jsonBellatrixBlock); err != nil { + return nil, errors.Wrap(err, "failed to decode blinded bellatrix block response json") + } + genericBlock, err := jsonBellatrixBlock.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get blinded bellatrix block") + } + response = genericBlock + } else { + jsonBellatrixBlock := shared.BeaconBlockBellatrix{} + if err := decoder.Decode(&jsonBellatrixBlock); err != nil { + return nil, errors.Wrap(err, "failed to decode bellatrix block response json") + } + genericBlock, err := jsonBellatrixBlock.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get bellatrix block") + } + response = genericBlock } - case "deneb": - jsonDenebBlockContents := shared.BeaconBlockContentsDeneb{} - if err := decoder.Decode(&jsonDenebBlockContents); err != nil { - return nil, errors.Wrap(err, "failed to decode deneb block response json") + case version.String(version.Capella): + if blinded { + jsonCapellaBlock := shared.BlindedBeaconBlockCapella{} + if err := decoder.Decode(&jsonCapellaBlock); err != nil { + return nil, errors.Wrap(err, "failed to decode blinded capella block response json") + } + genericBlock, err := jsonCapellaBlock.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get blinded capella block") + } + response = genericBlock + } else { + jsonCapellaBlock := shared.BeaconBlockCapella{} + if err := decoder.Decode(&jsonCapellaBlock); err != nil { + return nil, errors.Wrap(err, "failed to decode capella block response json") + } + genericBlock, err := jsonCapellaBlock.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get capella block") + } + response = genericBlock } - genericBlock, err := jsonDenebBlockContents.ToGeneric() - if err != nil { - return nil, errors.Wrap(err, "could not convert deneb block contents to generic block") + case version.String(version.Deneb): + if blinded { + jsonDenebBlockContents := shared.BlindedBeaconBlockContentsDeneb{} + if err := decoder.Decode(&jsonDenebBlockContents); err != nil { + return nil, errors.Wrap(err, "failed to decode blinded deneb block response json") + } + genericBlock, err := jsonDenebBlockContents.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get blinded deneb block") + } + response = genericBlock + } else { + jsonDenebBlockContents := shared.BeaconBlockContentsDeneb{} + if err := decoder.Decode(&jsonDenebBlockContents); err != nil { + return nil, errors.Wrap(err, "failed to decode deneb block response json") + } + genericBlock, err := jsonDenebBlockContents.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get deneb block") + } + response = genericBlock } - response = genericBlock default: - return nil, errors.Errorf("unsupported consensus version `%s`", produceBlockResponseJson.Version) + return nil, errors.Errorf("unsupported consensus version `%s`", ver) } return response, nil } diff --git a/validator/client/beacon-api/get_beacon_block_test.go b/validator/client/beacon-api/get_beacon_block_test.go index 529bba9173fa..f05db18f83ae 100644 --- a/validator/client/beacon-api/get_beacon_block_test.go +++ b/validator/client/beacon-api/get_beacon_block_test.go @@ -5,13 +5,13 @@ import ( "encoding/json" "errors" "fmt" + http2 "net/http" "testing" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/golang/mock/gomock" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared" - rpctesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared/testing" + "github.com/prysmaticlabs/prysm/v4/api/gateway/apimiddleware" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/validator" "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v4/testing/assert" @@ -43,20 +43,12 @@ func TestGetBeaconBlock_RequestFailed(t *testing.T) { } func TestGetBeaconBlock_Error(t *testing.T) { - phase0BeaconBlockBytes, err := json.Marshal(apimiddleware.BeaconBlockJson{}) - require.NoError(t, err) - altairBeaconBlockBytes, err := json.Marshal(apimiddleware.BeaconBlockAltairJson{}) - require.NoError(t, err) - bellatrixBeaconBlockBytes, err := json.Marshal(apimiddleware.BeaconBlockBellatrixJson{}) - require.NoError(t, err) - capellaBeaconBlockBytes, err := json.Marshal(apimiddleware.BeaconBlockCapellaJson{}) - require.NoError(t, err) - testCases := []struct { name string beaconBlock interface{} expectedErrorMessage string consensusVersion string + blinded bool data json.RawMessage }{ { @@ -65,49 +57,59 @@ func TestGetBeaconBlock_Error(t *testing.T) { consensusVersion: "phase0", data: []byte{}, }, - { - name: "phase0 block conversion failed", - expectedErrorMessage: "failed to get phase0 block", - consensusVersion: "phase0", - data: phase0BeaconBlockBytes, - }, { name: "altair block decoding failed", expectedErrorMessage: "failed to decode altair block response json", consensusVersion: "altair", data: []byte{}, }, - { - name: "altair block conversion failed", - expectedErrorMessage: "failed to get altair block", - consensusVersion: "altair", - data: altairBeaconBlockBytes, - }, { name: "bellatrix block decoding failed", expectedErrorMessage: "failed to decode bellatrix block response json", beaconBlock: "foo", consensusVersion: "bellatrix", + blinded: false, data: []byte{}, }, { - name: "bellatrix block conversion failed", - expectedErrorMessage: "failed to get bellatrix block", + name: "blinded bellatrix block decoding failed", + expectedErrorMessage: "failed to decode bellatrix block response json", + beaconBlock: "foo", consensusVersion: "bellatrix", - data: bellatrixBeaconBlockBytes, + blinded: true, + data: []byte{}, }, { name: "capella block decoding failed", expectedErrorMessage: "failed to decode capella block response json", beaconBlock: "foo", consensusVersion: "capella", + blinded: false, data: []byte{}, }, { - name: "capella block conversion failed", - expectedErrorMessage: "failed to get capella block", + name: "blinded capella block decoding failed", + expectedErrorMessage: "failed to decode capella block response json", + beaconBlock: "foo", consensusVersion: "capella", - data: capellaBeaconBlockBytes, + blinded: true, + data: []byte{}, + }, + { + name: "deneb block decoding failed", + expectedErrorMessage: "failed to decode deneb block response json", + beaconBlock: "foo", + consensusVersion: "deneb", + blinded: false, + data: []byte{}, + }, + { + name: "blinded deneb block decoding failed", + expectedErrorMessage: "failed to decode deneb block response json", + beaconBlock: "foo", + consensusVersion: "deneb", + blinded: true, + data: []byte{}, }, { name: "unsupported consensus version", @@ -127,10 +129,10 @@ func TestGetBeaconBlock_Error(t *testing.T) { jsonRestHandler.EXPECT().GetRestJsonResponse( ctx, gomock.Any(), - &abstractProduceBlockResponseJson{}, + &validator.ProduceBlockV3Response{}, ).SetArg( 2, - abstractProduceBlockResponseJson{ + validator.ProduceBlockV3Response{ Version: testCase.consensusVersion, Data: testCase.data, }, @@ -139,36 +141,7 @@ func TestGetBeaconBlock_Error(t *testing.T) { nil, ).Times(1) - beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl) - beaconBlockConverter.EXPECT().ConvertRESTPhase0BlockToProto( - gomock.Any(), - ).Return( - nil, - errors.New(testCase.expectedErrorMessage), - ).AnyTimes() - - beaconBlockConverter.EXPECT().ConvertRESTAltairBlockToProto( - gomock.Any(), - ).Return( - nil, - errors.New(testCase.expectedErrorMessage), - ).AnyTimes() - - beaconBlockConverter.EXPECT().ConvertRESTBellatrixBlockToProto( - gomock.Any(), - ).Return( - nil, - errors.New(testCase.expectedErrorMessage), - ).AnyTimes() - - beaconBlockConverter.EXPECT().ConvertRESTCapellaBlockToProto( - gomock.Any(), - ).Return( - nil, - errors.New(testCase.expectedErrorMessage), - ).AnyTimes() - - validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter} + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} _, err := validatorClient.getBeaconBlock(ctx, 1, []byte{1}, []byte{2}) assert.ErrorContains(t, testCase.expectedErrorMessage, err) }) @@ -179,9 +152,9 @@ func TestGetBeaconBlock_Phase0Valid(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - phase0ProtoBeaconBlock := test_helpers.GenerateProtoPhase0BeaconBlock() - phase0BeaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock() - phase0BeaconBlockBytes, err := json.Marshal(phase0BeaconBlock) + proto := test_helpers.GenerateProtoPhase0BeaconBlock() + block := test_helpers.GenerateJsonPhase0BeaconBlock() + bytes, err := json.Marshal(block) require.NoError(t, err) const slot = primitives.Slot(1) @@ -192,34 +165,26 @@ func TestGetBeaconBlock_Phase0Valid(t *testing.T) { jsonRestHandler := mock.NewMockjsonRestHandler(ctrl) jsonRestHandler.EXPECT().GetRestJsonResponse( ctx, - fmt.Sprintf("/eth/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), - &abstractProduceBlockResponseJson{}, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, ).SetArg( 2, - abstractProduceBlockResponseJson{ + validator.ProduceBlockV3Response{ Version: "phase0", - Data: phase0BeaconBlockBytes, + Data: bytes, }, ).Return( nil, nil, ).Times(1) - beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl) - beaconBlockConverter.EXPECT().ConvertRESTPhase0BlockToProto( - phase0BeaconBlock, - ).Return( - phase0ProtoBeaconBlock, - nil, - ).Times(1) - - validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter} + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) require.NoError(t, err) expectedBeaconBlock := ðpb.GenericBeaconBlock{ Block: ðpb.GenericBeaconBlock_Phase0{ - Phase0: phase0ProtoBeaconBlock, + Phase0: proto, }, } @@ -230,9 +195,9 @@ func TestGetBeaconBlock_AltairValid(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - altairProtoBeaconBlock := test_helpers.GenerateProtoAltairBeaconBlock() - altairBeaconBlock := test_helpers.GenerateJsonAltairBeaconBlock() - altairBeaconBlockBytes, err := json.Marshal(altairBeaconBlock) + proto := test_helpers.GenerateProtoAltairBeaconBlock() + block := test_helpers.GenerateJsonAltairBeaconBlock() + bytes, err := json.Marshal(block) require.NoError(t, err) const slot = primitives.Slot(1) @@ -244,34 +209,26 @@ func TestGetBeaconBlock_AltairValid(t *testing.T) { jsonRestHandler := mock.NewMockjsonRestHandler(ctrl) jsonRestHandler.EXPECT().GetRestJsonResponse( ctx, - fmt.Sprintf("/eth/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), - &abstractProduceBlockResponseJson{}, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, ).SetArg( 2, - abstractProduceBlockResponseJson{ + validator.ProduceBlockV3Response{ Version: "altair", - Data: altairBeaconBlockBytes, + Data: bytes, }, ).Return( nil, nil, ).Times(1) - beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl) - beaconBlockConverter.EXPECT().ConvertRESTAltairBlockToProto( - altairBeaconBlock, - ).Return( - altairProtoBeaconBlock, - nil, - ).Times(1) - - validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter} + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) require.NoError(t, err) expectedBeaconBlock := ðpb.GenericBeaconBlock{ Block: ðpb.GenericBeaconBlock_Altair{ - Altair: altairProtoBeaconBlock, + Altair: proto, }, } @@ -282,9 +239,9 @@ func TestGetBeaconBlock_BellatrixValid(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - bellatrixProtoBeaconBlock := test_helpers.GenerateProtoBellatrixBeaconBlock() - bellatrixBeaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock() - bellatrixBeaconBlockBytes, err := json.Marshal(bellatrixBeaconBlock) + proto := test_helpers.GenerateProtoBellatrixBeaconBlock() + block := test_helpers.GenerateJsonBellatrixBeaconBlock() + bytes, err := json.Marshal(block) require.NoError(t, err) const slot = primitives.Slot(1) @@ -296,35 +253,75 @@ func TestGetBeaconBlock_BellatrixValid(t *testing.T) { jsonRestHandler := mock.NewMockjsonRestHandler(ctrl) jsonRestHandler.EXPECT().GetRestJsonResponse( ctx, - fmt.Sprintf("/eth/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), - &abstractProduceBlockResponseJson{}, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, ).SetArg( 2, - abstractProduceBlockResponseJson{ - Version: "bellatrix", - Data: bellatrixBeaconBlockBytes, + validator.ProduceBlockV3Response{ + Version: "bellatrix", + ExecutionPayloadBlinded: false, + Data: bytes, }, ).Return( nil, nil, ).Times(1) - beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl) - beaconBlockConverter.EXPECT().ConvertRESTBellatrixBlockToProto( - bellatrixBeaconBlock, + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) + require.NoError(t, err) + + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_Bellatrix{ + Bellatrix: proto, + }, + IsBlinded: false, + } + + assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) +} + +func TestGetBeaconBlock_BlindedBellatrixValid(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + proto := test_helpers.GenerateProtoBlindedBellatrixBeaconBlock() + block := test_helpers.GenerateJsonBlindedBellatrixBeaconBlock() + 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().GetRestJsonResponse( + ctx, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, + ).SetArg( + 2, + validator.ProduceBlockV3Response{ + Version: "bellatrix", + ExecutionPayloadBlinded: true, + Data: bytes, + }, ).Return( - bellatrixProtoBeaconBlock, + nil, nil, ).Times(1) - validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter} + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) require.NoError(t, err) expectedBeaconBlock := ðpb.GenericBeaconBlock{ - Block: ðpb.GenericBeaconBlock_Bellatrix{ - Bellatrix: bellatrixProtoBeaconBlock, + Block: ðpb.GenericBeaconBlock_BlindedBellatrix{ + BlindedBellatrix: proto, }, + IsBlinded: true, } assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) @@ -334,9 +331,9 @@ func TestGetBeaconBlock_CapellaValid(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - capellaProtoBeaconBlock := test_helpers.GenerateProtoCapellaBeaconBlock() - capellaBeaconBlock := test_helpers.GenerateJsonCapellaBeaconBlock() - capellaBeaconBlockBytes, err := json.Marshal(capellaBeaconBlock) + proto := test_helpers.GenerateProtoCapellaBeaconBlock() + block := test_helpers.GenerateJsonCapellaBeaconBlock() + bytes, err := json.Marshal(block) require.NoError(t, err) const slot = primitives.Slot(1) @@ -348,35 +345,75 @@ func TestGetBeaconBlock_CapellaValid(t *testing.T) { jsonRestHandler := mock.NewMockjsonRestHandler(ctrl) jsonRestHandler.EXPECT().GetRestJsonResponse( ctx, - fmt.Sprintf("/eth/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), - &abstractProduceBlockResponseJson{}, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, ).SetArg( 2, - abstractProduceBlockResponseJson{ - Version: "capella", - Data: capellaBeaconBlockBytes, + validator.ProduceBlockV3Response{ + Version: "capella", + ExecutionPayloadBlinded: false, + Data: bytes, }, ).Return( nil, nil, ).Times(1) - beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl) - beaconBlockConverter.EXPECT().ConvertRESTCapellaBlockToProto( - capellaBeaconBlock, + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) + require.NoError(t, err) + + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_Capella{ + Capella: proto, + }, + IsBlinded: false, + } + + assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) +} + +func TestGetBeaconBlock_BlindedCapellaValid(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + proto := test_helpers.GenerateProtoBlindedCapellaBeaconBlock() + block := test_helpers.GenerateJsonBlindedCapellaBeaconBlock() + 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().GetRestJsonResponse( + ctx, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, + ).SetArg( + 2, + validator.ProduceBlockV3Response{ + Version: "capella", + ExecutionPayloadBlinded: true, + Data: bytes, + }, ).Return( - capellaProtoBeaconBlock, + nil, nil, ).Times(1) - validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter} + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) require.NoError(t, err) expectedBeaconBlock := ðpb.GenericBeaconBlock{ - Block: ðpb.GenericBeaconBlock_Capella{ - Capella: capellaProtoBeaconBlock, + Block: ðpb.GenericBeaconBlock_BlindedCapella{ + BlindedCapella: proto, }, + IsBlinded: true, } assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) @@ -386,20 +423,179 @@ func TestGetBeaconBlock_DenebValid(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - var blockContents shared.SignedBeaconBlockContentsDeneb - err := json.Unmarshal([]byte(rpctesting.DenebBlockContents), &blockContents) + proto := test_helpers.GenerateProtoDenebBeaconBlock() + block := test_helpers.GenerateJsonDenebBeaconBlock() + bytes, err := json.Marshal(block) require.NoError(t, err) - denebBeaconBlockBytes, err := json.Marshal(blockContents.ToUnsigned()) + const slot = primitives.Slot(1) + randaoReveal := []byte{2} + graffiti := []byte{3} + + ctx := context.Background() + + jsonRestHandler := mock.NewMockjsonRestHandler(ctrl) + jsonRestHandler.EXPECT().GetRestJsonResponse( + ctx, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, + ).SetArg( + 2, + validator.ProduceBlockV3Response{ + Version: "deneb", + ExecutionPayloadBlinded: false, + Data: bytes, + }, + ).Return( + nil, + nil, + ).Times(1) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) + require.NoError(t, err) + + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_Deneb{ + Deneb: proto, + }, + IsBlinded: false, + } + + assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) +} + +func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + proto := test_helpers.GenerateProtoBlindedDenebBeaconBlock() + block := test_helpers.GenerateJsonBlindedDenebBeaconBlock() + 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().GetRestJsonResponse( + ctx, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, + ).SetArg( + 2, + validator.ProduceBlockV3Response{ + Version: "deneb", + ExecutionPayloadBlinded: true, + Data: bytes, + }, + ).Return( + nil, + nil, + ).Times(1) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) + require.NoError(t, err) + + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_BlindedDeneb{ + BlindedDeneb: proto, + }, + IsBlinded: true, + } + + assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) +} + +func TestGetBeaconBlock_FallbackToBlindedBlock(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + proto := test_helpers.GenerateProtoBlindedDenebBeaconBlock() + block := test_helpers.GenerateJsonBlindedDenebBeaconBlock() + blockBytes, err := json.Marshal(block) + require.NoError(t, err) + const slot = primitives.Slot(1) - randaoReveal, err := hexutil.Decode("0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505") + randaoReveal := []byte{2} + graffiti := []byte{3} + + ctx := context.Background() + + jsonRestHandler := mock.NewMockjsonRestHandler(ctrl) + jsonRestHandler.EXPECT().GetRestJsonResponse( + ctx, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, + ).Return( + &apimiddleware.DefaultErrorJson{Code: http2.StatusNotFound}, + errors.New("foo"), + ).Times(1) + jsonRestHandler.EXPECT().GetRestJsonResponse( + ctx, + fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &abstractProduceBlockResponseJson{}, + ).SetArg( + 2, + abstractProduceBlockResponseJson{ + Version: "deneb", + Data: blockBytes, + }, + ).Return( + nil, + nil, + ).Times(1) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) require.NoError(t, err) - graffiti, err := hexutil.Decode("0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2") + + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_BlindedDeneb{ + BlindedDeneb: proto, + }, + IsBlinded: true, + } + + assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) +} + +func TestGetBeaconBlock_FallbackToFullBlock(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + proto := test_helpers.GenerateProtoDenebBeaconBlock() + block := test_helpers.GenerateJsonDenebBeaconBlock() + blockBytes, 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().GetRestJsonResponse( + ctx, + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &validator.ProduceBlockV3Response{}, + ).Return( + &apimiddleware.DefaultErrorJson{Code: http2.StatusNotFound}, + errors.New("foo"), + ).Times(1) + jsonRestHandler.EXPECT().GetRestJsonResponse( + ctx, + fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &abstractProduceBlockResponseJson{}, + ).Return( + &apimiddleware.DefaultErrorJson{Code: http2.StatusInternalServerError}, + errors.New("foo"), + ).Times(1) jsonRestHandler.EXPECT().GetRestJsonResponse( ctx, fmt.Sprintf("/eth/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), @@ -408,7 +604,7 @@ func TestGetBeaconBlock_DenebValid(t *testing.T) { 2, abstractProduceBlockResponseJson{ Version: "deneb", - Data: denebBeaconBlockBytes, + Data: blockBytes, }, ).Return( nil, @@ -416,12 +612,15 @@ func TestGetBeaconBlock_DenebValid(t *testing.T) { ).Times(1) validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} - beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti) require.NoError(t, err) - expectedBeaconBlock, err := blockContents.ToUnsigned().ToGeneric() - require.NoError(t, err) + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_Deneb{ + Deneb: proto, + }, + IsBlinded: false, + } assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) } diff --git a/validator/client/beacon-api/json_rest_handler.go b/validator/client/beacon-api/json_rest_handler.go index ae885973ce84..88597b4e7e0a 100644 --- a/validator/client/beacon-api/json_rest_handler.go +++ b/validator/client/beacon-api/json_rest_handler.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "io" "net/http" "github.com/pkg/errors" @@ -88,14 +89,25 @@ func decodeJsonResp(resp *http.Response, responseJson interface{}) (*apimiddlewa if resp.StatusCode != http.StatusOK { errorJson := &apimiddleware.DefaultErrorJson{} if err := decoder.Decode(errorJson); err != nil { - return nil, errors.Wrapf(err, "failed to decode error json for %s", resp.Request.URL) + if resp.StatusCode == http.StatusNotFound { + errorJson = &apimiddleware.DefaultErrorJson{Code: http.StatusNotFound, Message: "Resource not found"} + } else { + remaining, readErr := io.ReadAll(decoder.Buffered()) + if readErr == nil { + log.Debugf("Undecoded value: %s", string(remaining)) + } + return nil, errors.Wrapf(err, "failed to decode error json for %s", resp.Request.URL) + } } - return errorJson, errors.Errorf("error %d: %s", errorJson.Code, errorJson.Message) } if responseJson != nil { if err := decoder.Decode(responseJson); err != nil { + remaining, readErr := io.ReadAll(decoder.Buffered()) + if readErr == nil { + log.Debugf("Undecoded value: %s", string(remaining)) + } return nil, errors.Wrapf(err, "failed to decode response json for %s", resp.Request.URL) } } diff --git a/validator/client/beacon-api/json_rest_handler_test.go b/validator/client/beacon-api/json_rest_handler_test.go index 68548b322b36..109e91ec3916 100644 --- a/validator/client/beacon-api/json_rest_handler_test.go +++ b/validator/client/beacon-api/json_rest_handler_test.go @@ -138,6 +138,17 @@ func TestGetRestJsonResponse_Error(t *testing.T) { timeout: 1, responseJson: &beacon.GetGenesisResponse{}, }, + { + name: "resource not found", + funcHandler: resourceNotFoundHandler, + expectedErrorMessage: "error 404: Resource not found", + expectedErrorJson: &apimiddleware.DefaultErrorJson{ + Code: 404, + Message: "Resource not found", + }, + timeout: time.Second * 5, + responseJson: &beacon.GetGenesisResponse{}, + }, } for _, testCase := range testCases { @@ -420,8 +431,12 @@ func httpErrorJsonHandler(statusCode int, errorMessage string) func(w http.Respo } } -func invalidJsonErrHandler(w http.ResponseWriter, _ *http.Request) { +func resourceNotFoundHandler(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) +} + +func invalidJsonErrHandler(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusInternalServerError) _, err := w.Write([]byte("foo")) if err != nil { panic(err) diff --git a/validator/client/beacon-api/test-helpers/BUILD.bazel b/validator/client/beacon-api/test-helpers/BUILD.bazel index 37e09500c914..dee0ff5921ab 100644 --- a/validator/client/beacon-api/test-helpers/BUILD.bazel +++ b/validator/client/beacon-api/test-helpers/BUILD.bazel @@ -7,6 +7,7 @@ go_library( "altair_beacon_block_test_helpers.go", "bellatrix_beacon_block_test_helpers.go", "capella_beacon_block_test_helpers.go", + "deneb_beacon_block_test_helpers.go", "phase0_beacon_block_test_helpers.go", "test_helpers.go", ], @@ -14,6 +15,7 @@ go_library( visibility = ["//validator:__subpackages__"], deps = [ "//beacon-chain/rpc/apimiddleware:go_default_library", + "//beacon-chain/rpc/eth/shared:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/validator/client/beacon-api/test-helpers/bellatrix_beacon_block_test_helpers.go b/validator/client/beacon-api/test-helpers/bellatrix_beacon_block_test_helpers.go index 20fe84414d03..65653cc2cc0a 100644 --- a/validator/client/beacon-api/test-helpers/bellatrix_beacon_block_test_helpers.go +++ b/validator/client/beacon-api/test-helpers/bellatrix_beacon_block_test_helpers.go @@ -2,6 +2,7 @@ package test_helpers import ( "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v4/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" @@ -240,6 +241,236 @@ func GenerateProtoBellatrixBeaconBlock() *ethpb.BeaconBlockBellatrix { } } +func GenerateProtoBlindedBellatrixBeaconBlock() *ethpb.BlindedBeaconBlockBellatrix { + return ðpb.BlindedBeaconBlockBellatrix{ + Slot: 1, + ProposerIndex: 2, + ParentRoot: FillByteSlice(32, 3), + StateRoot: FillByteSlice(32, 4), + Body: ðpb.BlindedBeaconBlockBodyBellatrix{ + 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.AttesterSlashing{ + { + Attestation_1: ðpb.IndexedAttestation{ + 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.IndexedAttestation{ + 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.IndexedAttestation{ + 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.IndexedAttestation{ + 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.Attestation{ + { + 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), + }, + { + 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), + }, + }, + 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.ExecutionPayloadHeader{ + 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), + }, + }, + } +} + func GenerateJsonBellatrixBeaconBlock() *apimiddleware.BeaconBlockBellatrixJson { return &apimiddleware.BeaconBlockBellatrixJson{ Slot: "1", @@ -472,3 +703,233 @@ func GenerateJsonBellatrixBeaconBlock() *apimiddleware.BeaconBlockBellatrixJson }, } } + +func GenerateJsonBlindedBellatrixBeaconBlock() *shared.BlindedBeaconBlockBellatrix { + return &shared.BlindedBeaconBlockBellatrix{ + Slot: "1", + ProposerIndex: "2", + ParentRoot: FillEncodedByteSlice(32, 3), + StateRoot: FillEncodedByteSlice(32, 4), + Body: &shared.BlindedBeaconBlockBodyBellatrix{ + RandaoReveal: FillEncodedByteSlice(96, 5), + Eth1Data: &shared.Eth1Data{ + DepositRoot: FillEncodedByteSlice(32, 6), + DepositCount: "7", + BlockHash: FillEncodedByteSlice(32, 8), + }, + Graffiti: FillEncodedByteSlice(32, 9), + ProposerSlashings: []*shared.ProposerSlashing{ + { + SignedHeader1: &shared.SignedBeaconBlockHeader{ + Message: &shared.BeaconBlockHeader{ + Slot: "10", + ProposerIndex: "11", + ParentRoot: FillEncodedByteSlice(32, 12), + StateRoot: FillEncodedByteSlice(32, 13), + BodyRoot: FillEncodedByteSlice(32, 14), + }, + Signature: FillEncodedByteSlice(96, 15), + }, + SignedHeader2: &shared.SignedBeaconBlockHeader{ + Message: &shared.BeaconBlockHeader{ + Slot: "16", + ProposerIndex: "17", + ParentRoot: FillEncodedByteSlice(32, 18), + StateRoot: FillEncodedByteSlice(32, 19), + BodyRoot: FillEncodedByteSlice(32, 20), + }, + Signature: FillEncodedByteSlice(96, 21), + }, + }, + { + SignedHeader1: &shared.SignedBeaconBlockHeader{ + Message: &shared.BeaconBlockHeader{ + Slot: "22", + ProposerIndex: "23", + ParentRoot: FillEncodedByteSlice(32, 24), + StateRoot: FillEncodedByteSlice(32, 25), + BodyRoot: FillEncodedByteSlice(32, 26), + }, + Signature: FillEncodedByteSlice(96, 27), + }, + SignedHeader2: &shared.SignedBeaconBlockHeader{ + Message: &shared.BeaconBlockHeader{ + Slot: "28", + ProposerIndex: "29", + ParentRoot: FillEncodedByteSlice(32, 30), + StateRoot: FillEncodedByteSlice(32, 31), + BodyRoot: FillEncodedByteSlice(32, 32), + }, + Signature: FillEncodedByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*shared.AttesterSlashing{ + { + Attestation1: &shared.IndexedAttestation{ + AttestingIndices: []string{"34", "35"}, + Data: &shared.AttestationData{ + Slot: "36", + CommitteeIndex: "37", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "39", + Root: FillEncodedByteSlice(32, 40), + }, + Target: &shared.Checkpoint{ + Epoch: "41", + Root: FillEncodedByteSlice(32, 42), + }, + }, + Signature: FillEncodedByteSlice(96, 43), + }, + Attestation2: &shared.IndexedAttestation{ + AttestingIndices: []string{"44", "45"}, + Data: &shared.AttestationData{ + Slot: "46", + CommitteeIndex: "47", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "49", + Root: FillEncodedByteSlice(32, 50), + }, + Target: &shared.Checkpoint{ + Epoch: "51", + Root: FillEncodedByteSlice(32, 52), + }, + }, + Signature: FillEncodedByteSlice(96, 53), + }, + }, + { + Attestation1: &shared.IndexedAttestation{ + AttestingIndices: []string{"54", "55"}, + Data: &shared.AttestationData{ + Slot: "56", + CommitteeIndex: "57", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "59", + Root: FillEncodedByteSlice(32, 60), + }, + Target: &shared.Checkpoint{ + Epoch: "61", + Root: FillEncodedByteSlice(32, 62), + }, + }, + Signature: FillEncodedByteSlice(96, 63), + }, + Attestation2: &shared.IndexedAttestation{ + AttestingIndices: []string{"64", "65"}, + Data: &shared.AttestationData{ + Slot: "66", + CommitteeIndex: "67", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "69", + Root: FillEncodedByteSlice(32, 70), + }, + Target: &shared.Checkpoint{ + Epoch: "71", + Root: FillEncodedByteSlice(32, 72), + }, + }, + Signature: FillEncodedByteSlice(96, 73), + }, + }, + }, + Attestations: []*shared.Attestation{ + { + AggregationBits: FillEncodedByteSlice(4, 74), + Data: &shared.AttestationData{ + Slot: "75", + CommitteeIndex: "76", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "78", + Root: FillEncodedByteSlice(32, 79), + }, + Target: &shared.Checkpoint{ + Epoch: "80", + Root: FillEncodedByteSlice(32, 81), + }, + }, + Signature: FillEncodedByteSlice(96, 82), + }, + { + AggregationBits: FillEncodedByteSlice(4, 83), + Data: &shared.AttestationData{ + Slot: "84", + CommitteeIndex: "85", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "87", + Root: FillEncodedByteSlice(32, 88), + }, + Target: &shared.Checkpoint{ + Epoch: "89", + Root: FillEncodedByteSlice(32, 90), + }, + }, + Signature: FillEncodedByteSlice(96, 91), + }, + }, + Deposits: []*shared.Deposit{ + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 92)), + Data: &shared.DepositData{ + Pubkey: FillEncodedByteSlice(48, 94), + WithdrawalCredentials: FillEncodedByteSlice(32, 95), + Amount: "96", + Signature: FillEncodedByteSlice(96, 97), + }, + }, + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 98)), + Data: &shared.DepositData{ + Pubkey: FillEncodedByteSlice(48, 100), + WithdrawalCredentials: FillEncodedByteSlice(32, 101), + Amount: "102", + Signature: FillEncodedByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*shared.SignedVoluntaryExit{ + { + Message: &shared.VoluntaryExit{ + Epoch: "104", + ValidatorIndex: "105", + }, + Signature: FillEncodedByteSlice(96, 106), + }, + { + Message: &shared.VoluntaryExit{ + Epoch: "107", + ValidatorIndex: "108", + }, + Signature: FillEncodedByteSlice(96, 109), + }, + }, + SyncAggregate: &shared.SyncAggregate{ + SyncCommitteeBits: FillEncodedByteSlice(64, 110), + SyncCommitteeSignature: FillEncodedByteSlice(96, 111), + }, + ExecutionPayloadHeader: &shared.ExecutionPayloadHeader{ + 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), + }, + }, + } +} diff --git a/validator/client/beacon-api/test-helpers/capella_beacon_block_test_helpers.go b/validator/client/beacon-api/test-helpers/capella_beacon_block_test_helpers.go index d8f9002e9bc4..972bfac3a32c 100644 --- a/validator/client/beacon-api/test-helpers/capella_beacon_block_test_helpers.go +++ b/validator/client/beacon-api/test-helpers/capella_beacon_block_test_helpers.go @@ -2,6 +2,7 @@ package test_helpers import ( "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v4/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" @@ -272,6 +273,255 @@ func GenerateProtoCapellaBeaconBlock() *ethpb.BeaconBlockCapella { } } +func GenerateProtoBlindedCapellaBeaconBlock() *ethpb.BlindedBeaconBlockCapella { + return ðpb.BlindedBeaconBlockCapella{ + Slot: 1, + ProposerIndex: 2, + ParentRoot: FillByteSlice(32, 3), + StateRoot: FillByteSlice(32, 4), + Body: ðpb.BlindedBeaconBlockBodyCapella{ + 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.AttesterSlashing{ + { + Attestation_1: ðpb.IndexedAttestation{ + 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.IndexedAttestation{ + 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.IndexedAttestation{ + 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.IndexedAttestation{ + 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.Attestation{ + { + 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), + }, + { + 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), + }, + }, + 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.ExecutionPayloadHeaderCapella{ + 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), + }, + BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{ + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 135, + FromBlsPubkey: FillByteSlice(48, 136), + ToExecutionAddress: FillByteSlice(20, 137), + }, + Signature: FillByteSlice(96, 138), + }, + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 139, + FromBlsPubkey: FillByteSlice(48, 140), + ToExecutionAddress: FillByteSlice(20, 141), + }, + Signature: FillByteSlice(96, 142), + }, + }, + }, + } +} + func GenerateJsonCapellaBeaconBlock() *apimiddleware.BeaconBlockCapellaJson { return &apimiddleware.BeaconBlockCapellaJson{ Slot: "1", @@ -536,3 +786,252 @@ func GenerateJsonCapellaBeaconBlock() *apimiddleware.BeaconBlockCapellaJson { }, } } + +func GenerateJsonBlindedCapellaBeaconBlock() *shared.BlindedBeaconBlockCapella { + return &shared.BlindedBeaconBlockCapella{ + Slot: "1", + ProposerIndex: "2", + ParentRoot: FillEncodedByteSlice(32, 3), + StateRoot: FillEncodedByteSlice(32, 4), + Body: &shared.BlindedBeaconBlockBodyCapella{ + RandaoReveal: FillEncodedByteSlice(96, 5), + Eth1Data: &shared.Eth1Data{ + DepositRoot: FillEncodedByteSlice(32, 6), + DepositCount: "7", + BlockHash: FillEncodedByteSlice(32, 8), + }, + Graffiti: FillEncodedByteSlice(32, 9), + ProposerSlashings: []*shared.ProposerSlashing{ + { + SignedHeader1: &shared.SignedBeaconBlockHeader{ + Message: &shared.BeaconBlockHeader{ + Slot: "10", + ProposerIndex: "11", + ParentRoot: FillEncodedByteSlice(32, 12), + StateRoot: FillEncodedByteSlice(32, 13), + BodyRoot: FillEncodedByteSlice(32, 14), + }, + Signature: FillEncodedByteSlice(96, 15), + }, + SignedHeader2: &shared.SignedBeaconBlockHeader{ + Message: &shared.BeaconBlockHeader{ + Slot: "16", + ProposerIndex: "17", + ParentRoot: FillEncodedByteSlice(32, 18), + StateRoot: FillEncodedByteSlice(32, 19), + BodyRoot: FillEncodedByteSlice(32, 20), + }, + Signature: FillEncodedByteSlice(96, 21), + }, + }, + { + SignedHeader1: &shared.SignedBeaconBlockHeader{ + Message: &shared.BeaconBlockHeader{ + Slot: "22", + ProposerIndex: "23", + ParentRoot: FillEncodedByteSlice(32, 24), + StateRoot: FillEncodedByteSlice(32, 25), + BodyRoot: FillEncodedByteSlice(32, 26), + }, + Signature: FillEncodedByteSlice(96, 27), + }, + SignedHeader2: &shared.SignedBeaconBlockHeader{ + Message: &shared.BeaconBlockHeader{ + Slot: "28", + ProposerIndex: "29", + ParentRoot: FillEncodedByteSlice(32, 30), + StateRoot: FillEncodedByteSlice(32, 31), + BodyRoot: FillEncodedByteSlice(32, 32), + }, + Signature: FillEncodedByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*shared.AttesterSlashing{ + { + Attestation1: &shared.IndexedAttestation{ + AttestingIndices: []string{"34", "35"}, + Data: &shared.AttestationData{ + Slot: "36", + CommitteeIndex: "37", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "39", + Root: FillEncodedByteSlice(32, 40), + }, + Target: &shared.Checkpoint{ + Epoch: "41", + Root: FillEncodedByteSlice(32, 42), + }, + }, + Signature: FillEncodedByteSlice(96, 43), + }, + Attestation2: &shared.IndexedAttestation{ + AttestingIndices: []string{"44", "45"}, + Data: &shared.AttestationData{ + Slot: "46", + CommitteeIndex: "47", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "49", + Root: FillEncodedByteSlice(32, 50), + }, + Target: &shared.Checkpoint{ + Epoch: "51", + Root: FillEncodedByteSlice(32, 52), + }, + }, + Signature: FillEncodedByteSlice(96, 53), + }, + }, + { + Attestation1: &shared.IndexedAttestation{ + AttestingIndices: []string{"54", "55"}, + Data: &shared.AttestationData{ + Slot: "56", + CommitteeIndex: "57", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "59", + Root: FillEncodedByteSlice(32, 60), + }, + Target: &shared.Checkpoint{ + Epoch: "61", + Root: FillEncodedByteSlice(32, 62), + }, + }, + Signature: FillEncodedByteSlice(96, 63), + }, + Attestation2: &shared.IndexedAttestation{ + AttestingIndices: []string{"64", "65"}, + Data: &shared.AttestationData{ + Slot: "66", + CommitteeIndex: "67", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "69", + Root: FillEncodedByteSlice(32, 70), + }, + Target: &shared.Checkpoint{ + Epoch: "71", + Root: FillEncodedByteSlice(32, 72), + }, + }, + Signature: FillEncodedByteSlice(96, 73), + }, + }, + }, + Attestations: []*shared.Attestation{ + { + AggregationBits: FillEncodedByteSlice(4, 74), + Data: &shared.AttestationData{ + Slot: "75", + CommitteeIndex: "76", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "78", + Root: FillEncodedByteSlice(32, 79), + }, + Target: &shared.Checkpoint{ + Epoch: "80", + Root: FillEncodedByteSlice(32, 81), + }, + }, + Signature: FillEncodedByteSlice(96, 82), + }, + { + AggregationBits: FillEncodedByteSlice(4, 83), + Data: &shared.AttestationData{ + Slot: "84", + CommitteeIndex: "85", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &shared.Checkpoint{ + Epoch: "87", + Root: FillEncodedByteSlice(32, 88), + }, + Target: &shared.Checkpoint{ + Epoch: "89", + Root: FillEncodedByteSlice(32, 90), + }, + }, + Signature: FillEncodedByteSlice(96, 91), + }, + }, + Deposits: []*shared.Deposit{ + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 92)), + Data: &shared.DepositData{ + Pubkey: FillEncodedByteSlice(48, 94), + WithdrawalCredentials: FillEncodedByteSlice(32, 95), + Amount: "96", + Signature: FillEncodedByteSlice(96, 97), + }, + }, + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 98)), + Data: &shared.DepositData{ + Pubkey: FillEncodedByteSlice(48, 100), + WithdrawalCredentials: FillEncodedByteSlice(32, 101), + Amount: "102", + Signature: FillEncodedByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*shared.SignedVoluntaryExit{ + { + Message: &shared.VoluntaryExit{ + Epoch: "104", + ValidatorIndex: "105", + }, + Signature: FillEncodedByteSlice(96, 106), + }, + { + Message: &shared.VoluntaryExit{ + Epoch: "107", + ValidatorIndex: "108", + }, + Signature: FillEncodedByteSlice(96, 109), + }, + }, + SyncAggregate: &shared.SyncAggregate{ + SyncCommitteeBits: FillEncodedByteSlice(64, 110), + SyncCommitteeSignature: FillEncodedByteSlice(96, 111), + }, + ExecutionPayloadHeader: &shared.ExecutionPayloadHeaderCapella{ + 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), + }, + BlsToExecutionChanges: []*shared.SignedBlsToExecutionChange{ + { + Message: &shared.BlsToExecutionChange{ + ValidatorIndex: "135", + FromBlsPubkey: FillEncodedByteSlice(48, 136), + ToExecutionAddress: FillEncodedByteSlice(20, 137), + }, + Signature: FillEncodedByteSlice(96, 138), + }, + { + Message: &shared.BlsToExecutionChange{ + ValidatorIndex: "139", + FromBlsPubkey: FillEncodedByteSlice(48, 140), + ToExecutionAddress: FillEncodedByteSlice(20, 141), + }, + Signature: FillEncodedByteSlice(96, 142), + }, + }, + }, + } +} diff --git a/validator/client/beacon-api/test-helpers/deneb_beacon_block_test_helpers.go b/validator/client/beacon-api/test-helpers/deneb_beacon_block_test_helpers.go new file mode 100644 index 000000000000..959921005bb9 --- /dev/null +++ b/validator/client/beacon-api/test-helpers/deneb_beacon_block_test_helpers.go @@ -0,0 +1,1144 @@ +package test_helpers + +import ( + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware" + "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" + enginev1 "github.com/prysmaticlabs/prysm/v4/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" +) + +func GenerateProtoDenebBeaconBlock() *ethpb.BeaconBlockAndBlobsDeneb { + return ðpb.BeaconBlockAndBlobsDeneb{ + Block: ðpb.BeaconBlockDeneb{ + Slot: 1, + ProposerIndex: 2, + ParentRoot: FillByteSlice(32, 3), + StateRoot: FillByteSlice(32, 4), + Body: ðpb.BeaconBlockBodyDeneb{ + 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.AttesterSlashing{ + { + Attestation_1: ðpb.IndexedAttestation{ + 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.IndexedAttestation{ + 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.IndexedAttestation{ + 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.IndexedAttestation{ + 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.Attestation{ + { + 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), + }, + { + 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), + }, + }, + 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)}, + }, + }, + Blobs: []*ethpb.BlobSidecar{ + { + BlockRoot: FillByteSlice(32, 147), + Index: 148, + Slot: 149, + BlockParentRoot: FillByteSlice(32, 150), + ProposerIndex: 151, + Blob: FillByteSlice(131072, 152), + KzgCommitment: FillByteSlice(48, 153), + KzgProof: FillByteSlice(48, 154), + }, + { + BlockRoot: FillByteSlice(32, 155), + Index: 156, + Slot: 157, + BlockParentRoot: FillByteSlice(32, 158), + ProposerIndex: 159, + Blob: FillByteSlice(131072, 160), + KzgCommitment: FillByteSlice(48, 161), + KzgProof: FillByteSlice(48, 162), + }, + }, + } +} + +func GenerateProtoBlindedDenebBeaconBlock() *ethpb.BlindedBeaconBlockAndBlobsDeneb { + return ðpb.BlindedBeaconBlockAndBlobsDeneb{ + Block: ðpb.BlindedBeaconBlockDeneb{ + Slot: 1, + ProposerIndex: 2, + ParentRoot: FillByteSlice(32, 3), + StateRoot: FillByteSlice(32, 4), + Body: ðpb.BlindedBeaconBlockBodyDeneb{ + 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.AttesterSlashing{ + { + Attestation_1: ðpb.IndexedAttestation{ + 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.IndexedAttestation{ + 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.IndexedAttestation{ + 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.IndexedAttestation{ + 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.Attestation{ + { + 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), + }, + { + 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), + }, + }, + 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)}, + }, + }, + Blobs: []*ethpb.BlindedBlobSidecar{ + { + BlockRoot: FillByteSlice(32, 139), + Index: 140, + Slot: 141, + BlockParentRoot: FillByteSlice(32, 142), + ProposerIndex: 143, + BlobRoot: FillByteSlice(32, 144), + KzgCommitment: FillByteSlice(48, 145), + KzgProof: FillByteSlice(48, 146), + }, + { + BlockRoot: FillByteSlice(32, 147), + Index: 148, + Slot: 149, + BlockParentRoot: FillByteSlice(32, 150), + ProposerIndex: 151, + BlobRoot: FillByteSlice(32, 152), + KzgCommitment: FillByteSlice(48, 153), + KzgProof: FillByteSlice(48, 154), + }, + }, + } +} + +func GenerateJsonDenebBeaconBlock() *apimiddleware.BeaconBlockContentsDenebJson { + return &apimiddleware.BeaconBlockContentsDenebJson{ + Block: &apimiddleware.BeaconBlockDenebJson{ + Slot: "1", + ProposerIndex: "2", + ParentRoot: FillEncodedByteSlice(32, 3), + StateRoot: FillEncodedByteSlice(32, 4), + Body: &apimiddleware.BeaconBlockBodyDenebJson{ + RandaoReveal: FillEncodedByteSlice(96, 5), + Eth1Data: &apimiddleware.Eth1DataJson{ + DepositRoot: FillEncodedByteSlice(32, 6), + DepositCount: "7", + BlockHash: FillEncodedByteSlice(32, 8), + }, + Graffiti: FillEncodedByteSlice(32, 9), + ProposerSlashings: []*apimiddleware.ProposerSlashingJson{ + { + Header_1: &apimiddleware.SignedBeaconBlockHeaderJson{ + Header: &apimiddleware.BeaconBlockHeaderJson{ + Slot: "10", + ProposerIndex: "11", + ParentRoot: FillEncodedByteSlice(32, 12), + StateRoot: FillEncodedByteSlice(32, 13), + BodyRoot: FillEncodedByteSlice(32, 14), + }, + Signature: FillEncodedByteSlice(96, 15), + }, + Header_2: &apimiddleware.SignedBeaconBlockHeaderJson{ + Header: &apimiddleware.BeaconBlockHeaderJson{ + Slot: "16", + ProposerIndex: "17", + ParentRoot: FillEncodedByteSlice(32, 18), + StateRoot: FillEncodedByteSlice(32, 19), + BodyRoot: FillEncodedByteSlice(32, 20), + }, + Signature: FillEncodedByteSlice(96, 21), + }, + }, + { + Header_1: &apimiddleware.SignedBeaconBlockHeaderJson{ + Header: &apimiddleware.BeaconBlockHeaderJson{ + Slot: "22", + ProposerIndex: "23", + ParentRoot: FillEncodedByteSlice(32, 24), + StateRoot: FillEncodedByteSlice(32, 25), + BodyRoot: FillEncodedByteSlice(32, 26), + }, + Signature: FillEncodedByteSlice(96, 27), + }, + Header_2: &apimiddleware.SignedBeaconBlockHeaderJson{ + Header: &apimiddleware.BeaconBlockHeaderJson{ + Slot: "28", + ProposerIndex: "29", + ParentRoot: FillEncodedByteSlice(32, 30), + StateRoot: FillEncodedByteSlice(32, 31), + BodyRoot: FillEncodedByteSlice(32, 32), + }, + Signature: FillEncodedByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*apimiddleware.AttesterSlashingJson{ + { + Attestation_1: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"34", "35"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "36", + CommitteeIndex: "37", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "39", + Root: FillEncodedByteSlice(32, 40), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "41", + Root: FillEncodedByteSlice(32, 42), + }, + }, + Signature: FillEncodedByteSlice(96, 43), + }, + Attestation_2: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"44", "45"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "46", + CommitteeIndex: "47", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "49", + Root: FillEncodedByteSlice(32, 50), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "51", + Root: FillEncodedByteSlice(32, 52), + }, + }, + Signature: FillEncodedByteSlice(96, 53), + }, + }, + { + Attestation_1: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"54", "55"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "56", + CommitteeIndex: "57", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "59", + Root: FillEncodedByteSlice(32, 60), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "61", + Root: FillEncodedByteSlice(32, 62), + }, + }, + Signature: FillEncodedByteSlice(96, 63), + }, + Attestation_2: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"64", "65"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "66", + CommitteeIndex: "67", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "69", + Root: FillEncodedByteSlice(32, 70), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "71", + Root: FillEncodedByteSlice(32, 72), + }, + }, + Signature: FillEncodedByteSlice(96, 73), + }, + }, + }, + Attestations: []*apimiddleware.AttestationJson{ + { + AggregationBits: FillEncodedByteSlice(4, 74), + Data: &apimiddleware.AttestationDataJson{ + Slot: "75", + CommitteeIndex: "76", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "78", + Root: FillEncodedByteSlice(32, 79), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "80", + Root: FillEncodedByteSlice(32, 81), + }, + }, + Signature: FillEncodedByteSlice(96, 82), + }, + { + AggregationBits: FillEncodedByteSlice(4, 83), + Data: &apimiddleware.AttestationDataJson{ + Slot: "84", + CommitteeIndex: "85", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "87", + Root: FillEncodedByteSlice(32, 88), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "89", + Root: FillEncodedByteSlice(32, 90), + }, + }, + Signature: FillEncodedByteSlice(96, 91), + }, + }, + Deposits: []*apimiddleware.DepositJson{ + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 92)), + Data: &apimiddleware.Deposit_DataJson{ + PublicKey: FillEncodedByteSlice(48, 94), + WithdrawalCredentials: FillEncodedByteSlice(32, 95), + Amount: "96", + Signature: FillEncodedByteSlice(96, 97), + }, + }, + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 98)), + Data: &apimiddleware.Deposit_DataJson{ + PublicKey: FillEncodedByteSlice(48, 100), + WithdrawalCredentials: FillEncodedByteSlice(32, 101), + Amount: "102", + Signature: FillEncodedByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*apimiddleware.SignedVoluntaryExitJson{ + { + Exit: &apimiddleware.VoluntaryExitJson{ + Epoch: "104", + ValidatorIndex: "105", + }, + Signature: FillEncodedByteSlice(96, 106), + }, + { + Exit: &apimiddleware.VoluntaryExitJson{ + Epoch: "107", + ValidatorIndex: "108", + }, + Signature: FillEncodedByteSlice(96, 109), + }, + }, + SyncAggregate: &apimiddleware.SyncAggregateJson{ + SyncCommitteeBits: FillEncodedByteSlice(64, 110), + SyncCommitteeSignature: FillEncodedByteSlice(96, 111), + }, + ExecutionPayload: &apimiddleware.ExecutionPayloadDenebJson{ + 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: []*apimiddleware.WithdrawalJson{ + { + 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: []*apimiddleware.SignedBLSToExecutionChangeJson{ + { + Message: &apimiddleware.BLSToExecutionChangeJson{ + ValidatorIndex: "137", + FromBLSPubkey: FillEncodedByteSlice(48, 138), + ToExecutionAddress: FillEncodedByteSlice(20, 139), + }, + Signature: FillEncodedByteSlice(96, 140), + }, + { + Message: &apimiddleware.BLSToExecutionChangeJson{ + ValidatorIndex: "141", + FromBLSPubkey: FillEncodedByteSlice(48, 142), + ToExecutionAddress: FillEncodedByteSlice(20, 143), + }, + Signature: FillEncodedByteSlice(96, 144), + }, + }, + BlobKzgCommitments: []string{FillEncodedByteSlice(48, 145), FillEncodedByteSlice(48, 146)}, + }, + }, + BlobSidecars: []*apimiddleware.BlobSidecarJson{ + { + BlockRoot: FillEncodedByteSlice(32, 147), + Index: "148", + Slot: "149", + BlockParentRoot: FillEncodedByteSlice(32, 150), + ProposerIndex: "151", + Blob: FillEncodedByteSlice(131072, 152), + KzgCommitment: FillEncodedByteSlice(48, 153), + KzgProof: FillEncodedByteSlice(48, 154), + }, + { + BlockRoot: FillEncodedByteSlice(32, 155), + Index: "156", + Slot: "157", + BlockParentRoot: FillEncodedByteSlice(32, 158), + ProposerIndex: "159", + Blob: FillEncodedByteSlice(131072, 160), + KzgCommitment: FillEncodedByteSlice(48, 161), + KzgProof: FillEncodedByteSlice(48, 162), + }, + }, + } +} + +func GenerateJsonBlindedDenebBeaconBlock() *apimiddleware.BlindedBeaconBlockContentsDenebJson { + return &apimiddleware.BlindedBeaconBlockContentsDenebJson{ + BlindedBlock: &apimiddleware.BlindedBeaconBlockDenebJson{ + Slot: "1", + ProposerIndex: "2", + ParentRoot: FillEncodedByteSlice(32, 3), + StateRoot: FillEncodedByteSlice(32, 4), + Body: &apimiddleware.BlindedBeaconBlockBodyDenebJson{ + RandaoReveal: FillEncodedByteSlice(96, 5), + Eth1Data: &apimiddleware.Eth1DataJson{ + DepositRoot: FillEncodedByteSlice(32, 6), + DepositCount: "7", + BlockHash: FillEncodedByteSlice(32, 8), + }, + Graffiti: FillEncodedByteSlice(32, 9), + ProposerSlashings: []*apimiddleware.ProposerSlashingJson{ + { + Header_1: &apimiddleware.SignedBeaconBlockHeaderJson{ + Header: &apimiddleware.BeaconBlockHeaderJson{ + Slot: "10", + ProposerIndex: "11", + ParentRoot: FillEncodedByteSlice(32, 12), + StateRoot: FillEncodedByteSlice(32, 13), + BodyRoot: FillEncodedByteSlice(32, 14), + }, + Signature: FillEncodedByteSlice(96, 15), + }, + Header_2: &apimiddleware.SignedBeaconBlockHeaderJson{ + Header: &apimiddleware.BeaconBlockHeaderJson{ + Slot: "16", + ProposerIndex: "17", + ParentRoot: FillEncodedByteSlice(32, 18), + StateRoot: FillEncodedByteSlice(32, 19), + BodyRoot: FillEncodedByteSlice(32, 20), + }, + Signature: FillEncodedByteSlice(96, 21), + }, + }, + { + Header_1: &apimiddleware.SignedBeaconBlockHeaderJson{ + Header: &apimiddleware.BeaconBlockHeaderJson{ + Slot: "22", + ProposerIndex: "23", + ParentRoot: FillEncodedByteSlice(32, 24), + StateRoot: FillEncodedByteSlice(32, 25), + BodyRoot: FillEncodedByteSlice(32, 26), + }, + Signature: FillEncodedByteSlice(96, 27), + }, + Header_2: &apimiddleware.SignedBeaconBlockHeaderJson{ + Header: &apimiddleware.BeaconBlockHeaderJson{ + Slot: "28", + ProposerIndex: "29", + ParentRoot: FillEncodedByteSlice(32, 30), + StateRoot: FillEncodedByteSlice(32, 31), + BodyRoot: FillEncodedByteSlice(32, 32), + }, + Signature: FillEncodedByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*apimiddleware.AttesterSlashingJson{ + { + Attestation_1: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"34", "35"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "36", + CommitteeIndex: "37", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "39", + Root: FillEncodedByteSlice(32, 40), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "41", + Root: FillEncodedByteSlice(32, 42), + }, + }, + Signature: FillEncodedByteSlice(96, 43), + }, + Attestation_2: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"44", "45"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "46", + CommitteeIndex: "47", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "49", + Root: FillEncodedByteSlice(32, 50), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "51", + Root: FillEncodedByteSlice(32, 52), + }, + }, + Signature: FillEncodedByteSlice(96, 53), + }, + }, + { + Attestation_1: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"54", "55"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "56", + CommitteeIndex: "57", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "59", + Root: FillEncodedByteSlice(32, 60), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "61", + Root: FillEncodedByteSlice(32, 62), + }, + }, + Signature: FillEncodedByteSlice(96, 63), + }, + Attestation_2: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"64", "65"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "66", + CommitteeIndex: "67", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "69", + Root: FillEncodedByteSlice(32, 70), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "71", + Root: FillEncodedByteSlice(32, 72), + }, + }, + Signature: FillEncodedByteSlice(96, 73), + }, + }, + }, + Attestations: []*apimiddleware.AttestationJson{ + { + AggregationBits: FillEncodedByteSlice(4, 74), + Data: &apimiddleware.AttestationDataJson{ + Slot: "75", + CommitteeIndex: "76", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "78", + Root: FillEncodedByteSlice(32, 79), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "80", + Root: FillEncodedByteSlice(32, 81), + }, + }, + Signature: FillEncodedByteSlice(96, 82), + }, + { + AggregationBits: FillEncodedByteSlice(4, 83), + Data: &apimiddleware.AttestationDataJson{ + Slot: "84", + CommitteeIndex: "85", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &apimiddleware.CheckpointJson{ + Epoch: "87", + Root: FillEncodedByteSlice(32, 88), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "89", + Root: FillEncodedByteSlice(32, 90), + }, + }, + Signature: FillEncodedByteSlice(96, 91), + }, + }, + Deposits: []*apimiddleware.DepositJson{ + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 92)), + Data: &apimiddleware.Deposit_DataJson{ + PublicKey: FillEncodedByteSlice(48, 94), + WithdrawalCredentials: FillEncodedByteSlice(32, 95), + Amount: "96", + Signature: FillEncodedByteSlice(96, 97), + }, + }, + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 98)), + Data: &apimiddleware.Deposit_DataJson{ + PublicKey: FillEncodedByteSlice(48, 100), + WithdrawalCredentials: FillEncodedByteSlice(32, 101), + Amount: "102", + Signature: FillEncodedByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*apimiddleware.SignedVoluntaryExitJson{ + { + Exit: &apimiddleware.VoluntaryExitJson{ + Epoch: "104", + ValidatorIndex: "105", + }, + Signature: FillEncodedByteSlice(96, 106), + }, + { + Exit: &apimiddleware.VoluntaryExitJson{ + Epoch: "107", + ValidatorIndex: "108", + }, + Signature: FillEncodedByteSlice(96, 109), + }, + }, + SyncAggregate: &apimiddleware.SyncAggregateJson{ + SyncCommitteeBits: FillEncodedByteSlice(64, 110), + SyncCommitteeSignature: FillEncodedByteSlice(96, 111), + }, + ExecutionPayloadHeader: &apimiddleware.ExecutionPayloadHeaderDenebJson{ + 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: []*apimiddleware.SignedBLSToExecutionChangeJson{ + { + Message: &apimiddleware.BLSToExecutionChangeJson{ + ValidatorIndex: "129", + FromBLSPubkey: FillEncodedByteSlice(48, 130), + ToExecutionAddress: FillEncodedByteSlice(20, 131), + }, + Signature: FillEncodedByteSlice(96, 132), + }, + { + Message: &apimiddleware.BLSToExecutionChangeJson{ + ValidatorIndex: "133", + FromBLSPubkey: FillEncodedByteSlice(48, 134), + ToExecutionAddress: FillEncodedByteSlice(20, 135), + }, + Signature: FillEncodedByteSlice(96, 136), + }, + }, + BlobKzgCommitments: []string{FillEncodedByteSlice(48, 137), FillEncodedByteSlice(48, 138)}, + }, + }, + BlindedBlobSidecars: []*apimiddleware.BlindedBlobSidecarJson{ + { + BlockRoot: FillEncodedByteSlice(32, 139), + Index: "140", + Slot: "141", + BlockParentRoot: FillEncodedByteSlice(32, 142), + ProposerIndex: "143", + BlobRoot: FillEncodedByteSlice(32, 144), + KzgCommitment: FillEncodedByteSlice(48, 145), + KzgProof: FillEncodedByteSlice(48, 146), + }, + { + BlockRoot: FillEncodedByteSlice(32, 147), + Index: "148", + Slot: "149", + BlockParentRoot: FillEncodedByteSlice(32, 150), + ProposerIndex: "151", + BlobRoot: FillEncodedByteSlice(32, 152), + KzgCommitment: FillEncodedByteSlice(48, 153), + KzgProof: FillEncodedByteSlice(48, 154), + }, + }, + } +} diff --git a/validator/client/propose.go b/validator/client/propose.go index c6f27c76476f..41613849b571 100644 --- a/validator/client/propose.go +++ b/validator/client/propose.go @@ -411,7 +411,7 @@ func signVoluntaryExit( func (v *validator) getGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte) ([]byte, error) { // When specified, default graffiti from the command line takes the first priority. if len(v.graffiti) != 0 { - return v.graffiti, nil + return bytesutil.PadTo(v.graffiti, 32), nil } if v.graffitiStruct == nil { @@ -421,11 +421,11 @@ func (v *validator) getGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubk // When specified, individual validator specified graffiti takes the second priority. idx, err := v.validatorClient.ValidatorIndex(ctx, ðpb.ValidatorIndexRequest{PublicKey: pubKey[:]}) if err != nil { - return []byte{}, err + return nil, err } g, ok := v.graffitiStruct.Specific[idx.Index] if ok { - return []byte(g), nil + return bytesutil.PadTo([]byte(g), 32), nil } // When specified, a graffiti from the ordered list in the file take third priority. @@ -436,7 +436,7 @@ func (v *validator) getGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubk if err != nil { return nil, errors.Wrap(err, "failed to update graffiti ordered index") } - return []byte(graffiti), nil + return bytesutil.PadTo([]byte(graffiti), 32), nil } // When specified, a graffiti from the random list in the file take fourth priority. @@ -444,12 +444,12 @@ func (v *validator) getGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubk r := rand.NewGenerator() r.Seed(time.Now().Unix()) i := r.Uint64() % uint64(len(v.graffitiStruct.Random)) - return []byte(v.graffitiStruct.Random[i]), nil + return bytesutil.PadTo([]byte(v.graffitiStruct.Random[i]), 32), nil } // Finally, default graffiti if specified in the file will be used. if v.graffitiStruct.Default != "" { - return []byte(v.graffitiStruct.Default), nil + return bytesutil.PadTo([]byte(v.graffitiStruct.Default), 32), nil } return []byte{}, nil diff --git a/validator/client/propose_test.go b/validator/client/propose_test.go index 18f33f463004..8ebd829fee85 100644 --- a/validator/client/propose_test.go +++ b/validator/client/propose_test.go @@ -963,7 +963,7 @@ func TestGetGraffiti_Ok(t *testing.T) { }, }, }, - want: []byte{'b'}, + want: bytesutil.PadTo([]byte{'b'}, 32), }, {name: "use default file graffiti", v: &validator{ @@ -972,7 +972,7 @@ func TestGetGraffiti_Ok(t *testing.T) { Default: "c", }, }, - want: []byte{'c'}, + want: bytesutil.PadTo([]byte{'c'}, 32), }, {name: "use random file graffiti", v: &validator{ @@ -982,7 +982,7 @@ func TestGetGraffiti_Ok(t *testing.T) { Default: "c", }, }, - want: []byte{'d'}, + want: bytesutil.PadTo([]byte{'d'}, 32), }, {name: "use validator file graffiti, has validator", v: &validator{ @@ -996,7 +996,7 @@ func TestGetGraffiti_Ok(t *testing.T) { }, }, }, - want: []byte{'g'}, + want: bytesutil.PadTo([]byte{'g'}, 32), }, {name: "use validator file graffiti, none specified", v: &validator{ @@ -1041,7 +1041,7 @@ func TestGetGraffitiOrdered_Ok(t *testing.T) { Default: "d", }, } - for _, want := range [][]byte{{'a'}, {'b'}, {'c'}, {'d'}, {'d'}} { + for _, want := range [][]byte{bytesutil.PadTo([]byte{'a'}, 32), bytesutil.PadTo([]byte{'b'}, 32), bytesutil.PadTo([]byte{'c'}, 32), bytesutil.PadTo([]byte{'d'}, 32), bytesutil.PadTo([]byte{'d'}, 32)} { got, err := v.getGraffiti(context.Background(), pubKey) require.NoError(t, err) require.DeepEqual(t, want, got)