Implement WaitForChainStart RPC Server and Client (#1421)

This commit is contained in:
Raul Jordan
2019-01-30 13:28:53 +01:00
committed by GitHub
parent 3f25b1ae84
commit ec9240106e
33 changed files with 1349 additions and 443 deletions

View File

@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1 (interfaces: BeaconServiceServer,BeaconService_LatestAttestationServer)
// Source: github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1 (interfaces: BeaconServiceServer,BeaconService_LatestAttestationServer,BeaconService_WaitForChainStartServer)
package internal
@@ -62,6 +62,18 @@ func (mr *MockBeaconServiceServerMockRecorder) LatestAttestation(arg0, arg1 inte
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LatestAttestation", reflect.TypeOf((*MockBeaconServiceServer)(nil).LatestAttestation), arg0, arg1)
}
// WaitForChainStart mocks base method
func (m *MockBeaconServiceServer) WaitForChainStart(arg0 *types.Empty, arg1 v10.BeaconService_WaitForChainStartServer) error {
ret := m.ctrl.Call(m, "WaitForChainStart", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// WaitForChainStart indicates an expected call of WaitForChainStart
func (mr *MockBeaconServiceServerMockRecorder) WaitForChainStart(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitForChainStart", reflect.TypeOf((*MockBeaconServiceServer)(nil).WaitForChainStart), arg0, arg1)
}
// MockBeaconService_LatestAttestationServer is a mock of BeaconService_LatestAttestationServer interface
type MockBeaconService_LatestAttestationServer struct {
ctrl *gomock.Controller
@@ -166,3 +178,108 @@ func (m *MockBeaconService_LatestAttestationServer) SetTrailer(arg0 metadata.MD)
func (mr *MockBeaconService_LatestAttestationServerMockRecorder) SetTrailer(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTrailer", reflect.TypeOf((*MockBeaconService_LatestAttestationServer)(nil).SetTrailer), arg0)
}
// MockBeaconService_WaitForChainStartServer is a mock of BeaconService_WaitForChainStartServer interface
type MockBeaconService_WaitForChainStartServer struct {
ctrl *gomock.Controller
recorder *MockBeaconService_WaitForChainStartServerMockRecorder
}
// MockBeaconService_WaitForChainStartServerMockRecorder is the mock recorder for MockBeaconService_WaitForChainStartServer
type MockBeaconService_WaitForChainStartServerMockRecorder struct {
mock *MockBeaconService_WaitForChainStartServer
}
// NewMockBeaconService_WaitForChainStartServer creates a new mock instance
func NewMockBeaconService_WaitForChainStartServer(ctrl *gomock.Controller) *MockBeaconService_WaitForChainStartServer {
mock := &MockBeaconService_WaitForChainStartServer{ctrl: ctrl}
mock.recorder = &MockBeaconService_WaitForChainStartServerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockBeaconService_WaitForChainStartServer) EXPECT() *MockBeaconService_WaitForChainStartServerMockRecorder {
return m.recorder
}
// Context mocks base method
func (m *MockBeaconService_WaitForChainStartServer) Context() context.Context {
ret := m.ctrl.Call(m, "Context")
ret0, _ := ret[0].(context.Context)
return ret0
}
// Context indicates an expected call of Context
func (mr *MockBeaconService_WaitForChainStartServerMockRecorder) Context() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockBeaconService_WaitForChainStartServer)(nil).Context))
}
// RecvMsg mocks base method
func (m *MockBeaconService_WaitForChainStartServer) RecvMsg(arg0 interface{}) error {
ret := m.ctrl.Call(m, "RecvMsg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// RecvMsg indicates an expected call of RecvMsg
func (mr *MockBeaconService_WaitForChainStartServerMockRecorder) RecvMsg(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockBeaconService_WaitForChainStartServer)(nil).RecvMsg), arg0)
}
// Send mocks base method
func (m *MockBeaconService_WaitForChainStartServer) Send(arg0 *v10.ChainStartResponse) error {
ret := m.ctrl.Call(m, "Send", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Send indicates an expected call of Send
func (mr *MockBeaconService_WaitForChainStartServerMockRecorder) Send(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockBeaconService_WaitForChainStartServer)(nil).Send), arg0)
}
// SendHeader mocks base method
func (m *MockBeaconService_WaitForChainStartServer) SendHeader(arg0 metadata.MD) error {
ret := m.ctrl.Call(m, "SendHeader", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SendHeader indicates an expected call of SendHeader
func (mr *MockBeaconService_WaitForChainStartServerMockRecorder) SendHeader(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendHeader", reflect.TypeOf((*MockBeaconService_WaitForChainStartServer)(nil).SendHeader), arg0)
}
// SendMsg mocks base method
func (m *MockBeaconService_WaitForChainStartServer) SendMsg(arg0 interface{}) error {
ret := m.ctrl.Call(m, "SendMsg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SendMsg indicates an expected call of SendMsg
func (mr *MockBeaconService_WaitForChainStartServerMockRecorder) SendMsg(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockBeaconService_WaitForChainStartServer)(nil).SendMsg), arg0)
}
// SetHeader mocks base method
func (m *MockBeaconService_WaitForChainStartServer) SetHeader(arg0 metadata.MD) error {
ret := m.ctrl.Call(m, "SetHeader", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SetHeader indicates an expected call of SetHeader
func (mr *MockBeaconService_WaitForChainStartServerMockRecorder) SetHeader(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHeader", reflect.TypeOf((*MockBeaconService_WaitForChainStartServer)(nil).SetHeader), arg0)
}
// SetTrailer mocks base method
func (m *MockBeaconService_WaitForChainStartServer) SetTrailer(arg0 metadata.MD) {
m.ctrl.Call(m, "SetTrailer", arg0)
}
// SetTrailer indicates an expected call of SetTrailer
func (mr *MockBeaconService_WaitForChainStartServerMockRecorder) SetTrailer(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTrailer", reflect.TypeOf((*MockBeaconService_WaitForChainStartServer)(nil).SetTrailer), arg0)
}

View File

@@ -186,7 +186,6 @@ func (b *BeaconNode) registerBlockchainService(ctx *cli.Context) error {
Web3Service: web3Service,
BeaconBlockBuf: 10,
IncomingBlockBuf: 100, // Big buffer to accommodate other feed subscribers.
EnablePOWChain: enablePOWChain,
})
if err != nil {
return fmt.Errorf("could not register blockchain service: %v", err)
@@ -304,7 +303,6 @@ func (b *BeaconNode) registerRPCService(ctx *cli.Context) error {
ChainService: chainService,
AttestationService: attestationService,
POWChainService: web3Service,
EnablePOWChain: enablePOWChain,
})
return b.services.RegisterService(rpcService)

View File

@@ -56,7 +56,6 @@ func TestNodeClose(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.String("web3provider", "ws//127.0.0.1:8546", "web3 provider ws or IPC endpoint")
set.String("datadir", tmp, "node data directory")
set.Bool("enable-powchain", false, "no powchain service")
set.Bool("demo-config", true, "demo configuration")
context := cli.NewContext(app, set, nil)

View File

@@ -143,18 +143,119 @@ func (w *Web3Service) Status() error {
return nil
}
// initDataFromVRC calls the vrc contract and finds the deposit count
// and deposit root.
func (w *Web3Service) initDataFromVRC() error {
root, err := w.vrcCaller.GetDepositRoot(&bind.CallOpts{})
// LatestBlockNumber in the ETH1.0 chain.
func (w *Web3Service) LatestBlockNumber() *big.Int {
return w.blockNumber
}
// LatestBlockHash in the ETH1.0 chain.
func (w *Web3Service) LatestBlockHash() common.Hash {
return w.blockHash
}
// Client for interacting with the ETH1.0 chain.
func (w *Web3Service) Client() Client {
return w.client
}
// HasChainStartLogOccurred queries all logs in the deposit contract to verify
// if ChainStart has occurred. If so, it returns true alongside the ChainStart timestamp.
func (w *Web3Service) HasChainStartLogOccurred() (bool, time.Time, error) {
query := ethereum.FilterQuery{
Addresses: []common.Address{
w.depositContractAddress,
},
}
logs, err := w.logger.FilterLogs(w.ctx, query)
if err != nil {
return fmt.Errorf("could not retrieve deposit root %v", err)
return false, time.Now(), fmt.Errorf("could not filter deposit contract logs: %v", err)
}
for _, log := range logs {
if log.Topics[0] == hashutil.Hash(chainStartEventSignature) {
_, timestampData, err := contracts.UnpackChainStartLogData(log.Data)
if err != nil {
return false, time.Now(), fmt.Errorf("unable to unpack ChainStart log data %v", err)
}
timestamp := binary.BigEndian.Uint64(timestampData)
if uint64(time.Now().Unix()) < timestamp {
return false, time.Now(), fmt.Errorf(
"invalid timestamp from log expected %d > %d",
time.Now().Unix(),
timestamp,
)
}
return true, time.Unix(int64(timestamp), 0), nil
}
}
return false, time.Now(), nil
}
// ProcessLog is the main method which handles the processing of all
// logs from the deposit contract on the ETH1.0 chain.
func (w *Web3Service) ProcessLog(VRClog gethTypes.Log) {
// Process logs according to their event signature.
if VRClog.Topics[0] == hashutil.Hash(depositEventSignature) {
w.ProcessDepositLog(VRClog)
return
}
w.depositRoot = root[:]
w.depositTrie = trie.NewDepositTrie()
if VRClog.Topics[0] == hashutil.Hash(chainStartEventSignature) {
w.ProcessChainStartLog(VRClog)
return
}
return nil
log.Debugf("Log is not of a valid event signature %#x", VRClog.Topics[0])
}
// ProcessDepositLog processes the log which had been received from
// the ETH1.0 chain by trying to ascertain which participant deposited
// in the contract.
func (w *Web3Service) ProcessDepositLog(VRClog gethTypes.Log) {
merkleRoot, depositData, MerkleTreeIndex, err := contracts.UnpackDepositLogData(VRClog.Data)
if err != nil {
log.Errorf("Could not unpack log %v", err)
return
}
if err := w.saveInTrie(depositData, merkleRoot); err != nil {
log.Errorf("Could not save in trie %v", err)
return
}
depositInput, err := blocks.DecodeDepositInput(depositData)
if err != nil {
log.Errorf("Could not decode deposit input %v", err)
return
}
index := binary.BigEndian.Uint64(MerkleTreeIndex)
log.WithFields(logrus.Fields{
"publicKey": depositInput.Pubkey,
"merkle tree index": index,
}).Info("Validator registered in VRC with public key and index")
}
// ProcessChainStartLog processes the log which had been received from
// the ETH1.0 chain by trying to determine when to start the beacon chain.
func (w *Web3Service) ProcessChainStartLog(VRClog gethTypes.Log) {
receiptRoot, timestampData, err := contracts.UnpackChainStartLogData(VRClog.Data)
if err != nil {
log.Errorf("Unable to unpack ChainStart log data %v", err)
return
}
if w.depositTrie.Root() != receiptRoot {
log.Errorf("Receipt root from log doesn't match the root saved in memory,"+
" want %#x but got %#x", w.depositTrie.Root(), receiptRoot)
return
}
timestamp := binary.BigEndian.Uint64(timestampData)
if uint64(time.Now().Unix()) < timestamp {
log.Errorf("Invalid timestamp from log expected %d > %d", time.Now().Unix(), timestamp)
}
chainStartTime := time.Unix(int64(timestamp), 0)
log.WithFields(logrus.Fields{
"ChainStartTime": chainStartTime,
}).Info("Minimum Number of Validators Reached for beacon-chain to start")
w.chainStartFeed.Send(chainStartTime)
}
// run subscribes to all the services for the ETH1.0 chain.
@@ -205,79 +306,25 @@ func (w *Web3Service) run(done <-chan struct{}) {
"blockHash": w.blockHash.Hex(),
}).Debug("Latest web3 chain event")
case VRClog := <-w.logChan:
log.Info("Received deposit contract log")
w.ProcessLog(VRClog)
}
}
}
// ProcessLog is the main method which handles the processing of all
// logs from the deposit contract on the ETH1.0 chain.
func (w *Web3Service) ProcessLog(VRClog gethTypes.Log) {
// Process logs according to their event signature.
if VRClog.Topics[0] == hashutil.Hash(depositEventSignature) {
w.ProcessDepositLog(VRClog)
return
}
if VRClog.Topics[0] == hashutil.Hash(chainStartEventSignature) {
w.ProcessChainStartLog(VRClog)
return
}
log.Debugf("Log is not of a valid event signature %#x", VRClog.Topics[0])
}
// ProcessDepositLog processes the log which had been received from
// the ETH1.0 chain by trying to ascertain which participant deposited
// in the contract.
func (w *Web3Service) ProcessDepositLog(VRClog gethTypes.Log) {
merkleRoot, depositData, MerkleTreeIndex, err := contracts.UnpackDepositLogData(VRClog.Data)
// initDataFromVRC calls the vrc contract and finds the deposit count
// and deposit root.
func (w *Web3Service) initDataFromVRC() error {
root, err := w.vrcCaller.GetDepositRoot(&bind.CallOpts{})
if err != nil {
log.Errorf("Could not unpack log %v", err)
return
}
if err := w.saveInTrie(depositData, merkleRoot); err != nil {
log.Errorf("Could not save in trie %v", err)
return
}
depositInput, err := blocks.DecodeDepositInput(depositData)
if err != nil {
log.Errorf("Could not decode deposit input %v", err)
return
}
index := binary.BigEndian.Uint64(MerkleTreeIndex)
log.WithFields(logrus.Fields{
"publicKey": depositInput.Pubkey,
"merkle tree index": index,
}).Info("Validator registered in VRC with public key and index")
}
// ProcessChainStartLog processes the log which had been received from
// the ETH1.0 chain by trying to determine when to start the beacon chain.
func (w *Web3Service) ProcessChainStartLog(VRClog gethTypes.Log) {
receiptRoot, timestampData, err := contracts.UnpackChainStartLogData(VRClog.Data)
if err != nil {
log.Errorf("Unable to unpack ChainStart log data %v", err)
return
}
if w.depositTrie.Root() != receiptRoot {
log.Errorf("Receipt root from log doesn't match the root saved in memory,"+
" want %#x but got %#x", w.depositTrie.Root(), receiptRoot)
return
return fmt.Errorf("could not retrieve deposit root %v", err)
}
timestamp := binary.BigEndian.Uint64(timestampData)
if uint64(time.Now().Unix()) < timestamp {
log.Errorf("Invalid timestamp from log expected %d > %d", time.Now().Unix(), timestamp)
}
w.depositRoot = root[:]
w.depositTrie = trie.NewDepositTrie()
chainStartTime := time.Unix(int64(timestamp), 0)
log.WithFields(logrus.Fields{
"ChainStartTime": chainStartTime,
}).Info("Minimum Number of Validators Reached for beacon-chain to start")
w.chainStartFeed.Send(chainStartTime)
return nil
}
// saveInTrie saves in the in-memory deposit trie.
@@ -303,18 +350,3 @@ func (w *Web3Service) processPastLogs(query ethereum.FilterQuery) error {
}
return nil
}
// LatestBlockNumber in the ETH1.0 chain.
func (w *Web3Service) LatestBlockNumber() *big.Int {
return w.blockNumber
}
// LatestBlockHash in the ETH1.0 chain.
func (w *Web3Service) LatestBlockHash() common.Hash {
return w.blockHash
}
// Client for interacting with the ETH1.0 chain.
func (w *Web3Service) Client() Client {
return w.client
}

