Add payload attribute type (#11710)

* Add payload attribute type

* Gazelle

* Fix test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
terencechain
2022-12-02 10:23:47 -08:00
committed by GitHub
parent 8be73a52b1
commit f7cecf9f8a
7 changed files with 346 additions and 10 deletions

View File

@@ -117,7 +117,7 @@ func (b *SignedBeaconBlock) PbGenericBlock() (*eth.GenericSignedBeaconBlock, err
// PbPhase0Block returns the underlying protobuf object.
func (b *SignedBeaconBlock) PbPhase0Block() (*eth.SignedBeaconBlock, error) {
if b.version != version.Phase0 {
return nil, errNotSupported("PbPhase0Block", b.version)
return nil, ErrNotSupported("PbPhase0Block", b.version)
}
pb, err := b.Proto()
if err != nil {
@@ -129,7 +129,7 @@ func (b *SignedBeaconBlock) PbPhase0Block() (*eth.SignedBeaconBlock, error) {
// PbAltairBlock returns the underlying protobuf object.
func (b *SignedBeaconBlock) PbAltairBlock() (*eth.SignedBeaconBlockAltair, error) {
if b.version != version.Altair {
return nil, errNotSupported("PbAltairBlock", b.version)
return nil, ErrNotSupported("PbAltairBlock", b.version)
}
pb, err := b.Proto()
if err != nil {
@@ -141,7 +141,7 @@ func (b *SignedBeaconBlock) PbAltairBlock() (*eth.SignedBeaconBlockAltair, error
// PbBellatrixBlock returns the underlying protobuf object.
func (b *SignedBeaconBlock) PbBellatrixBlock() (*eth.SignedBeaconBlockBellatrix, error) {
if b.version != version.Bellatrix || b.IsBlinded() {
return nil, errNotSupported("PbBellatrixBlock", b.version)
return nil, ErrNotSupported("PbBellatrixBlock", b.version)
}
pb, err := b.Proto()
if err != nil {
@@ -153,7 +153,7 @@ func (b *SignedBeaconBlock) PbBellatrixBlock() (*eth.SignedBeaconBlockBellatrix,
// PbBlindedBellatrixBlock returns the underlying protobuf object.
func (b *SignedBeaconBlock) PbBlindedBellatrixBlock() (*eth.SignedBlindedBeaconBlockBellatrix, error) {
if b.version != version.Bellatrix || !b.IsBlinded() {
return nil, errNotSupported("PbBlindedBellatrixBlock", b.version)
return nil, ErrNotSupported("PbBlindedBellatrixBlock", b.version)
}
pb, err := b.Proto()
if err != nil {
@@ -165,7 +165,7 @@ func (b *SignedBeaconBlock) PbBlindedBellatrixBlock() (*eth.SignedBlindedBeaconB
// PbCapellaBlock returns the underlying protobuf object.
func (b *SignedBeaconBlock) PbCapellaBlock() (*eth.SignedBeaconBlockCapella, error) {
if b.version != version.Capella || b.IsBlinded() {
return nil, errNotSupported("PbCapellaBlock", b.version)
return nil, ErrNotSupported("PbCapellaBlock", b.version)
}
pb, err := b.Proto()
if err != nil {
@@ -177,7 +177,7 @@ func (b *SignedBeaconBlock) PbCapellaBlock() (*eth.SignedBeaconBlockCapella, err
// PbBlindedCapellaBlock returns the underlying protobuf object.
func (b *SignedBeaconBlock) PbBlindedCapellaBlock() (*eth.SignedBlindedBeaconBlockCapella, error) {
if b.version != version.Capella || !b.IsBlinded() {
return nil, errNotSupported("PbBlindedCapellaBlock", b.version)
return nil, ErrNotSupported("PbBlindedCapellaBlock", b.version)
}
pb, err := b.Proto()
if err != nil {
@@ -779,7 +779,7 @@ func (b *BeaconBlockBody) VoluntaryExits() []*eth.SignedVoluntaryExit {
// SyncAggregate returns the sync aggregate in the block.
func (b *BeaconBlockBody) SyncAggregate() (*eth.SyncAggregate, error) {
if b.version == version.Phase0 {
return nil, errNotSupported("SyncAggregate", b.version)
return nil, ErrNotSupported("SyncAggregate", b.version)
}
return b.syncAggregate, nil
}
@@ -788,7 +788,7 @@ func (b *BeaconBlockBody) SyncAggregate() (*eth.SyncAggregate, error) {
func (b *BeaconBlockBody) Execution() (interfaces.ExecutionData, error) {
switch b.version {
case version.Phase0, version.Altair:
return nil, errNotSupported("Execution", b.version)
return nil, ErrNotSupported("Execution", b.version)
case version.Bellatrix:
if b.isBlinded {
var ph *enginev1.ExecutionPayloadHeader
@@ -838,7 +838,7 @@ func (b *BeaconBlockBody) Execution() (interfaces.ExecutionData, error) {
func (b *BeaconBlockBody) BLSToExecutionChanges() ([]*eth.SignedBLSToExecutionChange, error) {
if b.version < version.Capella {
return nil, errNotSupported("BLSToExecutionChanges", b.version)
return nil, ErrNotSupported("BLSToExecutionChanges", b.version)
}
return b.blsToExecutionChanges, nil
}

View File

@@ -75,6 +75,6 @@ type SignedBeaconBlock struct {
signature [field_params.BLSSignatureLength]byte
}
func errNotSupported(funcName string, ver int) error {
func ErrNotSupported(funcName string, ver int) error {
return errors.Wrap(ErrUnsupportedGetter, fmt.Sprintf("%s is not supported for %s", funcName, version.String(ver)))
}

View File

@@ -0,0 +1,29 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"getters.go",
"interface.go",
"types.go",
],
importpath = "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute",
visibility = ["//visibility:public"],
deps = [
"//consensus-types/blocks:go_default_library",
"//proto/engine/v1:go_default_library",
"//runtime/version:go_default_library",
"@com_github_pkg_errors//:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["getters_test.go"],
embed = [":go_default_library"],
deps = [
"//proto/engine/v1:go_default_library",
"//runtime/version:go_default_library",
"//testing/require:go_default_library",
],
)

View File

@@ -0,0 +1,76 @@
package payloadattribute
import (
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
)
// Version returns the version of the payload attribute.
func (a *data) Version() int {
return a.version
}
// PrevRandao returns the previous randao value of the payload attribute.
func (a *data) PrevRandao() []byte {
return a.prevRandao
}
// Timestamps returns the timestamp of the payload attribute.
func (a *data) Timestamps() uint64 {
return a.timeStamp
}
// SuggestedFeeRecipient returns the suggested fee recipient of the payload attribute.
func (a *data) SuggestedFeeRecipient() []byte {
return a.suggestedFeeRecipient
}
// Withdrawals returns the withdrawals of the payload attribute.
// Support for withdrawals was added in version 2 of the payload attribute.
func (a *data) Withdrawals() ([]*enginev1.Withdrawal, error) {
if a == nil {
return nil, errNilPayloadAttribute
}
if a.version < version.Capella {
return nil, blocks.ErrNotSupported("Withdrawals", a.version)
}
return a.withdrawals, nil
}
// PbV1 returns the payload attribute in version 1.
func (a *data) PbV1() (*enginev1.PayloadAttributes, error) {
if a == nil {
return nil, errNilPayloadAttribute
}
if a.version != version.Bellatrix {
return nil, blocks.ErrNotSupported("PayloadAttributePbV1", a.version)
}
if a.timeStamp == 0 && len(a.prevRandao) == 0 {
return nil, nil
}
return &enginev1.PayloadAttributes{
Timestamp: a.timeStamp,
PrevRandao: a.prevRandao,
SuggestedFeeRecipient: a.suggestedFeeRecipient,
}, nil
}
// PbV2 returns the payload attribute in version 2.
func (a *data) PbV2() (*enginev1.PayloadAttributesV2, error) {
if a == nil {
return nil, errNilPayloadAttribute
}
if a.version != version.Capella {
return nil, blocks.ErrNotSupported("PayloadAttributePbV2", a.version)
}
if a.timeStamp == 0 && len(a.prevRandao) == 0 {
return nil, nil
}
return &enginev1.PayloadAttributesV2{
Timestamp: a.timeStamp,
PrevRandao: a.prevRandao,
SuggestedFeeRecipient: a.suggestedFeeRecipient,
Withdrawals: a.withdrawals,
}, nil
}

View File

@@ -0,0 +1,143 @@
package payloadattribute
import (
"testing"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/testing/require"
)
func TestPayloadAttributeGetters(t *testing.T) {
tests := []struct {
name string
tc func(t *testing.T)
}{
{
name: "Get version",
tc: func(t *testing.T) {
a := EmptyWithVersion(version.Capella)
require.Equal(t, version.Capella, a.Version())
},
},
{
name: "Get prev randao",
tc: func(t *testing.T) {
r := []byte{1, 2, 3}
a, err := New(&enginev1.PayloadAttributes{PrevRandao: r})
require.NoError(t, err)
require.DeepEqual(t, r, a.PrevRandao())
},
},
{
name: "Get suggested fee recipient",
tc: func(t *testing.T) {
r := []byte{4, 5, 6}
a, err := New(&enginev1.PayloadAttributes{SuggestedFeeRecipient: r})
require.NoError(t, err)
require.DeepEqual(t, r, a.SuggestedFeeRecipient())
},
},
{
name: "Get timestamp",
tc: func(t *testing.T) {
r := uint64(123)
a, err := New(&enginev1.PayloadAttributes{Timestamp: r})
require.NoError(t, err)
require.Equal(t, r, a.Timestamps())
},
},
{
name: "Get withdrawals (bellatrix)",
tc: func(t *testing.T) {
a := EmptyWithVersion(version.Bellatrix)
_, err := a.Withdrawals()
require.ErrorContains(t, "Withdrawals is not supported for bellatrix: unsupported getter", err)
},
},
{
name: "Get withdrawals (capella)",
tc: func(t *testing.T) {
wd := []*enginev1.Withdrawal{{WithdrawalIndex: 1}, {WithdrawalIndex: 2}, {WithdrawalIndex: 3}}
a, err := New(&enginev1.PayloadAttributesV2{Withdrawals: wd})
require.NoError(t, err)
got, err := a.Withdrawals()
require.NoError(t, err)
require.DeepEqual(t, wd, got)
},
},
{
name: "Get PbV1 (bad version)",
tc: func(t *testing.T) {
a, err := New(&enginev1.PayloadAttributes{})
require.NoError(t, err)
_, err = a.PbV2()
require.ErrorContains(t, "PayloadAttributePbV2 is not supported for bellatrix: unsupported getter", err)
},
},
{
name: "Get PbV2 (bad version)",
tc: func(t *testing.T) {
a, err := New(&enginev1.PayloadAttributesV2{})
require.NoError(t, err)
_, err = a.PbV1()
require.ErrorContains(t, "PayloadAttributePbV1 is not supported for capella: unsupported getter", err)
},
},
{
name: "Get PbV1 (nil)",
tc: func(t *testing.T) {
a, err := New(&enginev1.PayloadAttributes{})
require.NoError(t, err)
got, err := a.PbV1()
require.NoError(t, err)
require.Equal(t, (*enginev1.PayloadAttributes)(nil), got)
},
},
{
name: "Get PbV2 (nil)",
tc: func(t *testing.T) {
a, err := New(&enginev1.PayloadAttributesV2{})
require.NoError(t, err)
got, err := a.PbV2()
require.NoError(t, err)
require.Equal(t, (*enginev1.PayloadAttributesV2)(nil), got)
},
},
{
name: "Get PbV1",
tc: func(t *testing.T) {
p := &enginev1.PayloadAttributes{
Timestamp: 1,
PrevRandao: []byte{1, 2, 3},
SuggestedFeeRecipient: []byte{4, 5, 6},
}
a, err := New(p)
require.NoError(t, err)
got, err := a.PbV1()
require.NoError(t, err)
require.DeepEqual(t, p, got)
},
},
{
name: "Get PbV2",
tc: func(t *testing.T) {
p := &enginev1.PayloadAttributesV2{
Timestamp: 1,
PrevRandao: []byte{1, 2, 3},
SuggestedFeeRecipient: []byte{4, 5, 6},
Withdrawals: []*enginev1.Withdrawal{{WithdrawalIndex: 1}, {WithdrawalIndex: 2}, {WithdrawalIndex: 3}},
}
a, err := New(p)
require.NoError(t, err)
got, err := a.PbV2()
require.NoError(t, err)
require.DeepEqual(t, p, got)
},
},
}
for _, test := range tests {
t.Run(test.name, test.tc)
}
}

View File

@@ -0,0 +1,15 @@
package payloadattribute
import (
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
)
type Attributer interface {
Version() int
PrevRandao() []byte
Timestamps() uint64
SuggestedFeeRecipient() []byte
Withdrawals() ([]*enginev1.Withdrawal, error)
PbV1() (*enginev1.PayloadAttributes, error)
PbV2() (*enginev1.PayloadAttributesV2, error)
}

View File

@@ -0,0 +1,73 @@
package payloadattribute
import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
)
var (
_ = Attributer(&data{})
)
type data struct {
version int
timeStamp uint64
prevRandao []byte
suggestedFeeRecipient []byte
withdrawals []*enginev1.Withdrawal
}
var (
errNilPayloadAttribute = errors.New("received nil payload attribute")
errUnsupportedPayloadAttribute = errors.New("unsupported payload attribute")
)
// New returns a new payload attribute with the given input object.
func New(i interface{}) (Attributer, error) {
switch a := i.(type) {
case nil:
return nil, blocks.ErrNilObject
case *enginev1.PayloadAttributes:
return initPayloadAttributeFromV1(a)
case *enginev1.PayloadAttributesV2:
return initPayloadAttributeFromV2(a)
default:
return nil, errors.Wrapf(errUnsupportedPayloadAttribute, "unable to create payload attribute from type %T", i)
}
}
// EmptyWithVersion returns an empty payload attribute with the given version.
func EmptyWithVersion(version int) Attributer {
return &data{
version: version,
}
}
func initPayloadAttributeFromV1(a *enginev1.PayloadAttributes) (Attributer, error) {
if a == nil {
return nil, errNilPayloadAttribute
}
return &data{
version: version.Bellatrix,
prevRandao: a.PrevRandao,
timeStamp: a.Timestamp,
suggestedFeeRecipient: a.SuggestedFeeRecipient,
}, nil
}
func initPayloadAttributeFromV2(a *enginev1.PayloadAttributesV2) (Attributer, error) {
if a == nil {
return nil, errNilPayloadAttribute
}
return &data{
version: version.Capella,
prevRandao: a.PrevRandao,
timeStamp: a.Timestamp,
suggestedFeeRecipient: a.SuggestedFeeRecipient,
withdrawals: a.Withdrawals,
}, nil
}