mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
Update ProposeBeaconBlock Prysm RPC for Deneb (Non builder) (#12495)
This commit is contained in:
committed by
Preston Van Loon
parent
2dadf36fa9
commit
5b1634b335
@@ -52,6 +52,11 @@ func (mb *mockBroadcaster) BroadcastSyncCommitteeMessage(_ context.Context, _ ui
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mb *mockBroadcaster) BroadcastBlob(_ context.Context, _ uint64, _ *ethpb.SignedBlobSidecar) error {
|
||||
mb.broadcastCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mb *mockBroadcaster) BroadcastBLSChanges(_ context.Context, _ []*ethpb.SignedBLSToExecutionChange) {
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ type Broadcaster interface {
|
||||
Broadcast(context.Context, proto.Message) error
|
||||
BroadcastAttestation(ctx context.Context, subnet uint64, att *ethpb.Attestation) error
|
||||
BroadcastSyncCommitteeMessage(ctx context.Context, subnet uint64, sMsg *ethpb.SyncCommitteeMessage) error
|
||||
BroadcastBlob(ctx context.Context, subnet uint64, blob *ethpb.SignedBlobSidecar) error
|
||||
}
|
||||
|
||||
// SetStreamHandler configures p2p to handle streams of a certain topic ID.
|
||||
|
||||
@@ -143,6 +143,11 @@ func (_ *FakeP2P) BroadcastSyncCommitteeMessage(_ context.Context, _ uint64, _ *
|
||||
return nil
|
||||
}
|
||||
|
||||
// BroadcastBlob -- fake.
|
||||
func (_ *FakeP2P) BroadcastBlob(_ context.Context, _ uint64, _ *ethpb.SignedBlobSidecar) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// InterceptPeerDial -- fake.
|
||||
func (_ *FakeP2P) InterceptPeerDial(peer.ID) (allow bool) {
|
||||
return true
|
||||
|
||||
@@ -33,3 +33,9 @@ func (m *MockBroadcaster) BroadcastSyncCommitteeMessage(_ context.Context, _ uin
|
||||
m.BroadcastCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// BroadcastBlob broadcasts a blob for mock.
|
||||
func (m *MockBroadcaster) BroadcastBlob(context.Context, uint64, *ethpb.SignedBlobSidecar) error {
|
||||
m.BroadcastCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -176,6 +176,12 @@ func (p *TestP2P) BroadcastSyncCommitteeMessage(_ context.Context, _ uint64, _ *
|
||||
return nil
|
||||
}
|
||||
|
||||
// BroadcastBlob broadcasts a blob for mock.
|
||||
func (p *TestP2P) BroadcastBlob(context.Context, uint64, *ethpb.SignedBlobSidecar) error {
|
||||
p.BroadcastCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetStreamHandler for RPC.
|
||||
func (p *TestP2P) SetStreamHandler(topic string, handler network.StreamHandler) {
|
||||
p.BHost.SetStreamHandler(protocol.ID(topic), handler)
|
||||
|
||||
@@ -19,11 +19,13 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db/kv"
|
||||
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/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
||||
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"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -214,11 +216,74 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
|
||||
func (vs *Server) ProposeBeaconBlock(ctx context.Context, req *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.ProposeBeaconBlock")
|
||||
defer span.End()
|
||||
|
||||
blk, err := blocks.NewSignedBeaconBlock(req.Block)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "%s: %v", CouldNotDecodeBlock, err)
|
||||
}
|
||||
return vs.proposeGenericBeaconBlock(ctx, blk)
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// Broadcast the new block to the network.
|
||||
blkPb, err := blk.Proto()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get protobuf block")
|
||||
}
|
||||
if err := vs.P2P.Broadcast(ctx, blkPb); err != nil {
|
||||
return nil, fmt.Errorf("could not broadcast block: %v", err)
|
||||
}
|
||||
|
||||
if blk.Version() >= version.Deneb {
|
||||
b, ok := req.GetBlock().(*ethpb.GenericSignedBeaconBlock_Deneb)
|
||||
if !ok {
|
||||
return nil, status.Error(codes.Internal, "Could not cast block to Deneb")
|
||||
}
|
||||
if len(b.Deneb.Blobs) > fieldparams.MaxBlobsPerBlock {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Too many blobs in block: %d", len(b.Deneb.Blobs))
|
||||
}
|
||||
scs := make([]*ethpb.BlobSidecar, len(b.Deneb.Blobs))
|
||||
for i, blob := range b.Deneb.Blobs {
|
||||
if err := vs.P2P.BroadcastBlob(ctx, blob.Message.Index, blob); err != nil {
|
||||
log.WithError(err).Errorf("Could not broadcast blob index %d / %d", i, len(b.Deneb.Blobs))
|
||||
}
|
||||
scs[i] = blob.Message
|
||||
}
|
||||
if len(scs) > 0 {
|
||||
if err := vs.BeaconDB.SaveBlobSidecar(ctx, scs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not tree hash block: %v", err)
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"blockRoot": hex.EncodeToString(root[:]),
|
||||
}).Debug("Broadcasting block")
|
||||
|
||||
if err := vs.BlockReceiver.ReceiveBlock(ctx, blk, root); err != nil {
|
||||
return nil, fmt.Errorf("could not process beacon block: %v", err)
|
||||
}
|
||||
|
||||
log.WithField("slot", blk.Block().Slot()).Debugf(
|
||||
"Block proposal received via RPC")
|
||||
vs.BlockNotifier.BlockFeed().Send(&feed.Event{
|
||||
Type: blockfeed.ReceivedBlock,
|
||||
Data: &blockfeed.ReceivedBlockData{SignedBlock: blk},
|
||||
})
|
||||
|
||||
return ðpb.ProposeResponse{
|
||||
BlockRoot: root[:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PrepareBeaconProposer caches and updates the fee recipient for the given proposer.
|
||||
@@ -300,52 +365,6 @@ func (vs *Server) GetFeeRecipientByPubKey(ctx context.Context, request *ethpb.Fe
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, blk interfaces.SignedBeaconBlock) (*ethpb.ProposeResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.proposeGenericBeaconBlock")
|
||||
defer span.End()
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// Broadcast the new block to the network.
|
||||
blkPb, err := blk.Proto()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get protobuf block")
|
||||
}
|
||||
if err := vs.P2P.Broadcast(ctx, blkPb); err != nil {
|
||||
return nil, fmt.Errorf("could not broadcast block: %v", err)
|
||||
}
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not tree hash block: %v", err)
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"blockRoot": hex.EncodeToString(root[:]),
|
||||
}).Debug("Broadcasting block")
|
||||
|
||||
if err := vs.BlockReceiver.ReceiveBlock(ctx, blk, root); err != nil {
|
||||
return nil, fmt.Errorf("could not process beacon block: %v", err)
|
||||
}
|
||||
|
||||
log.WithField("slot", blk.Block().Slot()).Debugf(
|
||||
"Block proposal received via RPC")
|
||||
vs.BlockNotifier.BlockFeed().Send(&feed.Event{
|
||||
Type: blockfeed.ReceivedBlock,
|
||||
Data: &blockfeed.ReceivedBlockData{SignedBlock: blk},
|
||||
})
|
||||
|
||||
return ðpb.ProposeResponse{
|
||||
BlockRoot: root[:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
// computeStateRoot computes the state root after a block has been processed through a state transition and
|
||||
// returns it to the validator client.
|
||||
func (vs *Server) computeStateRoot(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) {
|
||||
|
||||
@@ -631,6 +631,7 @@ func TestProposer_ProposeBlock_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
block func([32]byte) *ethpb.GenericSignedBeaconBlock
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: "phase0",
|
||||
@@ -678,6 +679,66 @@ func TestProposer_ProposeBlock_OK(t *testing.T) {
|
||||
return ðpb.GenericSignedBeaconBlock{Block: blk}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bellatrix",
|
||||
block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock {
|
||||
blockToPropose := util.NewBeaconBlockBellatrix()
|
||||
blockToPropose.Block.Slot = 5
|
||||
blockToPropose.Block.ParentRoot = parent[:]
|
||||
blk := ðpb.GenericSignedBeaconBlock_Bellatrix{Bellatrix: blockToPropose}
|
||||
return ðpb.GenericSignedBeaconBlock{Block: blk}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deneb block no blob",
|
||||
block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock {
|
||||
blockToPropose := util.NewBeaconBlockDeneb()
|
||||
blockToPropose.Block.Slot = 5
|
||||
blockToPropose.Block.ParentRoot = parent[:]
|
||||
blk := ðpb.GenericSignedBeaconBlock_Deneb{Deneb: ðpb.SignedBeaconBlockAndBlobsDeneb{
|
||||
Block: blockToPropose,
|
||||
}}
|
||||
return ðpb.GenericSignedBeaconBlock{Block: blk}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deneb block has blobs",
|
||||
block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock {
|
||||
blockToPropose := util.NewBeaconBlockDeneb()
|
||||
blockToPropose.Block.Slot = 5
|
||||
blockToPropose.Block.ParentRoot = parent[:]
|
||||
blk := ðpb.GenericSignedBeaconBlock_Deneb{Deneb: ðpb.SignedBeaconBlockAndBlobsDeneb{
|
||||
Block: blockToPropose,
|
||||
Blobs: []*ethpb.SignedBlobSidecar{
|
||||
{Message: ðpb.BlobSidecar{Index: 0, Slot: 5, BlockParentRoot: parent[:]}},
|
||||
{Message: ðpb.BlobSidecar{Index: 1, Slot: 5, BlockParentRoot: parent[:]}},
|
||||
{Message: ðpb.BlobSidecar{Index: 2, Slot: 5, BlockParentRoot: parent[:]}},
|
||||
{Message: ðpb.BlobSidecar{Index: 3, Slot: 5, BlockParentRoot: parent[:]}},
|
||||
},
|
||||
}}
|
||||
return ðpb.GenericSignedBeaconBlock{Block: blk}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deneb block has too many blobs",
|
||||
err: "Too many blobs in block: 5",
|
||||
block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock {
|
||||
blockToPropose := util.NewBeaconBlockDeneb()
|
||||
blockToPropose.Block.Slot = 5
|
||||
blockToPropose.Block.ParentRoot = parent[:]
|
||||
blk := ðpb.GenericSignedBeaconBlock_Deneb{Deneb: ðpb.SignedBeaconBlockAndBlobsDeneb{
|
||||
Block: blockToPropose,
|
||||
Blobs: []*ethpb.SignedBlobSidecar{
|
||||
{Message: ðpb.BlobSidecar{Index: 0, Slot: 5, BlockParentRoot: parent[:]}},
|
||||
{Message: ðpb.BlobSidecar{Index: 1, Slot: 5, BlockParentRoot: parent[:]}},
|
||||
{Message: ðpb.BlobSidecar{Index: 2, Slot: 5, BlockParentRoot: parent[:]}},
|
||||
{Message: ðpb.BlobSidecar{Index: 3, Slot: 5, BlockParentRoot: parent[:]}},
|
||||
{Message: ðpb.BlobSidecar{Index: 4, Slot: 5, BlockParentRoot: parent[:]}},
|
||||
},
|
||||
}}
|
||||
return ðpb.GenericSignedBeaconBlock{Block: blk}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -690,17 +751,31 @@ func TestProposer_ProposeBlock_OK(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
|
||||
db := dbutil.SetupDB(t)
|
||||
proposerServer := &Server{
|
||||
BlockReceiver: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
P2P: mockp2p.NewTestP2P(t),
|
||||
BlockBuilder: &builderTest.MockBuilderService{HasConfigured: true, PayloadCapella: emptyPayloadCapella()},
|
||||
BeaconDB: db,
|
||||
}
|
||||
blockToPropose := tt.block(bsRoot)
|
||||
res, err := proposerServer.ProposeBeaconBlock(context.Background(), blockToPropose)
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
if res == nil || len(res.BlockRoot) == 0 {
|
||||
t.Error("No block root was returned")
|
||||
if tt.err != "" { // Expecting an error
|
||||
require.ErrorContains(t, tt.err, err)
|
||||
} else {
|
||||
assert.NoError(t, err, "Could not propose block correctly")
|
||||
if res == nil || len(res.BlockRoot) == 0 {
|
||||
t.Error("No block root was returned")
|
||||
}
|
||||
}
|
||||
if tt.name == "deneb block has blobs" {
|
||||
scs, err := db.BlobSidecarsBySlot(ctx, blockToPropose.GetDeneb().Block.Block.Slot)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 4, len(scs))
|
||||
for i, sc := range scs {
|
||||
require.Equal(t, uint64(i), sc.Index)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -108,6 +108,10 @@ func (e *ExecutionBlock) UnmarshalJSON(enc []byte) error {
|
||||
edg, has := decoded["excessDataGas"]
|
||||
if has && edg != nil {
|
||||
e.Version = version.Deneb
|
||||
e.ExcessDataGas, err = hexutil.DecodeUint64(edg.(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
dgu, has := decoded["dataGasUsed"]
|
||||
if has && dgu != nil {
|
||||
|
||||
Reference in New Issue
Block a user