mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 12:57:18 +00:00
a80b1c252a
* Refactor rpc proposer into smaller files * Update BUILD.bazel * Fix test * Update BUILD.bazel
149 lines
5.9 KiB
Go
149 lines
5.9 KiB
Go
package validator
|
|
|
|
import (
|
|
"context"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
|
blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
|
"github.com/prysmaticlabs/prysm/config/params"
|
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
|
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
|
"github.com/prysmaticlabs/prysm/time/slots"
|
|
"github.com/sirupsen/logrus"
|
|
"go.opencensus.io/trace"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
// eth1DataNotification is a latch to stop flooding logs with the same warning.
|
|
var eth1DataNotification bool
|
|
|
|
const eth1dataTimeout = 2 * time.Second
|
|
|
|
// GetBeaconBlock is called by a proposer during its assigned slot to request a block to sign
|
|
// by passing in the slot and the signed randao reveal of the slot. Returns phase0 beacon blocks
|
|
// before the Altair fork epoch and Altair blocks post-fork epoch.
|
|
func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
|
|
ctx, span := trace.StartSpan(ctx, "ProposerServer.GetBeaconBlock")
|
|
defer span.End()
|
|
span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot)))
|
|
if slots.ToEpoch(req.Slot) < params.BeaconConfig().AltairForkEpoch {
|
|
blk, err := vs.getPhase0BeaconBlock(ctx, req)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not fetch phase0 beacon block: %v", err)
|
|
}
|
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: blk}}, nil
|
|
}
|
|
blk, err := vs.getAltairBeaconBlock(ctx, req)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not fetch Altair beacon block: %v", err)
|
|
}
|
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: blk}}, nil
|
|
}
|
|
|
|
// GetBlock is called by a proposer during its assigned slot to request a block to sign
|
|
// by passing in the slot and the signed randao reveal of the slot.
|
|
//
|
|
// DEPRECATED: Use GetBeaconBlock instead to handle blocks pre and post-Altair hard fork. This endpoint
|
|
// cannot handle blocks after the Altair fork epoch.
|
|
func (vs *Server) GetBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlock, error) {
|
|
ctx, span := trace.StartSpan(ctx, "ProposerServer.GetBlock")
|
|
defer span.End()
|
|
span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot)))
|
|
return vs.getPhase0BeaconBlock(ctx, req)
|
|
}
|
|
|
|
// ProposeBeaconBlock is called by a proposer during its assigned slot to create a block in an attempt
|
|
// to get it processed by the beacon node as the canonical head.
|
|
func (vs *Server) ProposeBeaconBlock(ctx context.Context, req *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) {
|
|
ctx, span := trace.StartSpan(ctx, "ProposerServer.ProposeBeaconBlock")
|
|
defer span.End()
|
|
var blk block.SignedBeaconBlock
|
|
var err error
|
|
switch b := req.Block.(type) {
|
|
case *ethpb.GenericSignedBeaconBlock_Phase0:
|
|
blk = wrapper.WrappedPhase0SignedBeaconBlock(b.Phase0)
|
|
case *ethpb.GenericSignedBeaconBlock_Altair:
|
|
blk, err = wrapper.WrappedAltairSignedBeaconBlock(b.Altair)
|
|
if err != nil {
|
|
return nil, status.Error(codes.Internal, "could not wrap altair beacon block")
|
|
}
|
|
default:
|
|
return nil, status.Error(codes.Internal, "block version not supported")
|
|
}
|
|
return vs.proposeGenericBeaconBlock(ctx, blk)
|
|
}
|
|
|
|
// ProposeBlock is called by a proposer during its assigned slot to create a block in an attempt
|
|
// to get it processed by the beacon node as the canonical head.
|
|
//
|
|
// DEPRECATED: Use ProposeBeaconBlock instead.
|
|
func (vs *Server) ProposeBlock(ctx context.Context, rBlk *ethpb.SignedBeaconBlock) (*ethpb.ProposeResponse, error) {
|
|
ctx, span := trace.StartSpan(ctx, "ProposerServer.ProposeBlock")
|
|
defer span.End()
|
|
blk := wrapper.WrappedPhase0SignedBeaconBlock(rBlk)
|
|
return vs.proposeGenericBeaconBlock(ctx, blk)
|
|
}
|
|
|
|
func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, blk block.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)
|
|
}
|
|
|
|
// Do not block proposal critical path with debug logging or block feed updates.
|
|
defer func() {
|
|
log.WithField("blockRoot", fmt.Sprintf("%#x", bytesutil.Trunc(root[:]))).Debugf(
|
|
"Block proposal received via RPC")
|
|
vs.BlockNotifier.BlockFeed().Send(&feed.Event{
|
|
Type: blockfeed.ReceivedBlock,
|
|
Data: &blockfeed.ReceivedBlockData{SignedBlock: blk},
|
|
})
|
|
}()
|
|
|
|
// Broadcast the new block to the network.
|
|
if err := vs.P2P.Broadcast(ctx, blk.Proto()); err != nil {
|
|
return nil, fmt.Errorf("could not broadcast 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)
|
|
}
|
|
|
|
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 block.SignedBeaconBlock) ([]byte, error) {
|
|
beaconState, err := vs.StateGen.StateByRoot(ctx, bytesutil.ToBytes32(block.Block().ParentRoot()))
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not retrieve beacon state")
|
|
}
|
|
root, err := transition.CalculateStateRoot(
|
|
ctx,
|
|
beaconState,
|
|
block,
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "could not calculate state root at slot %d", beaconState.Slot())
|
|
}
|
|
|
|
log.WithField("beaconStateRoot", fmt.Sprintf("%#x", root)).Debugf("Computed state root")
|
|
return root[:], nil
|
|
}
|