prysm-pulse/beacon-chain/rpc/beacon_server.go
2019-08-26 13:06:16 -07:00

119 lines
4.2 KiB
Go

package rpc
import (
"context"
"fmt"
"time"
ptypes "github.com/gogo/protobuf/types"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/trieutil"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type stateFeedListener interface {
StateInitializedFeed() *event.Feed
}
// BeaconServer defines a server implementation of the gRPC Beacon service,
// providing RPC endpoints for obtaining the canonical beacon chain head,
// fetching latest observed attestations, and more.
type BeaconServer struct {
beaconDB db.Database
ctx context.Context
powChainService powChainService
chainService stateFeedListener
operationService operationService
incomingAttestation chan *ethpb.Attestation
canonicalStateChan chan *pbp2p.BeaconState
chainStartChan chan time.Time
}
// WaitForChainStart queries the logs of the Deposit Contract in order to verify the beacon chain
// has started its runtime and validators begin their responsibilities. If it has not, it then
// subscribes to an event stream triggered by the powchain service whenever the ChainStart log does
// occur in the Deposit Contract on ETH 1.0.
func (bs *BeaconServer) WaitForChainStart(req *ptypes.Empty, stream pb.BeaconService_WaitForChainStartServer) error {
ok := bs.powChainService.HasChainStarted()
if ok {
genesisTime, _ := bs.powChainService.ETH2GenesisTime()
res := &pb.ChainStartResponse{
Started: true,
GenesisTime: genesisTime,
}
return stream.Send(res)
}
sub := bs.chainService.StateInitializedFeed().Subscribe(bs.chainStartChan)
defer sub.Unsubscribe()
for {
select {
case chainStartTime := <-bs.chainStartChan:
log.Info("Sending ChainStart log and genesis time to connected validator clients")
res := &pb.ChainStartResponse{
Started: true,
GenesisTime: uint64(chainStartTime.Unix()),
}
return stream.Send(res)
case <-sub.Err():
return errors.New("subscriber closed, exiting goroutine")
case <-bs.ctx.Done():
return errors.New("rpc context closed, exiting goroutine")
}
}
}
// CanonicalHead of the current beacon chain. This method is requested on-demand
// by a validator when it is their time to propose or attest.
func (bs *BeaconServer) CanonicalHead(ctx context.Context, req *ptypes.Empty) (*ethpb.BeaconBlock, error) {
var headBlock *ethpb.BeaconBlock
var err error
if d, isLegacyDB := bs.beaconDB.(*db.BeaconDB); isLegacyDB {
headBlock, err = d.ChainHead()
if err != nil {
return nil, errors.Wrap(err, "could not get canonical head block")
}
} else {
headBlock = bs.chainService.(blockchain.HeadRetriever).HeadBlock()
}
return headBlock, nil
}
// BlockTree returns the current tree of saved blocks and their votes starting from the justified state.
func (bs *BeaconServer) BlockTree(ctx context.Context, _ *ptypes.Empty) (*pb.BlockTreeResponse, error) {
// TODO(3219): Add after new fork choice service.
return nil, status.Error(codes.Unimplemented, "not implemented")
}
// BlockTreeBySlots returns the current tree of saved blocks and their
// votes starting from the justified state.
func (bs *BeaconServer) BlockTreeBySlots(ctx context.Context, req *pb.TreeBlockSlotRequest) (*pb.BlockTreeResponse, error) {
// TODO(3219): Add after new fork choice service.
return nil, status.Error(codes.Unimplemented, "not implemented")
}
func constructMerkleProof(trie *trieutil.MerkleTrie, index int, deposit *ethpb.Deposit) (*ethpb.Deposit, error) {
proof, err := trie.MerkleProof(index)
if err != nil {
return nil, fmt.Errorf(
"could not generate merkle proof for deposit at index %d: %v",
index,
err,
)
}
// For every deposit, we construct a Merkle proof using the powchain service's
// in-memory deposits trie, which is updated only once the state's LatestETH1Data
// property changes during a state transition after a voting period.
deposit.Proof = proof
return deposit, nil
}