prysm-pulse/beacon-chain/rpc/beacon_server.go
Raul Jordan f342224410
Full RPC Package Compliance With New DB Interface (#3275)
* deprecate db

* fix build

* begin integrating new db

* gaz

* use more of the new db

* newest implementation uses head state

* remove more deprecated items

* setup validators in state helper

* fix up some tests with the new db

* resolve broken build

* gaz

* begin ensuring tests pass

* optional idx

* list validator balances passing

* default page size passing

* only two failing

* fixed most tests, found edge case

* allow nil return and add proper tests

* pass tests

* fix head block root problem

* working with the new db

* every ethereumapis method now compliant with both dbs

* pass in db into server

* proposer server all compliant

* validator service fully compliant

* fix broken build, tests pass

* spacing

* compute state root and propose block tests passing with new db

* complete proposer server tests revamp

* validator tests halfway through passing with new db

* more validator server tests

* more than halfway there

* so so close

* all validators tests done

* attester server tests fixing

* use new api

* attester server complete

* complete
2019-08-22 20:39:06 -05:00

119 lines
4.3 KiB
Go

package rpc
import (
"context"
"fmt"
"time"
ptypes "github.com/gogo/protobuf/types"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
blockchain "github.com/prysmaticlabs/prysm/beacon-chain/deprecated-blockchain"
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/trieutil"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// 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 chainService
targetsFetcher blockchain.TargetsFetcher
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, err = bs.beaconDB.(*kv.Store).HeadBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not get canonical head block")
}
}
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
}