View File

@@ -730,3 +730,66 @@ func TestUnpackChainStartLogs(t *testing.T) {
t.Errorf("Timestamp from log is higher than the current time %d > %d", timestamp, time.Now().Unix())
}
}
func TestHasChainStartLogOccurred(t *testing.T) {
endpoint := "ws://127.0.0.1"
testAcc, err := setup()
if err != nil {
t.Fatalf("Unable to set up simulated backend %v", err)
}
web3Service, err := NewWeb3Service(context.Background(), &Web3ServiceConfig{
Endpoint: endpoint,
DepositContract: testAcc.contractAddr,
Reader: &goodReader{},
Logger: testAcc.backend,
ContractBackend: testAcc.backend,
})
if err != nil {
t.Fatalf("unable to setup web3 ETH1.0 chain service: %v", err)
}
testAcc.backend.Commit()
testAcc.backend.AdjustTime(time.Duration(int64(time.Now().Nanosecond())))
var stub [48]byte
copy(stub[:], []byte("testing"))
data := &pb.DepositInput{
Pubkey: stub[:],
ProofOfPossession: stub[:],
WithdrawalCredentialsHash32: []byte("withdraw"),
RandaoCommitmentHash32: []byte("randao"),
CustodyCommitmentHash32: []byte("custody"),
}
serializedData := new(bytes.Buffer)
if err := ssz.Encode(serializedData, data); err != nil {
t.Fatalf("Could not serialize data %v", err)
}
ok, _, err := web3Service.HasChainStartLogOccurred()
if err != nil {
t.Fatalf("Could not check if chain start log occurred: %v", err)
}
if ok {
t.Error("Expected chain start log to not have occurred")
}
// 8 Validators are used as size required for beacon-chain to start. This number
// is defined in the VRC as the number required for the testnet.
for i := 0; i < depositsReqForChainStart; i++ {
testAcc.txOpts.Value = amount32Eth
if _, err := testAcc.contract.Deposit(testAcc.txOpts, serializedData.Bytes()); err != nil {
t.Fatalf("Could not deposit to VRC %v", err)
}
testAcc.backend.Commit()
}
ok, _, err = web3Service.HasChainStartLogOccurred()
if err != nil {
t.Fatalf("Could not check if chain start log occurred: %v", err)
}
if !ok {
t.Error("Expected chain start log to have occurred")
}
}

View File

