diff --git a/consensus-types/blocks/execution.go b/consensus-types/blocks/execution.go index 9b754481b3..08cc5aeabf 100644 --- a/consensus-types/blocks/execution.go +++ b/consensus-types/blocks/execution.go @@ -35,11 +35,15 @@ func NewWrappedExecutionData(v proto.Message, weiValue math.Wei) (interfaces.Exe return WrappedExecutionPayloadCapella(pbStruct, weiValue) case *enginev1.ExecutionPayloadDeneb: return WrappedExecutionPayloadDeneb(pbStruct, weiValue) + case *enginev1.ExecutionPayloadElectra: + return WrappedExecutionPayloadElectra(pbStruct, weiValue) default: return nil, ErrUnsupportedVersion } } +var _ interfaces.ExecutionData = &executionPayload{} + // WrappedExecutionPayload is a constructor which wraps a protobuf execution payload into an interface. func WrappedExecutionPayload(p *enginev1.ExecutionPayload) (interfaces.ExecutionData, error) { w := executionPayload{p: p} @@ -199,16 +203,6 @@ func (executionPayload) ValueInGwei() (uint64, error) { return 0, consensus_types.ErrUnsupportedField } -// DepositReceipts -- -func (e executionPayload) DepositReceipts() ([]*enginev1.DepositReceipt, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// WithdrawalRequests -- -func (e executionPayload) WithdrawalRequests() ([]*enginev1.ExecutionLayerWithdrawalRequest, error) { - return nil, consensus_types.ErrUnsupportedField -} - // executionPayloadHeader is a convenience wrapper around a blinded beacon block body's execution header data structure // This wrapper allows us to conform to a common interface so that beacon // blocks for future forks can also be applied across Prysm without issues. @@ -216,6 +210,8 @@ type executionPayloadHeader struct { p *enginev1.ExecutionPayloadHeader } +var _ interfaces.ExecutionData = &executionPayloadHeader{} + // WrappedExecutionPayloadHeader is a constructor which wraps a protobuf execution header into an interface. func WrappedExecutionPayloadHeader(p *enginev1.ExecutionPayloadHeader) (interfaces.ExecutionData, error) { w := executionPayloadHeader{p: p} @@ -375,16 +371,6 @@ func (executionPayloadHeader) ValueInGwei() (uint64, error) { return 0, consensus_types.ErrUnsupportedField } -// DepositReceipts -- -func (e executionPayloadHeader) DepositReceipts() ([]*enginev1.DepositReceipt, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// WithdrawalRequests -- -func (e executionPayloadHeader) WithdrawalRequests() ([]*enginev1.ExecutionLayerWithdrawalRequest, error) { - return nil, consensus_types.ErrUnsupportedField -} - // PayloadToHeader converts `payload` into execution payload header format. func PayloadToHeader(payload interfaces.ExecutionData) (*enginev1.ExecutionPayloadHeader, error) { txs, err := payload.Transactions() @@ -422,6 +408,8 @@ type executionPayloadCapella struct { gweiValue uint64 } +var _ interfaces.ExecutionData = &executionPayloadCapella{} + // WrappedExecutionPayloadCapella is a constructor which wraps a protobuf execution payload into an interface. func WrappedExecutionPayloadCapella(p *enginev1.ExecutionPayloadCapella, value math.Wei) (interfaces.ExecutionData, error) { w := executionPayloadCapella{p: p, weiValue: value, gweiValue: uint64(math.WeiToGwei(value))} @@ -581,16 +569,6 @@ func (e executionPayloadCapella) ValueInGwei() (uint64, error) { return e.gweiValue, nil } -// DepositReceipts -- -func (e executionPayloadCapella) DepositReceipts() ([]*enginev1.DepositReceipt, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// WithdrawalRequests -- -func (e executionPayloadCapella) WithdrawalRequests() ([]*enginev1.ExecutionLayerWithdrawalRequest, error) { - return nil, consensus_types.ErrUnsupportedField -} - // executionPayloadHeaderCapella is a convenience wrapper around a blinded beacon block body's execution header data structure // This wrapper allows us to conform to a common interface so that beacon // blocks for future forks can also be applied across Prysm without issues. @@ -600,6 +578,8 @@ type executionPayloadHeaderCapella struct { gweiValue uint64 } +var _ interfaces.ExecutionData = &executionPayloadHeaderCapella{} + // WrappedExecutionPayloadHeaderCapella is a constructor which wraps a protobuf execution header into an interface. func WrappedExecutionPayloadHeaderCapella(p *enginev1.ExecutionPayloadHeaderCapella, value math.Wei) (interfaces.ExecutionData, error) { w := executionPayloadHeaderCapella{p: p, weiValue: value, gweiValue: uint64(math.WeiToGwei(value))} @@ -759,16 +739,6 @@ func (e executionPayloadHeaderCapella) ValueInGwei() (uint64, error) { return e.gweiValue, nil } -// DepositReceipts -- -func (e executionPayloadHeaderCapella) DepositReceipts() ([]*enginev1.DepositReceipt, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// WithdrawalRequests -- -func (e executionPayloadHeaderCapella) WithdrawalRequests() ([]*enginev1.ExecutionLayerWithdrawalRequest, error) { - return nil, consensus_types.ErrUnsupportedField -} - // PayloadToHeaderCapella converts `payload` into execution payload header format. func PayloadToHeaderCapella(payload interfaces.ExecutionData) (*enginev1.ExecutionPayloadHeaderCapella, error) { txs, err := payload.Transactions() @@ -856,7 +826,7 @@ func PayloadToHeaderDeneb(payload interfaces.ExecutionData) (*enginev1.Execution } // PayloadToHeaderElectra converts `payload` into execution payload header format. -func PayloadToHeaderElectra(payload interfaces.ExecutionData) (*enginev1.ExecutionPayloadHeaderElectra, error) { +func PayloadToHeaderElectra(payload interfaces.ExecutionDataElectra) (*enginev1.ExecutionPayloadHeaderElectra, error) { txs, err := payload.Transactions() if err != nil { return nil, err @@ -882,18 +852,13 @@ func PayloadToHeaderElectra(payload interfaces.ExecutionData) (*enginev1.Executi return nil, err } - depositReceipts, err := payload.DepositReceipts() - if err != nil { - return nil, err - } + depositReceipts := payload.DepositReceipts() depositReceiptsRoot, err := ssz.DepositReceiptSliceRoot(depositReceipts, fieldparams.MaxDepositReceiptsPerPayload) if err != nil { return nil, err } - withdrawalRequests, err := payload.WithdrawalRequests() - if err != nil { - return nil, err - } + + withdrawalRequests := payload.WithdrawalRequests() withdrawalRequestsRoot, err := ssz.WithdrawalRequestSliceRoot(withdrawalRequests, fieldparams.MaxWithdrawalRequestsPerPayload) if err != nil { return nil, err @@ -980,23 +945,14 @@ func IsEmptyExecutionData(data interfaces.ExecutionData) (bool, error) { return false, nil } - drs, err := data.DepositReceipts() - switch { - case errors.Is(err, consensus_types.ErrUnsupportedField): - case err != nil: - return false, err - default: + epe, postElectra := data.(interfaces.ExecutionDataElectra) + if postElectra { + drs := epe.DepositReceipts() if len(drs) != 0 { return false, nil } - } - wrs, err := data.WithdrawalRequests() - switch { - case errors.Is(err, consensus_types.ErrUnsupportedField): - case err != nil: - return false, err - default: + wrs := epe.WithdrawalRequests() if len(wrs) != 0 { return false, nil } @@ -1014,6 +970,8 @@ type executionPayloadHeaderDeneb struct { gweiValue uint64 } +var _ interfaces.ExecutionData = &executionPayloadHeaderDeneb{} + // WrappedExecutionPayloadHeaderDeneb is a constructor which wraps a protobuf execution header into an interface. func WrappedExecutionPayloadHeaderDeneb(p *enginev1.ExecutionPayloadHeaderDeneb, value math.Wei) (interfaces.ExecutionData, error) { w := executionPayloadHeaderDeneb{p: p, weiValue: value, gweiValue: uint64(math.WeiToGwei(value))} @@ -1168,16 +1126,6 @@ func (e executionPayloadHeaderDeneb) ValueInGwei() (uint64, error) { return e.gweiValue, nil } -// DepositReceipts -- -func (e executionPayloadHeaderDeneb) DepositReceipts() ([]*enginev1.DepositReceipt, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// WithdrawalRequests -- -func (e executionPayloadHeaderDeneb) WithdrawalRequests() ([]*enginev1.ExecutionLayerWithdrawalRequest, error) { - return nil, consensus_types.ErrUnsupportedField -} - // IsBlinded returns true if the underlying data is blinded. func (e executionPayloadHeaderDeneb) IsBlinded() bool { return true @@ -1192,6 +1140,8 @@ type executionPayloadDeneb struct { gweiValue uint64 } +var _ interfaces.ExecutionData = &executionPayloadDeneb{} + // WrappedExecutionPayloadDeneb is a constructor which wraps a protobuf execution payload into an interface. func WrappedExecutionPayloadDeneb(p *enginev1.ExecutionPayloadDeneb, value math.Wei) (interfaces.ExecutionData, error) { w := executionPayloadDeneb{p: p, weiValue: value, gweiValue: uint64(math.WeiToGwei(value))} @@ -1344,16 +1294,6 @@ func (e executionPayloadDeneb) ValueInGwei() (uint64, error) { return e.gweiValue, nil } -// DepositReceipts -- -func (e executionPayloadDeneb) DepositReceipts() ([]*enginev1.DepositReceipt, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// WithdrawalRequests -- -func (e executionPayloadDeneb) WithdrawalRequests() ([]*enginev1.ExecutionLayerWithdrawalRequest, error) { - return nil, consensus_types.ErrUnsupportedField -} - // IsBlinded returns true if the underlying data is blinded. func (e executionPayloadDeneb) IsBlinded() bool { return false @@ -1368,6 +1308,9 @@ type executionPayloadHeaderElectra struct { gweiValue uint64 } +var _ interfaces.ExecutionData = &executionPayloadElectra{} +var _ interfaces.ExecutionDataElectra = &executionPayloadElectra{} + // WrappedExecutionPayloadHeaderElectra is a constructor which wraps a protobuf execution header into an interface. func WrappedExecutionPayloadHeaderElectra(p *enginev1.ExecutionPayloadHeaderElectra, value math.Wei) (interfaces.ExecutionData, error) { w := executionPayloadHeaderElectra{p: p, weiValue: value, gweiValue: uint64(math.WeiToGwei(value))} @@ -1512,26 +1455,6 @@ func (e executionPayloadHeaderElectra) ExcessBlobGas() (uint64, error) { return e.p.ExcessBlobGas, nil } -// PbElectra -- -func (e executionPayloadHeaderElectra) PbElectra() (*enginev1.ExecutionPayloadElectra, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbDeneb -- -func (executionPayloadHeaderElectra) PbDeneb() (*enginev1.ExecutionPayloadDeneb, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbBellatrix -- -func (executionPayloadHeaderElectra) PbBellatrix() (*enginev1.ExecutionPayload, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbCapella -- -func (executionPayloadHeaderElectra) PbCapella() (*enginev1.ExecutionPayloadCapella, error) { - return nil, consensus_types.ErrUnsupportedField -} - // ValueInWei -- func (e executionPayloadHeaderElectra) ValueInWei() (math.Wei, error) { return e.weiValue, nil @@ -1575,6 +1498,9 @@ func WrappedExecutionPayloadElectra(p *enginev1.ExecutionPayloadElectra, value m return w, nil } +var _ interfaces.ExecutionData = &executionPayloadElectra{} +var _ interfaces.ExecutionDataElectra = &executionPayloadElectra{} + // IsNil checks if the underlying data is nil. func (e executionPayloadElectra) IsNil() bool { return e.p == nil @@ -1708,26 +1634,6 @@ func (e executionPayloadElectra) ExcessBlobGas() (uint64, error) { return e.p.ExcessBlobGas, nil } -// PbBellatrix -- -func (e executionPayloadElectra) PbBellatrix() (*enginev1.ExecutionPayload, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbCapella -- -func (e executionPayloadElectra) PbCapella() (*enginev1.ExecutionPayloadCapella, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbDeneb -- -func (e executionPayloadElectra) PbDeneb() (*enginev1.ExecutionPayloadDeneb, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbElectra -- -func (e executionPayloadElectra) PbElectra() (*enginev1.ExecutionPayloadElectra, error) { - return e.p, nil -} - // ValueInWei -- func (e executionPayloadElectra) ValueInWei() (math.Wei, error) { return e.weiValue, nil @@ -1739,13 +1645,13 @@ func (e executionPayloadElectra) ValueInGwei() (uint64, error) { } // DepositReceipts -- -func (e executionPayloadElectra) DepositReceipts() ([]*enginev1.DepositReceipt, error) { - return e.p.DepositReceipts, nil +func (e executionPayloadElectra) DepositReceipts() []*enginev1.DepositReceipt { + return e.p.DepositReceipts } // WithdrawalRequests -- -func (e executionPayloadElectra) WithdrawalRequests() ([]*enginev1.ExecutionLayerWithdrawalRequest, error) { - return e.p.WithdrawalRequests, nil +func (e executionPayloadElectra) WithdrawalRequests() []*enginev1.ExecutionLayerWithdrawalRequest { + return e.p.WithdrawalRequests } // IsBlinded returns true if the underlying data is blinded. diff --git a/consensus-types/blocks/factory.go b/consensus-types/blocks/factory.go index 80d266a45e..b7a1c826b1 100644 --- a/consensus-types/blocks/factory.go +++ b/consensus-types/blocks/factory.go @@ -460,10 +460,11 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea if err != nil { return nil, err } - consolidations, err := b.Body().Consolidations() - if err != nil { - return nil, err + electraBody, ok := b.Body().(interfaces.ROBlockBodyElectra) + if !ok { + return nil, errors.Wrapf(interfaces.ErrInvalidCast, "%T does not support electra getters", b.Body()) } + consolidations := electraBody.Consolidations() var atts []*eth.AttestationElectra if b.Body().Attestations() != nil { atts = make([]*eth.AttestationElectra, len(b.Body().Attestations())) diff --git a/consensus-types/blocks/factory_test.go b/consensus-types/blocks/factory_test.go index 2d9dc92c22..80a4a4f4f1 100644 --- a/consensus-types/blocks/factory_test.go +++ b/consensus-types/blocks/factory_test.go @@ -7,6 +7,7 @@ import ( "testing" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -537,3 +538,26 @@ func TestBuildSignedBeaconBlockFromExecutionPayload(t *testing.T) { require.DeepEqual(t, uint64(321), payload.BlobGasUsed) }) } + +func TestElectraBlockBodyCast(t *testing.T) { + t.Run("deneb cast fails", func(t *testing.T) { + pb := ð.BeaconBlockBodyDeneb{} + i, err := NewBeaconBlockBody(pb) + require.NoError(t, err) + b, ok := i.(*BeaconBlockBody) + require.Equal(t, true, ok) + assert.Equal(t, version.Deneb, b.version) + _, err = interfaces.AsROBlockBodyElectra(b) + require.ErrorIs(t, err, interfaces.ErrInvalidCast) + }) + t.Run("electra cast succeeds", func(t *testing.T) { + pb := ð.BeaconBlockBodyElectra{} + i, err := NewBeaconBlockBody(pb) + require.NoError(t, err) + b, ok := i.(*BeaconBlockBody) + require.Equal(t, true, ok) + assert.Equal(t, version.Electra, b.version) + _, err = interfaces.AsROBlockBodyElectra(b) + require.NoError(t, err) + }) +} diff --git a/consensus-types/blocks/getters.go b/consensus-types/blocks/getters.go index 2f737e80db..e45e2f7dbe 100644 --- a/consensus-types/blocks/getters.go +++ b/consensus-types/blocks/getters.go @@ -252,7 +252,11 @@ func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, e Signature: b.signature[:], }) case *enginev1.ExecutionPayloadElectra: - header, err := PayloadToHeaderElectra(payload) + pe, ok := payload.(interfaces.ExecutionDataElectra) + if !ok { + return nil, interfaces.ErrIncompatibleFork + } + header, err := PayloadToHeaderElectra(pe) if err != nil { return nil, err } @@ -281,7 +285,6 @@ func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, e }, Signature: b.signature[:], }) - default: return nil, fmt.Errorf("%T is not an execution payload header", p) } @@ -1170,11 +1173,8 @@ func (b *BeaconBlockBody) BlobKzgCommitments() ([][]byte, error) { } } -func (b *BeaconBlockBody) Consolidations() ([]*eth.SignedConsolidation, error) { - if b.version < version.Electra { - return nil, consensus_types.ErrNotSupported("Consolidations", b.version) - } - return b.signedConsolidations, nil +func (b *BeaconBlockBody) Consolidations() []*eth.SignedConsolidation { + return b.signedConsolidations } // Version returns the version of the beacon block body diff --git a/consensus-types/blocks/getters_test.go b/consensus-types/blocks/getters_test.go index 22c2fd63dd..95d9bc177d 100644 --- a/consensus-types/blocks/getters_test.go +++ b/consensus-types/blocks/getters_test.go @@ -490,3 +490,9 @@ func hydrateBeaconBlockBody() *eth.BeaconBlockBody { }, } } + +func TestPreElectraFailsInterfaceAssertion(t *testing.T) { + var epd interfaces.ExecutionData = &executionPayloadDeneb{} + _, ok := epd.(interfaces.ExecutionDataElectra) + require.Equal(t, false, ok) +} diff --git a/consensus-types/blocks/types.go b/consensus-types/blocks/types.go index c6216b1d59..b450ede833 100644 --- a/consensus-types/blocks/types.go +++ b/consensus-types/blocks/types.go @@ -57,6 +57,9 @@ type BeaconBlockBody struct { signedConsolidations []*eth.SignedConsolidation } +var _ interfaces.ReadOnlyBeaconBlockBody = &BeaconBlockBody{} +var _ interfaces.ROBlockBodyElectra = &BeaconBlockBody{} + // BeaconBlock is the main beacon block structure. It can represent any block type. type BeaconBlock struct { version int diff --git a/consensus-types/interfaces/BUILD.bazel b/consensus-types/interfaces/BUILD.bazel index 84eb1c643f..6dbc9a37a0 100644 --- a/consensus-types/interfaces/BUILD.bazel +++ b/consensus-types/interfaces/BUILD.bazel @@ -4,6 +4,8 @@ go_library( name = "go_default_library", srcs = [ "beacon_block.go", + "cast.go", + "error.go", "utils.go", ], importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces", @@ -15,6 +17,7 @@ go_library( "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", + "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", @@ -24,14 +27,19 @@ go_library( go_test( name = "go_default_test", - srcs = ["utils_test.go"], + srcs = [ + "error_test.go", + "utils_test.go", + ], + embed = [":go_default_library"], deps = [ - ":go_default_library", "//config/fieldparams:go_default_library", "//consensus-types/blocks:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", + "@com_github_pkg_errors//:go_default_library", ], ) diff --git a/consensus-types/interfaces/beacon_block.go b/consensus-types/interfaces/beacon_block.go index 06d427b628..3eae02c695 100644 --- a/consensus-types/interfaces/beacon_block.go +++ b/consensus-types/interfaces/beacon_block.go @@ -1,6 +1,7 @@ package interfaces import ( + "github.com/pkg/errors" ssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/go-bitfield" field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams" @@ -12,6 +13,8 @@ import ( "google.golang.org/protobuf/proto" ) +var ErrIncompatibleFork = errors.New("Can't convert to fork-specific interface") + // ReadOnlySignedBeaconBlock is an interface describing the method set of // a signed beacon block. type ReadOnlySignedBeaconBlock interface { @@ -70,7 +73,11 @@ type ReadOnlyBeaconBlockBody interface { Execution() (ExecutionData, error) BLSToExecutionChanges() ([]*ethpb.SignedBLSToExecutionChange, error) BlobKzgCommitments() ([][]byte, error) - Consolidations() ([]*ethpb.SignedConsolidation, error) +} + +type ROBlockBodyElectra interface { + ReadOnlyBeaconBlockBody + Consolidations() []*ethpb.SignedConsolidation } type SignedBeaconBlock interface { @@ -125,8 +132,12 @@ type ExecutionData interface { WithdrawalsRoot() ([]byte, error) ValueInWei() (math.Wei, error) ValueInGwei() (uint64, error) - DepositReceipts() ([]*enginev1.DepositReceipt, error) - WithdrawalRequests() ([]*enginev1.ExecutionLayerWithdrawalRequest, error) +} + +type ExecutionDataElectra interface { + ExecutionData + DepositReceipts() []*enginev1.DepositReceipt + WithdrawalRequests() []*enginev1.ExecutionLayerWithdrawalRequest } type Attestation interface { diff --git a/consensus-types/interfaces/cast.go b/consensus-types/interfaces/cast.go new file mode 100644 index 0000000000..29f0c7a830 --- /dev/null +++ b/consensus-types/interfaces/cast.go @@ -0,0 +1,15 @@ +package interfaces + +import "github.com/prysmaticlabs/prysm/v5/runtime/version" + +// AsROBlockBodyElectra safely asserts the ReadOnlyBeaconBlockBody to a ROBlockBodyElectra. +// This allows the caller to access methods on the block body which are only available on values after +// the Electra hard fork. If the value is for an earlier fork (based on comparing its Version() to the electra version) +// an error will be returned. Callers that want to conditionally process electra data can check for this condition +// and safely ignore it like `if err != nil && errors.Is(interfaces.ErrInvalidCast) {` +func AsROBlockBodyElectra(in ReadOnlyBeaconBlockBody) (ROBlockBodyElectra, error) { + if in.Version() >= version.Electra { + return in.(ROBlockBodyElectra), nil + } + return nil, NewInvalidCastError(in.Version(), version.Electra) +} diff --git a/consensus-types/interfaces/error.go b/consensus-types/interfaces/error.go new file mode 100644 index 0000000000..98d9da5a17 --- /dev/null +++ b/consensus-types/interfaces/error.go @@ -0,0 +1,27 @@ +package interfaces + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/runtime/version" +) + +var ErrInvalidCast = errors.New("unable to cast between types") + +type InvalidCastError struct { + from int + to int +} + +func (e *InvalidCastError) Error() string { + return errors.Wrapf(ErrInvalidCast, + "from=%s(%d), to=%s(%d)", version.String(e.from), e.from, version.String(e.to), e.to). + Error() +} + +func (*InvalidCastError) Is(err error) bool { + return errors.Is(err, ErrInvalidCast) +} + +func NewInvalidCastError(from, to int) *InvalidCastError { + return &InvalidCastError{from: from, to: to} +} diff --git a/consensus-types/interfaces/error_test.go b/consensus-types/interfaces/error_test.go new file mode 100644 index 0000000000..4bac169a25 --- /dev/null +++ b/consensus-types/interfaces/error_test.go @@ -0,0 +1,14 @@ +package interfaces + +import ( + "testing" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +func TestNewInvalidCastError(t *testing.T) { + err := NewInvalidCastError(version.Phase0, version.Electra) + require.Equal(t, true, errors.Is(err, ErrInvalidCast)) +} diff --git a/consensus-types/mock/block.go b/consensus-types/mock/block.go index 6c9909e595..846eb42618 100644 --- a/consensus-types/mock/block.go +++ b/consensus-types/mock/block.go @@ -284,8 +284,7 @@ func (b *BeaconBlockBody) BlobKzgCommitments() ([][]byte, error) { func (b *BeaconBlockBody) Attestations() []interfaces.Attestation { panic("implement me") } - -func (b *BeaconBlockBody) Consolidations() ([]*eth.SignedConsolidation, error) { +func (b *BeaconBlockBody) Consolidations() []*eth.SignedConsolidation { panic("implement me") } @@ -296,3 +295,4 @@ func (b *BeaconBlockBody) Version() int { var _ interfaces.ReadOnlySignedBeaconBlock = &SignedBeaconBlock{} var _ interfaces.ReadOnlyBeaconBlock = &BeaconBlock{} var _ interfaces.ReadOnlyBeaconBlockBody = &BeaconBlockBody{} +var _ interfaces.ROBlockBodyElectra = &BeaconBlockBody{}