Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

demo fork-specific interface #13928

Merged
merged 1 commit into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 30 additions & 86 deletions consensus-types/blocks/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type executionPayload struct {
p *enginev1.ExecutionPayload
}

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}
Expand Down Expand Up @@ -202,23 +204,15 @@ 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.
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}
Expand Down Expand Up @@ -398,16 +392,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()
Expand Down Expand Up @@ -445,6 +429,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))}
Expand Down Expand Up @@ -624,16 +610,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.
Expand All @@ -643,6 +619,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))}
Expand Down Expand Up @@ -822,16 +800,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()
Expand Down Expand Up @@ -919,7 +887,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
Expand All @@ -945,18 +913,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
Expand Down Expand Up @@ -1043,23 +1006,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
}
Expand All @@ -1077,6 +1031,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))}
Expand Down Expand Up @@ -1251,16 +1207,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
Expand All @@ -1275,6 +1221,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))}
Expand Down Expand Up @@ -1447,16 +1395,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
Expand All @@ -1471,6 +1409,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))}
Expand Down Expand Up @@ -1678,6 +1619,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
Expand Down Expand Up @@ -1842,13 +1786,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.
Expand Down
24 changes: 24 additions & 0 deletions consensus-types/blocks/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 := &eth.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 := &eth.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)
})
}
14 changes: 7 additions & 7 deletions consensus-types/blocks/getters.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,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
}
Expand Down Expand Up @@ -377,7 +381,6 @@ func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, e
},
Signature: b.signature[:],
})

default:
return nil, fmt.Errorf("%T is not an execution payload header", p)
}
Expand Down Expand Up @@ -1230,11 +1233,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
Expand Down
6 changes: 6 additions & 0 deletions consensus-types/blocks/getters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
3 changes: 3 additions & 0 deletions consensus-types/blocks/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 10 additions & 2 deletions consensus-types/interfaces/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
"@org_golang_google_protobuf//proto:go_default_library",
Expand All @@ -23,14 +26,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",
],
)
Loading
Loading