@@ -21,7 +21,6 @@ go_library(
"//shared/event:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_gogo_protobuf//types:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
@@ -50,7 +49,6 @@ go_test(
"//shared/event:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_gogo_protobuf//types:go_default_library",
"@com_github_golang_mock//gomock:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",

View File

@@ -3,6 +3,7 @@ package rpc
import (
"context"
"fmt"
"time"
ptypes "github.com/gogo/protobuf/types"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
@@ -16,9 +17,49 @@ import (
type BeaconServer struct {
beaconDB *db.BeaconDB
ctx context.Context
powChainService powChainService
attestationService attestationService
incomingAttestation chan *pbp2p.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, genesisTime, err := bs.powChainService.HasChainStartLogOccurred()
if err != nil {
return fmt.Errorf("could not verify ChainStart log occurred: %v", err)
}
if ok {
res := &pb.ChainStartResponse{
Started: true,
GenesisTime: uint64(genesisTime.Unix()),
}
return stream.Send(res)
}
sub := bs.powChainService.ChainStartFeed().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():
log.Debug("Subscriber closed, exiting goroutine")
return nil
case <-bs.ctx.Done():
log.Debug("RPC context closed, exiting goroutine")
return nil
}
}
}
// CanonicalHead of the current beacon chain. This method is requested on-demand

View File

@@ -4,16 +4,117 @@ import (
"context"
"errors"
"testing"
"time"
"github.com/prysmaticlabs/prysm/shared/event"
ptypes "github.com/gogo/protobuf/types"
"github.com/golang/mock/gomock"
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/prysmaticlabs/prysm/shared/testutil"
logTest "github.com/sirupsen/logrus/hooks/test"
)
func TestLatestAttestationContextClosed(t *testing.T) {
type faultyPOWChainService struct {
chainStartFeed *event.Feed
}
func (f *faultyPOWChainService) HasChainStartLogOccurred() (bool, time.Time, error) {
return false, time.Now(), nil
}
func (f *faultyPOWChainService) ChainStartFeed() *event.Feed {
return f.chainStartFeed
}
type mockPOWChainService struct {
chainStartFeed *event.Feed
}
func (m *mockPOWChainService) HasChainStartLogOccurred() (bool, time.Time, error) {
return true, time.Unix(0, 0), nil
}
func (m *mockPOWChainService) ChainStartFeed() *event.Feed {
return m.chainStartFeed
}
func TestWaitForChainStart_ContextClosed(t *testing.T) {
hook := logTest.NewGlobal()
ctx, cancel := context.WithCancel(context.Background())
beaconServer := &BeaconServer{
ctx: ctx,
powChainService: &faultyPOWChainService{
chainStartFeed: new(event.Feed),
},
}
exitRoutine := make(chan bool)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockStream := internal.NewMockBeaconService_WaitForChainStartServer(ctrl)
go func(tt *testing.T) {
if err := beaconServer.WaitForChainStart(&ptypes.Empty{}, mockStream); err != nil {
tt.Errorf("Could not call RPC method: %v", err)
}
<-exitRoutine
}(t)
cancel()
exitRoutine <- true
testutil.AssertLogsContain(t, hook, "RPC context closed, exiting goroutine")
}
func TestWaitForChainStart_AlreadyStarted(t *testing.T) {
beaconServer := &BeaconServer{
ctx: context.Background(),
powChainService: &mockPOWChainService{
chainStartFeed: new(event.Feed),
},
}
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockStream := internal.NewMockBeaconService_WaitForChainStartServer(ctrl)
mockStream.EXPECT().Send(
&pb.ChainStartResponse{
Started: true,
GenesisTime: uint64(time.Unix(0, 0).Unix()),
},
).Return(nil)
if err := beaconServer.WaitForChainStart(&ptypes.Empty{}, mockStream); err != nil {
t.Errorf("Could not call RPC method: %v", err)
}
}
func TestWaitForChainStart_NotStartedThenLogFired(t *testing.T) {
hook := logTest.NewGlobal()
beaconServer := &BeaconServer{
ctx: context.Background(),
chainStartChan: make(chan time.Time, 1),
powChainService: &faultyPOWChainService{
chainStartFeed: new(event.Feed),
},
}
exitRoutine := make(chan bool)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockStream := internal.NewMockBeaconService_WaitForChainStartServer(ctrl)
mockStream.EXPECT().Send(
&pb.ChainStartResponse{
Started: true,
GenesisTime: uint64(time.Unix(0, 0).Unix()),
},
).Return(nil)
go func(tt *testing.T) {
if err := beaconServer.WaitForChainStart(&ptypes.Empty{}, mockStream); err != nil {
tt.Errorf("Could not call RPC method: %v", err)
}
<-exitRoutine
}(t)
beaconServer.chainStartChan <- time.Unix(0, 0)
exitRoutine <- true
testutil.AssertLogsContain(t, hook, "Sending ChainStart log and genesis time to connected validator clients")
}
func TestLatestAttestation_ContextClosed(t *testing.T) {
hook := logTest.NewGlobal()
mockAttestationService := &mockAttestationService{}
ctx, cancel := context.WithCancel(context.Background())
@@ -36,7 +137,7 @@ func TestLatestAttestationContextClosed(t *testing.T) {
testutil.AssertLogsContain(t, hook, "RPC context closed, exiting goroutine")
}
func TestLatestAttestationFaulty(t *testing.T) {
func TestLatestAttestation_FaultyServer(t *testing.T) {
attestationService := &mockAttestationService{}
ctx, cancel := context.WithCancel(context.Background())
beaconServer := &BeaconServer{
@@ -65,7 +166,7 @@ func TestLatestAttestationFaulty(t *testing.T) {
exitRoutine <- true
}
func TestLatestAttestation(t *testing.T) {
func TestLatestAttestation_SendsCorrectly(t *testing.T) {
hook := logTest.NewGlobal()
attestationService := &mockAttestationService{}
ctx, cancel := context.WithCancel(context.Background())

View File

@@ -22,7 +22,6 @@ type ProposerServer struct {
chainService chainService
powChainService powChainService
canonicalStateChan chan *pbp2p.BeaconState
enablePOWChain bool
}
// ProposerIndex sends a response to the client which returns the proposer index for a given slot. Validators

View File

@@ -7,7 +7,6 @@ import (
"net"
"time"
"github.com/ethereum/go-ethereum/common"
"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"
@@ -35,7 +34,8 @@ type attestationService interface {
}
type powChainService interface {
LatestBlockHash() common.Hash
HasChainStartLogOccurred() (bool, time.Time, error)
ChainStartFeed() *event.Feed
}
// Service defining an RPC server for a beacon node.
@@ -54,7 +54,6 @@ type Service struct {
canonicalBlockChan chan *pbp2p.BeaconBlock
canonicalStateChan chan *pbp2p.BeaconState
incomingAttestation chan *pbp2p.Attestation
enablePOWChain bool
slotAlignmentDuration time.Duration
}
@@ -68,7 +67,6 @@ type Config struct {
ChainService chainService
POWChainService powChainService
AttestationService attestationService
EnablePOWChain bool
}
// NewRPCService creates a new instance of a struct implementing the BeaconServiceServer
@@ -89,7 +87,6 @@ func NewRPCService(ctx context.Context, cfg *Config) *Service {
canonicalBlockChan: make(chan *pbp2p.BeaconBlock, cfg.SubscriptionBuf),
canonicalStateChan: make(chan *pbp2p.BeaconState, cfg.SubscriptionBuf),
incomingAttestation: make(chan *pbp2p.Attestation, cfg.SubscriptionBuf),
enablePOWChain: cfg.EnablePOWChain,
}
}
@@ -121,16 +118,17 @@ func (s *Service) Start() {
beaconServer := &BeaconServer{
beaconDB: s.beaconDB,
ctx: s.ctx,
powChainService: s.powChainService,
attestationService: s.attestationService,
incomingAttestation: s.incomingAttestation,
canonicalStateChan: s.canonicalStateChan,
chainStartChan: make(chan time.Time, 1),
}
proposerServer := &ProposerServer{
beaconDB: s.beaconDB,
chainService: s.chainService,
powChainService: s.powChainService,
canonicalStateChan: s.canonicalStateChan,
enablePOWChain: s.enablePOWChain,
}
attesterServer := &AttesterServer{
attestationService: s.attestationService,

View File

@@ -6,7 +6,6 @@ import (
"io/ioutil"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/sirupsen/logrus"
@@ -18,12 +17,6 @@ func init() {
logrus.SetOutput(ioutil.Discard)
}
type mockPOWChainService struct{}
func (m *mockPOWChainService) LatestBlockHash() common.Hash {
return common.BytesToHash([]byte{})
}
type mockAttestationService struct{}
func (m *mockAttestationService) IncomingAttestationFeed() *event.Feed {

View File

@@ -2,7 +2,6 @@ package rpc
import (
"context"
"fmt"
"strconv"
"testing"
"time"
@@ -71,7 +70,6 @@ func TestValidatorEpochAssignments(t *testing.T) {
for i := 0; i < len(deposits); i++ {
var pubKey [48]byte
copy(pubKey[:], []byte(strconv.Itoa(i)))
fmt.Println(len(pubKey))
depositInput := &pbp2p.DepositInput{
Pubkey: pubKey[:],
RandaoCommitmentHash32: []byte{0},

View File

@@ -48,7 +48,62 @@ func (x ValidatorRole) String() string {
return proto.EnumName(ValidatorRole_name, int32(x))
}
func (ValidatorRole) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{0}
return fileDescriptor_services_bf909c06e4b5edfe, []int{0}
}
type ChainStartResponse struct {
Started bool `protobuf:"varint,1,opt,name=started,proto3" json:"started,omitempty"`
GenesisTime uint64 `protobuf:"varint,2,opt,name=genesis_time,json=genesisTime,proto3" json:"genesis_time,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ChainStartResponse) Reset() { *m = ChainStartResponse{} }
func (m *ChainStartResponse) String() string { return proto.CompactTextString(m) }
func (*ChainStartResponse) ProtoMessage() {}
func (*ChainStartResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_services_bf909c06e4b5edfe, []int{0}
}
func (m *ChainStartResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ChainStartResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ChainStartResponse.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (dst *ChainStartResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ChainStartResponse.Merge(dst, src)
}
func (m *ChainStartResponse) XXX_Size() int {
return m.Size()
}
func (m *ChainStartResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ChainStartResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ChainStartResponse proto.InternalMessageInfo
func (m *ChainStartResponse) GetStarted() bool {
if m != nil {
return m.Started
}
return false
}
func (m *ChainStartResponse) GetGenesisTime() uint64 {
if m != nil {
return m.GenesisTime
}
return 0
}
type ProposeRequest struct {
@@ -67,7 +122,7 @@ func (m *ProposeRequest) Reset() { *m = ProposeRequest{} }
func (m *ProposeRequest) String() string { return proto.CompactTextString(m) }
func (*ProposeRequest) ProtoMessage() {}
func (*ProposeRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{0}
return fileDescriptor_services_bf909c06e4b5edfe, []int{1}
}
func (m *ProposeRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -149,7 +204,7 @@ func (m *ProposeResponse) Reset() { *m = ProposeResponse{} }
func (m *ProposeResponse) String() string { return proto.CompactTextString(m) }
func (*ProposeResponse) ProtoMessage() {}
func (*ProposeResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{1}
return fileDescriptor_services_bf909c06e4b5edfe, []int{2}
}
func (m *ProposeResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -196,7 +251,7 @@ func (m *ProposerIndexRequest) Reset() { *m = ProposerIndexRequest{} }
func (m *ProposerIndexRequest) String() string { return proto.CompactTextString(m) }
func (*ProposerIndexRequest) ProtoMessage() {}
func (*ProposerIndexRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{2}
return fileDescriptor_services_bf909c06e4b5edfe, []int{3}
}
func (m *ProposerIndexRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -243,7 +298,7 @@ func (m *ProposerIndexResponse) Reset() { *m = ProposerIndexResponse{} }
func (m *ProposerIndexResponse) String() string { return proto.CompactTextString(m) }
func (*ProposerIndexResponse) ProtoMessage() {}
func (*ProposerIndexResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{3}
return fileDescriptor_services_bf909c06e4b5edfe, []int{4}
}
func (m *ProposerIndexResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -290,7 +345,7 @@ func (m *StateRootResponse) Reset() { *m = StateRootResponse{} }
func (m *StateRootResponse) String() string { return proto.CompactTextString(m) }
func (*StateRootResponse) ProtoMessage() {}
func (*StateRootResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{4}
return fileDescriptor_services_bf909c06e4b5edfe, []int{5}
}
func (m *StateRootResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -337,7 +392,7 @@ func (m *AttestRequest) Reset() { *m = AttestRequest{} }
func (m *AttestRequest) String() string { return proto.CompactTextString(m) }
func (*AttestRequest) ProtoMessage() {}
func (*AttestRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{5}
return fileDescriptor_services_bf909c06e4b5edfe, []int{6}
}
func (m *AttestRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -384,7 +439,7 @@ func (m *AttestResponse) Reset() { *m = AttestResponse{} }
func (m *AttestResponse) String() string { return proto.CompactTextString(m) }
func (*AttestResponse) ProtoMessage() {}
func (*AttestResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{6}
return fileDescriptor_services_bf909c06e4b5edfe, []int{7}
}
func (m *AttestResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -434,7 +489,7 @@ func (m *Assignment) Reset() { *m = Assignment{} }
func (m *Assignment) String() string { return proto.CompactTextString(m) }
func (*Assignment) ProtoMessage() {}
func (*Assignment) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{7}
return fileDescriptor_services_bf909c06e4b5edfe, []int{8}
}
func (m *Assignment) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -502,7 +557,7 @@ func (m *ValidatorIndexRequest) Reset() { *m = ValidatorIndexRequest{} }
func (m *ValidatorIndexRequest) String() string { return proto.CompactTextString(m) }
func (*ValidatorIndexRequest) ProtoMessage() {}
func (*ValidatorIndexRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{8}
return fileDescriptor_services_bf909c06e4b5edfe, []int{9}
}
func (m *ValidatorIndexRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -549,7 +604,7 @@ func (m *ValidatorIndexResponse) Reset() { *m = ValidatorIndexResponse{}
func (m *ValidatorIndexResponse) String() string { return proto.CompactTextString(m) }
func (*ValidatorIndexResponse) ProtoMessage() {}
func (*ValidatorIndexResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{9}
return fileDescriptor_services_bf909c06e4b5edfe, []int{10}
}
func (m *ValidatorIndexResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -597,7 +652,7 @@ func (m *ValidatorEpochAssignmentsRequest) Reset() { *m = ValidatorEpoch
func (m *ValidatorEpochAssignmentsRequest) String() string { return proto.CompactTextString(m) }
func (*ValidatorEpochAssignmentsRequest) ProtoMessage() {}
func (*ValidatorEpochAssignmentsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{10}
return fileDescriptor_services_bf909c06e4b5edfe, []int{11}
}
func (m *ValidatorEpochAssignmentsRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -651,7 +706,7 @@ func (m *ValidatorEpochAssignmentsResponse) Reset() { *m = ValidatorEpoc
func (m *ValidatorEpochAssignmentsResponse) String() string { return proto.CompactTextString(m) }
func (*ValidatorEpochAssignmentsResponse) ProtoMessage() {}
func (*ValidatorEpochAssignmentsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_services_e10adba4df963591, []int{11}
return fileDescriptor_services_bf909c06e4b5edfe, []int{12}
}
func (m *ValidatorEpochAssignmentsResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -688,6 +743,7 @@ func (m *ValidatorEpochAssignmentsResponse) GetAssignment() *Assignment {
}
func init() {
proto.RegisterType((*ChainStartResponse)(nil), "ethereum.beacon.rpc.v1.ChainStartResponse")
proto.RegisterType((*ProposeRequest)(nil), "ethereum.beacon.rpc.v1.ProposeRequest")
proto.RegisterType((*ProposeResponse)(nil), "ethereum.beacon.rpc.v1.ProposeResponse")
proto.RegisterType((*ProposerIndexRequest)(nil), "ethereum.beacon.rpc.v1.ProposerIndexRequest")
@@ -714,6 +770,7 @@ const _ = grpc.SupportPackageIsVersion4
// Client API for BeaconService service
type BeaconServiceClient interface {
WaitForChainStart(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (BeaconService_WaitForChainStartClient, error)
CanonicalHead(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*v1.BeaconBlock, error)
LatestAttestation(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (BeaconService_LatestAttestationClient, error)
}
@@ -726,6 +783,38 @@ func NewBeaconServiceClient(cc *grpc.ClientConn) BeaconServiceClient {
return &beaconServiceClient{cc}
}
func (c *beaconServiceClient) WaitForChainStart(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (BeaconService_WaitForChainStartClient, error) {
stream, err := c.cc.NewStream(ctx, &_BeaconService_serviceDesc.Streams[0], "/ethereum.beacon.rpc.v1.BeaconService/WaitForChainStart", opts...)
if err != nil {
return nil, err
}
x := &beaconServiceWaitForChainStartClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type BeaconService_WaitForChainStartClient interface {
Recv() (*ChainStartResponse, error)
grpc.ClientStream
}
type beaconServiceWaitForChainStartClient struct {
grpc.ClientStream
}
func (x *beaconServiceWaitForChainStartClient) Recv() (*ChainStartResponse, error) {
m := new(ChainStartResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *beaconServiceClient) CanonicalHead(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*v1.BeaconBlock, error) {
out := new(v1.BeaconBlock)
err := c.cc.Invoke(ctx, "/ethereum.beacon.rpc.v1.BeaconService/CanonicalHead", in, out, opts...)
@@ -736,7 +825,7 @@ func (c *beaconServiceClient) CanonicalHead(ctx context.Context, in *types.Empty
}
func (c *beaconServiceClient) LatestAttestation(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (BeaconService_LatestAttestationClient, error) {
stream, err := c.cc.NewStream(ctx, &_BeaconService_serviceDesc.Streams[0], "/ethereum.beacon.rpc.v1.BeaconService/LatestAttestation", opts...)
stream, err := c.cc.NewStream(ctx, &_BeaconService_serviceDesc.Streams[1], "/ethereum.beacon.rpc.v1.BeaconService/LatestAttestation", opts...)
if err != nil {
return nil, err
}
@@ -770,6 +859,7 @@ func (x *beaconServiceLatestAttestationClient) Recv() (*v1.Attestation, error) {
// Server API for BeaconService service
type BeaconServiceServer interface {
WaitForChainStart(*types.Empty, BeaconService_WaitForChainStartServer) error
CanonicalHead(context.Context, *types.Empty) (*v1.BeaconBlock, error)
LatestAttestation(*types.Empty, BeaconService_LatestAttestationServer) error
}
@@ -778,6 +868,27 @@ func RegisterBeaconServiceServer(s *grpc.Server, srv BeaconServiceServer) {
s.RegisterService(&_BeaconService_serviceDesc, srv)
}
func _BeaconService_WaitForChainStart_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(types.Empty)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(BeaconServiceServer).WaitForChainStart(m, &beaconServiceWaitForChainStartServer{stream})
}
type BeaconService_WaitForChainStartServer interface {
Send(*ChainStartResponse) error
grpc.ServerStream
}
type beaconServiceWaitForChainStartServer struct {
grpc.ServerStream
}
func (x *beaconServiceWaitForChainStartServer) Send(m *ChainStartResponse) error {
return x.ServerStream.SendMsg(m)
}
func _BeaconService_CanonicalHead_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(types.Empty)
if err := dec(in); err != nil {
@@ -827,6 +938,11 @@ var _BeaconService_serviceDesc = grpc.ServiceDesc{
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "WaitForChainStart",
Handler: _BeaconService_WaitForChainStart_Handler,
ServerStreams: true,
},
{
StreamName: "LatestAttestation",
Handler: _BeaconService_LatestAttestation_Handler,
@@ -1127,6 +1243,42 @@ var _ValidatorService_serviceDesc = grpc.ServiceDesc{
Metadata: "proto/beacon/rpc/v1/services.proto",
}
func (m *ChainStartResponse) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ChainStartResponse) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Started {
dAtA[i] = 0x8
i++
if m.Started {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if m.GenesisTime != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintServices(dAtA, i, uint64(m.GenesisTime))
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
return i, nil
}
func (m *ProposeRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@@ -1529,6 +1681,21 @@ func encodeVarintServices(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *ChainStartResponse) Size() (n int) {
var l int
_ = l
if m.Started {
n += 2
}
if m.GenesisTime != 0 {
n += 1 + sovServices(uint64(m.GenesisTime))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *ProposeRequest) Size() (n int) {
var l int
_ = l
@@ -1729,6 +1896,96 @@ func sovServices(x uint64) (n int) {
func sozServices(x uint64) (n int) {
return sovServices(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *ChainStartResponse) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowServices
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ChainStartResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ChainStartResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Started", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowServices
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Started = bool(v != 0)
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field GenesisTime", wireType)
}
m.GenesisTime = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowServices
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.GenesisTime |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipServices(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthServices
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ProposeRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@@ -3039,63 +3296,67 @@ var (
)
func init() {
proto.RegisterFile("proto/beacon/rpc/v1/services.proto", fileDescriptor_services_e10adba4df963591)
proto.RegisterFile("proto/beacon/rpc/v1/services.proto", fileDescriptor_services_bf909c06e4b5edfe)
}
var fileDescriptor_services_e10adba4df963591 = []byte{
// 856 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xd1, 0x6e, 0x23, 0x35,
0x14, 0x65, 0xb2, 0xd9, 0x85, 0xbd, 0x49, 0xda, 0xac, 0xe9, 0x96, 0xec, 0x20, 0xda, 0x30, 0x2b,
0xa0, 0x8b, 0xd8, 0x49, 0x3b, 0x2b, 0x41, 0x81, 0xa7, 0x64, 0x15, 0xa9, 0x68, 0x57, 0x6d, 0x35,
0x29, 0xcb, 0x03, 0x48, 0x23, 0x4f, 0x62, 0x26, 0xa3, 0x4e, 0xc6, 0xc6, 0x76, 0x22, 0xfa, 0x0d,
0xbc, 0xf0, 0xc4, 0x4f, 0xf0, 0xc4, 0x27, 0xf0, 0xc6, 0x23, 0x9f, 0x80, 0xfa, 0x25, 0xc8, 0xf6,
0xcc, 0xd4, 0x4d, 0x9b, 0xb6, 0xf0, 0xe8, 0x73, 0xcf, 0xb9, 0xf7, 0xfa, 0xf8, 0xfa, 0x82, 0xc7,
0x38, 0x95, 0xb4, 0x17, 0x13, 0x3c, 0xa6, 0x79, 0x8f, 0xb3, 0x71, 0x6f, 0xb1, 0xd7, 0x13, 0x84,
0x2f, 0xd2, 0x31, 0x11, 0xbe, 0x0e, 0xa2, 0x4d, 0x22, 0xa7, 0x84, 0x93, 0xf9, 0xcc, 0x37, 0x34,
0x9f, 0xb3, 0xb1, 0xbf, 0xd8, 0x73, 0xb7, 0x2f, 0x69, 0x59, 0xc0, 0x94, 0x56, 0x9e, 0xb1, 0x52,
0xe8, 0xbe, 0x9f, 0x50, 0x9a, 0x64, 0xa4, 0xa7, 0x4f, 0xf1, 0xfc, 0xc7, 0x1e, 0x99, 0x31, 0x79,
0x56, 0x04, 0xb7, 0x97, 0x83, 0x32, 0x9d, 0x11, 0x21, 0xf1, 0x8c, 0x19, 0x82, 0xf7, 0x7b, 0x0d,
0xd6, 0x8e, 0x39, 0x65, 0x54, 0x90, 0x90, 0xfc, 0x34, 0x27, 0x42, 0xa2, 0x6d, 0x68, 0x30, 0xcc,
0x49, 0x2e, 0xa3, 0x29, 0x16, 0xd3, 0x8e, 0xd3, 0x75, 0x76, 0x9a, 0x21, 0x18, 0xe8, 0x00, 0x8b,
0xa9, 0x22, 0x88, 0x8c, 0xca, 0x28, 0x9f, 0xcf, 0x62, 0xc2, 0x3b, 0xb5, 0xae, 0xb3, 0x53, 0x0f,
0x41, 0x41, 0x87, 0x1a, 0x41, 0xbb, 0xb0, 0xc1, 0x71, 0x3e, 0xc1, 0x34, 0xe2, 0x64, 0x41, 0x70,
0xa6, 0x13, 0xbd, 0x08, 0x3a, 0xf7, 0x74, 0x2a, 0x64, 0x62, 0xa1, 0x0e, 0x1d, 0xe8, 0x08, 0xea,
0xc1, 0xbb, 0x58, 0x4a, 0xd5, 0x99, 0x4c, 0x69, 0x1e, 0xc5, 0xa9, 0x9c, 0x61, 0x71, 0xda, 0xa9,
0x1b, 0x81, 0x15, 0x1a, 0x98, 0x08, 0xfa, 0x0a, 0x9e, 0xd8, 0x02, 0x9c, 0x24, 0x9c, 0x24, 0x58,
0x92, 0x48, 0xa4, 0x49, 0xe7, 0x7e, 0xf7, 0xde, 0x4e, 0x3d, 0x7c, 0xcf, 0x22, 0xf4, 0xcb, 0xf8,
0x28, 0x4d, 0xd0, 0x3e, 0x3c, 0xac, 0x6c, 0xe8, 0x3c, 0xe8, 0x3a, 0x3b, 0x8d, 0xc0, 0xf5, 0x8d,
0x51, 0x7e, 0x69, 0x94, 0x7f, 0x52, 0x32, 0xc2, 0x0b, 0xb2, 0xb7, 0x0b, 0xeb, 0x95, 0x59, 0x82,
0xd1, 0x5c, 0x10, 0xf4, 0x01, 0x40, 0x9c, 0xd1, 0xf1, 0xa9, 0x6d, 0xd6, 0x43, 0x8d, 0xa8, 0xab,
0x79, 0x5f, 0xc0, 0x46, 0xa1, 0xe0, 0xdf, 0xe4, 0x13, 0xf2, 0xb3, 0x65, 0xb2, 0xed, 0xa1, 0xb3,
0xec, 0xa1, 0xf7, 0x1c, 0x1e, 0x2f, 0x09, 0x8b, 0x82, 0x1b, 0x70, 0x3f, 0x55, 0x40, 0xa1, 0x31,
0x07, 0x2f, 0x80, 0x47, 0x23, 0x89, 0x25, 0x09, 0x29, 0x95, 0x76, 0x6f, 0xea, 0xfe, 0x24, 0xe2,
0x94, 0xca, 0xb2, 0x37, 0x51, 0xd2, 0xbc, 0x37, 0xd0, 0xea, 0x6b, 0x8b, 0xca, 0xa6, 0x86, 0xd0,
0xb0, 0x3c, 0xd3, 0x82, 0x46, 0xf0, 0xd4, 0x5f, 0x9e, 0x4c, 0x16, 0x30, 0x7f, 0xb1, 0xe7, 0xf7,
0x2f, 0xa8, 0xa1, 0xad, 0xf3, 0xbe, 0x86, 0xb5, 0x32, 0x6f, 0xd1, 0xc8, 0x33, 0x68, 0xdb, 0xaf,
0x65, 0x59, 0xb5, 0x6e, 0xe1, 0xda, 0xb0, 0x5f, 0x1c, 0x80, 0xbe, 0x10, 0x69, 0x92, 0xcf, 0x48,
0x2e, 0xd5, 0x15, 0xd8, 0x3c, 0xce, 0xd2, 0x71, 0x74, 0x4a, 0xce, 0xca, 0x2b, 0x18, 0xe4, 0x15,
0x39, 0x53, 0x66, 0x88, 0x29, 0xe6, 0x93, 0x62, 0x08, 0xcd, 0x01, 0x3d, 0x85, 0x96, 0x49, 0x4b,
0x78, 0xa4, 0x2c, 0xd5, 0x83, 0x57, 0x0f, 0x9b, 0x25, 0x38, 0xca, 0xa8, 0x54, 0x24, 0x56, 0x18,
0x6c, 0x48, 0x75, 0x43, 0x2a, 0x41, 0x45, 0xf2, 0x3e, 0x87, 0xc7, 0x6f, 0x70, 0x96, 0x4e, 0xb0,
0xa4, 0x97, 0xdf, 0xef, 0xe6, 0xbe, 0x3c, 0x1f, 0x36, 0x97, 0x75, 0x37, 0x3e, 0x5f, 0x0c, 0xdd,
0x8a, 0x3f, 0x64, 0x74, 0x3c, 0xbd, 0xb0, 0x40, 0x58, 0x23, 0x43, 0x54, 0x28, 0x12, 0x12, 0x73,
0x59, 0x8e, 0x8c, 0x86, 0x46, 0x0a, 0x59, 0xea, 0xa9, 0xb6, 0xdc, 0x53, 0x02, 0x1f, 0xde, 0x50,
0xa3, 0x68, 0x6f, 0x00, 0x80, 0x2b, 0x58, 0xe7, 0x68, 0x04, 0x9e, 0x7f, 0xfd, 0x6e, 0xf2, 0x2f,
0x12, 0x84, 0x96, 0xea, 0xd3, 0x7d, 0x68, 0x55, 0x85, 0x42, 0x9a, 0x11, 0xd4, 0x80, 0xb7, 0xbf,
0x3d, 0x7c, 0x75, 0x78, 0xf4, 0xdd, 0x61, 0xfb, 0x2d, 0xd4, 0x84, 0x77, 0xfa, 0x27, 0x27, 0xc3,
0xd1, 0xc9, 0x30, 0x6c, 0x3b, 0xea, 0x74, 0x1c, 0x1e, 0x1d, 0x1f, 0x8d, 0x86, 0x61, 0xbb, 0x16,
0xfc, 0xe1, 0x40, 0x6b, 0xa0, 0x4b, 0x8c, 0xcc, 0x76, 0x44, 0xaf, 0xa1, 0xf5, 0x12, 0xe7, 0x34,
0x4f, 0xc7, 0x38, 0x3b, 0x20, 0x78, 0x82, 0x36, 0xaf, 0xfc, 0xd4, 0xa1, 0xda, 0x77, 0xee, 0xca,
0x31, 0x35, 0xf9, 0x06, 0xea, 0x47, 0xa2, 0x10, 0x1e, 0xbd, 0xc6, 0x6a, 0x06, 0xac, 0xd9, 0xfd,
0xef, 0x19, 0x2d, 0xf1, 0xae, 0x13, 0xe4, 0xb0, 0xde, 0x2f, 0xe7, 0xaa, 0x68, 0xfa, 0x7b, 0x00,
0x03, 0xe9, 0x8e, 0x3f, 0x5a, 0x69, 0x9f, 0xfd, 0xf9, 0xdc, 0x8f, 0x6f, 0xa3, 0x99, 0x17, 0x0a,
0xfe, 0xac, 0x55, 0x4b, 0xa8, 0x2a, 0x98, 0x41, 0xeb, 0xd2, 0xb2, 0x40, 0x9f, 0xad, 0x4a, 0x76,
0xdd, 0x32, 0x72, 0x9f, 0xdf, 0x91, 0x5d, 0xcc, 0xc8, 0x0f, 0xd0, 0x2c, 0x02, 0xc6, 0xd5, 0xbb,
0x58, 0xef, 0x7e, 0x72, 0x4b, 0x8d, 0x2a, 0x7b, 0x0c, 0xed, 0x97, 0x74, 0xc6, 0xe6, 0x92, 0x54,
0x0b, 0xed, 0x6e, 0x15, 0x9e, 0xad, 0xaa, 0x70, 0x65, 0x31, 0x06, 0xbf, 0xd5, 0xa0, 0x5d, 0x8d,
0x68, 0x69, 0x22, 0x85, 0xb5, 0xcb, 0x7f, 0x16, 0xad, 0xf4, 0xe5, 0xda, 0x9d, 0xe0, 0xfa, 0x77,
0xa5, 0x17, 0x37, 0xfd, 0xd5, 0x81, 0x27, 0x2b, 0x7f, 0x24, 0xda, 0xbf, 0x35, 0xdb, 0x8a, 0x45,
0xe1, 0x7e, 0xf9, 0x3f, 0x94, 0xa6, 0xa5, 0x41, 0xf3, 0xaf, 0xf3, 0x2d, 0xe7, 0xef, 0xf3, 0x2d,
0xe7, 0x9f, 0xf3, 0x2d, 0x27, 0x7e, 0xa0, 0x7f, 0xc4, 0x8b, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff,
0xbe, 0x05, 0x6e, 0x91, 0xc0, 0x08, 0x00, 0x00,
var fileDescriptor_services_bf909c06e4b5edfe = []byte{
// 920 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xdd, 0x6e, 0xe3, 0x44,
0x14, 0xc6, 0xd9, 0xee, 0xdf, 0x49, 0xd2, 0xa6, 0x43, 0xb7, 0x64, 0x83, 0x68, 0xb3, 0x5e, 0x01,
0xdd, 0x15, 0xeb, 0xb4, 0x5e, 0x09, 0x0a, 0x5c, 0x25, 0x55, 0x50, 0xd1, 0xae, 0xda, 0xe2, 0x84,
0x5d, 0x21, 0x90, 0xac, 0x49, 0x72, 0x70, 0xac, 0xda, 0x1e, 0xe3, 0x99, 0x44, 0xf4, 0x19, 0xe0,
0x82, 0x2b, 0x5e, 0x82, 0xa7, 0xe0, 0x8e, 0x4b, 0x1e, 0x01, 0xf5, 0x49, 0xd0, 0xcc, 0xd8, 0x8e,
0x9b, 0xd6, 0x6d, 0xe1, 0x72, 0xce, 0xf9, 0xce, 0x37, 0x67, 0xbe, 0x39, 0xe7, 0x03, 0x33, 0x4e,
0x98, 0x60, 0x9d, 0x11, 0xd2, 0x31, 0x8b, 0x3a, 0x49, 0x3c, 0xee, 0xcc, 0xf7, 0x3a, 0x1c, 0x93,
0xb9, 0x3f, 0x46, 0x6e, 0xa9, 0x24, 0xd9, 0x44, 0x31, 0xc5, 0x04, 0x67, 0xa1, 0xa5, 0x61, 0x56,
0x12, 0x8f, 0xad, 0xf9, 0x5e, 0x6b, 0xfb, 0x42, 0x6d, 0x6c, 0xc7, 0xb2, 0x56, 0x9c, 0xc5, 0x59,
0x61, 0xeb, 0x7d, 0x8f, 0x31, 0x2f, 0xc0, 0x8e, 0x3a, 0x8d, 0x66, 0x3f, 0x76, 0x30, 0x8c, 0xc5,
0x59, 0x9a, 0xdc, 0x5e, 0x4e, 0x0a, 0x3f, 0x44, 0x2e, 0x68, 0x18, 0x6b, 0x80, 0xf9, 0x0d, 0x90,
0x83, 0x29, 0xf5, 0xa3, 0x81, 0xa0, 0x89, 0x70, 0x90, 0xc7, 0x2c, 0xe2, 0x48, 0x9a, 0x70, 0x9f,
0xcb, 0x00, 0x4e, 0x9a, 0x46, 0xdb, 0xd8, 0x79, 0xe0, 0x64, 0x47, 0xf2, 0x04, 0x6a, 0x1e, 0x46,
0xc8, 0x7d, 0xee, 0x4a, 0xaa, 0x66, 0xa5, 0x6d, 0xec, 0xac, 0x38, 0xd5, 0x34, 0x36, 0xf4, 0x43,
0x34, 0xff, 0xa8, 0xc0, 0xea, 0x49, 0xc2, 0x62, 0xc6, 0xd1, 0xc1, 0x9f, 0x66, 0xc8, 0x05, 0xd9,
0x86, 0x6a, 0x4c, 0x13, 0x8c, 0x84, 0x3b, 0xa5, 0x7c, 0xaa, 0x38, 0x6b, 0x0e, 0xe8, 0xd0, 0x21,
0xe5, 0x53, 0x09, 0xe0, 0x01, 0x13, 0x6e, 0x34, 0x0b, 0x47, 0x98, 0xa4, 0xac, 0x20, 0x43, 0x47,
0x2a, 0x42, 0x76, 0x61, 0x23, 0xa1, 0xd1, 0x84, 0x32, 0x37, 0xc1, 0x39, 0xd2, 0x40, 0x11, 0xbd,
0xb4, 0x9b, 0x77, 0x14, 0x15, 0xd1, 0x39, 0x47, 0xa5, 0x0e, 0x55, 0x86, 0x74, 0xe0, 0x5d, 0x2a,
0x84, 0x7c, 0xac, 0xf0, 0x59, 0xe4, 0x8e, 0x7c, 0x11, 0x52, 0x7e, 0xda, 0x5c, 0xd1, 0x05, 0x85,
0x54, 0x4f, 0x67, 0xc8, 0x17, 0xf0, 0xb8, 0x58, 0x40, 0x3d, 0x2f, 0x41, 0x8f, 0x0a, 0x74, 0xb9,
0xef, 0x35, 0xef, 0xb6, 0xef, 0xec, 0xac, 0x38, 0xef, 0x15, 0x00, 0xdd, 0x2c, 0x3f, 0xf0, 0x3d,
0xb2, 0x0f, 0x0f, 0x73, 0x65, 0x9b, 0xf7, 0xda, 0xc6, 0x4e, 0xd5, 0x6e, 0x59, 0x5a, 0x7b, 0x2b,
0xd3, 0xde, 0x1a, 0x66, 0x08, 0x67, 0x01, 0x36, 0x77, 0x61, 0x2d, 0x17, 0x2b, 0x55, 0xff, 0x03,
0x80, 0x51, 0xc0, 0xc6, 0xa7, 0x45, 0xb1, 0x1e, 0xaa, 0x88, 0x7c, 0x9a, 0xf9, 0x19, 0x6c, 0xa4,
0x15, 0xc9, 0xd7, 0xd1, 0x04, 0x7f, 0x2e, 0x88, 0x5c, 0xd4, 0xd0, 0x58, 0xd6, 0xd0, 0x7c, 0x01,
0x8f, 0x96, 0x0a, 0xd3, 0x0b, 0x37, 0xe0, 0xae, 0x2f, 0x03, 0x69, 0x8d, 0x3e, 0x98, 0x36, 0xac,
0x0f, 0x04, 0x15, 0xe8, 0x30, 0x26, 0x8a, 0xbd, 0xc9, 0xf7, 0xa3, 0x9b, 0x30, 0x26, 0xb2, 0xde,
0x78, 0x06, 0x33, 0xdf, 0x40, 0xbd, 0xab, 0x24, 0xca, 0x9a, 0xea, 0x43, 0xb5, 0xa0, 0x99, 0x2a,
0xa8, 0xda, 0x4f, 0xad, 0xe5, 0x61, 0x8f, 0xed, 0xd8, 0x9a, 0xef, 0x59, 0xdd, 0x05, 0xd4, 0x29,
0xd6, 0x99, 0x5f, 0xc2, 0x6a, 0xc6, 0x9b, 0x36, 0xf2, 0x0c, 0x1a, 0xc5, 0xdf, 0x2a, 0x48, 0xb5,
0x56, 0x88, 0x2b, 0xc1, 0x7e, 0x31, 0x00, 0xba, 0x9c, 0xfb, 0x5e, 0x14, 0x62, 0x24, 0xe4, 0x13,
0xe2, 0xd9, 0x28, 0xf0, 0xc7, 0xee, 0x29, 0x9e, 0x65, 0x4f, 0xd0, 0x91, 0x57, 0x78, 0x26, 0xc5,
0xe0, 0x53, 0x9a, 0x4c, 0xd2, 0x21, 0xd4, 0x07, 0xf2, 0x14, 0xea, 0x9a, 0x16, 0x13, 0x57, 0x4a,
0xaa, 0x06, 0x6f, 0xc5, 0xa9, 0x65, 0xc1, 0x41, 0xc0, 0x84, 0x04, 0xc5, 0xa9, 0xc0, 0x1a, 0xb4,
0xa2, 0x41, 0x59, 0x50, 0x82, 0xcc, 0x4f, 0xe1, 0xd1, 0x1b, 0x1a, 0xf8, 0x13, 0x2a, 0xd8, 0xc5,
0xff, 0xbb, 0xbe, 0x2f, 0xd3, 0x82, 0xcd, 0xe5, 0xba, 0x6b, 0xbf, 0x6f, 0x04, 0xed, 0x1c, 0xdf,
0x8f, 0xd9, 0x78, 0xba, 0x90, 0x80, 0x17, 0x46, 0x06, 0x65, 0xca, 0x55, 0xeb, 0x9d, 0x8d, 0x8c,
0x0a, 0x29, 0x43, 0x58, 0xea, 0xa9, 0xb2, 0xdc, 0x93, 0x07, 0x4f, 0xae, 0xb9, 0x23, 0x6d, 0xaf,
0x07, 0x40, 0xf3, 0xb0, 0xe2, 0xa8, 0xda, 0xa6, 0x75, 0xb5, 0xdd, 0x59, 0x0b, 0x02, 0xa7, 0x50,
0xf5, 0x7c, 0x1f, 0xea, 0xf9, 0x45, 0x0e, 0x0b, 0x90, 0x54, 0xe1, 0xfe, 0xb7, 0x47, 0xaf, 0x8e,
0x8e, 0xdf, 0x1e, 0x35, 0xde, 0x21, 0x35, 0x78, 0xd0, 0x1d, 0x0e, 0xfb, 0x83, 0x61, 0xdf, 0x69,
0x18, 0xf2, 0x74, 0xe2, 0x1c, 0x9f, 0x1c, 0x0f, 0xfa, 0x4e, 0xa3, 0x62, 0xff, 0x5a, 0x81, 0x7a,
0x4f, 0x5d, 0x31, 0xd0, 0x86, 0x4b, 0xbe, 0x83, 0xf5, 0xb7, 0xd4, 0x17, 0x5f, 0xb1, 0x64, 0xe1,
0x7c, 0x64, 0xf3, 0xd2, 0xb6, 0xf6, 0xa5, 0x8d, 0xb6, 0x9e, 0x97, 0x35, 0x7a, 0xd9, 0x35, 0x77,
0x0d, 0xf2, 0x1a, 0xea, 0x07, 0x34, 0x62, 0x91, 0x3f, 0xa6, 0xc1, 0x21, 0xd2, 0x49, 0x29, 0x6d,
0xe9, 0x06, 0xe8, 0x56, 0x7b, 0x72, 0xd9, 0x89, 0x03, 0xeb, 0xaf, 0xa9, 0x1c, 0xaf, 0xc2, 0x5a,
0xfc, 0x77, 0xc6, 0x42, 0xf1, 0xae, 0x61, 0x47, 0xb0, 0xd6, 0xcd, 0x46, 0x36, 0xd5, 0xe3, 0x7b,
0x00, 0x1d, 0x52, 0x1d, 0x7f, 0x58, 0xfa, 0x33, 0xc5, 0xbd, 0x6e, 0x7d, 0x74, 0x13, 0x4c, 0x6b,
0x62, 0xff, 0x59, 0xc9, 0xfd, 0x2d, 0xbf, 0x30, 0x80, 0xfa, 0x05, 0x1f, 0x22, 0x9f, 0x94, 0x91,
0x5d, 0xe5, 0x73, 0xad, 0x17, 0xb7, 0x44, 0xa7, 0xe3, 0xf7, 0x03, 0xd4, 0xd2, 0x84, 0x56, 0xf5,
0x36, 0xd2, 0xb7, 0x3e, 0xbe, 0xe1, 0x8e, 0x9c, 0x7d, 0x04, 0x8d, 0x03, 0x16, 0xc6, 0x33, 0x81,
0xb9, 0x57, 0xde, 0xee, 0x86, 0x67, 0x65, 0x37, 0x5c, 0xf2, 0x5c, 0xfb, 0xf7, 0x0a, 0x34, 0xf2,
0xe9, 0xcf, 0x44, 0x64, 0xb0, 0x7a, 0xd1, 0x0e, 0x48, 0xa9, 0x2e, 0x57, 0xda, 0x4d, 0xcb, 0xba,
0x2d, 0x3c, 0x7d, 0xe9, 0x6f, 0x06, 0x3c, 0x2e, 0x5d, 0x76, 0xb2, 0x7f, 0x23, 0x5b, 0x89, 0x07,
0xb5, 0x3e, 0xff, 0x1f, 0x95, 0xba, 0xa5, 0x5e, 0xed, 0xaf, 0xf3, 0x2d, 0xe3, 0xef, 0xf3, 0x2d,
0xe3, 0x9f, 0xf3, 0x2d, 0x63, 0x74, 0x4f, 0x6d, 0xc4, 0xcb, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff,
0xc6, 0x16, 0xb6, 0xab, 0x6e, 0x09, 0x00, 0x00,
}

View File

@@ -7,11 +7,10 @@ import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
service BeaconService {
// CanonicalHead can be called on demand to fetch the current, head block of a
// beacon node.
rpc WaitForChainStart(google.protobuf.Empty) returns (stream ChainStartResponse);
// CanonicalHead can be called on demand to fetch the current, head block of a beacon node.
rpc CanonicalHead(google.protobuf.Empty) returns (ethereum.beacon.p2p.v1.BeaconBlock);
// LatestAttestation streams the latest aggregated attestation to connected
// validator clients.
// LatestAttestation streams the latest aggregated attestation to connected validator clients.
rpc LatestAttestation(google.protobuf.Empty) returns (stream ethereum.beacon.p2p.v1.Attestation);
}
@@ -30,6 +29,11 @@ service ValidatorService {
rpc ValidatorEpochAssignments(ValidatorEpochAssignmentsRequest) returns (ValidatorEpochAssignmentsResponse);
}
message ChainStartResponse {
bool started = 1;
uint64 genesis_time = 2;
}
message ProposeRequest {
bytes parent_hash = 1;
uint64 slot_number = 2;

View File

@@ -43,7 +43,6 @@ func (s *ServiceRegistry) StartAll() {
log.Debugf("Starting service type %v", kind)
s.services[kind].Start()
}
log.Info("All services started")
}
// StopAll ends every service in reverse order of registration, logging a

View File

@@ -29,8 +29,8 @@ func (s *SlotTicker) Done() {
}
// GetSlotTicker is the constructor for SlotTicker.
func GetSlotTicker(genesisTime time.Time, slotDuration uint64) SlotTicker {
ticker := SlotTicker{
func GetSlotTicker(genesisTime time.Time, slotDuration uint64) *SlotTicker {
ticker := &SlotTicker{
c: make(chan uint64),
done: make(chan struct{}),
}

View File

@@ -6,7 +6,7 @@ import (
)
func TestSlotTicker(t *testing.T) {
ticker := SlotTicker{
ticker := &SlotTicker{
c: make(chan uint64),
done: make(chan struct{}),
}
@@ -54,7 +54,7 @@ func TestSlotTicker(t *testing.T) {
}
func TestSlotTickerGenesis(t *testing.T) {
ticker := SlotTicker{
ticker := &SlotTicker{
c: make(chan uint64),
done: make(chan struct{}),
}

View File

@@ -13,8 +13,11 @@ go_library(
"//proto/beacon/rpc/v1:go_default_library",
"//shared/params:go_default_library",
"//shared/slotticker:go_default_library",
"@com_github_gogo_protobuf//types:go_default_library",
"@com_github_opentracing_opentracing_go//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//credentials:go_default_library",
],
)
@@ -34,7 +37,9 @@ go_test(
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
"//validator/internal:go_default_library",
"@com_github_gogo_protobuf//types:go_default_library",
"@com_github_golang_mock//gomock:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],
)

View File

@@ -12,6 +12,7 @@ type fakeValidator struct {
InitializeCalled bool
DoneCalled bool
WaitForActivationCalled bool
WaitForChainStartCalled bool
NextSlotRet <-chan uint64
NextSlotCalled bool
UpdateAssignmentsCalled bool
@@ -34,6 +35,10 @@ func (fv *fakeValidator) Done() {
fv.DoneCalled = true
}
func (fv *fakeValidator) WaitForChainStart(_ context.Context) {
fv.WaitForChainStartCalled = true
}
func (fv *fakeValidator) WaitForActivation(_ context.Context) {
fv.WaitForActivationCalled = true
}

View File

@@ -12,6 +12,7 @@ import (
type Validator interface {
Initialize(ctx context.Context)
Done()
WaitForChainStart(ctx context.Context)
WaitForActivation(ctx context.Context)
NextSlot() <-chan uint64
UpdateAssignments(ctx context.Context, slot uint64) error
@@ -33,17 +34,16 @@ type Validator interface {
func run(ctx context.Context, v Validator) {
v.Initialize(ctx)
defer v.Done()
v.WaitForChainStart(ctx)
v.WaitForActivation(ctx)
span, ctx := opentracing.StartSpanFromContext(ctx, "processSlot")
defer span.Finish()
for {
select {
case <-ctx.Done():
log.Info("Context cancelled, stopping validator")
return // Exit if context is cancelled.
case slot := <-v.NextSlot():
span, ctx := opentracing.StartSpanFromContext(ctx, "processSlot")
defer span.Finish()
if err := v.UpdateAssignments(ctx, slot); err != nil {
log.WithField("error", err).Error("Failed to update assignments")
continue

View File

@@ -32,6 +32,14 @@ func TestRunCleansUpValidator(t *testing.T) {
}
}
func TestRunWaitsForChainStart(t *testing.T) {
v := &fakeValidator{}
run(cancelledContext(), v)
if !v.WaitForChainStartCalled {
t.Error("Expected WaitForChainStart() to be called")
}
}
func TestRunWaitsForActivation(t *testing.T) {
v := &fakeValidator{}
run(cancelledContext(), v)

View File

@@ -2,7 +2,12 @@ package client
import (
"context"
"errors"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/sirupsen/logrus"
)
@@ -14,27 +19,65 @@ type ValidatorService struct {
ctx context.Context
cancel context.CancelFunc
validator Validator
conn *grpc.ClientConn
endpoint string
withCert string
}
// Config for the validator service.
type Config struct {
Endpoint string
CertFlag string
}
// NewValidatorService creates a new validator service for the service
// registry.
func NewValidatorService(ctx context.Context) *ValidatorService {
func NewValidatorService(ctx context.Context, cfg *Config) *ValidatorService {
ctx, cancel := context.WithCancel(ctx)
return &ValidatorService{
ctx: ctx,
cancel: cancel,
ctx: ctx,
cancel: cancel,
endpoint: cfg.Endpoint,
withCert: cfg.CertFlag,
}
}
// Start the validator service. Launches the main go routine for the validator
// client.
func (v *ValidatorService) Start() {
var dialOpt grpc.DialOption
if v.withCert != "" {
creds, err := credentials.NewClientTLSFromFile(v.withCert, "")
if err != nil {
log.Errorf("Could not get valid credentials: %v", err)
return
}
dialOpt = grpc.WithTransportCredentials(creds)
} else {
dialOpt = grpc.WithInsecure()
log.Warn("You are using an insecure gRPC connection! Please provide a certificate and key to use a secure connection.")
}
conn, err := grpc.DialContext(v.ctx, v.endpoint, dialOpt)
if err != nil {
log.Errorf("Could not dial endpoint: %s, %v", v.endpoint, err)
return
}
log.Info("Successfully started gRPC connection")
v.conn = conn
v.validator = &validator{
beaconClient: pb.NewBeaconServiceClient(v.conn),
validatorClient: pb.NewValidatorServiceClient(v.conn),
}
go run(v.ctx, v.validator)
}
// Stop the validator service.
func (v *ValidatorService) Stop() error {
v.cancel()
log.Info("Stopping service")
if v.conn != nil {
return v.conn.Close()
}
return nil
}
@@ -42,5 +85,8 @@ func (v *ValidatorService) Stop() error {
//
// WIP - not done.
func (v *ValidatorService) Status() error {
if v.conn == nil {
return errors.New("no connection to beacon RPC")
}
return nil
}

View File

@@ -2,10 +2,14 @@ package client
import (
"context"
"strings"
"testing"
"time"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared"
logTest "github.com/sirupsen/logrus/hooks/test"
)
var _ = shared.Service(&ValidatorService{})
@@ -27,3 +31,53 @@ func TestStop_cancelsContext(t *testing.T) {
case <-vs.ctx.Done():
}
}
func TestLifecycle(t *testing.T) {
hook := logTest.NewGlobal()
// Use cancelled context so that the run function exits immediately..
ctx, cancel := context.WithCancel(context.Background())
cancel()
validatorService := NewValidatorService(
ctx,
&Config{
Endpoint: "merkle tries",
CertFlag: "alice.crt",
},
)
validatorService.Start()
if err := validatorService.Stop(); err != nil {
t.Fatalf("Could not stop service: %v", err)
}
testutil.AssertLogsContain(t, hook, "Stopping service")
}
func TestLifecycle_WithInsecure(t *testing.T) {
hook := logTest.NewGlobal()
// Use cancelled context so that the run function exits immediately.
ctx, cancel := context.WithCancel(context.Background())
cancel()
validatorService := NewValidatorService(
ctx,
&Config{
Endpoint: "merkle tries",
},
)
validatorService.Start()
testutil.AssertLogsContain(t, hook, "You are using an insecure gRPC connection")
if err := validatorService.Stop(); err != nil {
t.Fatalf("Could not stop service: %v", err)
}
testutil.AssertLogsContain(t, hook, "Stopping service")
}
func TestStatus(t *testing.T) {
validatorService := NewValidatorService(
context.Background(),
&Config{
Endpoint: "merkle tries",
},
)
if err := validatorService.Status(); !strings.Contains(err.Error(), "no connection") {
t.Errorf("Expected status check to fail if no connection is found, received: %v", err)
}
}

View File

@@ -2,6 +2,10 @@ package client
import (
"context"
"io"
"time"
ptypes "github.com/gogo/protobuf/types"
"github.com/opentracing/opentracing-go"
@@ -14,10 +18,11 @@ import (
//
// WIP - not done.
type validator struct {
ticker slotticker.SlotTicker
assignment *pb.Assignment
genesisTime uint64
ticker *slotticker.SlotTicker
assignment *pb.Assignment
validatorClient pb.ValidatorServiceClient
beaconClient pb.BeaconServiceClient
pubKey []byte
}
@@ -27,9 +32,6 @@ type validator struct {
func (v *validator) Initialize(ctx context.Context) {
span, ctx := opentracing.StartSpanFromContext(ctx, "validator.Initialize")
defer span.Finish()
cfg := params.BeaconConfig()
v.ticker = slotticker.GetSlotTicker(cfg.GenesisTime, cfg.SlotDuration)
}
// Done cleans up the validator.
@@ -37,14 +39,55 @@ func (v *validator) Done() {
v.ticker.Done()
}
// WaitForChainStart checks whether the beacon node has started its runtime. That is,
// it calls to the beacon node which then verifies the ETH1.0 deposit contract logs to check
// for the ChainStart log to have been emitted. If so, it starts a ticker based on the ChainStart
// unix timestamp which will be used to keep track of time within the validator client.
func (v *validator) WaitForChainStart(ctx context.Context) {
span, ctx := opentracing.StartSpanFromContext(ctx, "validator.WaitForChainStart")
defer span.Finish()
// First, check if the beacon chain has started.
stream, err := v.beaconClient.WaitForChainStart(ctx, &ptypes.Empty{})
if err != nil {
log.Errorf("Could not setup beacon chain ChainStart streaming client: %v", err)
return
}
for {
log.Info("Waiting for beacon chain start log from the ETH 1.0 deposit contract...")
chainStartRes, err := stream.Recv()
// If the stream is closed, we stop the loop.
if err == io.EOF {
break
}
// If context is canceled we stop the loop.
if ctx.Err() == context.Canceled {
log.Debugf("Context has been canceled so shutting down the loop: %v", ctx.Err())
break
}
if err != nil {
log.Errorf("Could not receive ChainStart from stream: %v", err)
continue
}
v.genesisTime = chainStartRes.GenesisTime
break
}
log.Infof("Beacon chain initialized at unix time: %v", time.Unix(int64(v.genesisTime), 0))
// Once the ChainStart log is received, we update the genesis time of the validator client
// and begin a slot ticker used to track the current slot the beacon node is in.
v.ticker = slotticker.GetSlotTicker(time.Unix(int64(v.genesisTime), 0), params.BeaconConfig().SlotDuration)
}
// WaitForActivation checks whether the validator pubkey is in the active
// validator set. If not, this operation will block until an activation is
// validator set. If not, this operation will block until an activation message is
// received.
//
// WIP - not done.
func (v *validator) WaitForActivation(ctx context.Context) {
span, ctx := opentracing.StartSpanFromContext(ctx, "validator.WaitForActivation")
defer span.Finish()
// First, check if the validator has deposited into the Deposit Contract.
// If the validator has deposited, subscribe to a stream receiving the activation status.
// of the validator until a final ACTIVATED check if received, then this function can return.
}
// NextSlot emits the next slot number at the start time of that slot.
@@ -99,7 +142,6 @@ func (v *validator) RoleAt(slot uint64) pb.ValidatorRole {
func (v *validator) ProposeBlock(ctx context.Context, slot uint64) {
span, ctx := opentracing.StartSpanFromContext(ctx, "validator.ProposeBlock")
defer span.Finish()
}
// AttestToBlockHead
@@ -108,5 +150,4 @@ func (v *validator) ProposeBlock(ctx context.Context, slot uint64) {
func (v *validator) AttestToBlockHead(ctx context.Context, slot uint64) {
span, ctx := opentracing.StartSpanFromContext(ctx, "validator.AttestToBlockHead")
defer span.Finish()
}

View File

@@ -3,19 +3,143 @@ package client
import (
"context"
"errors"
"io"
"io/ioutil"
"testing"
"time"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/sirupsen/logrus"
ptypes "github.com/gogo/protobuf/types"
"github.com/golang/mock/gomock"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/validator/internal"
logTest "github.com/sirupsen/logrus/hooks/test"
)
func init() {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetOutput(ioutil.Discard)
}
var _ = Validator(&validator{})
var fakePubKey = []byte{1}
func TestUpdateAssignmentsDoesNothingWhenNotEpochStart(t *testing.T) {
func TestWaitForChainStart_SetsChainStartGenesisTime(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := internal.NewMockBeaconServiceClient(ctrl)
v := validator{
pubKey: fakePubKey,
beaconClient: client,
}
genesis := uint64(time.Unix(0, 0).Unix())
clientStream := internal.NewMockBeaconService_WaitForChainStartClient(ctrl)
client.EXPECT().WaitForChainStart(
gomock.Any(),
&ptypes.Empty{},
).Return(clientStream, nil)
clientStream.EXPECT().Recv().Return(
&pb.ChainStartResponse{
Started: true,
GenesisTime: genesis,
},
nil,
)
v.WaitForChainStart(context.Background())
if v.genesisTime != genesis {
t.Errorf("Expected chain start time to equal %d, received %d", genesis, v.genesisTime)
}
if v.ticker == nil {
t.Error("Expected ticker to be set, received nil")
}
}
func TestWaitForChainStart_ContextCanceled(t *testing.T) {
hook := logTest.NewGlobal()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := internal.NewMockBeaconServiceClient(ctrl)
v := validator{
pubKey: fakePubKey,
beaconClient: client,
}
genesis := uint64(time.Unix(0, 0).Unix())
clientStream := internal.NewMockBeaconService_WaitForChainStartClient(ctrl)
client.EXPECT().WaitForChainStart(
gomock.Any(),
&ptypes.Empty{},
).Return(clientStream, nil)
clientStream.EXPECT().Recv().Return(
&pb.ChainStartResponse{
Started: true,
GenesisTime: genesis,
},
nil,
)
ctx, cancel := context.WithCancel(context.Background())
cancel()
v.WaitForChainStart(ctx)
testutil.AssertLogsContain(t, hook, "Context has been canceled")
}
func TestWaitForChainStart_StreamSetupFails(t *testing.T) {
hook := logTest.NewGlobal()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := internal.NewMockBeaconServiceClient(ctrl)
v := validator{
pubKey: fakePubKey,
beaconClient: client,
}
clientStream := internal.NewMockBeaconService_WaitForChainStartClient(ctrl)
client.EXPECT().WaitForChainStart(
gomock.Any(),
&ptypes.Empty{},
).Return(clientStream, errors.New("failed stream"))
v.WaitForChainStart(context.Background())
testutil.AssertLogsContain(t, hook, "Could not setup beacon chain ChainStart streaming client")
}
func TestWaitForChainStart_ReceiveErrorFromStream(t *testing.T) {
hook := logTest.NewGlobal()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := internal.NewMockBeaconServiceClient(ctrl)
v := validator{
pubKey: fakePubKey,
beaconClient: client,
}
genesis := uint64(time.Unix(0, 0).Unix())
clientStream := internal.NewMockBeaconService_WaitForChainStartClient(ctrl)
client.EXPECT().WaitForChainStart(
gomock.Any(),
&ptypes.Empty{},
).Return(clientStream, nil)
clientStream.EXPECT().Recv().Return(
nil,
errors.New("fails"),
)
clientStream.EXPECT().Recv().Return(
&pb.ChainStartResponse{
Started: true,
GenesisTime: genesis,
},
io.EOF,
)
v.WaitForChainStart(context.Background())
testutil.AssertLogsContain(t, hook, "Could not receive ChainStart from stream")
}
func TestUpdateAssignments_DoesNothingWhenNotEpochStart(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := internal.NewMockValidatorServiceClient(ctrl)
@@ -30,10 +154,12 @@ func TestUpdateAssignmentsDoesNothingWhenNotEpochStart(t *testing.T) {
gomock.Any(),
).Times(0)
v.UpdateAssignments(context.Background(), slot)
if err := v.UpdateAssignments(context.Background(), slot); err != nil {
t.Errorf("Could not update assignments: %v", err)
}
}
func TestUpdateAssignmentsReturnsError(t *testing.T) {
func TestUpdateAssignments_ReturnsError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := internal.NewMockValidatorServiceClient(ctrl)
@@ -56,7 +182,7 @@ func TestUpdateAssignmentsReturnsError(t *testing.T) {
}
}
func TestUpdateAssignmentsDoesUpdateAssignments(t *testing.T) {
func TestUpdateAssignments_DoesUpdateAssignments(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := internal.NewMockValidatorServiceClient(ctrl)
@@ -77,7 +203,9 @@ func TestUpdateAssignmentsDoesUpdateAssignments(t *testing.T) {
gomock.Any(),
).Return(resp, nil)
v.UpdateAssignments(context.Background(), slot)
if err := v.UpdateAssignments(context.Background(), slot); err != nil {
t.Fatalf("Could not update assignments: %v", err)
}
if v.assignment.ProposerSlot != 67 {
t.Errorf("Unexpected validator assignments. want=%v got=%v", 67, v.assignment.ProposerSlot)

View File

@@ -17,5 +17,6 @@ go_library(
"@com_github_gogo_protobuf//types:go_default_library",
"@com_github_golang_mock//gomock:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//metadata:go_default_library",
],
)

View File

@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1 (interfaces: BeaconServiceClient)
// Source: github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1 (interfaces: BeaconServiceClient,BeaconService_LatestAttestationClient,BeaconService_WaitForChainStartClient)
package internal
@@ -12,6 +12,7 @@ import (
v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
v10 "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
grpc "google.golang.org/grpc"
metadata "google.golang.org/grpc/metadata"
)
// MockBeaconServiceClient is a mock of BeaconServiceClient interface
@@ -72,3 +73,239 @@ func (mr *MockBeaconServiceClientMockRecorder) LatestAttestation(arg0, arg1 inte
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LatestAttestation", reflect.TypeOf((*MockBeaconServiceClient)(nil).LatestAttestation), varargs...)
}
// WaitForChainStart mocks base method
func (m *MockBeaconServiceClient) WaitForChainStart(arg0 context.Context, arg1 *types.Empty, arg2 ...grpc.CallOption) (v10.BeaconService_WaitForChainStartClient, error) {
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "WaitForChainStart", varargs...)
ret0, _ := ret[0].(v10.BeaconService_WaitForChainStartClient)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// WaitForChainStart indicates an expected call of WaitForChainStart
func (mr *MockBeaconServiceClientMockRecorder) WaitForChainStart(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitForChainStart", reflect.TypeOf((*MockBeaconServiceClient)(nil).WaitForChainStart), varargs...)
}
// MockBeaconService_LatestAttestationClient is a mock of BeaconService_LatestAttestationClient interface
type MockBeaconService_LatestAttestationClient struct {
ctrl *gomock.Controller
recorder *MockBeaconService_LatestAttestationClientMockRecorder
}
// MockBeaconService_LatestAttestationClientMockRecorder is the mock recorder for MockBeaconService_LatestAttestationClient
type MockBeaconService_LatestAttestationClientMockRecorder struct {
mock *MockBeaconService_LatestAttestationClient
}
// NewMockBeaconService_LatestAttestationClient creates a new mock instance
func NewMockBeaconService_LatestAttestationClient(ctrl *gomock.Controller) *MockBeaconService_LatestAttestationClient {
mock := &MockBeaconService_LatestAttestationClient{ctrl: ctrl}
mock.recorder = &MockBeaconService_LatestAttestationClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockBeaconService_LatestAttestationClient) EXPECT() *MockBeaconService_LatestAttestationClientMockRecorder {
return m.recorder
}
// CloseSend mocks base method
func (m *MockBeaconService_LatestAttestationClient) CloseSend() error {
ret := m.ctrl.Call(m, "CloseSend")
ret0, _ := ret[0].(error)
return ret0
}
// CloseSend indicates an expected call of CloseSend
func (mr *MockBeaconService_LatestAttestationClientMockRecorder) CloseSend() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseSend", reflect.TypeOf((*MockBeaconService_LatestAttestationClient)(nil).CloseSend))
}
// Context mocks base method
func (m *MockBeaconService_LatestAttestationClient) Context() context.Context {
ret := m.ctrl.Call(m, "Context")
ret0, _ := ret[0].(context.Context)
return ret0
}
// Context indicates an expected call of Context
func (mr *MockBeaconService_LatestAttestationClientMockRecorder) Context() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockBeaconService_LatestAttestationClient)(nil).Context))
}
// Header mocks base method
func (m *MockBeaconService_LatestAttestationClient) Header() (metadata.MD, error) {
ret := m.ctrl.Call(m, "Header")
ret0, _ := ret[0].(metadata.MD)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Header indicates an expected call of Header
func (mr *MockBeaconService_LatestAttestationClientMockRecorder) Header() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockBeaconService_LatestAttestationClient)(nil).Header))
}
// Recv mocks base method
func (m *MockBeaconService_LatestAttestationClient) Recv() (*v1.Attestation, error) {
ret := m.ctrl.Call(m, "Recv")
ret0, _ := ret[0].(*v1.Attestation)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Recv indicates an expected call of Recv
func (mr *MockBeaconService_LatestAttestationClientMockRecorder) Recv() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Recv", reflect.TypeOf((*MockBeaconService_LatestAttestationClient)(nil).Recv))
}
// RecvMsg mocks base method
func (m *MockBeaconService_LatestAttestationClient) RecvMsg(arg0 interface{}) error {
ret := m.ctrl.Call(m, "RecvMsg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// RecvMsg indicates an expected call of RecvMsg
func (mr *MockBeaconService_LatestAttestationClientMockRecorder) RecvMsg(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockBeaconService_LatestAttestationClient)(nil).RecvMsg), arg0)
}
// SendMsg mocks base method
func (m *MockBeaconService_LatestAttestationClient) SendMsg(arg0 interface{}) error {
ret := m.ctrl.Call(m, "SendMsg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SendMsg indicates an expected call of SendMsg
func (mr *MockBeaconService_LatestAttestationClientMockRecorder) SendMsg(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockBeaconService_LatestAttestationClient)(nil).SendMsg), arg0)
}
// Trailer mocks base method
func (m *MockBeaconService_LatestAttestationClient) Trailer() metadata.MD {
ret := m.ctrl.Call(m, "Trailer")
ret0, _ := ret[0].(metadata.MD)
return ret0
}
// Trailer indicates an expected call of Trailer
func (mr *MockBeaconService_LatestAttestationClientMockRecorder) Trailer() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockBeaconService_LatestAttestationClient)(nil).Trailer))
}
// MockBeaconService_WaitForChainStartClient is a mock of BeaconService_WaitForChainStartClient interface
type MockBeaconService_WaitForChainStartClient struct {
ctrl *gomock.Controller
recorder *MockBeaconService_WaitForChainStartClientMockRecorder
}
// MockBeaconService_WaitForChainStartClientMockRecorder is the mock recorder for MockBeaconService_WaitForChainStartClient
type MockBeaconService_WaitForChainStartClientMockRecorder struct {
mock *MockBeaconService_WaitForChainStartClient
}
// NewMockBeaconService_WaitForChainStartClient creates a new mock instance
func NewMockBeaconService_WaitForChainStartClient(ctrl *gomock.Controller) *MockBeaconService_WaitForChainStartClient {
mock := &MockBeaconService_WaitForChainStartClient{ctrl: ctrl}
mock.recorder = &MockBeaconService_WaitForChainStartClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockBeaconService_WaitForChainStartClient) EXPECT() *MockBeaconService_WaitForChainStartClientMockRecorder {
return m.recorder
}
// CloseSend mocks base method
func (m *MockBeaconService_WaitForChainStartClient) CloseSend() error {
ret := m.ctrl.Call(m, "CloseSend")
ret0, _ := ret[0].(error)
return ret0
}
// CloseSend indicates an expected call of CloseSend
func (mr *MockBeaconService_WaitForChainStartClientMockRecorder) CloseSend() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseSend", reflect.TypeOf((*MockBeaconService_WaitForChainStartClient)(nil).CloseSend))
}
// Context mocks base method
func (m *MockBeaconService_WaitForChainStartClient) Context() context.Context {
ret := m.ctrl.Call(m, "Context")
ret0, _ := ret[0].(context.Context)
return ret0
}
// Context indicates an expected call of Context
func (mr *MockBeaconService_WaitForChainStartClientMockRecorder) Context() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockBeaconService_WaitForChainStartClient)(nil).Context))
}
// Header mocks base method
func (m *MockBeaconService_WaitForChainStartClient) Header() (metadata.MD, error) {
ret := m.ctrl.Call(m, "Header")
ret0, _ := ret[0].(metadata.MD)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Header indicates an expected call of Header
func (mr *MockBeaconService_WaitForChainStartClientMockRecorder) Header() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockBeaconService_WaitForChainStartClient)(nil).Header))
}
// Recv mocks base method
func (m *MockBeaconService_WaitForChainStartClient) Recv() (*v10.ChainStartResponse, error) {
ret := m.ctrl.Call(m, "Recv")
ret0, _ := ret[0].(*v10.ChainStartResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Recv indicates an expected call of Recv
func (mr *MockBeaconService_WaitForChainStartClientMockRecorder) Recv() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Recv", reflect.TypeOf((*MockBeaconService_WaitForChainStartClient)(nil).Recv))
}
// RecvMsg mocks base method
func (m *MockBeaconService_WaitForChainStartClient) RecvMsg(arg0 interface{}) error {
ret := m.ctrl.Call(m, "RecvMsg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// RecvMsg indicates an expected call of RecvMsg
func (mr *MockBeaconService_WaitForChainStartClientMockRecorder) RecvMsg(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockBeaconService_WaitForChainStartClient)(nil).RecvMsg), arg0)
}
// SendMsg mocks base method
func (m *MockBeaconService_WaitForChainStartClient) SendMsg(arg0 interface{}) error {
ret := m.ctrl.Call(m, "SendMsg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SendMsg indicates an expected call of SendMsg
func (mr *MockBeaconService_WaitForChainStartClientMockRecorder) SendMsg(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockBeaconService_WaitForChainStartClient)(nil).SendMsg), arg0)
}
// Trailer mocks base method
func (m *MockBeaconService_WaitForChainStartClient) Trailer() metadata.MD {
ret := m.ctrl.Call(m, "Trailer")
ret0, _ := ret[0].(metadata.MD)
return ret0
}
// Trailer indicates an expected call of Trailer
func (mr *MockBeaconService_WaitForChainStartClientMockRecorder) Trailer() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockBeaconService_WaitForChainStartClient)(nil).Trailer))
}

View File

@@ -25,6 +25,7 @@ go_library(
"//shared/prometheus:go_default_library",
"//shared/version:go_default_library",
"//validator/client:go_default_library",
"//validator/types:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_urfave_cli//:go_default_library",

View File

@@ -10,6 +10,8 @@ import (
"sync"
"syscall"
"github.com/prysmaticlabs/prysm/validator/types"
"github.com/prysmaticlabs/prysm/shared"
"github.com/prysmaticlabs/prysm/shared/cmd"
"github.com/prysmaticlabs/prysm/shared/debug"
@@ -49,7 +51,7 @@ func NewValidatorClient(ctx *cli.Context) (*ValidatorClient, error) {
return nil, err
}
if err := ValidatorClient.registerClientService(); err != nil {
if err := ValidatorClient.registerClientService(ctx); err != nil {
return nil, err
}
@@ -119,8 +121,10 @@ func (s *ValidatorClient) registerPrometheusService(ctx *cli.Context) error {
return s.services.RegisterService(service)
}
func (s *ValidatorClient) registerClientService() error {
v := client.NewValidatorService(context.TODO())
func (s *ValidatorClient) registerClientService(ctx *cli.Context) error {
endpoint := ctx.GlobalString(types.BeaconRPCProviderFlag.Name)
v := client.NewValidatorService(context.TODO(), &client.Config{
Endpoint: endpoint,
})
return s.services.RegisterService(v)
}

View File

@@ -1,25 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "github.com/prysmaticlabs/prysm/validator/rpcclient",
visibility = ["//validator:__subpackages__"],
deps = [
"//proto/beacon/rpc/v1:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//credentials:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
deps = [
"//proto/beacon/rpc/v1:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],
)

View File

@@ -1,118 +0,0 @@
// Package rpcclient defines a gRPC connection to a beacon node.
package rpcclient
import (
"context"
"errors"
"fmt"
"net/url"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
var log = logrus.WithField("prefix", "rpc-client")
// Service for an RPCClient to a Beacon Node.
type Service struct {
ctx context.Context
cancel context.CancelFunc
conn *grpc.ClientConn
endpoint string
withCert string
}
// Config for the RPCClient service.
type Config struct {
Endpoint string
CertFlag string
}
// NewRPCClient sets up a new beacon node RPC client connection.
func NewRPCClient(ctx context.Context, cfg *Config) *Service {
ctx, cancel := context.WithCancel(ctx)
return &Service{
ctx: ctx,
cancel: cancel,
endpoint: cfg.Endpoint,
withCert: cfg.CertFlag,
}
}
// Start the grpc connection.
func (s *Service) Start() {
log.Info("Starting service")
var server grpc.DialOption
if s.withCert != "" {
creds, err := credentials.NewClientTLSFromFile(s.withCert, "")
if err != nil {
log.Errorf("Could not get valid credentials: %v", err)
return
}
server = grpc.WithTransportCredentials(creds)
} else {
server = grpc.WithInsecure()
log.Warn("You are using an insecure gRPC connection! Please provide a certificate and key to use a secure connection.")
}
providerURL, err := url.Parse(s.endpoint)
if err != nil {
log.Fatalf("Unable to parse beacon RPC provider endpoint url: %v", err)
}
conn, err := grpc.Dial(fmt.Sprintf("[%s]:%s", providerURL.Hostname(), providerURL.Port()), server)
if err != nil {
log.Errorf("Could not dial endpoint: %s, %v", s.endpoint, err)
return
}
s.conn = conn
}
// Stop the dialed connection.
func (s *Service) Stop() error {
log.Info("Stopping service")
if s.conn != nil {
return s.conn.Close()
}
return nil
}
// Status returns error if there is no connection to the beacon chain RPC.
func (s *Service) Status() error {
if s.conn == nil {
return errors.New("no connection to beacon RPC")
}
return nil
}
// BeaconServiceClient initializes a new beacon gRPC service using
// an underlying connection object.
// This wrapper is important because the underlying gRPC connection is
// only defined after the service .Start() function is called.
func (s *Service) BeaconServiceClient() pb.BeaconServiceClient {
return pb.NewBeaconServiceClient(s.conn)
}
// ProposerServiceClient initializes a new proposer gRPC service using
// an underlying connection object.
// This wrapper is important because the underlying gRPC connection is
// only defined after the service .Start() function is called.
func (s *Service) ProposerServiceClient() pb.ProposerServiceClient {
return pb.NewProposerServiceClient(s.conn)
}
// AttesterServiceClient initializes a new attester gRPC service using
// an underlying connection object.
// This wrapper is important because the underlying gRPC connection is
// only defined after the service .Start() function is called.
func (s *Service) AttesterServiceClient() pb.AttesterServiceClient {
return pb.NewAttesterServiceClient(s.conn)
}
// ValidatorServiceClient initializes a new validator gRPC service using
// an underlying connection object.
// This wrapper is important because the underlying gRPC connection is
// only defined after the service .Start() function is called.
func (s *Service) ValidatorServiceClient() pb.ValidatorServiceClient {
return pb.NewValidatorServiceClient(s.conn)
}

View File

@@ -1,82 +0,0 @@
package rpcclient
import (
"context"
"testing"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/prysmaticlabs/prysm/shared/testutil"
logTest "github.com/sirupsen/logrus/hooks/test"
)
func TestLifecycle(t *testing.T) {
hook := logTest.NewGlobal()
rpcClientService := NewRPCClient(
context.Background(),
&Config{
Endpoint: "merkle tries",
CertFlag: "alice.crt",
},
)
rpcClientService.Start()
testutil.AssertLogsContain(t, hook, "Starting service")
rpcClientService.Stop()
testutil.AssertLogsContain(t, hook, "Stopping service")
}
func TestInsecure(t *testing.T) {
hook := logTest.NewGlobal()
rpcClientService := NewRPCClient(
context.Background(),
&Config{
Endpoint: "merkle tries",
},
)
rpcClientService.Start()
testutil.AssertLogsContain(t, hook, "Starting service")
testutil.AssertLogsContain(t, hook, "You are using an insecure gRPC connection")
rpcClientService.Stop()
testutil.AssertLogsContain(t, hook, "Stopping service")
}
func TestBeaconServiceClient(t *testing.T) {
rpcClientService := NewRPCClient(
context.Background(),
&Config{
Endpoint: "merkle tries",
},
)
rpcClientService.conn = nil
client := rpcClientService.BeaconServiceClient()
if _, ok := client.(pb.BeaconServiceClient); !ok {
t.Error("Beacon service client function does not implement interface")
}
}
func TestProposerServiceClient(t *testing.T) {
rpcClientService := NewRPCClient(
context.Background(),
&Config{
Endpoint: "merkle tries",
},
)
rpcClientService.conn = nil
client := rpcClientService.ProposerServiceClient()
if _, ok := client.(pb.ProposerServiceClient); !ok {
t.Error("Beacon service client function does not implement interface")
}
}
func TestAttesterServiceClient(t *testing.T) {
rpcClientService := NewRPCClient(
context.Background(),
&Config{
Endpoint: "merkle tries",
},
)
rpcClientService.conn = nil
client := rpcClientService.AttesterServiceClient()
if _, ok := client.(pb.AttesterServiceClient); !ok {
t.Error("Beacon service client function does not implement interface")
}
}

View File

@@ -9,7 +9,7 @@ var (
BeaconRPCProviderFlag = cli.StringFlag{
Name: "beacon-rpc-provider",
Usage: "Beacon node RPC provider endpoint",
Value: "http://localhost:4000/",
Value: "localhost:4000",
}
// PubKeyFlag defines a flag for validator's public key on the mainchain
PubKeyFlag = cli.StringFlag{