2021-07-02 15:54:52 +00:00
|
|
|
package beacon
|
2020-10-05 00:15:27 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-10-15 18:00:49 +00:00
|
|
|
"fmt"
|
|
|
|
"strconv"
|
2020-10-05 00:15:27 +00:00
|
|
|
|
2020-10-15 18:00:49 +00:00
|
|
|
"github.com/pkg/errors"
|
2021-02-16 07:45:34 +00:00
|
|
|
types "github.com/prysmaticlabs/eth2-types"
|
2020-10-15 18:00:49 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
|
|
|
blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
2021-06-02 23:49:52 +00:00
|
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
2021-07-06 15:34:05 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
|
|
|
|
"github.com/prysmaticlabs/prysm/proto/interfaces"
|
2020-10-15 18:00:49 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/proto/migration"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
2021-05-20 19:56:53 +00:00
|
|
|
"go.opencensus.io/trace"
|
2020-10-15 18:00:49 +00:00
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
"google.golang.org/grpc/status"
|
2021-05-17 18:32:04 +00:00
|
|
|
"google.golang.org/protobuf/types/known/emptypb"
|
2020-10-05 00:15:27 +00:00
|
|
|
)
|
|
|
|
|
2021-06-15 15:28:49 +00:00
|
|
|
// blockIdParseError represents an error scenario where a block ID could not be parsed.
|
|
|
|
type blockIdParseError struct {
|
|
|
|
message string
|
|
|
|
}
|
|
|
|
|
|
|
|
// newBlockIdParseError creates a new error instance.
|
|
|
|
func newBlockIdParseError(reason error) blockIdParseError {
|
|
|
|
return blockIdParseError{
|
|
|
|
message: errors.Wrapf(reason, "could not parse block ID").Error(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Error returns the underlying error message.
|
|
|
|
func (e *blockIdParseError) Error() string {
|
|
|
|
return e.message
|
|
|
|
}
|
|
|
|
|
2020-10-05 00:15:27 +00:00
|
|
|
// GetBlockHeader retrieves block header for given block id.
|
|
|
|
func (bs *Server) GetBlockHeader(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BlockHeaderResponse, error) {
|
2021-05-20 19:56:53 +00:00
|
|
|
ctx, span := trace.StartSpan(ctx, "beaconv1.GetBlockHeader")
|
|
|
|
defer span.End()
|
|
|
|
|
2021-05-26 16:19:54 +00:00
|
|
|
rBlk, err := bs.blockFromBlockID(ctx, req.BlockId)
|
2021-06-15 15:28:49 +00:00
|
|
|
if invalidBlockIdErr, ok := err.(*blockIdParseError); ok {
|
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "Invalid block ID: %v", invalidBlockIdErr)
|
|
|
|
}
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get block from block ID: %v", err)
|
|
|
|
}
|
2021-05-26 16:19:54 +00:00
|
|
|
if rBlk == nil || rBlk.IsNil() {
|
2020-10-15 18:00:49 +00:00
|
|
|
return nil, status.Errorf(codes.NotFound, "Could not find requested block header")
|
|
|
|
}
|
2021-05-26 16:19:54 +00:00
|
|
|
blk, err := rBlk.PbPhase0Block()
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get raw block: %v", err)
|
|
|
|
}
|
2020-10-15 18:00:49 +00:00
|
|
|
|
|
|
|
v1BlockHdr, err := migration.V1Alpha1BlockToV1BlockHeader(blk)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get block header from block: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
blkRoot, err := blk.Block.HashTreeRoot()
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not hash block: %v", err)
|
|
|
|
}
|
|
|
|
canonical, err := bs.ChainInfoFetcher.IsCanonical(ctx, blkRoot)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not determine if block root is canonical: %v", err)
|
|
|
|
}
|
|
|
|
root, err := v1BlockHdr.HashTreeRoot()
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not hash block header: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return ðpb.BlockHeaderResponse{
|
|
|
|
Data: ðpb.BlockHeaderContainer{
|
|
|
|
Root: root[:],
|
|
|
|
Canonical: canonical,
|
|
|
|
Header: ðpb.BeaconBlockHeaderContainer{
|
2021-05-25 01:02:01 +00:00
|
|
|
Message: v1BlockHdr.Message,
|
2020-10-15 18:00:49 +00:00
|
|
|
Signature: v1BlockHdr.Signature,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, nil
|
2020-10-05 00:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ListBlockHeaders retrieves block headers matching given query. By default it will fetch current head slot blocks.
|
|
|
|
func (bs *Server) ListBlockHeaders(ctx context.Context, req *ethpb.BlockHeadersRequest) (*ethpb.BlockHeadersResponse, error) {
|
2021-05-20 19:56:53 +00:00
|
|
|
ctx, span := trace.StartSpan(ctx, "beaconv1.ListBlockHeaders")
|
|
|
|
defer span.End()
|
|
|
|
|
2020-10-15 18:00:49 +00:00
|
|
|
var err error
|
2021-05-26 16:19:54 +00:00
|
|
|
var blks []interfaces.SignedBeaconBlock
|
2020-10-18 16:39:27 +00:00
|
|
|
var blkRoots [][32]byte
|
2020-10-15 18:00:49 +00:00
|
|
|
if len(req.ParentRoot) == 32 {
|
2020-10-18 16:39:27 +00:00
|
|
|
blks, blkRoots, err = bs.BeaconDB.Blocks(ctx, filters.NewFilter().SetParentRoot(req.ParentRoot))
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve blocks: %v", err)
|
|
|
|
}
|
|
|
|
} else {
|
2021-05-17 18:32:04 +00:00
|
|
|
slot := bs.ChainInfoFetcher.HeadSlot()
|
|
|
|
if req.Slot != nil {
|
|
|
|
slot = *req.Slot
|
|
|
|
}
|
|
|
|
_, blks, err = bs.BeaconDB.BlocksBySlot(ctx, slot)
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve blocks for slot %d: %v", req.Slot, err)
|
|
|
|
}
|
2021-05-17 18:32:04 +00:00
|
|
|
_, blkRoots, err = bs.BeaconDB.BlockRootsBySlot(ctx, slot)
|
2021-01-12 18:31:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve block roots for slot %d: %v", req.Slot, err)
|
|
|
|
}
|
2020-10-15 18:00:49 +00:00
|
|
|
}
|
2021-05-26 16:19:54 +00:00
|
|
|
if len(blks) == 0 {
|
2020-10-15 18:00:49 +00:00
|
|
|
return nil, status.Error(codes.NotFound, "Could not find requested blocks")
|
|
|
|
}
|
|
|
|
|
|
|
|
blkHdrs := make([]*ethpb.BlockHeaderContainer, len(blks))
|
2021-05-26 16:19:54 +00:00
|
|
|
for i, bl := range blks {
|
|
|
|
blk, err := bl.PbPhase0Block()
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get raw block: %v", err)
|
|
|
|
}
|
2020-10-15 18:00:49 +00:00
|
|
|
blkHdr, err := migration.V1Alpha1BlockToV1BlockHeader(blk)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get block header from block: %v", err)
|
|
|
|
}
|
2020-10-18 16:39:27 +00:00
|
|
|
canonical, err := bs.ChainInfoFetcher.IsCanonical(ctx, blkRoots[i])
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not determine if block root is canonical: %v", err)
|
|
|
|
}
|
2021-05-25 01:02:01 +00:00
|
|
|
root, err := blkHdr.Message.HashTreeRoot()
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not hash block header: %v", err)
|
|
|
|
}
|
|
|
|
blkHdrs[i] = ðpb.BlockHeaderContainer{
|
|
|
|
Root: root[:],
|
|
|
|
Canonical: canonical,
|
|
|
|
Header: ðpb.BeaconBlockHeaderContainer{
|
2021-05-25 01:02:01 +00:00
|
|
|
Message: blkHdr.Message,
|
2020-10-15 18:00:49 +00:00
|
|
|
Signature: blkHdr.Signature,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ðpb.BlockHeadersResponse{Data: blkHdrs}, nil
|
2020-10-05 00:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SubmitBlock instructs the beacon node to broadcast a newly signed beacon block to the beacon network, to be
|
|
|
|
// included in the beacon chain. The beacon node is not required to validate the signed BeaconBlock, and a successful
|
|
|
|
// response (20X) only indicates that the broadcast has been successful. The beacon node is expected to integrate the
|
|
|
|
// new block into its state, and therefore validate the block internally, however blocks which fail the validation are
|
|
|
|
// still broadcast but a different status code is returned (202).
|
2021-05-17 18:32:04 +00:00
|
|
|
func (bs *Server) SubmitBlock(ctx context.Context, req *ethpb.BeaconBlockContainer) (*emptypb.Empty, error) {
|
2021-05-20 19:56:53 +00:00
|
|
|
ctx, span := trace.StartSpan(ctx, "beaconv1.SubmitBlock")
|
|
|
|
defer span.End()
|
2020-10-15 18:00:49 +00:00
|
|
|
|
2021-05-20 19:56:53 +00:00
|
|
|
blk := req.Message
|
2021-05-26 16:19:54 +00:00
|
|
|
rBlock, err := migration.V1ToV1Alpha1Block(ðpb.SignedBeaconBlock{Block: blk, Signature: req.Signature})
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
2021-06-15 15:28:49 +00:00
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "Could not convert block to v1 block")
|
2020-10-15 18:00:49 +00:00
|
|
|
}
|
2021-07-06 15:34:05 +00:00
|
|
|
v1alpha1Block := wrapper.WrappedPhase0SignedBeaconBlock(rBlock)
|
2020-10-15 18:00:49 +00:00
|
|
|
|
|
|
|
root, err := blk.HashTreeRoot()
|
|
|
|
if err != nil {
|
2021-06-15 15:28:49 +00:00
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "Could not tree hash block: %v", err)
|
2020-10-15 18:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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")
|
|
|
|
bs.BlockNotifier.BlockFeed().Send(&feed.Event{
|
|
|
|
Type: blockfeed.ReceivedBlock,
|
|
|
|
Data: &blockfeed.ReceivedBlockData{SignedBlock: v1alpha1Block},
|
|
|
|
})
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Broadcast the new block to the network.
|
2021-05-26 16:19:54 +00:00
|
|
|
if err := bs.Broadcaster.Broadcast(ctx, v1alpha1Block.Proto()); err != nil {
|
2020-10-15 18:00:49 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not broadcast block: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := bs.BlockReceiver.ReceiveBlock(ctx, v1alpha1Block, root); err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not process beacon block: %v", err)
|
|
|
|
}
|
|
|
|
|
2021-05-17 18:32:04 +00:00
|
|
|
return &emptypb.Empty{}, nil
|
2020-10-05 00:15:27 +00:00
|
|
|
}
|
|
|
|
|
2021-06-15 15:28:49 +00:00
|
|
|
// GetBlock retrieves block details for given block ID.
|
2020-10-05 00:15:27 +00:00
|
|
|
func (bs *Server) GetBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BlockResponse, error) {
|
2021-05-20 19:56:53 +00:00
|
|
|
ctx, span := trace.StartSpan(ctx, "beaconv1.GetBlock")
|
|
|
|
defer span.End()
|
|
|
|
|
2021-06-15 15:28:49 +00:00
|
|
|
block, err := bs.blockFromBlockID(ctx, req.BlockId)
|
|
|
|
if invalidBlockIdErr, ok := err.(*blockIdParseError); ok {
|
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "Invalid block ID: %v", invalidBlockIdErr)
|
|
|
|
}
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get block from block ID: %v", err)
|
|
|
|
}
|
2021-06-15 15:28:49 +00:00
|
|
|
signedBeaconBlock, err := migration.SignedBeaconBlock(block)
|
2021-05-26 16:19:54 +00:00
|
|
|
if err != nil {
|
2021-06-15 15:28:49 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
2020-10-15 18:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ðpb.BlockResponse{
|
|
|
|
Data: ðpb.BeaconBlockContainer{
|
2021-06-15 15:28:49 +00:00
|
|
|
Message: signedBeaconBlock.Block,
|
|
|
|
Signature: signedBeaconBlock.Signature,
|
2020-10-15 18:00:49 +00:00
|
|
|
},
|
|
|
|
}, nil
|
2020-10-05 00:15:27 +00:00
|
|
|
}
|
|
|
|
|
2021-06-15 15:28:49 +00:00
|
|
|
// GetBlockSSZ returns the SSZ-serialized version of the becaon block for given block ID.
|
|
|
|
func (bs *Server) GetBlockSSZ(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BlockSSZResponse, error) {
|
|
|
|
ctx, span := trace.StartSpan(ctx, "beaconv1.GetBlockSSZ")
|
|
|
|
defer span.End()
|
|
|
|
|
|
|
|
block, err := bs.blockFromBlockID(ctx, req.BlockId)
|
|
|
|
if invalidBlockIdErr, ok := err.(*blockIdParseError); ok {
|
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "Invalid block ID: %v", invalidBlockIdErr)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get block from block ID: %v", err)
|
|
|
|
}
|
|
|
|
signedBeaconBlock, err := migration.SignedBeaconBlock(block)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
|
|
|
|
}
|
|
|
|
sszBlock, err := signedBeaconBlock.MarshalSSZ()
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return ðpb.BlockSSZResponse{Data: sszBlock}, nil
|
|
|
|
}
|
|
|
|
|
2020-10-05 00:15:27 +00:00
|
|
|
// GetBlockRoot retrieves hashTreeRoot of BeaconBlock/BeaconBlockHeader.
|
|
|
|
func (bs *Server) GetBlockRoot(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BlockRootResponse, error) {
|
2021-05-20 19:56:53 +00:00
|
|
|
ctx, span := trace.StartSpan(ctx, "beaconv1.GetBlockRoot")
|
|
|
|
defer span.End()
|
|
|
|
|
2020-10-15 18:00:49 +00:00
|
|
|
var root []byte
|
|
|
|
var err error
|
|
|
|
switch string(req.BlockId) {
|
|
|
|
case "head":
|
|
|
|
root, err = bs.ChainInfoFetcher.HeadRoot(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve head block: %v", err)
|
|
|
|
}
|
|
|
|
if root == nil {
|
|
|
|
return nil, status.Errorf(codes.NotFound, "No head root was found")
|
|
|
|
}
|
|
|
|
case "finalized":
|
|
|
|
finalized := bs.ChainInfoFetcher.FinalizedCheckpt()
|
|
|
|
root = finalized.Root
|
|
|
|
case "genesis":
|
|
|
|
blk, err := bs.BeaconDB.GenesisBlock(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve blocks for genesis slot: %v", err)
|
|
|
|
}
|
2021-05-26 16:19:54 +00:00
|
|
|
if blk == nil || blk.IsNil() {
|
2020-10-15 18:00:49 +00:00
|
|
|
return nil, status.Error(codes.NotFound, "Could not find genesis block")
|
|
|
|
}
|
2021-05-26 16:19:54 +00:00
|
|
|
blkRoot, err := blk.Block().HashTreeRoot()
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Error(codes.Internal, "Could not hash genesis block")
|
|
|
|
}
|
|
|
|
root = blkRoot[:]
|
|
|
|
default:
|
|
|
|
if len(req.BlockId) == 32 {
|
|
|
|
block, err := bs.BeaconDB.Block(ctx, bytesutil.ToBytes32(req.BlockId))
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve block for block root %#x: %v", req.BlockId, err)
|
|
|
|
}
|
2021-05-26 16:19:54 +00:00
|
|
|
if block == nil || block.IsNil() {
|
2020-10-15 18:00:49 +00:00
|
|
|
return nil, status.Error(codes.NotFound, "Could not find any blocks with given root")
|
|
|
|
}
|
|
|
|
|
|
|
|
root = req.BlockId
|
|
|
|
} else {
|
|
|
|
slot, err := strconv.ParseUint(string(req.BlockId), 10, 64)
|
|
|
|
if err != nil {
|
2021-06-15 15:28:49 +00:00
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "Could not parse block ID: %v", err)
|
2020-10-15 18:00:49 +00:00
|
|
|
}
|
2021-02-16 07:45:34 +00:00
|
|
|
hasRoots, roots, err := bs.BeaconDB.BlockRootsBySlot(ctx, types.Slot(slot))
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve blocks for slot %d: %v", slot, err)
|
|
|
|
}
|
|
|
|
|
2021-01-12 18:31:15 +00:00
|
|
|
if !hasRoots {
|
2020-10-15 18:00:49 +00:00
|
|
|
return nil, status.Error(codes.NotFound, "Could not find any blocks with given slot")
|
|
|
|
}
|
|
|
|
root = roots[0][:]
|
2021-01-12 18:31:15 +00:00
|
|
|
if len(roots) == 1 {
|
2020-10-15 18:00:49 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
for _, blockRoot := range roots {
|
|
|
|
canonical, err := bs.ChainInfoFetcher.IsCanonical(ctx, blockRoot)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not determine if block root is canonical: %v", err)
|
|
|
|
}
|
|
|
|
if canonical {
|
|
|
|
root = blockRoot[:]
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ðpb.BlockRootResponse{
|
|
|
|
Data: ðpb.BlockRootContainer{
|
|
|
|
Root: root,
|
|
|
|
},
|
|
|
|
}, nil
|
2020-10-05 00:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ListBlockAttestations retrieves attestation included in requested block.
|
|
|
|
func (bs *Server) ListBlockAttestations(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BlockAttestationsResponse, error) {
|
2021-05-20 19:56:53 +00:00
|
|
|
ctx, span := trace.StartSpan(ctx, "beaconv1.ListBlockAttestations")
|
|
|
|
defer span.End()
|
|
|
|
|
2021-05-26 16:19:54 +00:00
|
|
|
rBlk, err := bs.blockFromBlockID(ctx, req.BlockId)
|
2021-06-15 15:28:49 +00:00
|
|
|
if invalidBlockIdErr, ok := err.(*blockIdParseError); ok {
|
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "Invalid block ID: %v", invalidBlockIdErr)
|
|
|
|
}
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get block from block ID: %v", err)
|
|
|
|
}
|
2021-05-26 16:19:54 +00:00
|
|
|
if rBlk == nil || rBlk.IsNil() {
|
2020-10-15 18:00:49 +00:00
|
|
|
return nil, status.Errorf(codes.NotFound, "Could not find requested block")
|
|
|
|
}
|
|
|
|
|
2021-05-26 16:19:54 +00:00
|
|
|
blk, err := rBlk.PbPhase0Block()
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not get raw block: %v", err)
|
|
|
|
}
|
|
|
|
|
2020-10-15 18:00:49 +00:00
|
|
|
v1Block, err := migration.V1Alpha1ToV1Block(blk)
|
|
|
|
if err != nil {
|
2021-06-15 15:28:49 +00:00
|
|
|
return nil, status.Errorf(codes.Internal, "Could not convert block to v1 block")
|
2020-10-15 18:00:49 +00:00
|
|
|
}
|
|
|
|
return ðpb.BlockAttestationsResponse{
|
|
|
|
Data: v1Block.Block.Body.Attestations,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2021-05-26 16:19:54 +00:00
|
|
|
func (bs *Server) blockFromBlockID(ctx context.Context, blockId []byte) (interfaces.SignedBeaconBlock, error) {
|
2020-10-15 18:00:49 +00:00
|
|
|
var err error
|
2021-05-26 16:19:54 +00:00
|
|
|
var blk interfaces.SignedBeaconBlock
|
2020-10-15 18:00:49 +00:00
|
|
|
switch string(blockId) {
|
|
|
|
case "head":
|
|
|
|
blk, err = bs.ChainInfoFetcher.HeadBlock(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not retrieve head block")
|
|
|
|
}
|
|
|
|
case "finalized":
|
|
|
|
finalized := bs.ChainInfoFetcher.FinalizedCheckpt()
|
|
|
|
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
|
|
|
|
blk, err = bs.BeaconDB.Block(ctx, finalizedRoot)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("could not get finalized block from db")
|
|
|
|
}
|
|
|
|
case "genesis":
|
|
|
|
blk, err = bs.BeaconDB.GenesisBlock(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not retrieve blocks for genesis slot")
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if len(blockId) == 32 {
|
|
|
|
blk, err = bs.BeaconDB.Block(ctx, bytesutil.ToBytes32(blockId))
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not retrieve block")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
slot, err := strconv.ParseUint(string(blockId), 10, 64)
|
|
|
|
if err != nil {
|
2021-06-15 15:28:49 +00:00
|
|
|
e := newBlockIdParseError(err)
|
|
|
|
return nil, &e
|
2020-10-15 18:00:49 +00:00
|
|
|
}
|
2021-02-16 07:45:34 +00:00
|
|
|
_, blks, err := bs.BeaconDB.BlocksBySlot(ctx, types.Slot(slot))
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "could not retrieve blocks for slot %d", slot)
|
|
|
|
}
|
2021-02-16 07:45:34 +00:00
|
|
|
_, roots, err := bs.BeaconDB.BlockRootsBySlot(ctx, types.Slot(slot))
|
2021-01-12 18:31:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "could not retrieve block roots for slot %d", slot)
|
|
|
|
}
|
2020-10-15 18:00:49 +00:00
|
|
|
|
|
|
|
numBlks := len(blks)
|
|
|
|
if numBlks == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
blk = blks[0]
|
|
|
|
if numBlks == 1 {
|
|
|
|
break
|
|
|
|
}
|
2020-10-18 16:39:27 +00:00
|
|
|
for i, block := range blks {
|
|
|
|
canonical, err := bs.ChainInfoFetcher.IsCanonical(ctx, roots[i])
|
2020-10-15 18:00:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Errorf(codes.Internal, "Could not determine if block root is canonical: %v", err)
|
|
|
|
}
|
|
|
|
if canonical {
|
|
|
|
blk = block
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return blk, nil
|
2020-10-05 00:15:27 +00:00
|
|
|
}
|