Add Gloas consensus type block package (#15618)

Co-authored-by: Bastin <43618253+Inspector-Butters@users.noreply.github.com>
This commit is contained in:
terence
2025-11-25 04:21:19 -05:00
committed by GitHub
parent 26100e074d
commit 5bbdebee22
21 changed files with 933 additions and 44 deletions

View File

@@ -2805,6 +2805,10 @@ func TestProcessLightClientUpdate(t *testing.T) {
require.NoError(t, s.cfg.BeaconDB.SaveHeadBlockRoot(ctx, [32]byte{1, 2}))
for _, testVersion := range version.All()[1:] {
if testVersion == version.Gloas {
// TODO(16027): Unskip light client tests for Gloas
continue
}
t.Run(version.String(testVersion), func(t *testing.T) {
l := util.NewTestLightClient(t, testVersion)

View File

@@ -90,6 +90,9 @@ func IsExecutionEnabled(st state.ReadOnlyBeaconState, body interfaces.ReadOnlyBe
if st == nil || body == nil {
return false, errors.New("nil state or block body")
}
if st.Version() >= version.Capella {
return true, nil
}
if IsPreBellatrixVersion(st.Version()) {
return false, nil
}

View File

@@ -260,11 +260,12 @@ func Test_IsExecutionBlockCapella(t *testing.T) {
func Test_IsExecutionEnabled(t *testing.T) {
tests := []struct {
name string
payload *enginev1.ExecutionPayload
header interfaces.ExecutionData
useAltairSt bool
want bool
name string
payload *enginev1.ExecutionPayload
header interfaces.ExecutionData
useAltairSt bool
useCapellaSt bool
want bool
}{
{
name: "use older than bellatrix state",
@@ -331,6 +332,17 @@ func Test_IsExecutionEnabled(t *testing.T) {
}(),
want: true,
},
{
name: "capella state always enabled",
payload: emptyPayload(),
header: func() interfaces.ExecutionData {
h, err := emptyPayloadHeader()
require.NoError(t, err)
return h
}(),
useCapellaSt: true,
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -342,6 +354,8 @@ func Test_IsExecutionEnabled(t *testing.T) {
require.NoError(t, err)
if tt.useAltairSt {
st, _ = util.DeterministicGenesisStateAltair(t, 1)
} else if tt.useCapellaSt {
st, _ = util.DeterministicGenesisStateCapella(t, 1)
}
got, err := blocks.IsExecutionEnabled(st, body)
require.NoError(t, err)

View File

@@ -216,6 +216,10 @@ func TestStore_LightClientUpdate_CanSaveRetrieve(t *testing.T) {
db := setupDB(t)
ctx := t.Context()
for _, testVersion := range version.All()[1:] {
if testVersion == version.Gloas {
// TODO(16027): Unskip light client tests for Gloas
continue
}
t.Run(version.String(testVersion), func(t *testing.T) {
update, err := createUpdate(t, testVersion)
require.NoError(t, err)
@@ -572,6 +576,10 @@ func TestStore_LightClientBootstrap_CanSaveRetrieve(t *testing.T) {
require.IsNil(t, retrievedBootstrap)
})
for _, testVersion := range version.All()[1:] {
if testVersion == version.Gloas {
// TODO(16027): Unskip light client tests for Gloas
continue
}
t.Run(version.String(testVersion), func(t *testing.T) {
bootstrap, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().VersionToForkEpochMap()[testVersion]) * uint64(params.BeaconConfig().SlotsPerEpoch)))
require.NoError(t, err)

View File

@@ -33,6 +33,10 @@ func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T)
params.OverrideBeaconConfig(cfg)
for _, testVersion := range version.All()[1:] {
if testVersion == version.Gloas {
// TODO(16027): Unskip light client tests for Gloas
continue
}
t.Run(version.String(testVersion), func(t *testing.T) {
l := util.NewTestLightClient(t, testVersion)

View File

@@ -47,6 +47,10 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) {
params.OverrideBeaconConfig(cfg)
for _, testVersion := range version.All()[1:] {
if testVersion == version.Gloas {
// TODO(16027): Unskip light client tests for Gloas
continue
}
t.Run(version.String(testVersion), func(t *testing.T) {
l := util.NewTestLightClient(t, testVersion)
@@ -178,6 +182,10 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) {
t.Run("can save retrieve", func(t *testing.T) {
for _, testVersion := range version.All()[1:] {
if testVersion == version.Gloas {
// TODO(16027): Unskip light client tests for Gloas
continue
}
t.Run(version.String(testVersion), func(t *testing.T) {
slot := primitives.Slot(params.BeaconConfig().VersionToForkEpochMap()[testVersion] * primitives.Epoch(config.SlotsPerEpoch)).Add(1)
@@ -732,6 +740,10 @@ func TestLightClientHandler_GetLightClientFinalityUpdate(t *testing.T) {
})
for _, testVersion := range version.All()[1:] {
if testVersion == version.Gloas {
// TODO(16027): Unskip light client tests for Gloas
continue
}
t.Run(version.String(testVersion), func(t *testing.T) {
ctx := t.Context()
@@ -827,6 +839,10 @@ func TestLightClientHandler_GetLightClientOptimisticUpdate(t *testing.T) {
})
for _, testVersion := range version.All()[1:] {
if testVersion == version.Gloas {
// TODO(16027): Unskip light client tests for Gloas
continue
}
t.Run(version.String(testVersion), func(t *testing.T) {
ctx := t.Context()
l := util.NewTestLightClient(t, testVersion)

View File

@@ -0,0 +1,3 @@
### Added
- Implement Gloas fork support in consensus-types/blocks with factory methods, getters, setters, and proto handling

View File

@@ -53,6 +53,7 @@ go_test(
"roblob_test.go",
"roblock_test.go",
"rodatacolumn_test.go",
"setters_test.go",
],
embed = [":go_default_library"],
deps = [

View File

@@ -82,6 +82,8 @@ func NewSignedBeaconBlock(i any) (interfaces.SignedBeaconBlock, error) {
return initBlindedSignedBlockFromProtoFulu(b)
case *eth.GenericSignedBeaconBlock_BlindedFulu:
return initBlindedSignedBlockFromProtoFulu(b.BlindedFulu)
case *eth.SignedBeaconBlockGloas:
return initSignedBlockFromProtoGloas(b)
default:
return nil, errors.Wrapf(ErrUnsupportedSignedBeaconBlock, "unable to create block from type %T", i)
}
@@ -138,6 +140,8 @@ func NewBeaconBlock(i any) (interfaces.ReadOnlyBeaconBlock, error) {
return initBlindedBlockFromProtoFulu(b)
case *eth.GenericBeaconBlock_BlindedFulu:
return initBlindedBlockFromProtoFulu(b.BlindedFulu)
case *eth.BeaconBlockGloas:
return initBlockFromProtoGloas(b)
default:
return nil, errors.Wrapf(errUnsupportedBeaconBlock, "unable to create block from type %T", i)
}
@@ -168,6 +172,8 @@ func NewBeaconBlockBody(i any) (interfaces.ReadOnlyBeaconBlockBody, error) {
return initBlockBodyFromProtoElectra(b)
case *eth.BlindedBeaconBlockBodyElectra:
return initBlindedBlockBodyFromProtoElectra(b)
case *eth.BeaconBlockBodyGloas:
return initBlockBodyFromProtoGloas(b)
default:
return nil, errors.Wrapf(errUnsupportedBeaconBlockBody, "unable to create block body from type %T", i)
}
@@ -260,6 +266,12 @@ func BuildSignedBeaconBlock(blk interfaces.ReadOnlyBeaconBlock, signature []byte
return nil, errIncorrectBlockVersion
}
return NewSignedBeaconBlock(&eth.SignedBeaconBlockFulu{Block: pb, Signature: signature})
case version.Gloas:
pb, ok := pb.(*eth.BeaconBlockGloas)
if !ok {
return nil, errIncorrectBlockVersion
}
return NewSignedBeaconBlock(&eth.SignedBeaconBlockGloas{Block: pb, Signature: signature})
default:
return nil, errUnsupportedBeaconBlock
}

View File

@@ -161,6 +161,18 @@ func Test_NewSignedBeaconBlock(t *testing.T) {
assert.Equal(t, version.Deneb, b.Version())
assert.Equal(t, true, b.IsBlinded())
})
t.Run("SignedBeaconBlockGloas", func(t *testing.T) {
pb := &eth.SignedBeaconBlockGloas{
Block: &eth.BeaconBlockGloas{
Body: &eth.BeaconBlockBodyGloas{},
},
Signature: []byte("sig"),
}
b, err := NewSignedBeaconBlock(pb)
require.NoError(t, err)
assert.Equal(t, version.Gloas, b.Version())
assert.Equal(t, false, b.IsBlinded())
})
t.Run("nil", func(t *testing.T) {
_, err := NewSignedBeaconBlock(nil)
assert.ErrorContains(t, "received nil object", err)
@@ -276,6 +288,13 @@ func Test_NewBeaconBlock(t *testing.T) {
assert.Equal(t, version.Deneb, b.Version())
assert.Equal(t, true, b.IsBlinded())
})
t.Run("BeaconBlockGloas", func(t *testing.T) {
pb := &eth.BeaconBlockGloas{Body: &eth.BeaconBlockBodyGloas{}}
b, err := NewBeaconBlock(pb)
require.NoError(t, err)
assert.Equal(t, version.Gloas, b.Version())
assert.Equal(t, false, b.IsBlinded())
})
t.Run("nil", func(t *testing.T) {
_, err := NewBeaconBlock(nil)
assert.ErrorContains(t, "received nil object", err)
@@ -354,6 +373,15 @@ func Test_NewBeaconBlockBody(t *testing.T) {
assert.Equal(t, version.Deneb, b.version)
assert.Equal(t, true, b.IsBlinded())
})
t.Run("BeaconBlockBodyGloas", func(t *testing.T) {
pb := &eth.BeaconBlockBodyGloas{}
i, err := NewBeaconBlockBody(pb)
require.NoError(t, err)
b, ok := i.(*BeaconBlockBody)
require.Equal(t, true, ok)
assert.Equal(t, version.Gloas, b.version)
assert.Equal(t, false, b.IsBlinded())
})
t.Run("nil", func(t *testing.T) {
_, err := NewBeaconBlockBody(nil)
assert.ErrorContains(t, "received nil object", err)
@@ -425,6 +453,14 @@ func Test_BuildSignedBeaconBlock(t *testing.T) {
assert.Equal(t, version.Deneb, sb.Version())
assert.Equal(t, true, sb.IsBlinded())
})
t.Run("Gloas", func(t *testing.T) {
b := &BeaconBlock{version: version.Gloas, body: &BeaconBlockBody{version: version.Gloas}}
sb, err := BuildSignedBeaconBlock(b, sig[:])
require.NoError(t, err)
assert.DeepEqual(t, sig, sb.Signature())
assert.Equal(t, version.Gloas, sb.Version())
assert.Equal(t, false, sb.IsBlinded())
})
}
func TestBuildSignedBeaconBlockFromExecutionPayload(t *testing.T) {
@@ -535,4 +571,21 @@ func TestBuildSignedBeaconBlockFromExecutionPayload(t *testing.T) {
require.DeepEqual(t, uint64(123), payload.ExcessBlobGas)
require.DeepEqual(t, uint64(321), payload.BlobGasUsed)
})
t.Run("gloas execution unsupported", func(t *testing.T) {
base := &SignedBeaconBlock{
version: version.Gloas,
block: &BeaconBlock{version: version.Gloas, body: &BeaconBlockBody{version: version.Gloas}},
}
blinded := &testBlindedSignedBeaconBlock{SignedBeaconBlock: base}
_, err := BuildSignedBeaconBlockFromExecutionPayload(blinded, nil)
require.ErrorContains(t, "Execution is not supported for gloas", err)
})
}
type testBlindedSignedBeaconBlock struct {
*SignedBeaconBlock
}
func (b *testBlindedSignedBeaconBlock) IsBlinded() bool {
return true
}

View File

@@ -80,6 +80,8 @@ func (b *SignedBeaconBlock) Copy() (interfaces.SignedBeaconBlock, error) {
return initBlindedSignedBlockFromProtoFulu(pb.(*eth.SignedBlindedBeaconBlockFulu).Copy())
}
return initSignedBlockFromProtoFulu(pb.(*eth.SignedBeaconBlockFulu).Copy())
case version.Gloas:
return initSignedBlockFromProtoGloas(eth.CopySignedBeaconBlockGloas(pb.(*eth.SignedBeaconBlockGloas)))
default:
return nil, errIncorrectBlockVersion
}
@@ -157,6 +159,9 @@ func (b *SignedBeaconBlock) PbGenericBlock() (*eth.GenericSignedBeaconBlock, err
return &eth.GenericSignedBeaconBlock{
Block: &eth.GenericSignedBeaconBlock_Fulu{Fulu: bc},
}, nil
case version.Gloas:
// Gloas doesn't support GenericSignedBeaconBlock yet
return nil, errors.New("Gloas blocks don't support GenericSignedBeaconBlock conversion")
default:
return nil, errIncorrectBlockVersion
}
@@ -164,7 +169,7 @@ func (b *SignedBeaconBlock) PbGenericBlock() (*eth.GenericSignedBeaconBlock, err
// ToBlinded converts a non-blinded block to its blinded equivalent.
func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, error) {
if b.version < version.Bellatrix {
if b.version < version.Bellatrix || b.version >= version.Gloas {
return nil, ErrUnsupportedVersion
}
if b.IsBlinded() {
@@ -376,7 +381,7 @@ func (b *SignedBeaconBlock) Version() int {
// IsBlinded metadata on whether a block is blinded
func (b *SignedBeaconBlock) IsBlinded() bool {
return b.version >= version.Bellatrix && b.block.body.executionPayload == nil
return b.version < version.Gloas && b.version >= version.Bellatrix && b.block.body.executionPayload == nil
}
// Header converts the underlying protobuf object from blinded block to header format.
@@ -437,6 +442,8 @@ func (b *SignedBeaconBlock) MarshalSSZ() ([]byte, error) {
return pb.(*eth.SignedBlindedBeaconBlockFulu).MarshalSSZ()
}
return pb.(*eth.SignedBeaconBlockFulu).MarshalSSZ()
case version.Gloas:
return pb.(*eth.SignedBeaconBlockGloas).MarshalSSZ()
default:
return []byte{}, errIncorrectBlockVersion
}
@@ -479,6 +486,8 @@ func (b *SignedBeaconBlock) MarshalSSZTo(dst []byte) ([]byte, error) {
return pb.(*eth.SignedBlindedBeaconBlockFulu).MarshalSSZTo(dst)
}
return pb.(*eth.SignedBeaconBlockFulu).MarshalSSZTo(dst)
case version.Gloas:
return pb.(*eth.SignedBeaconBlockGloas).MarshalSSZTo(dst)
default:
return []byte{}, errIncorrectBlockVersion
}
@@ -526,6 +535,8 @@ func (b *SignedBeaconBlock) SizeSSZ() int {
return pb.(*eth.SignedBlindedBeaconBlockFulu).SizeSSZ()
}
return pb.(*eth.SignedBeaconBlockFulu).SizeSSZ()
case version.Gloas:
return pb.(*eth.SignedBeaconBlockGloas).SizeSSZ()
default:
panic(incorrectBlockVersion)
}
@@ -666,6 +677,16 @@ func (b *SignedBeaconBlock) UnmarshalSSZ(buf []byte) error {
return err
}
}
case version.Gloas:
pb := &eth.SignedBeaconBlockGloas{}
err := pb.UnmarshalSSZ(buf)
if err != nil {
return err
}
newBlock, err = initSignedBlockFromProtoGloas(pb)
if err != nil {
return err
}
default:
return errIncorrectBlockVersion
}
@@ -705,7 +726,7 @@ func (b *BeaconBlock) IsNil() bool {
// IsBlinded checks if the beacon block is a blinded block.
func (b *BeaconBlock) IsBlinded() bool {
return b.version >= version.Bellatrix && b.body.executionPayload == nil
return b.version < version.Gloas && b.version >= version.Bellatrix && b.body.executionPayload == nil
}
// Version of the underlying protobuf object.
@@ -749,6 +770,9 @@ func (b *BeaconBlock) HashTreeRoot() ([field_params.RootLength]byte, error) {
return pb.(*eth.BlindedBeaconBlockFulu).HashTreeRoot()
}
return pb.(*eth.BeaconBlockElectra).HashTreeRoot()
case version.Gloas:
return pb.(*eth.BeaconBlockGloas).HashTreeRoot()
default:
return [field_params.RootLength]byte{}, errIncorrectBlockVersion
}
@@ -790,6 +814,8 @@ func (b *BeaconBlock) HashTreeRootWith(h *ssz.Hasher) error {
return pb.(*eth.BlindedBeaconBlockFulu).HashTreeRootWith(h)
}
return pb.(*eth.BeaconBlockElectra).HashTreeRootWith(h)
case version.Gloas:
return pb.(*eth.BeaconBlockGloas).HashTreeRootWith(h)
default:
return errIncorrectBlockVersion
}
@@ -832,6 +858,8 @@ func (b *BeaconBlock) MarshalSSZ() ([]byte, error) {
return pb.(*eth.BlindedBeaconBlockFulu).MarshalSSZ()
}
return pb.(*eth.BeaconBlockElectra).MarshalSSZ()
case version.Gloas:
return pb.(*eth.BeaconBlockGloas).MarshalSSZ()
default:
return []byte{}, errIncorrectBlockVersion
}
@@ -874,6 +902,8 @@ func (b *BeaconBlock) MarshalSSZTo(dst []byte) ([]byte, error) {
return pb.(*eth.BlindedBeaconBlockFulu).MarshalSSZTo(dst)
}
return pb.(*eth.BeaconBlockElectra).MarshalSSZTo(dst)
case version.Gloas:
return pb.(*eth.BeaconBlockGloas).MarshalSSZTo(dst)
default:
return []byte{}, errIncorrectBlockVersion
}
@@ -921,6 +951,8 @@ func (b *BeaconBlock) SizeSSZ() int {
return pb.(*eth.BlindedBeaconBlockFulu).SizeSSZ()
}
return pb.(*eth.BeaconBlockElectra).SizeSSZ()
case version.Gloas:
return pb.(*eth.BeaconBlockGloas).SizeSSZ()
default:
panic(incorrectBodyVersion)
}
@@ -1061,6 +1093,16 @@ func (b *BeaconBlock) UnmarshalSSZ(buf []byte) error {
return err
}
}
case version.Gloas:
pb := &eth.BeaconBlockGloas{}
if err := pb.UnmarshalSSZ(buf); err != nil {
return err
}
var err error
newBlock, err = initBlockFromProtoGloas(pb)
if err != nil {
return err
}
default:
return errIncorrectBlockVersion
}
@@ -1200,15 +1242,13 @@ func (b *BeaconBlockBody) SyncAggregate() (*eth.SyncAggregate, error) {
// Execution returns the execution payload of the block body.
func (b *BeaconBlockBody) Execution() (interfaces.ExecutionData, error) {
switch b.version {
case version.Phase0, version.Altair:
if b.version <= version.Altair || b.version >= version.Gloas {
return nil, consensus_types.ErrNotSupported("Execution", b.version)
default:
if b.IsBlinded() {
return b.executionPayloadHeader, nil
}
return b.executionPayload, nil
}
if b.IsBlinded() {
return b.executionPayloadHeader, nil
}
return b.executionPayload, nil
}
func (b *BeaconBlockBody) BLSToExecutionChanges() ([]*eth.SignedBLSToExecutionChange, error) {
@@ -1233,12 +1273,28 @@ func (b *BeaconBlockBody) BlobKzgCommitments() ([][]byte, error) {
// ExecutionRequests returns the execution requests
func (b *BeaconBlockBody) ExecutionRequests() (*enginev1.ExecutionRequests, error) {
if b.version < version.Electra {
if b.version < version.Electra || b.version >= version.Gloas {
return nil, consensus_types.ErrNotSupported("ExecutionRequests", b.version)
}
return b.executionRequests, nil
}
// PayloadAttestations returns the payload attestations in the block.
func (b *BeaconBlockBody) PayloadAttestations() ([]*eth.PayloadAttestation, error) {
if b.version >= version.Gloas {
return b.payloadAttestations, nil
}
return nil, consensus_types.ErrNotSupported("PayloadAttestations", b.version)
}
// SignedExecutionPayloadBid returns the signed execution payload header in the block.
func (b *BeaconBlockBody) SignedExecutionPayloadBid() (*eth.SignedExecutionPayloadBid, error) {
if b.version >= version.Gloas {
return b.signedExecutionPayloadBid, nil
}
return nil, consensus_types.ErrNotSupported("SignedExecutionPayloadBid", b.version)
}
// Version returns the version of the beacon block body
func (b *BeaconBlockBody) Version() int {
return b.version
@@ -1280,6 +1336,8 @@ func (b *BeaconBlockBody) HashTreeRoot() ([field_params.RootLength]byte, error)
return pb.(*eth.BlindedBeaconBlockBodyElectra).HashTreeRoot()
}
return pb.(*eth.BeaconBlockBodyElectra).HashTreeRoot()
case version.Gloas:
return pb.(*eth.BeaconBlockBodyGloas).HashTreeRoot()
default:
return [field_params.RootLength]byte{}, errIncorrectBodyVersion
}
@@ -1287,5 +1345,5 @@ func (b *BeaconBlockBody) HashTreeRoot() ([field_params.RootLength]byte, error)
// IsBlinded checks if the beacon block body is a blinded block body.
func (b *BeaconBlockBody) IsBlinded() bool {
return b.version >= version.Bellatrix && b.executionPayload == nil
return b.version < version.Gloas && b.version >= version.Bellatrix && b.executionPayload == nil
}

View File

@@ -3,7 +3,9 @@ package blocks
import (
"testing"
bitfield "github.com/OffchainLabs/go-bitfield"
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
consensus_types "github.com/OffchainLabs/prysm/v7/consensus-types"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
@@ -73,14 +75,54 @@ func Test_SignedBeaconBlock_IsNil(t *testing.T) {
}
func Test_SignedBeaconBlock_Copy(t *testing.T) {
bb := &BeaconBlockBody{}
b := &BeaconBlock{body: bb}
sb := &SignedBeaconBlock{block: b}
cp, err := sb.Copy()
require.NoError(t, err)
assert.NotEqual(t, cp, sb)
assert.NotEqual(t, cp.Block(), sb.block)
assert.NotEqual(t, cp.Block().Body(), sb.block.body)
t.Run("basic", func(t *testing.T) {
bb := &BeaconBlockBody{}
b := &BeaconBlock{body: bb}
sb := &SignedBeaconBlock{block: b}
cp, err := sb.Copy()
require.NoError(t, err)
assert.NotEqual(t, cp, sb)
assert.NotEqual(t, cp.Block(), sb.block)
assert.NotEqual(t, cp.Block().Body(), sb.block.body)
})
t.Run("gloas deep copy", func(t *testing.T) {
payload := []*eth.PayloadAttestation{{Signature: []byte{0x01}}}
payloadBid := &eth.SignedExecutionPayloadBid{Signature: []byte{0x02}}
sb := &SignedBeaconBlock{
version: version.Gloas,
block: &BeaconBlock{
version: version.Gloas,
body: &BeaconBlockBody{
version: version.Gloas,
payloadAttestations: payload,
signedExecutionPayloadBid: payloadBid,
},
},
}
cpIntf, err := sb.Copy()
require.NoError(t, err)
cp, ok := cpIntf.(*SignedBeaconBlock)
require.Equal(t, true, ok)
assert.NotEqual(t, sb, cp)
require.Equal(t, version.Gloas, cp.version)
att, err := cp.Block().Body().PayloadAttestations()
require.NoError(t, err)
require.DeepEqual(t, payload, att)
origAttSig := att[0].Signature[0]
payload[0].Signature[0] ^= 0xFF
require.Equal(t, origAttSig, att[0].Signature[0])
bid, err := cp.Block().Body().SignedExecutionPayloadBid()
require.NoError(t, err)
require.DeepEqual(t, payloadBid, bid)
origBidSig := bid.Signature[0]
payloadBid.Signature[0] ^= 0xFF
require.Equal(t, origBidSig, bid.Signature[0])
})
}
func Test_SignedBeaconBlock_Version(t *testing.T) {
@@ -122,6 +164,16 @@ func Test_SignedBeaconBlock_Header(t *testing.T) {
assert.DeepEqual(t, expectedHTR[:], h.Header.BodyRoot)
}
func Test_SignedBeaconBlock_PbGenericBlockGloasUnsupported(t *testing.T) {
sb := &SignedBeaconBlock{
version: version.Gloas,
block: &BeaconBlock{version: version.Gloas, body: &BeaconBlockBody{version: version.Gloas}},
}
_, err := sb.PbGenericBlock()
require.ErrorContains(t, "Gloas blocks don't support GenericSignedBeaconBlock conversion", err)
}
func Test_SignedBeaconBlock_UnmarshalSSZ(t *testing.T) {
pb := hydrateSignedBeaconBlock()
buf, err := pb.MarshalSSZ()
@@ -190,6 +242,17 @@ func Test_BeaconBlock_IsBlinded(t *testing.T) {
b1 := &SignedBeaconBlock{version: version.Bellatrix, block: &BeaconBlock{body: &BeaconBlockBody{executionPayloadHeader: executionPayloadHeader{}}}}
assert.Equal(t, true, b1.IsBlinded())
t.Run("gloas never blinded", func(t *testing.T) {
sb := &SignedBeaconBlock{version: version.Gloas, block: &BeaconBlock{body: &BeaconBlockBody{version: version.Gloas}}}
assert.Equal(t, false, sb.IsBlinded())
})
}
func Test_SignedBeaconBlock_ToBlinded_GloasUnsupported(t *testing.T) {
sb := &SignedBeaconBlock{version: version.Gloas, block: &BeaconBlock{version: version.Gloas, body: &BeaconBlockBody{version: version.Gloas}}}
_, err := sb.ToBlinded()
require.ErrorIs(t, err, ErrUnsupportedVersion)
}
func Test_BeaconBlock_Version(t *testing.T) {
@@ -324,6 +387,46 @@ func Test_BeaconBlockBody_Deposits(t *testing.T) {
assert.DeepSSZEqual(t, d, bb.Block().Body().Deposits())
}
func Test_BeaconBlockBody_PayloadAttestations(t *testing.T) {
t.Run("unsupported before gloas", func(t *testing.T) {
bb := &BeaconBlockBody{version: version.Fulu}
_, err := bb.PayloadAttestations()
require.ErrorIs(t, err, consensus_types.ErrUnsupportedField)
})
t.Run("gloas returns payload", func(t *testing.T) {
payload := []*eth.PayloadAttestation{{Signature: []byte{0x01}}}
sb := &SignedBeaconBlock{
version: version.Gloas,
block: &BeaconBlock{version: version.Gloas, body: &BeaconBlockBody{version: version.Gloas}},
}
require.NoError(t, sb.SetPayloadAttestations(payload))
got, err := sb.Block().Body().PayloadAttestations()
require.NoError(t, err)
require.DeepEqual(t, payload, got)
})
}
func Test_BeaconBlockBody_SignedExecutionPayloadBid(t *testing.T) {
t.Run("unsupported before gloas", func(t *testing.T) {
bb := &BeaconBlockBody{version: version.Fulu}
_, err := bb.SignedExecutionPayloadBid()
require.ErrorIs(t, err, consensus_types.ErrUnsupportedField)
})
t.Run("gloas returns bid", func(t *testing.T) {
bid := &eth.SignedExecutionPayloadBid{Signature: []byte{0xFF}}
sb := &SignedBeaconBlock{
version: version.Gloas,
block: &BeaconBlock{version: version.Gloas, body: &BeaconBlockBody{version: version.Gloas}},
}
require.NoError(t, sb.SetSignedExecutionPayloadBid(bid))
got, err := sb.Block().Body().SignedExecutionPayloadBid()
require.NoError(t, err)
require.DeepEqual(t, bid, got)
})
}
func Test_BeaconBlockBody_VoluntaryExits(t *testing.T) {
ve := make([]*eth.SignedVoluntaryExit, 0)
bb := &SignedBeaconBlock{block: &BeaconBlock{body: &BeaconBlockBody{}}}
@@ -400,6 +503,32 @@ func Test_BeaconBlockBody_Execution(t *testing.T) {
gas, err = eDenebHeader.ExcessBlobGas()
require.NoError(t, err)
require.DeepEqual(t, gas, uint64(223))
bb = &SignedBeaconBlock{version: version.Gloas, block: &BeaconBlock{version: version.Gloas, body: &BeaconBlockBody{version: version.Gloas}}}
_, err = bb.Block().Body().Execution()
require.ErrorIs(t, err, consensus_types.ErrUnsupportedField)
}
func Test_BeaconBlockBody_ExecutionRequests(t *testing.T) {
t.Run("unsupported before Electra", func(t *testing.T) {
bb := &BeaconBlockBody{version: version.Deneb}
_, err := bb.ExecutionRequests()
require.ErrorIs(t, err, consensus_types.ErrUnsupportedField)
})
t.Run("electra returns requests", func(t *testing.T) {
reqs := &pb.ExecutionRequests{}
bb := &BeaconBlockBody{version: version.Electra, executionRequests: reqs}
result, err := bb.ExecutionRequests()
require.NoError(t, err)
require.Equal(t, reqs, result)
})
t.Run("unsupported for Gloas", func(t *testing.T) {
bb := &BeaconBlockBody{version: version.Gloas}
_, err := bb.ExecutionRequests()
require.ErrorIs(t, err, consensus_types.ErrUnsupportedField)
})
}
func Test_BeaconBlockBody_HashTreeRoot(t *testing.T) {
@@ -413,6 +542,17 @@ func Test_BeaconBlockBody_HashTreeRoot(t *testing.T) {
assert.DeepEqual(t, expectedHTR, actualHTR)
}
func Test_BeaconBlockBody_HashTreeRootGloas(t *testing.T) {
pb := hydrateBeaconBlockBodyGloas()
expectedHTR, err := pb.HashTreeRoot()
require.NoError(t, err)
b, err := initBlockBodyFromProtoGloas(pb)
require.NoError(t, err)
actualHTR, err := b.HashTreeRoot()
require.NoError(t, err)
assert.DeepEqual(t, expectedHTR, actualHTR)
}
func hydrateSignedBeaconBlock() *eth.SignedBeaconBlock {
return &eth.SignedBeaconBlock{
Signature: make([]byte, fieldparams.BLSSignatureLength),
@@ -509,6 +649,43 @@ func hydrateBeaconBlockBodyCapella() *eth.BeaconBlockBodyCapella {
}
}
func hydrateBeaconBlockBodyGloas() *eth.BeaconBlockBodyGloas {
bits := bitfield.NewBitvector512()
bits.SetBitAt(0, true)
return &eth.BeaconBlockBodyGloas{
RandaoReveal: make([]byte, fieldparams.BLSSignatureLength),
Graffiti: make([]byte, fieldparams.RootLength),
Eth1Data: &eth.Eth1Data{
DepositRoot: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
},
SyncAggregate: &eth.SyncAggregate{
SyncCommitteeBits: make([]byte, fieldparams.SyncAggregateSyncCommitteeBytesLength),
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
},
SignedExecutionPayloadBid: &eth.SignedExecutionPayloadBid{
Message: &eth.ExecutionPayloadBid{
ParentBlockHash: make([]byte, fieldparams.RootLength),
ParentBlockRoot: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, 20),
BlobKzgCommitmentsRoot: make([]byte, fieldparams.RootLength),
},
Signature: make([]byte, fieldparams.BLSSignatureLength),
},
PayloadAttestations: []*eth.PayloadAttestation{
{
AggregationBits: bits,
Data: &eth.PayloadAttestationData{
BeaconBlockRoot: make([]byte, fieldparams.RootLength),
},
Signature: make([]byte, fieldparams.BLSSignatureLength),
},
},
}
}
func hydrateBeaconBlockBodyDeneb() *eth.BeaconBlockBodyDeneb {
return &eth.BeaconBlockBodyDeneb{
RandaoReveal: make([]byte, fieldparams.BLSSignatureLength),

View File

@@ -185,6 +185,19 @@ func (b *SignedBeaconBlock) Proto() (proto.Message, error) { // nolint:gocognit
Block: block,
Signature: b.signature[:],
}, nil
case version.Gloas:
var block *eth.BeaconBlockGloas
if blockMessage != nil {
var ok bool
block, ok = blockMessage.(*eth.BeaconBlockGloas)
if !ok {
return nil, errIncorrectBlockVersion
}
}
return &eth.SignedBeaconBlockGloas{
Block: block,
Signature: b.signature[:],
}, nil
default:
return nil, errors.New("unsupported signed beacon block version")
}
@@ -399,6 +412,22 @@ func (b *BeaconBlock) Proto() (proto.Message, error) { // nolint:gocognit
StateRoot: b.stateRoot[:],
Body: body,
}, nil
case version.Gloas:
var body *eth.BeaconBlockBodyGloas
if bodyMessage != nil {
var ok bool
body, ok = bodyMessage.(*eth.BeaconBlockBodyGloas)
if !ok {
return nil, errIncorrectBodyVersion
}
}
return &eth.BeaconBlockGloas{
Slot: b.slot,
ProposerIndex: b.proposerIndex,
ParentRoot: b.parentRoot[:],
StateRoot: b.stateRoot[:],
Body: body,
}, nil
default:
return nil, fmt.Errorf("unsupported beacon block version: %s", version.String(b.version))
}
@@ -668,6 +697,21 @@ func (b *BeaconBlockBody) Proto() (proto.Message, error) {
BlobKzgCommitments: b.blobKzgCommitments,
ExecutionRequests: b.executionRequests,
}, nil
case version.Gloas:
return &eth.BeaconBlockBodyGloas{
RandaoReveal: b.randaoReveal[:],
Eth1Data: b.eth1Data,
Graffiti: b.graffiti[:],
ProposerSlashings: b.proposerSlashings,
AttesterSlashings: b.attesterSlashingsElectra,
Attestations: b.attestationsElectra,
Deposits: b.deposits,
VoluntaryExits: b.voluntaryExits,
SyncAggregate: b.syncAggregate,
BlsToExecutionChanges: b.blsToExecutionChanges,
SignedExecutionPayloadBid: b.signedExecutionPayloadBid,
PayloadAttestations: b.payloadAttestations,
}, nil
default:
return nil, errors.New("unsupported beacon block body version")
}
@@ -1477,3 +1521,67 @@ func initBlindedBlockBodyFromProtoFulu(pb *eth.BlindedBeaconBlockBodyElectra) (*
}
return b, nil
}
// ----------------------------------------------------------------------------
// Gloas
// ----------------------------------------------------------------------------
func initSignedBlockFromProtoGloas(pb *eth.SignedBeaconBlockGloas) (*SignedBeaconBlock, error) {
if pb == nil {
return nil, errNilBlock
}
block, err := initBlockFromProtoGloas(pb.Block)
if err != nil {
return nil, err
}
b := &SignedBeaconBlock{
version: version.Gloas,
block: block,
signature: bytesutil.ToBytes96(pb.Signature),
}
return b, nil
}
func initBlockFromProtoGloas(pb *eth.BeaconBlockGloas) (*BeaconBlock, error) {
if pb == nil {
return nil, errNilBlock
}
body, err := initBlockBodyFromProtoGloas(pb.Body)
if err != nil {
return nil, err
}
b := &BeaconBlock{
version: version.Gloas,
slot: pb.Slot,
proposerIndex: pb.ProposerIndex,
parentRoot: bytesutil.ToBytes32(pb.ParentRoot),
stateRoot: bytesutil.ToBytes32(pb.StateRoot),
body: body,
}
return b, nil
}
func initBlockBodyFromProtoGloas(pb *eth.BeaconBlockBodyGloas) (*BeaconBlockBody, error) {
if pb == nil {
return nil, errNilBlockBody
}
b := &BeaconBlockBody{
version: version.Gloas,
randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal),
eth1Data: pb.Eth1Data,
graffiti: bytesutil.ToBytes32(pb.Graffiti),
proposerSlashings: pb.ProposerSlashings,
attesterSlashingsElectra: pb.AttesterSlashings,
attestationsElectra: pb.Attestations,
deposits: pb.Deposits,
voluntaryExits: pb.VoluntaryExits,
syncAggregate: pb.SyncAggregate,
blsToExecutionChanges: pb.BlsToExecutionChanges,
signedExecutionPayloadBid: pb.SignedExecutionPayloadBid,
payloadAttestations: pb.PayloadAttestations,
}
return b, nil
}

View File

@@ -1792,6 +1792,61 @@ func bodyBlindedElectra(t *testing.T) *BeaconBlockBody {
}
}
func TestSignedBeaconBlockProtoGloas(t *testing.T) {
payload := []*eth.PayloadAttestation{{Signature: []byte{0x01}}}
bid := &eth.SignedExecutionPayloadBid{Signature: []byte{0x02}}
sb := &SignedBeaconBlock{
version: version.Gloas,
block: &BeaconBlock{
version: version.Gloas,
body: &BeaconBlockBody{
version: version.Gloas,
payloadAttestations: payload,
signedExecutionPayloadBid: bid,
},
},
}
msg, err := sb.Proto()
require.NoError(t, err)
gloas, ok := msg.(*eth.SignedBeaconBlockGloas)
require.Equal(t, true, ok)
require.DeepEqual(t, payload, gloas.Block.Body.PayloadAttestations)
require.DeepEqual(t, bid, gloas.Block.Body.SignedExecutionPayloadBid)
}
func TestInitSignedBlockFromProtoGloas(t *testing.T) {
bits := bitfield.NewBitvector512()
bits.SetBitAt(0, true)
pb := &eth.SignedBeaconBlockGloas{
Block: &eth.BeaconBlockGloas{
Body: &eth.BeaconBlockBodyGloas{
PayloadAttestations: []*eth.PayloadAttestation{
{
AggregationBits: bits,
Signature: []byte{0x01},
},
},
SignedExecutionPayloadBid: &eth.SignedExecutionPayloadBid{Signature: []byte{0x02}},
},
},
Signature: []byte{0x03},
}
sb, err := initSignedBlockFromProtoGloas(pb)
require.NoError(t, err)
require.Equal(t, version.Gloas, sb.Version())
gotPayload, err := sb.Block().Body().PayloadAttestations()
require.NoError(t, err)
require.Equal(t, 1, len(gotPayload))
require.DeepEqual(t, pb.Block.Body.PayloadAttestations, gotPayload)
gotBid, err := sb.Block().Body().SignedExecutionPayloadBid()
require.NoError(t, err)
require.DeepEqual(t, pb.Block.Body.SignedExecutionPayloadBid, gotBid)
}
func getFields() fields {
b20 := make([]byte, 20)
b48 := make([]byte, 48)

View File

@@ -144,7 +144,7 @@ func (b *SignedBeaconBlock) SetSyncAggregate(s *eth.SyncAggregate) error {
// SetExecution sets the execution payload of the block body.
// This function is not thread safe, it is only used during block creation.
func (b *SignedBeaconBlock) SetExecution(e interfaces.ExecutionData) error {
if b.version == version.Phase0 || b.version == version.Altair {
if b.version == version.Phase0 || b.version == version.Altair || b.version >= version.Gloas {
return consensus_types.ErrNotSupported("Execution", b.version)
}
if e.IsBlinded() {
@@ -176,9 +176,27 @@ func (b *SignedBeaconBlock) SetBlobKzgCommitments(c [][]byte) error {
// SetExecutionRequests sets the execution requests in the block.
func (b *SignedBeaconBlock) SetExecutionRequests(req *enginev1.ExecutionRequests) error {
if b.version < version.Electra {
if b.version < version.Electra || b.version >= version.Gloas {
return consensus_types.ErrNotSupported("SetExecutionRequests", b.version)
}
b.block.body.executionRequests = req
return nil
}
// SetPayloadAttestations sets the payload attestations in the block.
func (b *SignedBeaconBlock) SetPayloadAttestations(pa []*eth.PayloadAttestation) error {
if b.version < version.Gloas {
return consensus_types.ErrNotSupported("SetPayloadAttestations", b.version)
}
b.block.body.payloadAttestations = pa
return nil
}
// SetSignedExecutionPayloadBid sets the signed execution payload header in the block.
func (b *SignedBeaconBlock) SetSignedExecutionPayloadBid(header *eth.SignedExecutionPayloadBid) error {
if b.version < version.Gloas {
return consensus_types.ErrNotSupported("SetSignedExecutionPayloadBid", b.version)
}
b.block.body.signedExecutionPayloadBid = header
return nil
}

View File

@@ -0,0 +1,107 @@
package blocks
import (
"testing"
bitfield "github.com/OffchainLabs/go-bitfield"
consensus_types "github.com/OffchainLabs/prysm/v7/consensus-types"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
eth "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
"github.com/OffchainLabs/prysm/v7/testing/require"
)
func TestSignedBeaconBlock_SetPayloadAttestations(t *testing.T) {
t.Run("rejects pre-Gloas versions", func(t *testing.T) {
sb := newTestSignedBeaconBlock(version.Fulu)
payload := []*eth.PayloadAttestation{{}}
err := sb.SetPayloadAttestations(payload)
require.ErrorIs(t, err, consensus_types.ErrUnsupportedField)
require.IsNil(t, sb.block.body.payloadAttestations)
})
t.Run("sets payload attestations for Gloas", func(t *testing.T) {
sb := newTestSignedBeaconBlock(version.Gloas)
payload := []*eth.PayloadAttestation{
{
AggregationBits: bitfield.NewBitvector512(),
Data: &eth.PayloadAttestationData{
BeaconBlockRoot: []byte{0x01, 0x02},
PayloadPresent: true,
BlobDataAvailable: true,
},
Signature: []byte{0x03},
},
}
err := sb.SetPayloadAttestations(payload)
require.NoError(t, err)
require.DeepEqual(t, payload, sb.block.body.payloadAttestations)
})
}
func TestSignedBeaconBlock_SetSignedExecutionPayloadBid(t *testing.T) {
t.Run("rejects pre-Gloas versions", func(t *testing.T) {
sb := newTestSignedBeaconBlock(version.Fulu)
payloadBid := &eth.SignedExecutionPayloadBid{}
err := sb.SetSignedExecutionPayloadBid(payloadBid)
require.ErrorIs(t, err, consensus_types.ErrUnsupportedField)
require.IsNil(t, sb.block.body.signedExecutionPayloadBid)
})
t.Run("sets signed execution payload bid for Gloas", func(t *testing.T) {
sb := newTestSignedBeaconBlock(version.Gloas)
payloadBid := &eth.SignedExecutionPayloadBid{
Message: &eth.ExecutionPayloadBid{
ParentBlockHash: []byte{0xaa},
BlockHash: []byte{0xbb},
FeeRecipient: []byte{0xcc},
},
Signature: []byte{0xdd},
}
err := sb.SetSignedExecutionPayloadBid(payloadBid)
require.NoError(t, err)
require.Equal(t, payloadBid, sb.block.body.signedExecutionPayloadBid)
})
}
func TestSignedBeaconBlock_SetExecution(t *testing.T) {
t.Run("rejects Gloas version", func(t *testing.T) {
sb := newTestSignedBeaconBlock(version.Gloas)
payload := &enginev1.ExecutionPayload{}
wrapped, err := WrappedExecutionPayload(payload)
require.NoError(t, err)
err = sb.SetExecution(wrapped)
require.ErrorIs(t, err, consensus_types.ErrUnsupportedField)
})
}
func TestSignedBeaconBlock_SetExecutionRequests(t *testing.T) {
t.Run("rejects Gloas version", func(t *testing.T) {
sb := newTestSignedBeaconBlock(version.Gloas)
requests := &enginev1.ExecutionRequests{}
err := sb.SetExecutionRequests(requests)
require.ErrorIs(t, err, consensus_types.ErrUnsupportedField)
})
}
func newTestSignedBeaconBlock(ver int) *SignedBeaconBlock {
return &SignedBeaconBlock{
version: ver,
block: &BeaconBlock{
version: ver,
body: &BeaconBlockBody{
version: ver,
},
},
}
}

View File

@@ -40,23 +40,25 @@ var (
// BeaconBlockBody is the main beacon block body structure. It can represent any block type.
type BeaconBlockBody struct {
version int
randaoReveal [field_params.BLSSignatureLength]byte
eth1Data *eth.Eth1Data
graffiti [field_params.RootLength]byte
proposerSlashings []*eth.ProposerSlashing
attesterSlashings []*eth.AttesterSlashing
attesterSlashingsElectra []*eth.AttesterSlashingElectra
attestations []*eth.Attestation
attestationsElectra []*eth.AttestationElectra
deposits []*eth.Deposit
voluntaryExits []*eth.SignedVoluntaryExit
syncAggregate *eth.SyncAggregate
executionPayload interfaces.ExecutionData
executionPayloadHeader interfaces.ExecutionData
blsToExecutionChanges []*eth.SignedBLSToExecutionChange
blobKzgCommitments [][]byte
executionRequests *enginev1.ExecutionRequests
version int
randaoReveal [field_params.BLSSignatureLength]byte
eth1Data *eth.Eth1Data
graffiti [field_params.RootLength]byte
proposerSlashings []*eth.ProposerSlashing
attesterSlashings []*eth.AttesterSlashing
attesterSlashingsElectra []*eth.AttesterSlashingElectra
attestations []*eth.Attestation
attestationsElectra []*eth.AttestationElectra
deposits []*eth.Deposit
voluntaryExits []*eth.SignedVoluntaryExit
syncAggregate *eth.SyncAggregate
executionPayload interfaces.ExecutionData
executionPayloadHeader interfaces.ExecutionData
blsToExecutionChanges []*eth.SignedBLSToExecutionChange
blobKzgCommitments [][]byte
executionRequests *enginev1.ExecutionRequests
signedExecutionPayloadBid *eth.SignedExecutionPayloadBid
payloadAttestations []*eth.PayloadAttestation
}
var _ interfaces.ReadOnlyBeaconBlockBody = &BeaconBlockBody{}

View File

@@ -69,6 +69,8 @@ type ReadOnlyBeaconBlockBody interface {
BLSToExecutionChanges() ([]*ethpb.SignedBLSToExecutionChange, error)
BlobKzgCommitments() ([][]byte, error)
ExecutionRequests() (*enginev1.ExecutionRequests, error)
PayloadAttestations() ([]*ethpb.PayloadAttestation, error)
SignedExecutionPayloadBid() (*ethpb.SignedExecutionPayloadBid, error)
}
type SignedBeaconBlock interface {
@@ -91,6 +93,8 @@ type SignedBeaconBlock interface {
SetSlot(slot primitives.Slot)
SetSignature(sig []byte)
SetExecutionRequests(er *enginev1.ExecutionRequests) error
SetPayloadAttestations(pa []*ethpb.PayloadAttestation) error
SetSignedExecutionPayloadBid(header *ethpb.SignedExecutionPayloadBid) error
Unblind(e ExecutionData) error
}

View File

@@ -276,6 +276,14 @@ func (b *BeaconBlockBody) ExecutionRequests() (*enginev1.ExecutionRequests, erro
panic("implement me")
}
func (b *BeaconBlockBody) PayloadAttestations() ([]*eth.PayloadAttestation, error) {
panic("implement me")
}
func (b *BeaconBlockBody) SignedExecutionPayloadBid() (*eth.SignedExecutionPayloadBid, error) {
panic("implement me")
}
func (b *BeaconBlockBody) Attestations() []eth.Att {
panic("implement me")
}

View File

@@ -61,3 +61,116 @@ func CopySyncCommitteeContribution(c *SyncCommitteeContribution) *SyncCommitteeC
Signature: bytesutil.SafeCopyBytes(c.Signature),
}
}
// CopySignedBeaconBlockGloas copies the provided signed beacon block Gloas object.
func CopySignedBeaconBlockGloas(sb *SignedBeaconBlockGloas) *SignedBeaconBlockGloas {
if sb == nil {
return nil
}
return &SignedBeaconBlockGloas{
Block: copyBeaconBlockGloas(sb.Block),
Signature: bytesutil.SafeCopyBytes(sb.Signature),
}
}
// copyBeaconBlockGloas copies the provided beacon block Gloas object.
func copyBeaconBlockGloas(b *BeaconBlockGloas) *BeaconBlockGloas {
if b == nil {
return nil
}
return &BeaconBlockGloas{
Slot: b.Slot,
ProposerIndex: b.ProposerIndex,
ParentRoot: bytesutil.SafeCopyBytes(b.ParentRoot),
StateRoot: bytesutil.SafeCopyBytes(b.StateRoot),
Body: copyBeaconBlockBodyGloas(b.Body),
}
}
// copyPayloadAttestation copies the provided payload attestation object.
func copyPayloadAttestation(pa *PayloadAttestation) *PayloadAttestation {
if pa == nil {
return nil
}
copied := &PayloadAttestation{
AggregationBits: pa.AggregationBits,
Signature: bytesutil.SafeCopyBytes(pa.Signature),
}
if pa.Data != nil {
copied.Data = &PayloadAttestationData{
BeaconBlockRoot: bytesutil.SafeCopyBytes(pa.Data.BeaconBlockRoot),
Slot: pa.Data.Slot,
PayloadPresent: pa.Data.PayloadPresent,
BlobDataAvailable: pa.Data.BlobDataAvailable,
}
}
return copied
}
// copyPayloadAttestations copies a slice of payload attestations.
func copyPayloadAttestations(pas []*PayloadAttestation) []*PayloadAttestation {
if len(pas) == 0 {
return nil
}
copied := make([]*PayloadAttestation, len(pas))
for i, pa := range pas {
copied[i] = copyPayloadAttestation(pa)
}
return copied
}
// copySignedExecutionPayloadBid copies the provided signed execution payload header.
func copySignedExecutionPayloadBid(header *SignedExecutionPayloadBid) *SignedExecutionPayloadBid {
if header == nil {
return nil
}
copied := &SignedExecutionPayloadBid{
Signature: bytesutil.SafeCopyBytes(header.Signature),
}
if header.Message != nil {
copied.Message = &ExecutionPayloadBid{
ParentBlockHash: bytesutil.SafeCopyBytes(header.Message.ParentBlockHash),
ParentBlockRoot: bytesutil.SafeCopyBytes(header.Message.ParentBlockRoot),
BlockHash: bytesutil.SafeCopyBytes(header.Message.BlockHash),
FeeRecipient: bytesutil.SafeCopyBytes(header.Message.FeeRecipient),
GasLimit: header.Message.GasLimit,
BuilderIndex: header.Message.BuilderIndex,
Slot: header.Message.Slot,
Value: header.Message.Value,
BlobKzgCommitmentsRoot: bytesutil.SafeCopyBytes(header.Message.BlobKzgCommitmentsRoot),
}
}
return copied
}
// copyBeaconBlockBodyGloas copies the provided beacon block body Gloas object.
func copyBeaconBlockBodyGloas(body *BeaconBlockBodyGloas) *BeaconBlockBodyGloas {
if body == nil {
return nil
}
copied := &BeaconBlockBodyGloas{
RandaoReveal: bytesutil.SafeCopyBytes(body.RandaoReveal),
Graffiti: bytesutil.SafeCopyBytes(body.Graffiti),
}
if body.Eth1Data != nil {
copied.Eth1Data = body.Eth1Data.Copy()
}
if body.SyncAggregate != nil {
copied.SyncAggregate = body.SyncAggregate.Copy()
}
copied.ProposerSlashings = CopySlice(body.ProposerSlashings)
copied.AttesterSlashings = CopySlice(body.AttesterSlashings)
copied.Attestations = CopySlice(body.Attestations)
copied.Deposits = CopySlice(body.Deposits)
copied.VoluntaryExits = CopySlice(body.VoluntaryExits)
copied.BlsToExecutionChanges = CopySlice(body.BlsToExecutionChanges)
copied.SignedExecutionPayloadBid = copySignedExecutionPayloadBid(body.SignedExecutionPayloadBid)
copied.PayloadAttestations = copyPayloadAttestations(body.PayloadAttestations)
return copied
}

View File

@@ -5,9 +5,12 @@ import (
"reflect"
"testing"
bitfield "github.com/OffchainLabs/go-bitfield"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
v1alpha1 "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/testing/assert"
"google.golang.org/protobuf/proto"
)
func TestCopySignedBeaconBlock(t *testing.T) {
@@ -100,6 +103,49 @@ func TestCopySyncCommitteeContribution(t *testing.T) {
assert.NotEmpty(t, got, "Copied sync committee contribution has empty fields")
}
func TestCopySignedBeaconBlockGloasNil(t *testing.T) {
if got := v1alpha1.CopySignedBeaconBlockGloas(nil); got != nil {
t.Fatalf("CopySignedBeaconBlockGloas(nil) = %v, want nil", got)
}
}
func TestCopySignedBeaconBlockGloasDeepCopy(t *testing.T) {
original := genSignedBeaconBlockGloas()
copied := v1alpha1.CopySignedBeaconBlockGloas(original)
if copied == original {
t.Fatalf("CopySignedBeaconBlockGloas returned the original pointer")
}
if !reflect.DeepEqual(copied, original) {
t.Fatalf("CopySignedBeaconBlockGloas() = %v, want %v", copied, original)
}
want := proto.Clone(copied).(*v1alpha1.SignedBeaconBlockGloas)
original.Signature[0] ^= 0xFF
original.Block.ParentRoot[0] ^= 0xFF
original.Block.StateRoot[0] ^= 0xFF
original.Block.Body.RandaoReveal[0] ^= 0xFF
original.Block.Body.Graffiti[0] ^= 0xFF
original.Block.Body.SyncAggregate.SyncCommitteeSignature[0] ^= 0xFF
original.Block.Body.SignedExecutionPayloadBid.Signature[0] ^= 0xFF
original.Block.Body.SignedExecutionPayloadBid.Message.BlockHash[0] ^= 0xFF
original.Block.Body.PayloadAttestations[0].Signature[0] ^= 0xFF
original.Block.Body.PayloadAttestations[0].Data.BeaconBlockRoot[0] ^= 0xFF
original.Block.Body.PayloadAttestations = append(original.Block.Body.PayloadAttestations, &v1alpha1.PayloadAttestation{})
original.Block.Body.BlsToExecutionChanges[0].Message.ValidatorIndex++
if !reflect.DeepEqual(want, copied) {
t.Fatalf("copy mutated after modifying source: got %v, want %v", copied, want)
}
if copied.Block == original.Block {
t.Fatal("expected copied block pointer to differ from original")
}
if copied.Block.Body == original.Block.Body {
t.Fatal("expected copied block body pointer to differ from original")
}
}
func TestCopyPendingAttestationSlice(t *testing.T) {
tests := []struct {
name string
@@ -1125,3 +1171,78 @@ func genConsolidationRequest() *enginev1.ConsolidationRequest {
TargetPubkey: bytes(48),
}
}
func genSignedBeaconBlockGloas() *v1alpha1.SignedBeaconBlockGloas {
return &v1alpha1.SignedBeaconBlockGloas{
Block: genBeaconBlockGloas(),
Signature: bytes(96),
}
}
func genBeaconBlockGloas() *v1alpha1.BeaconBlockGloas {
return &v1alpha1.BeaconBlockGloas{
Slot: primitives.Slot(rand.Uint64()),
ProposerIndex: primitives.ValidatorIndex(rand.Uint64()),
ParentRoot: bytes(32),
StateRoot: bytes(32),
Body: genBeaconBlockBodyGloas(),
}
}
func genBeaconBlockBodyGloas() *v1alpha1.BeaconBlockBodyGloas {
return &v1alpha1.BeaconBlockBodyGloas{
RandaoReveal: bytes(96),
Eth1Data: genEth1Data(),
Graffiti: bytes(32),
ProposerSlashings: genProposerSlashings(3),
AttesterSlashings: genAttesterSlashingsElectra(3),
Attestations: genAttestationsElectra(3),
Deposits: genDeposits(3),
VoluntaryExits: genSignedVoluntaryExits(3),
SyncAggregate: genSyncAggregate(),
BlsToExecutionChanges: genBLSToExecutionChanges(2),
SignedExecutionPayloadBid: genSignedExecutionPayloadBidGloas(),
PayloadAttestations: genPayloadAttestations(2),
}
}
func genSignedExecutionPayloadBidGloas() *v1alpha1.SignedExecutionPayloadBid {
return &v1alpha1.SignedExecutionPayloadBid{
Message: genExecutionPayloadBidGloas(),
Signature: bytes(96),
}
}
func genExecutionPayloadBidGloas() *v1alpha1.ExecutionPayloadBid {
return &v1alpha1.ExecutionPayloadBid{
ParentBlockHash: bytes(32),
ParentBlockRoot: bytes(32),
BlockHash: bytes(32),
FeeRecipient: bytes(20),
GasLimit: rand.Uint64(),
BuilderIndex: primitives.ValidatorIndex(rand.Uint64()),
Slot: primitives.Slot(rand.Uint64()),
Value: primitives.Gwei(rand.Uint64()),
BlobKzgCommitmentsRoot: bytes(32),
}
}
func genPayloadAttestations(num int) []*v1alpha1.PayloadAttestation {
pas := make([]*v1alpha1.PayloadAttestation, num)
for i := range pas {
bits := bitfield.NewBitvector512()
bits.SetBitAt(uint64(i%512), true)
pas[i] = &v1alpha1.PayloadAttestation{
AggregationBits: bits,
Data: &v1alpha1.PayloadAttestationData{
BeaconBlockRoot: bytes(32),
Slot: primitives.Slot(rand.Uint64()),
PayloadPresent: i%2 == 0,
BlobDataAvailable: i%2 == 1,
},
Signature: bytes(96),
}
}
return pas
}