prysm-pulse/validator/client/beacon-api/get_beacon_block_test.go
Patrice Vignola 791110f795
Add REST implementation for Validator's StreamBlocksAltair (#11974)
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2023-02-13 14:22:11 +01:00

382 lines
11 KiB
Go

package beacon_api
import (
"context"
"encoding/json"
"errors"
"fmt"
"testing"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/golang/mock/gomock"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware"
"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/testing/assert"
"github.com/prysmaticlabs/prysm/v3/testing/require"
"github.com/prysmaticlabs/prysm/v3/validator/client/beacon-api/mock"
test_helpers "github.com/prysmaticlabs/prysm/v3/validator/client/beacon-api/test-helpers"
)
func TestGetBeaconBlock_RequestFailed(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetRestJsonResponse(
ctx,
gomock.Any(),
gomock.Any(),
).Return(
nil,
errors.New("foo error"),
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
_, err := validatorClient.getBeaconBlock(ctx, 1, []byte{1}, []byte{2})
assert.ErrorContains(t, "failed to query GET REST endpoint", err)
assert.ErrorContains(t, "foo error", err)
}
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
data json.RawMessage
}{
{
name: "phase0 block decoding failed",
expectedErrorMessage: "failed to decode phase0 block response json",
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",
data: []byte{},
},
{
name: "bellatrix block conversion failed",
expectedErrorMessage: "failed to get bellatrix block",
consensusVersion: "bellatrix",
data: bellatrixBeaconBlockBytes,
},
{
name: "capella block decoding failed",
expectedErrorMessage: "failed to decode capella block response json",
beaconBlock: "foo",
consensusVersion: "capella",
data: []byte{},
},
{
name: "capella block conversion failed",
expectedErrorMessage: "failed to get capella block",
consensusVersion: "capella",
data: capellaBeaconBlockBytes,
},
{
name: "unsupported consensus version",
expectedErrorMessage: "unsupported consensus version `foo`",
consensusVersion: "foo",
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetRestJsonResponse(
ctx,
gomock.Any(),
&abstractProduceBlockResponseJson{},
).SetArg(
2,
abstractProduceBlockResponseJson{
Version: testCase.consensusVersion,
Data: testCase.data,
},
).Return(
nil,
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}
_, err := validatorClient.getBeaconBlock(ctx, 1, []byte{1}, []byte{2})
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
})
}
}
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)
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/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
&abstractProduceBlockResponseJson{},
).SetArg(
2,
abstractProduceBlockResponseJson{
Version: "phase0",
Data: phase0BeaconBlockBytes,
},
).Return(
nil,
nil,
).Times(1)
beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl)
beaconBlockConverter.EXPECT().ConvertRESTPhase0BlockToProto(
phase0BeaconBlock,
).Return(
phase0ProtoBeaconBlock,
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
Block: &ethpb.GenericBeaconBlock_Phase0{
Phase0: phase0ProtoBeaconBlock,
},
}
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
}
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)
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/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
&abstractProduceBlockResponseJson{},
).SetArg(
2,
abstractProduceBlockResponseJson{
Version: "altair",
Data: altairBeaconBlockBytes,
},
).Return(
nil,
nil,
).Times(1)
beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl)
beaconBlockConverter.EXPECT().ConvertRESTAltairBlockToProto(
altairBeaconBlock,
).Return(
altairProtoBeaconBlock,
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
Block: &ethpb.GenericBeaconBlock_Altair{
Altair: altairProtoBeaconBlock,
},
}
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
}
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)
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/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
&abstractProduceBlockResponseJson{},
).SetArg(
2,
abstractProduceBlockResponseJson{
Version: "bellatrix",
Data: bellatrixBeaconBlockBytes,
},
).Return(
nil,
nil,
).Times(1)
beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl)
beaconBlockConverter.EXPECT().ConvertRESTBellatrixBlockToProto(
bellatrixBeaconBlock,
).Return(
bellatrixProtoBeaconBlock,
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
Block: &ethpb.GenericBeaconBlock_Bellatrix{
Bellatrix: bellatrixProtoBeaconBlock,
},
}
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
}
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)
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/v2/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
&abstractProduceBlockResponseJson{},
).SetArg(
2,
abstractProduceBlockResponseJson{
Version: "capella",
Data: capellaBeaconBlockBytes,
},
).Return(
nil,
nil,
).Times(1)
beaconBlockConverter := mock.NewMockbeaconBlockConverter(ctrl)
beaconBlockConverter.EXPECT().ConvertRESTCapellaBlockToProto(
capellaBeaconBlock,
).Return(
capellaProtoBeaconBlock,
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler, beaconBlockConverter: beaconBlockConverter}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
Block: &ethpb.GenericBeaconBlock_Capella{
Capella: capellaProtoBeaconBlock,
},
}
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
}