Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
1 change: 1 addition & 0 deletions beacon-chain/rpc/eth/beacon/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ go_test(
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
Expand Down
54 changes: 50 additions & 4 deletions beacon-chain/rpc/eth/beacon/blinded_blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
mockp2p "github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
Expand Down Expand Up @@ -407,7 +408,7 @@ func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) {
alphaServer := &validator.Server{
SyncCommitteePool: synccommittee.NewStore(),
P2P: &mockp2p.MockBroadcaster{},
BlockBuilder: &builderTest.MockBuilderService{},
BlockBuilder: &builderTest.MockBuilderService{HasConfigured: true, Payload: emptyPayload()},
BlockReceiver: c,
BlockNotifier: &mock.MockBlockNotifier{},
}
Expand All @@ -423,6 +424,9 @@ func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) {
req := util.NewBlindedBeaconBlockBellatrix()
req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().BellatrixForkEpoch))
req.Block.ParentRoot = bsRoot[:]
transactionsRoot, err := ssz.TransactionsRoot([][]byte{})
require.NoError(t, err)
req.Block.Body.ExecutionPayloadHeader.TransactionsRoot = transactionsRoot[:]
util.SaveBlock(t, ctx, beaconDB, req)
blockSsz, err := req.MarshalSSZ()
require.NoError(t, err)
Expand Down Expand Up @@ -455,7 +459,7 @@ func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) {
alphaServer := &validator.Server{
SyncCommitteePool: synccommittee.NewStore(),
P2P: &mockp2p.MockBroadcaster{},
BlockBuilder: &builderTest.MockBuilderService{},
BlockBuilder: &builderTest.MockBuilderService{HasConfigured: true, PayloadCapella: emptyPayloadCapella()},
BlockReceiver: c,
BlockNotifier: &mock.MockBlockNotifier{},
}
Expand All @@ -471,6 +475,12 @@ func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) {
req := util.NewBlindedBeaconBlockCapella()
req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().CapellaForkEpoch))
req.Block.ParentRoot = bsRoot[:]
transactionsRoot, err := ssz.TransactionsRoot([][]byte{})
require.NoError(t, err)
req.Block.Body.ExecutionPayloadHeader.TransactionsRoot = transactionsRoot[:]
withdrawalsRoot, err := ssz.WithdrawalSliceRoot([]*enginev1.Withdrawal{}, fieldparams.MaxWithdrawalsPerPayload)
require.NoError(t, err)
req.Block.Body.ExecutionPayloadHeader.WithdrawalsRoot = withdrawalsRoot[:]
util.SaveBlock(t, ctx, beaconDB, req)
blockSsz, err := req.MarshalSSZ()
require.NoError(t, err)
Expand Down Expand Up @@ -580,10 +590,12 @@ func TestSubmitBlindedBlock(t *testing.T) {
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")

c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
p := emptyPayload()
p.Transactions = transactions
alphaServer := &validator.Server{
SyncCommitteePool: synccommittee.NewStore(),
P2P: &mockp2p.MockBroadcaster{},
BlockBuilder: &builderTest.MockBuilderService{},
BlockBuilder: &builderTest.MockBuilderService{HasConfigured: true, Payload: p},
BlockReceiver: c,
BlockNotifier: &mock.MockBlockNotifier{},
}
Expand Down Expand Up @@ -651,10 +663,13 @@ func TestSubmitBlindedBlock(t *testing.T) {
require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")

c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
p := emptyPayloadCapella()
p.Transactions = transactions
p.Withdrawals = withdrawals
alphaServer := &validator.Server{
SyncCommitteePool: synccommittee.NewStore(),
P2P: &mockp2p.MockBroadcaster{},
BlockBuilder: &builderTest.MockBuilderService{},
BlockBuilder: &builderTest.MockBuilderService{HasConfigured: true, PayloadCapella: p},
BlockReceiver: c,
BlockNotifier: &mock.MockBlockNotifier{},
}
Expand Down Expand Up @@ -687,3 +702,34 @@ func TestSubmitBlindedBlock(t *testing.T) {
assert.NoError(t, err)
})
}

func emptyPayload() *enginev1.ExecutionPayload {
return &enginev1.ExecutionPayload{
ParentHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
PrevRandao: make([]byte, fieldparams.RootLength),
BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
Transactions: make([][]byte, 0),
ExtraData: make([]byte, 0),
}
}

func emptyPayloadCapella() *enginev1.ExecutionPayloadCapella {
return &enginev1.ExecutionPayloadCapella{
ParentHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
PrevRandao: make([]byte, fieldparams.RootLength),

@kasey kasey Apr 13, 2023

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presumably this omits BlockNumber, GasLimit, GasUsed, Timestamp because they are uint64s so they receive zero values, but we may want to always include all fields in functions like this as a matter of course to help verify completeness.

BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
Transactions: make([][]byte, 0),
Withdrawals: make([]*enginev1.Withdrawal, 0),
ExtraData: make([]byte, 0),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we put these fields in the same order as the consensus types? That would make this code a little easier to compare to generated protobuf code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean exactly? In consensus types we have an ExecutionData interface and a type that wraps a proto object.

}
}
4 changes: 3 additions & 1 deletion beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ go_library(
"server.go",
"status.go",
"sync_committee.go",
"unblinder.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator",
visibility = ["//beacon-chain:__subpackages__"],
Expand Down Expand Up @@ -95,6 +96,7 @@ go_library(
"@io_opencensus_go//trace:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_x_sync//errgroup:go_default_library",
],
Expand Down Expand Up @@ -180,7 +182,6 @@ go_test(
"proposer_attestations_test.go",
"proposer_bellatrix_test.go",
"proposer_builder_test.go",
"proposer_capella_test.go",
"proposer_deposits_test.go",
"proposer_empty_block_test.go",
"proposer_execution_payload_test.go",
Expand All @@ -193,6 +194,7 @@ go_test(
"status_mainnet_test.go",
"status_test.go",
"sync_committee_test.go",
"unblinder_test.go",
"validator_test.go",
],
embed = [":go_default_library"],
Expand Down
19 changes: 8 additions & 11 deletions beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,24 +247,21 @@ func (vs *Server) GetFeeRecipientByPubKey(ctx context.Context, request *ethpb.Fe
}, nil
}

func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*ethpb.ProposeResponse, error) {
func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, blk interfaces.SignedBeaconBlock) (*ethpb.ProposeResponse, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.proposeGenericBeaconBlock")
defer span.End()
root, err := blk.Block().HashTreeRoot()
if err != nil {
return nil, fmt.Errorf("could not tree hash block: %v", err)
}

if slots.ToEpoch(blk.Block().Slot()) >= params.BeaconConfig().CapellaForkEpoch {
blk, err = vs.unblindBuilderBlockCapella(ctx, blk)
if err != nil {
return nil, err
}
} else {
blk, err = vs.unblindBuilderBlock(ctx, blk)
if err != nil {
return nil, err
}
unblinder, err := newUnblinder(blk, vs.BlockBuilder)
if err != nil {
return nil, errors.Wrap(err, "could not create unblinder")
}
blk, err = unblinder.unblindBuilderBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not unblind builder block")
}

// Do not block proposal critical path with debug logging or block feed updates.
Expand Down
126 changes: 0 additions & 126 deletions beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
consensusblocks "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v4/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
"github.com/prysmaticlabs/prysm/v4/time/slots"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -201,129 +198,6 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv
return header, nil
}

// This function retrieves the full payload block using the input blind block. This input must be versioned as
// bellatrix blind block. The output block will contain the full payload. The original header block
// will be returned the block builder is not configured.
func (vs *Server) unblindBuilderBlock(ctx context.Context, b interfaces.ReadOnlySignedBeaconBlock) (interfaces.ReadOnlySignedBeaconBlock, error) {
if err := consensusblocks.BeaconBlockIsNil(b); err != nil {
return nil, err
}

// No-op if the input block is not version blind and bellatrix.
if b.Version() != version.Bellatrix || !b.IsBlinded() {
return b, nil
}
// No-op nothing if the builder has not been configured.
if !vs.BlockBuilder.Configured() {
return b, nil
}

agg, err := b.Block().Body().SyncAggregate()
if err != nil {
return nil, err
}
h, err := b.Block().Body().Execution()
if err != nil {
return nil, err
}
header, ok := h.Proto().(*enginev1.ExecutionPayloadHeader)
if !ok {
return nil, errors.New("execution data must be execution payload header")
}
parentRoot := b.Block().ParentRoot()
stateRoot := b.Block().StateRoot()
randaoReveal := b.Block().Body().RandaoReveal()
graffiti := b.Block().Body().Graffiti()
sig := b.Signature()
psb := &ethpb.SignedBlindedBeaconBlockBellatrix{
Block: &ethpb.BlindedBeaconBlockBellatrix{
Slot: b.Block().Slot(),
ProposerIndex: b.Block().ProposerIndex(),
ParentRoot: parentRoot[:],
StateRoot: stateRoot[:],
Body: &ethpb.BlindedBeaconBlockBodyBellatrix{
RandaoReveal: randaoReveal[:],
Eth1Data: b.Block().Body().Eth1Data(),
Graffiti: graffiti[:],
ProposerSlashings: b.Block().Body().ProposerSlashings(),
AttesterSlashings: b.Block().Body().AttesterSlashings(),
Attestations: b.Block().Body().Attestations(),
Deposits: b.Block().Body().Deposits(),
VoluntaryExits: b.Block().Body().VoluntaryExits(),
SyncAggregate: agg,
ExecutionPayloadHeader: header,
},
},
Signature: sig[:],
}

sb, err := consensusblocks.NewSignedBeaconBlock(psb)
if err != nil {
return nil, errors.Wrap(err, "could not create signed block")
}
payload, err := vs.BlockBuilder.SubmitBlindedBlock(ctx, sb)
if err != nil {
return nil, err
}
headerRoot, err := header.HashTreeRoot()
if err != nil {
return nil, err
}

payloadRoot, err := payload.HashTreeRoot()
if err != nil {
return nil, err
}
if headerRoot != payloadRoot {
return nil, fmt.Errorf("header and payload root do not match, consider disconnect from relay to avoid further issues, "+
"%#x != %#x", headerRoot, payloadRoot)
}

pbPayload, err := payload.PbBellatrix()
if err != nil {
return nil, errors.Wrap(err, "could not get payload")
}
bb := &ethpb.SignedBeaconBlockBellatrix{
Block: &ethpb.BeaconBlockBellatrix{
Slot: psb.Block.Slot,
ProposerIndex: psb.Block.ProposerIndex,
ParentRoot: psb.Block.ParentRoot,
StateRoot: psb.Block.StateRoot,
Body: &ethpb.BeaconBlockBodyBellatrix{
RandaoReveal: psb.Block.Body.RandaoReveal,
Eth1Data: psb.Block.Body.Eth1Data,
Graffiti: psb.Block.Body.Graffiti,
ProposerSlashings: psb.Block.Body.ProposerSlashings,
AttesterSlashings: psb.Block.Body.AttesterSlashings,
Attestations: psb.Block.Body.Attestations,
Deposits: psb.Block.Body.Deposits,
VoluntaryExits: psb.Block.Body.VoluntaryExits,
SyncAggregate: agg,
ExecutionPayload: pbPayload,
},
},
Signature: psb.Signature,
}
wb, err := consensusblocks.NewSignedBeaconBlock(bb)
if err != nil {
return nil, err
}

txs, err := payload.Transactions()
if err != nil {
return nil, errors.Wrap(err, "could not get transactions from payload")
}
log.WithFields(logrus.Fields{
"blockHash": fmt.Sprintf("%#x", h.BlockHash()),
"feeRecipient": fmt.Sprintf("%#x", h.FeeRecipient()),
"gasUsed": h.GasUsed,
"slot": b.Block().Slot(),
"txs": len(txs),
}).Info("Retrieved full payload from builder")

return wb, nil
}

// Validates builder signature and returns an error if the signature is invalid.
func validateBuilderSignature(signedBid builder.SignedBid) error {
d, err := signing.ComputeDomain(params.BeaconConfig().DomainApplicationBuilder,
Expand Down
Loading