[Interop] Improve RPC Codebase + Start Beacon Chain With Mock ETH1 Values (#3407)

* add main.go

* interop readme

* proper visibility

* standardize and abstract into simpler funcs

* formatting

* no os pkg

* add test

* no panics anywhere, properly and nicely handle errors

* proper comments

* fix broken test

* readme

* comment

* recommend ssz

* install

* tool now works

* README

* build

* readme

* 64 validators

* rem print

* register the no powchain flag

* work on mock eth1 start

* common interface

* getting closer with the interface defs

* only two uses of powchain

* remove powchain dependency

* remove powchain dependency

* common powchain interface

* proper comment in case of flag

* proper args into rpc services

* rename fields

* pass in mock flag into RPC

* conforms to iface

* use client instead of block fetcher iface

* broken tests

* block fetcher

* finalized

* resolved broken build

* fix build

* comment

* fix tests

* tests pass

* resolved confs

* took them out

* rename into smaller interfaces

* resolve some confs

* ensure tests pass

* properly utilize mock instead of localized mock

* res lint

* lint

* finish test for mock eth1data

* run gazelle

* include flag again

* fix broken build

* disable powchain

* dont dial eth1 nodes

* reenable pow

* use smaller interfaces, standardize naming

* abstract mock into its own package

* faulty mock lint

* fix stutter in lint

* rpc tests all passing

* use mocks for operations

* no more mocks in the entire rpc package

* no  mock

* viz

* testonly
This commit is contained in:
Raul Jordan
2019-09-09 17:13:50 -04:00
committed by GitHub
parent 8d234014a4
commit af07c13730
36 changed files with 926 additions and 676 deletions

View File

@@ -9,33 +9,32 @@ import (
"github.com/prysmaticlabs/prysm/shared/params" "github.com/prysmaticlabs/prysm/shared/params"
) )
// ChainInfoRetriever defines a common interface for methods in blockchain service which // ChainInfoFetcher defines a common interface for methods in blockchain service which
// directly retrieves chain info related data. // directly retrieves chain info related data.
type ChainInfoRetriever interface { type ChainInfoFetcher interface {
HeadRetriever HeadFetcher
CanonicalRetriever CanonicalRootFetcher
FinalizationRetriever FinalizationFetcher
GenesisTime() time.Time
} }
// HeadRetriever defines a common interface for methods in blockchain service which // HeadFetcher defines a common interface for methods in blockchain service which
// directly retrieves head related data. // directly retrieves head related data.
type HeadRetriever interface { type HeadFetcher interface {
HeadSlot() uint64 HeadSlot() uint64
HeadRoot() []byte HeadRoot() []byte
HeadBlock() *ethpb.BeaconBlock HeadBlock() *ethpb.BeaconBlock
HeadState() *pb.BeaconState HeadState() *pb.BeaconState
} }
// CanonicalRetriever defines a common interface for methods in blockchain service which // CanonicalRootFetcher defines a common interface for methods in blockchain service which
// directly retrieves canonical roots related data. // directly retrieves canonical roots related data.
type CanonicalRetriever interface { type CanonicalRootFetcher interface {
CanonicalRoot(slot uint64) []byte CanonicalRoot(slot uint64) []byte
} }
// FinalizationRetriever defines a common interface for methods in blockchain service which // FinalizationFetcher defines a common interface for methods in blockchain service which
// directly retrieves finalization related data. // directly retrieves finalization related data.
type FinalizationRetriever interface { type FinalizationFetcher interface {
FinalizedCheckpt() *ethpb.Checkpoint FinalizedCheckpt() *ethpb.Checkpoint
} }

View File

@@ -5,7 +5,6 @@ import (
"context" "context"
"reflect" "reflect"
"testing" "testing"
"time"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -14,7 +13,7 @@ import (
) )
// Ensure Service implements chain info interface. // Ensure Service implements chain info interface.
var _ = ChainInfoRetriever(&Service{}) var _ = ChainInfoFetcher(&Service{})
func TestFinalizedCheckpt_Nil(t *testing.T) { func TestFinalizedCheckpt_Nil(t *testing.T) {
c := setupBeaconChain(t, nil) c := setupBeaconChain(t, nil)
@@ -88,11 +87,3 @@ func TestCanonicalRoot_CanRetrieve(t *testing.T) {
t.Errorf("Wanted head root: %v, got: %d", []byte{'A'}, c.CanonicalRoot(slot)) t.Errorf("Wanted head root: %v, got: %d", []byte{'A'}, c.CanonicalRoot(slot))
} }
} }
func TestGenesisTime_CanRetrieve(t *testing.T) {
c := &Service{}
c.genesisTime = time.Unix(100, 0)
if c.GenesisTime() != time.Unix(100, 0) {
t.Error("incorrect genesis time received")
}
}

View File

@@ -43,7 +43,7 @@ type Service struct {
cancel context.CancelFunc cancel context.CancelFunc
beaconDB db.Database beaconDB db.Database
depositCache *depositcache.DepositCache depositCache *depositcache.DepositCache
web3Service *powchain.Service chainStartFetcher powchain.ChainStartFetcher
opsPoolService operations.OperationFeeds opsPoolService operations.OperationFeeds
forkChoiceStore forkchoice.ForkChoicer forkChoiceStore forkchoice.ForkChoicer
chainStartChan chan time.Time chainStartChan chan time.Time
@@ -61,14 +61,14 @@ type Service struct {
// Config options for the service. // Config options for the service.
type Config struct { type Config struct {
BeaconBlockBuf int BeaconBlockBuf int
Web3Service *powchain.Service ChainStartFetcher powchain.ChainStartFetcher
BeaconDB db.Database BeaconDB db.Database
DepositCache *depositcache.DepositCache DepositCache *depositcache.DepositCache
OpsPoolService operations.OperationFeeds OpsPoolService operations.OperationFeeds
P2p p2p.Broadcaster P2p p2p.Broadcaster
MaxRoutines int64 MaxRoutines int64
PreloadStatePath string PreloadStatePath string
} }
// NewService instantiates a new block service instance that will // NewService instantiates a new block service instance that will
@@ -81,7 +81,7 @@ func NewService(ctx context.Context, cfg *Config) (*Service, error) {
cancel: cancel, cancel: cancel,
beaconDB: cfg.BeaconDB, beaconDB: cfg.BeaconDB,
depositCache: cfg.DepositCache, depositCache: cfg.DepositCache,
web3Service: cfg.Web3Service, chainStartFetcher: cfg.ChainStartFetcher,
opsPoolService: cfg.OpsPoolService, opsPoolService: cfg.OpsPoolService,
forkChoiceStore: store, forkChoiceStore: store,
chainStartChan: make(chan time.Time), chainStartChan: make(chan time.Time),
@@ -136,11 +136,11 @@ func (s *Service) Start() {
s.stateInitializedFeed.Send(s.genesisTime) s.stateInitializedFeed.Send(s.genesisTime)
} else { } else {
log.Info("Waiting for ChainStart log from the Validator Deposit Contract to start the beacon chain...") log.Info("Waiting for ChainStart log from the Validator Deposit Contract to start the beacon chain...")
if s.web3Service == nil { if s.chainStartFetcher == nil {
log.Fatal("Not configured web3Service for POW chain") log.Fatal("Not configured web3Service for POW chain")
return // return need for TestStartUninitializedChainWithoutConfigPOWChain. return // return need for TestStartUninitializedChainWithoutConfigPOWChain.
} }
subChainStart := s.web3Service.ChainStartFeed().Subscribe(s.chainStartChan) subChainStart := s.chainStartFetcher.ChainStartFeed().Subscribe(s.chainStartChan)
go func() { go func() {
genesisTime := <-s.chainStartChan genesisTime := <-s.chainStartChan
s.processChainStartTime(ctx, genesisTime, subChainStart) s.processChainStartTime(ctx, genesisTime, subChainStart)
@@ -152,8 +152,8 @@ func (s *Service) Start() {
// processChainStartTime initializes a series of deposits from the ChainStart deposits in the eth1 // processChainStartTime initializes a series of deposits from the ChainStart deposits in the eth1
// deposit contract, initializes the beacon chain's state, and kicks off the beacon chain. // deposit contract, initializes the beacon chain's state, and kicks off the beacon chain.
func (s *Service) processChainStartTime(ctx context.Context, genesisTime time.Time, chainStartSub event.Subscription) { func (s *Service) processChainStartTime(ctx context.Context, genesisTime time.Time, chainStartSub event.Subscription) {
initialDeposits := s.web3Service.ChainStartDeposits() initialDeposits := s.chainStartFetcher.ChainStartDeposits()
if err := s.initializeBeaconChain(ctx, genesisTime, initialDeposits, s.web3Service.ChainStartETH1Data()); err != nil { if err := s.initializeBeaconChain(ctx, genesisTime, initialDeposits, s.chainStartFetcher.ChainStartEth1Data()); err != nil {
log.Fatalf("Could not initialize beacon chain: %v", err) log.Fatalf("Could not initialize beacon chain: %v", err)
} }
s.stateInitializedFeed.Send(genesisTime) s.stateInitializedFeed.Send(genesisTime)

View File

@@ -206,12 +206,12 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
} }
cfg := &Config{ cfg := &Config{
BeaconBlockBuf: 0, BeaconBlockBuf: 0,
BeaconDB: beaconDB, BeaconDB: beaconDB,
DepositCache: depositcache.NewDepositCache(), DepositCache: depositcache.NewDepositCache(),
Web3Service: web3Service, ChainStartFetcher: web3Service,
OpsPoolService: &mockOperationService{}, OpsPoolService: &mockOperationService{},
P2p: &mockBroadcaster{}, P2p: &mockBroadcaster{},
} }
if err != nil { if err != nil {
t.Fatalf("could not register blockchain service: %v", err) t.Fatalf("could not register blockchain service: %v", err)

View File

@@ -2,6 +2,7 @@ package testing
import ( import (
"context" "context"
"time"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
@@ -67,7 +68,12 @@ func (ms *ChainService) ReceiveAttestationNoPubsub(context.Context, *ethpb.Attes
return nil return nil
} }
// StateInitializedFeed mocks StateInitializedFeed method in chain service. // GenesisTime mocks the same method in the chain service.
func (ms *ChainService) GenesisTime() time.Time {
return time.Now()
}
// StateInitializedFeed mocks the same method in the chain service.
func (ms *ChainService) StateInitializedFeed() *event.Feed { func (ms *ChainService) StateInitializedFeed() *event.Feed {
return new(event.Feed) return new(event.Feed)
} }

View File

@@ -53,8 +53,13 @@ var (
Name: "grpc-gateway-port", Name: "grpc-gateway-port",
Usage: "Enable gRPC gateway for JSON requests", Usage: "Enable gRPC gateway for JSON requests",
} }
// GenesisState defines a flag for the beacon node to load genesis state via file. // InteropMockEth1DataVotesFlag enables mocking the eth1 proof-of-work chain data put into blocks by proposers.
GenesisState = cli.StringFlag{ InteropMockEth1DataVotesFlag = cli.BoolFlag{
Name: "interop-eth1data-votes",
Usage: "Enable mocking of eth1 data votes for proposers to package into blocks",
}
// InteropGenesisStateFlag defines a flag for the beacon node to load genesis state via file.
InteropGenesisStateFlag = cli.StringFlag{
Name: "interop-genesis-state", Name: "interop-genesis-state",
Usage: "The genesis state file (.SSZ) to load from", Usage: "The genesis state file (.SSZ) to load from",
} }

View File

@@ -30,7 +30,8 @@ var appFlags = []cli.Flag{
flags.KeyFlag, flags.KeyFlag,
flags.EnableDBCleanup, flags.EnableDBCleanup,
flags.GRPCGatewayPort, flags.GRPCGatewayPort,
flags.GenesisState, flags.InteropMockEth1DataVotesFlag,
flags.InteropGenesisStateFlag,
cmd.BootstrapNode, cmd.BootstrapNode,
cmd.NoDiscovery, cmd.NoDiscovery,
cmd.StaticPeers, cmd.StaticPeers,

View File

@@ -201,7 +201,7 @@ func (b *BeaconNode) startDB(ctx *cli.Context) error {
} }
func (b *BeaconNode) registerP2P(ctx *cli.Context) error { func (b *BeaconNode) registerP2P(ctx *cli.Context) error {
// Bootnode ENR may be a filepath to an ENR file. // Bootnode ENR may be a filepath to an ENR file.
bootnodeENR := ctx.GlobalString(cmd.BootstrapNode.Name) bootnodeENR := ctx.GlobalString(cmd.BootstrapNode.Name)
if filepath.Ext(bootnodeENR) == ".enr" { if filepath.Ext(bootnodeENR) == ".enr" {
b, err := ioutil.ReadFile(bootnodeENR) b, err := ioutil.ReadFile(bootnodeENR)
@@ -249,14 +249,15 @@ func (b *BeaconNode) registerBlockchainService(ctx *cli.Context) error {
} }
maxRoutines := ctx.GlobalInt64(cmd.MaxGoroutines.Name) maxRoutines := ctx.GlobalInt64(cmd.MaxGoroutines.Name)
interopLoadGenesisFlag := ctx.GlobalString(flags.InteropGenesisStateFlag.Name)
blockchainService, err := blockchain.NewService(context.Background(), &blockchain.Config{ blockchainService, err := blockchain.NewService(context.Background(), &blockchain.Config{
BeaconDB: b.db, BeaconDB: b.db,
DepositCache: b.depositCache, DepositCache: b.depositCache,
Web3Service: web3Service, ChainStartFetcher: web3Service,
OpsPoolService: opsService, OpsPoolService: opsService,
P2p: b.fetchP2P(ctx), P2p: b.fetchP2P(ctx),
MaxRoutines: maxRoutines, MaxRoutines: maxRoutines,
PreloadStatePath: interopLoadGenesisFlag,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "could not register blockchain service") return errors.Wrap(err, "could not register blockchain service")
@@ -277,9 +278,7 @@ func (b *BeaconNode) registerPOWChainService(cliCtx *cli.Context) error {
if cliCtx.GlobalBool(testSkipPowFlag) { if cliCtx.GlobalBool(testSkipPowFlag) {
return b.services.RegisterService(&powchain.Service{}) return b.services.RegisterService(&powchain.Service{})
} }
depAddress := cliCtx.GlobalString(flags.DepositContractFlag.Name) depAddress := cliCtx.GlobalString(flags.DepositContractFlag.Name)
if depAddress == "" { if depAddress == "" {
var err error var err error
depAddress, err = fetchDepositContract() depAddress, err = fetchDepositContract()
@@ -404,17 +403,23 @@ func (b *BeaconNode) registerRPCService(ctx *cli.Context) error {
port := ctx.GlobalString(flags.RPCPort.Name) port := ctx.GlobalString(flags.RPCPort.Name)
cert := ctx.GlobalString(flags.CertFlag.Name) cert := ctx.GlobalString(flags.CertFlag.Name)
key := ctx.GlobalString(flags.KeyFlag.Name) key := ctx.GlobalString(flags.KeyFlag.Name)
mockEth1DataVotes := ctx.GlobalBool(flags.InteropMockEth1DataVotesFlag.Name)
rpcService := rpc.NewService(context.Background(), &rpc.Config{ rpcService := rpc.NewService(context.Background(), &rpc.Config{
Port: port, Port: port,
CertFlag: cert, CertFlag: cert,
KeyFlag: key, KeyFlag: key,
BeaconDB: b.db, BeaconDB: b.db,
Broadcaster: b.fetchP2P(ctx), Broadcaster: b.fetchP2P(ctx),
ChainService: chainService, HeadFetcher: chainService,
OperationService: operationService, BlockReceiver: chainService,
POWChainService: web3Service, AttestationReceiver: chainService,
SyncService: syncService, StateFeedListener: chainService,
DepositCache: b.depositCache, AttestationsPool: operationService,
OperationsHandler: operationService,
POWChainService: web3Service,
MockEth1Votes: mockEth1DataVotes,
SyncService: syncService,
DepositCache: b.depositCache,
}) })
return b.services.RegisterService(rpcService) return b.services.RegisterService(rpcService)

View File

@@ -35,6 +35,11 @@ type Pool interface {
AttestationPool(ctx context.Context, requestedSlot uint64) ([]*ethpb.Attestation, error) AttestationPool(ctx context.Context, requestedSlot uint64) ([]*ethpb.Attestation, error)
} }
// Handler defines an interface for a struct equipped for receiving block operations.
type Handler interface {
HandleAttestation(context.Context, proto.Message) error
}
// OperationFeeds inteface defines the informational feeds from the operations // OperationFeeds inteface defines the informational feeds from the operations
// service. // service.
type OperationFeeds interface { type OperationFeeds interface {

View File

@@ -0,0 +1,13 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
testonly = True,
srcs = ["mock.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/operations/testing",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//proto/eth/v1alpha1:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
],
)

View File

@@ -0,0 +1,23 @@
package testing
import (
"context"
"github.com/gogo/protobuf/proto"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
)
// Operations defines a mock for the operations service.
type Operations struct {
Attestations []*ethpb.Attestation
}
// AttestationPool --
func (op *Operations) AttestationPool(ctx context.Context, requestedSlot uint64) ([]*ethpb.Attestation, error) {
return op.Attestations, nil
}
// HandleAttestation --
func (op *Operations) HandleAttestation(context.Context, proto.Message) error {
return nil
}

View File

@@ -25,10 +25,10 @@ func TestLatestMainchainInfo_OK(t *testing.T) {
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{ web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
Endpoint: endpoint, Endpoint: endpoint,
DepositContract: testAcc.ContractAddr, DepositContract: testAcc.ContractAddr,
BlockFetcher: &goodFetcher{},
Reader: &goodReader{}, Reader: &goodReader{},
Logger: &goodLogger{}, Logger: &goodLogger{},
HTTPLogger: &goodLogger{}, HTTPLogger: &goodLogger{},
BlockFetcher: &goodFetcher{},
ContractBackend: testAcc.Backend, ContractBackend: testAcc.Backend,
BeaconDB: beaconDB, BeaconDB: beaconDB,
}) })

View File

@@ -27,9 +27,9 @@ var (
depositEventSignature = []byte("DepositEvent(bytes,bytes,bytes,bytes,bytes)") depositEventSignature = []byte("DepositEvent(bytes,bytes,bytes,bytes,bytes)")
) )
// ETH2GenesisTime retrieves the genesis time and eth1 block number of the beacon chain // Eth2GenesisPowchainInfo retrieves the genesis time and eth1 block number of the beacon chain
// from the deposit contract. // from the deposit contract.
func (s *Service) ETH2GenesisTime() (uint64, *big.Int) { func (s *Service) Eth2GenesisPowchainInfo() (uint64, *big.Int) {
return s.eth2GenesisTime, s.chainStartBlockNumber return s.eth2GenesisTime, s.chainStartBlockNumber
} }

View File

@@ -50,22 +50,52 @@ type Reader interface {
SubscribeNewHead(ctx context.Context, ch chan<- *gethTypes.Header) (ethereum.Subscription, error) SubscribeNewHead(ctx context.Context, ch chan<- *gethTypes.Header) (ethereum.Subscription, error)
} }
// ChainStartFetcher retrieves information pertaining to the chain start event
// of the beacon chain for usage across various services.
type ChainStartFetcher interface {
ChainStartDeposits() []*ethpb.Deposit
ChainStartEth1Data() *ethpb.Eth1Data
ChainStartFeed() *event.Feed
HasChainStarted() bool
}
// ChainInfoFetcher retrieves information about eth1 metadata at the eth2 genesis time.
type ChainInfoFetcher interface {
Eth2GenesisPowchainInfo() (uint64, *big.Int)
}
// POWBlockFetcher defines a struct that can retrieve mainchain blocks. // POWBlockFetcher defines a struct that can retrieve mainchain blocks.
type POWBlockFetcher interface { type POWBlockFetcher interface {
BlockByHash(ctx context.Context, hash common.Hash) (*gethTypes.Block, error) BlockTimeByHeight(ctx context.Context, height *big.Int) (uint64, error)
BlockByNumber(ctx context.Context, number *big.Int) (*gethTypes.Block, error) BlockNumberByTimestamp(ctx context.Context, time uint64) (*big.Int, error)
HeaderByNumber(ctx context.Context, number *big.Int) (*gethTypes.Header, error) BlockHashByHeight(ctx context.Context, height *big.Int) (common.Hash, error)
BlockExists(ctx context.Context, hash common.Hash) (bool, *big.Int, error)
}
// Chain defines a standard interface for the powchain service in Prysm.
type Chain interface {
ChainStartFetcher
ChainInfoFetcher
POWBlockFetcher
} }
// Client defines a struct that combines all relevant ETH1.0 mainchain interactions required // Client defines a struct that combines all relevant ETH1.0 mainchain interactions required
// by the beacon chain node. // by the beacon chain node.
type Client interface { type Client interface {
Reader Reader
POWBlockFetcher RPCBlockFetcher
bind.ContractFilterer bind.ContractFilterer
bind.ContractCaller bind.ContractCaller
} }
// RPCBlockFetcher defines a subset of methods conformed to by ETH1.0 RPC clients for
// fetching block information.
type RPCBlockFetcher interface {
HeaderByNumber(ctx context.Context, number *big.Int) (*gethTypes.Header, error)
BlockByNumber(ctx context.Context, number *big.Int) (*gethTypes.Block, error)
BlockByHash(ctx context.Context, hash common.Hash) (*gethTypes.Block, error)
}
// Service fetches important information about the canonical // Service fetches important information about the canonical
// Ethereum ETH1.0 chain via a web3 endpoint using an ethclient. The Random // Ethereum ETH1.0 chain via a web3 endpoint using an ethclient. The Random
// Beacon Chain requires synchronization with the ETH1.0 chain's current // Beacon Chain requires synchronization with the ETH1.0 chain's current
@@ -83,7 +113,7 @@ type Service struct {
reader Reader reader Reader
logger bind.ContractFilterer logger bind.ContractFilterer
httpLogger bind.ContractFilterer httpLogger bind.ContractFilterer
blockFetcher POWBlockFetcher blockFetcher RPCBlockFetcher
blockHeight *big.Int // the latest ETH1.0 chain blockHeight. blockHeight *big.Int // the latest ETH1.0 chain blockHeight.
blockHash common.Hash // the latest ETH1.0 chain blockHash. blockHash common.Hash // the latest ETH1.0 chain blockHash.
blockTime time.Time // the latest ETH1.0 chain blockTime. blockTime time.Time // the latest ETH1.0 chain blockTime.
@@ -115,7 +145,7 @@ type Web3ServiceConfig struct {
Reader Reader Reader Reader
Logger bind.ContractFilterer Logger bind.ContractFilterer
HTTPLogger bind.ContractFilterer HTTPLogger bind.ContractFilterer
BlockFetcher POWBlockFetcher BlockFetcher RPCBlockFetcher
ContractBackend bind.ContractBackend ContractBackend bind.ContractBackend
BeaconDB db.Database BeaconDB db.Database
DepositCache *depositcache.DepositCache DepositCache *depositcache.DepositCache
@@ -201,8 +231,8 @@ func (s *Service) ChainStartDeposits() []*ethpb.Deposit {
return s.chainStartDeposits return s.chainStartDeposits
} }
// ChainStartETH1Data returns the eth1 data at chainstart. // ChainStartEth1Data returns the eth1 data at chainstart.
func (s *Service) ChainStartETH1Data() *ethpb.Eth1Data { func (s *Service) ChainStartEth1Data() *ethpb.Eth1Data {
return s.chainStartETH1Data return s.chainStartETH1Data
} }

View File

@@ -21,6 +21,11 @@ import (
logTest "github.com/sirupsen/logrus/hooks/test" logTest "github.com/sirupsen/logrus/hooks/test"
) )
var _ = ChainStartFetcher(&Service{})
var _ = ChainInfoFetcher(&Service{})
var _ = POWBlockFetcher(&Service{})
var _ = Chain(&Service{})
type badReader struct{} type badReader struct{}
func (b *badReader) SubscribeNewHead(ctx context.Context, ch chan<- *gethTypes.Header) (ethereum.Subscription, error) { func (b *badReader) SubscribeNewHead(ctx context.Context, ch chan<- *gethTypes.Header) (ethereum.Subscription, error) {

View File

@@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
testonly = True,
srcs = [
"faulty_mock.go",
"mock.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//proto/eth/v1alpha1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/event:go_default_library",
"//shared/trieutil:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
],
)

View File

@@ -0,0 +1,87 @@
package testing
import (
"context"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/trieutil"
)
// FaultyMockPOWChain defines an incorrectly functioning powchain service.
type FaultyMockPOWChain struct {
ChainFeed *event.Feed
HashesByHeight map[int][]byte
}
// HasChainStarted --
func (f *FaultyMockPOWChain) HasChainStarted() bool {
return false
}
// Eth2GenesisPowchainInfo --
func (f *FaultyMockPOWChain) Eth2GenesisPowchainInfo() (uint64, *big.Int) {
return 0, big.NewInt(0)
}
// ChainStartFeed --
func (f *FaultyMockPOWChain) ChainStartFeed() *event.Feed {
return f.ChainFeed
}
// LatestBlockHeight --
func (f *FaultyMockPOWChain) LatestBlockHeight() *big.Int {
return big.NewInt(0)
}
// BlockExists --
func (f *FaultyMockPOWChain) BlockExists(_ context.Context, hash common.Hash) (bool, *big.Int, error) {
if f.HashesByHeight == nil {
return false, big.NewInt(1), errors.New("failed")
}
return true, big.NewInt(1), nil
}
// BlockHashByHeight --
func (f *FaultyMockPOWChain) BlockHashByHeight(_ context.Context, height *big.Int) (common.Hash, error) {
return [32]byte{}, errors.New("failed")
}
// BlockTimeByHeight --
func (f *FaultyMockPOWChain) BlockTimeByHeight(_ context.Context, height *big.Int) (uint64, error) {
return 0, errors.New("failed")
}
// BlockNumberByTimestamp --
func (f *FaultyMockPOWChain) BlockNumberByTimestamp(_ context.Context, _ uint64) (*big.Int, error) {
return big.NewInt(0), nil
}
// DepositRoot --
func (f *FaultyMockPOWChain) DepositRoot() [32]byte {
return [32]byte{}
}
// DepositTrie --
func (f *FaultyMockPOWChain) DepositTrie() *trieutil.MerkleTrie {
return &trieutil.MerkleTrie{}
}
// ChainStartDeposits --
func (f *FaultyMockPOWChain) ChainStartDeposits() []*ethpb.Deposit {
return []*ethpb.Deposit{}
}
// ChainStartDepositHashes --
func (f *FaultyMockPOWChain) ChainStartDepositHashes() ([][]byte, error) {
return [][]byte{}, errors.New("hashing failed")
}
// ChainStartEth1Data --
func (f *FaultyMockPOWChain) ChainStartEth1Data() *ethpb.Eth1Data {
return &ethpb.Eth1Data{}
}

View File

@@ -0,0 +1,106 @@
package testing
import (
"context"
"fmt"
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/trieutil"
)
// POWChain defines a properly functioning mock for the powchain service.
type POWChain struct {
ChainFeed *event.Feed
LatestBlockNumber *big.Int
HashesByHeight map[int][]byte
TimesByHeight map[int]uint64
BlockNumberByHeight map[uint64]*big.Int
Eth1Data *ethpb.Eth1Data
GenesisEth1Block *big.Int
}
// ChainStartFeed --
func (m *POWChain) ChainStartFeed() *event.Feed {
return m.ChainFeed
}
// HasChainStarted --
func (m *POWChain) HasChainStarted() bool {
return true
}
// Eth2GenesisPowchainInfo --
func (m *POWChain) Eth2GenesisPowchainInfo() (uint64, *big.Int) {
blk := m.GenesisEth1Block
if blk == nil {
blk = big.NewInt(0)
}
return uint64(time.Unix(0, 0).Unix()), blk
}
// DepositTrie --
func (m *POWChain) DepositTrie() *trieutil.MerkleTrie {
return &trieutil.MerkleTrie{}
}
// BlockExists --
func (m *POWChain) BlockExists(_ context.Context, hash common.Hash) (bool, *big.Int, error) {
// Reverse the map of heights by hash.
heightsByHash := make(map[[32]byte]int)
for k, v := range m.HashesByHeight {
h := bytesutil.ToBytes32(v)
heightsByHash[h] = k
}
val, ok := heightsByHash[hash]
if !ok {
return false, nil, fmt.Errorf("could not fetch height for hash: %#x", hash)
}
return true, big.NewInt(int64(val)), nil
}
// BlockHashByHeight --
func (m *POWChain) BlockHashByHeight(_ context.Context, height *big.Int) (common.Hash, error) {
k := int(height.Int64())
val, ok := m.HashesByHeight[k]
if !ok {
return [32]byte{}, fmt.Errorf("could not fetch hash for height: %v", height)
}
return bytesutil.ToBytes32(val), nil
}
// BlockTimeByHeight --
func (m *POWChain) BlockTimeByHeight(_ context.Context, height *big.Int) (uint64, error) {
h := int(height.Int64())
return m.TimesByHeight[h], nil
}
// BlockNumberByTimestamp --
func (m *POWChain) BlockNumberByTimestamp(_ context.Context, time uint64) (*big.Int, error) {
return m.BlockNumberByHeight[time], nil
}
// DepositRoot --
func (m *POWChain) DepositRoot() [32]byte {
root := []byte("depositroot")
return bytesutil.ToBytes32(root)
}
// ChainStartDeposits --
func (m *POWChain) ChainStartDeposits() []*ethpb.Deposit {
return []*ethpb.Deposit{}
}
// ChainStartDepositHashes --
func (m *POWChain) ChainStartDepositHashes() ([][]byte, error) {
return [][]byte{}, nil
}
// ChainStartEth1Data --
func (m *POWChain) ChainStartEth1Data() *ethpb.Eth1Data {
return m.Eth1Data
}

View File

@@ -27,18 +27,17 @@ go_library(
"//beacon-chain/db/kv:go_default_library", "//beacon-chain/db/kv:go_default_library",
"//beacon-chain/operations:go_default_library", "//beacon-chain/operations:go_default_library",
"//beacon-chain/p2p:go_default_library", "//beacon-chain/p2p:go_default_library",
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/sync:go_default_library", "//beacon-chain/sync:go_default_library",
"//proto/beacon/p2p/v1:go_default_library", "//proto/beacon/p2p/v1:go_default_library",
"//proto/beacon/rpc/v1:go_default_library", "//proto/beacon/rpc/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library", "//proto/eth/v1alpha1:go_default_library",
"//shared/bytesutil:go_default_library", "//shared/bytesutil:go_default_library",
"//shared/event:go_default_library", "//shared/hashutil:go_default_library",
"//shared/pagination:go_default_library", "//shared/pagination:go_default_library",
"//shared/params:go_default_library", "//shared/params:go_default_library",
"//shared/trieutil:go_default_library", "//shared/trieutil:go_default_library",
"//shared/version:go_default_library", "//shared/version: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_gogo_protobuf//types:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library",
@@ -78,7 +77,11 @@ go_test(
"//beacon-chain/core/state:go_default_library", "//beacon-chain/core/state:go_default_library",
"//beacon-chain/db:go_default_library", "//beacon-chain/db:go_default_library",
"//beacon-chain/db/testing:go_default_library", "//beacon-chain/db/testing:go_default_library",
"//beacon-chain/operations/testing:go_default_library",
"//beacon-chain/p2p/testing:go_default_library",
"//beacon-chain/powchain/testing:go_default_library",
"//beacon-chain/rpc/testing:go_default_library", "//beacon-chain/rpc/testing:go_default_library",
"//beacon-chain/sync/testing:go_default_library",
"//proto/beacon/p2p/v1:go_default_library", "//proto/beacon/p2p/v1:go_default_library",
"//proto/beacon/rpc/v1:go_default_library", "//proto/beacon/rpc/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library", "//proto/eth/v1alpha1:go_default_library",
@@ -86,11 +89,11 @@ go_test(
"//shared/bytesutil:go_default_library", "//shared/bytesutil:go_default_library",
"//shared/event:go_default_library", "//shared/event:go_default_library",
"//shared/featureconfig:go_default_library", "//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library", "//shared/params:go_default_library",
"//shared/testutil:go_default_library", "//shared/testutil:go_default_library",
"//shared/trieutil:go_default_library", "//shared/trieutil:go_default_library",
"//shared/version:go_default_library", "//shared/version:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library", "@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_gogo_protobuf//types:go_default_library", "@com_github_gogo_protobuf//types:go_default_library",
"@com_github_golang_mock//gomock:go_default_library", "@com_github_golang_mock//gomock:go_default_library",

View File

@@ -5,10 +5,12 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prysmaticlabs/go-ssz" "github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/beacon-chain/cache" "github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/operations"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/beacon-chain/p2p"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
@@ -19,11 +21,12 @@ import (
// AttesterServer defines a server implementation of the gRPC Attester service, // AttesterServer defines a server implementation of the gRPC Attester service,
// providing RPC methods for validators acting as attesters to broadcast votes on beacon blocks. // providing RPC methods for validators acting as attesters to broadcast votes on beacon blocks.
type AttesterServer struct { type AttesterServer struct {
p2p p2p.Broadcaster p2p p2p.Broadcaster
beaconDB db.Database beaconDB db.Database
operationService operationService operationsHandler operations.Handler
chainService chainService attReceiver blockchain.AttestationReceiver
cache *cache.AttestationCache headFetcher blockchain.HeadFetcher
depositCache *cache.AttestationCache
} }
// SubmitAttestation is a function called by an attester in a sharding validator to vote // SubmitAttestation is a function called by an attester in a sharding validator to vote
@@ -34,12 +37,12 @@ func (as *AttesterServer) SubmitAttestation(ctx context.Context, att *ethpb.Atte
return nil, errors.Wrap(err, "failed to sign root attestation") return nil, errors.Wrap(err, "failed to sign root attestation")
} }
if err := as.operationService.HandleAttestation(ctx, att); err != nil { if err := as.operationsHandler.HandleAttestation(ctx, att); err != nil {
return nil, err return nil, err
} }
go func() { go func() {
if err := as.chainService.ReceiveAttestation(ctx, att); err != nil { if err := as.attReceiver.ReceiveAttestation(ctx, att); err != nil {
log.WithError(err).Error("could not receive attestation in chain service") log.WithError(err).Error("could not receive attestation in chain service")
} }
}() }()
@@ -56,7 +59,7 @@ func (as *AttesterServer) RequestAttestation(ctx context.Context, req *pb.Attest
trace.Int64Attribute("slot", int64(req.Slot)), trace.Int64Attribute("slot", int64(req.Slot)),
trace.Int64Attribute("shard", int64(req.Shard)), trace.Int64Attribute("shard", int64(req.Shard)),
) )
res, err := as.cache.Get(ctx, req) res, err := as.depositCache.Get(ctx, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -65,9 +68,9 @@ func (as *AttesterServer) RequestAttestation(ctx context.Context, req *pb.Attest
return res, nil return res, nil
} }
if err := as.cache.MarkInProgress(req); err != nil { if err := as.depositCache.MarkInProgress(req); err != nil {
if err == cache.ErrAlreadyInProgress { if err == cache.ErrAlreadyInProgress {
res, err := as.cache.Get(ctx, req) res, err := as.depositCache.Get(ctx, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -80,13 +83,13 @@ func (as *AttesterServer) RequestAttestation(ctx context.Context, req *pb.Attest
return nil, err return nil, err
} }
defer func() { defer func() {
if err := as.cache.MarkNotInProgress(req); err != nil { if err := as.depositCache.MarkNotInProgress(req); err != nil {
log.WithError(err).Error("Failed to mark cache not in progress") log.WithError(err).Error("Failed to mark cache not in progress")
} }
}() }()
headState := as.chainService.HeadState() headState := as.headFetcher.HeadState()
headRoot := as.chainService.HeadRoot() headRoot := as.headFetcher.HeadRoot()
headState, err = state.ProcessSlots(ctx, headState, req.Slot) headState, err = state.ProcessSlots(ctx, headState, req.Slot)
if err != nil { if err != nil {
@@ -130,7 +133,7 @@ func (as *AttesterServer) RequestAttestation(ctx context.Context, req *pb.Attest
}, },
} }
if err := as.cache.Put(ctx, req, res); err != nil { if err := as.depositCache.Put(ctx, req, res); err != nil {
return nil, err return nil, err
} }

View File

@@ -11,6 +11,8 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/cache" "github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
mockOps "github.com/prysmaticlabs/prysm/beacon-chain/operations/testing"
mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
@@ -18,24 +20,18 @@ import (
"github.com/prysmaticlabs/prysm/shared/params" "github.com/prysmaticlabs/prysm/shared/params"
) )
type mockBroadcaster struct{}
func (m *mockBroadcaster) Broadcast(ctx context.Context, msg proto.Message) error {
return nil
}
func TestSubmitAttestation_OK(t *testing.T) { func TestSubmitAttestation_OK(t *testing.T) {
db := dbutil.SetupDB(t) db := dbutil.SetupDB(t)
defer dbutil.TeardownDB(t, db) defer dbutil.TeardownDB(t, db)
ctx := context.Background() ctx := context.Background()
mockOperationService := &mockOperationService{}
attesterServer := &AttesterServer{ attesterServer := &AttesterServer{
chainService: &mock.ChainService{}, headFetcher: &mock.ChainService{},
operationService: mockOperationService, attReceiver: &mock.ChainService{},
p2p: &mockBroadcaster{}, operationsHandler: &mockOps.Operations{},
beaconDB: db, p2p: &mockp2p.MockBroadcaster{},
cache: cache.NewAttestationCache(), beaconDB: db,
depositCache: cache.NewAttestationCache(),
} }
head := &ethpb.BeaconBlock{ head := &ethpb.BeaconBlock{
Slot: 999, Slot: 999,
@@ -132,9 +128,10 @@ func TestRequestAttestation_OK(t *testing.T) {
beaconState.BlockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:] beaconState.BlockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:]
beaconState.BlockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:] beaconState.BlockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:]
attesterServer := &AttesterServer{ attesterServer := &AttesterServer{
p2p: &mockBroadcaster{}, p2p: &mockp2p.MockBroadcaster{},
cache: cache.NewAttestationCache(), depositCache: cache.NewAttestationCache(),
chainService: &mock.ChainService{State: beaconState, Root: blockRoot[:]}, headFetcher: &mock.ChainService{State: beaconState, Root: blockRoot[:]},
attReceiver: &mock.ChainService{State: beaconState, Root: blockRoot[:]},
} }
req := &pb.AttestationRequest{ req := &pb.AttestationRequest{
@@ -232,9 +229,10 @@ func TestAttestationDataAtSlot_handlesFarAwayJustifiedEpoch(t *testing.T) {
beaconState.BlockRoots[1*params.BeaconConfig().SlotsPerEpoch] = epochBoundaryRoot[:] beaconState.BlockRoots[1*params.BeaconConfig().SlotsPerEpoch] = epochBoundaryRoot[:]
beaconState.BlockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedBlockRoot[:] beaconState.BlockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedBlockRoot[:]
attesterServer := &AttesterServer{ attesterServer := &AttesterServer{
p2p: &mockBroadcaster{}, p2p: &mockp2p.MockBroadcaster{},
cache: cache.NewAttestationCache(), depositCache: cache.NewAttestationCache(),
chainService: &mock.ChainService{State: beaconState, Root: blockRoot[:]}, headFetcher: &mock.ChainService{State: beaconState, Root: blockRoot[:]},
attReceiver: &mock.ChainService{State: beaconState, Root: blockRoot[:]},
} }
req := &pb.AttestationRequest{ req := &pb.AttestationRequest{
@@ -283,7 +281,7 @@ func TestAttestationDataAtSlot_handlesInProgressRequest(t *testing.T) {
ctx := context.Background() ctx := context.Background()
server := &AttesterServer{ server := &AttesterServer{
cache: cache.NewAttestationCache(), depositCache: cache.NewAttestationCache(),
} }
req := &pb.AttestationRequest{ req := &pb.AttestationRequest{
@@ -295,7 +293,7 @@ func TestAttestationDataAtSlot_handlesInProgressRequest(t *testing.T) {
Target: &ethpb.Checkpoint{Epoch: 55}, Target: &ethpb.Checkpoint{Epoch: 55},
} }
if err := server.cache.MarkInProgress(req); err != nil { if err := server.depositCache.MarkInProgress(req); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -317,10 +315,10 @@ func TestAttestationDataAtSlot_handlesInProgressRequest(t *testing.T) {
go func() { go func() {
defer wg.Done() defer wg.Done()
if err := server.cache.Put(ctx, req, res); err != nil { if err := server.depositCache.Put(ctx, req, res); err != nil {
t.Error(err) t.Error(err)
} }
if err := server.cache.MarkNotInProgress(req); err != nil { if err := server.depositCache.MarkNotInProgress(req); err != nil {
t.Error(err) t.Error(err)
} }
}() }()

View File

@@ -24,9 +24,9 @@ import (
// providing RPC endpoints to access data relevant to the Ethereum 2.0 phase 0 // providing RPC endpoints to access data relevant to the Ethereum 2.0 phase 0
// beacon chain. // beacon chain.
type BeaconChainServer struct { type BeaconChainServer struct {
beaconDB db.Database beaconDB db.Database
chainService blockchain.HeadRetriever headFetcher blockchain.HeadFetcher
pool operations.Pool pool operations.Pool
} }
// sortableAttestations implements the Sort interface to sort attestations // sortableAttestations implements the Sort interface to sort attestations
@@ -197,13 +197,13 @@ func (bs *BeaconChainServer) ListBlocks(
// This includes the head block slot and root as well as information about // This includes the head block slot and root as well as information about
// the most recent finalized and justified slots. // the most recent finalized and justified slots.
func (bs *BeaconChainServer) GetChainHead(ctx context.Context, _ *ptypes.Empty) (*ethpb.ChainHead, error) { func (bs *BeaconChainServer) GetChainHead(ctx context.Context, _ *ptypes.Empty) (*ethpb.ChainHead, error) {
finalizedCheckpoint := bs.chainService.HeadState().FinalizedCheckpoint finalizedCheckpoint := bs.headFetcher.HeadState().FinalizedCheckpoint
justifiedCheckpoint := bs.chainService.HeadState().CurrentJustifiedCheckpoint justifiedCheckpoint := bs.headFetcher.HeadState().CurrentJustifiedCheckpoint
prevJustifiedCheckpoint := bs.chainService.HeadState().PreviousJustifiedCheckpoint prevJustifiedCheckpoint := bs.headFetcher.HeadState().PreviousJustifiedCheckpoint
return &ethpb.ChainHead{ return &ethpb.ChainHead{
BlockRoot: bs.chainService.HeadRoot(), BlockRoot: bs.headFetcher.HeadRoot(),
BlockSlot: bs.chainService.HeadSlot(), BlockSlot: bs.headFetcher.HeadSlot(),
FinalizedBlockRoot: finalizedCheckpoint.Root, FinalizedBlockRoot: finalizedCheckpoint.Root,
FinalizedSlot: finalizedCheckpoint.Epoch * params.BeaconConfig().SlotsPerEpoch, FinalizedSlot: finalizedCheckpoint.Epoch * params.BeaconConfig().SlotsPerEpoch,
JustifiedBlockRoot: justifiedCheckpoint.Root, JustifiedBlockRoot: justifiedCheckpoint.Root,
@@ -460,7 +460,7 @@ func (bs *BeaconChainServer) GetValidatorParticipation(
ctx context.Context, req *ethpb.GetValidatorParticipationRequest, ctx context.Context, req *ethpb.GetValidatorParticipationRequest,
) (*ethpb.ValidatorParticipation, error) { ) (*ethpb.ValidatorParticipation, error) {
headState := bs.chainService.HeadState() headState := bs.headFetcher.HeadState()
currentEpoch := helpers.SlotToEpoch(headState.Slot) currentEpoch := helpers.SlotToEpoch(headState.Slot)
finalized := currentEpoch == headState.FinalizedCheckpoint.Epoch finalized := currentEpoch == headState.FinalizedCheckpoint.Epoch

View File

@@ -17,28 +17,12 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/db"
testutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" testutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
mockOps "github.com/prysmaticlabs/prysm/beacon-chain/operations/testing"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params" "github.com/prysmaticlabs/prysm/shared/params"
) )
type mockPool struct{}
func (m *mockPool) AttestationPool(ctx context.Context, expectedSlot uint64) ([]*ethpb.Attestation, error) {
return []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("1"),
},
},
{
Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("2"),
},
},
}, nil
}
func TestBeaconChainServer_ListAttestationsNoPagination(t *testing.T) { func TestBeaconChainServer_ListAttestationsNoPagination(t *testing.T) {
db := testutil.SetupDB(t) db := testutil.SetupDB(t)
defer testutil.TeardownDB(t, db) defer testutil.TeardownDB(t, db)
@@ -259,7 +243,20 @@ func TestBeaconChainServer_AttestationPool(t *testing.T) {
db := testutil.SetupDB(t) db := testutil.SetupDB(t)
defer testutil.TeardownDB(t, db) defer testutil.TeardownDB(t, db)
bs := &BeaconChainServer{ bs := &BeaconChainServer{
pool: &mockPool{}, pool: &mockOps.Operations{
Attestations: []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("1"),
},
},
{
Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("2"),
},
},
},
},
beaconDB: db, beaconDB: db,
} }
block := &ethpb.BeaconBlock{ block := &ethpb.BeaconBlock{
@@ -806,8 +803,8 @@ func TestBeaconChainServer_GetValidatorsParticipation(t *testing.T) {
} }
bs := &BeaconChainServer{ bs := &BeaconChainServer{
beaconDB: db, beaconDB: db,
chainService: &mock.ChainService{State: s}, headFetcher: &mock.ChainService{State: s},
} }
res, err := bs.GetValidatorParticipation(ctx, &ethpb.GetValidatorParticipationRequest{Epoch: epoch}) res, err := bs.GetValidatorParticipation(ctx, &ethpb.GetValidatorParticipationRequest{Epoch: epoch})
@@ -1000,7 +997,7 @@ func TestBeaconChainServer_GetChainHead(t *testing.T) {
FinalizedCheckpoint: &ethpb.Checkpoint{Epoch: 1, Root: []byte{'C'}}, FinalizedCheckpoint: &ethpb.Checkpoint{Epoch: 1, Root: []byte{'C'}},
} }
bs := &BeaconChainServer{chainService: &mock.ChainService{State: s}} bs := &BeaconChainServer{headFetcher: &mock.ChainService{State: s}}
head, err := bs.GetChainHead(context.Background(), nil) head, err := bs.GetChainHead(context.Background(), nil)
if err != nil { if err != nil {

View File

@@ -8,6 +8,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
@@ -22,9 +23,10 @@ import (
type BeaconServer struct { type BeaconServer struct {
beaconDB db.Database beaconDB db.Database
ctx context.Context ctx context.Context
powChainService powChainService chainStartFetcher powchain.ChainStartFetcher
chainService chainService eth1InfoFetcher powchain.ChainInfoFetcher
operationService operationService headFetcher blockchain.HeadFetcher
stateFeedListener blockchain.ChainFeeds
incomingAttestation chan *ethpb.Attestation incomingAttestation chan *ethpb.Attestation
canonicalStateChan chan *pbp2p.BeaconState canonicalStateChan chan *pbp2p.BeaconState
chainStartChan chan time.Time chainStartChan chan time.Time
@@ -35,11 +37,9 @@ type BeaconServer struct {
// subscribes to an event stream triggered by the powchain service whenever the ChainStart log does // subscribes to an event stream triggered by the powchain service whenever the ChainStart log does
// occur in the Deposit Contract on ETH 1.0. // occur in the Deposit Contract on ETH 1.0.
func (bs *BeaconServer) WaitForChainStart(req *ptypes.Empty, stream pb.BeaconService_WaitForChainStartServer) error { func (bs *BeaconServer) WaitForChainStart(req *ptypes.Empty, stream pb.BeaconService_WaitForChainStartServer) error {
ok := bs.powChainService.HasChainStarted() ok := bs.chainStartFetcher.HasChainStarted()
if ok { if ok {
genesisTime, _ := bs.powChainService.ETH2GenesisTime() genesisTime, _ := bs.eth1InfoFetcher.Eth2GenesisPowchainInfo()
res := &pb.ChainStartResponse{ res := &pb.ChainStartResponse{
Started: true, Started: true,
GenesisTime: genesisTime, GenesisTime: genesisTime,
@@ -47,7 +47,7 @@ func (bs *BeaconServer) WaitForChainStart(req *ptypes.Empty, stream pb.BeaconSer
return stream.Send(res) return stream.Send(res)
} }
sub := bs.chainService.StateInitializedFeed().Subscribe(bs.chainStartChan) sub := bs.stateFeedListener.StateInitializedFeed().Subscribe(bs.chainStartChan)
defer sub.Unsubscribe() defer sub.Unsubscribe()
for { for {
select { select {
@@ -69,8 +69,7 @@ func (bs *BeaconServer) WaitForChainStart(req *ptypes.Empty, stream pb.BeaconSer
// CanonicalHead of the current beacon chain. This method is requested on-demand // CanonicalHead of the current beacon chain. This method is requested on-demand
// by a validator when it is their time to propose or attest. // 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) { func (bs *BeaconServer) CanonicalHead(ctx context.Context, req *ptypes.Empty) (*ethpb.BeaconBlock, error) {
headBlock := bs.chainService.(blockchain.HeadRetriever).HeadBlock() return bs.headFetcher.HeadBlock(), nil
return headBlock, nil
} }
// BlockTree returns the current tree of saved blocks and their votes starting from the justified state. // BlockTree returns the current tree of saved blocks and their votes starting from the justified state.

View File

@@ -2,186 +2,37 @@ package rpc
import ( import (
"context" "context"
"errors"
"fmt"
"math/big"
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/common"
ptypes "github.com/gogo/protobuf/types" ptypes "github.com/gogo/protobuf/types"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
mockClient "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
mockRPC "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testing" mockRPC "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testing"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/event" "github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/testutil" "github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/trieutil"
logTest "github.com/sirupsen/logrus/hooks/test" logTest "github.com/sirupsen/logrus/hooks/test"
) )
var closedContext = "context closed"
var mockSig [96]byte
var mockCreds [32]byte
type faultyPOWChainService struct {
chainStartFeed *event.Feed
hashesByHeight map[int][]byte
}
func (f *faultyPOWChainService) HasChainStarted() bool {
return false
}
func (f *faultyPOWChainService) ETH2GenesisTime() (uint64, *big.Int) {
return 0, big.NewInt(0)
}
func (f *faultyPOWChainService) ChainStartFeed() *event.Feed {
return f.chainStartFeed
}
func (f *faultyPOWChainService) LatestBlockHeight() *big.Int {
return big.NewInt(0)
}
func (f *faultyPOWChainService) BlockExists(_ context.Context, hash common.Hash) (bool, *big.Int, error) {
if f.hashesByHeight == nil {
return false, big.NewInt(1), errors.New("failed")
}
return true, big.NewInt(1), nil
}
func (f *faultyPOWChainService) BlockHashByHeight(_ context.Context, height *big.Int) (common.Hash, error) {
return [32]byte{}, errors.New("failed")
}
func (f *faultyPOWChainService) BlockTimeByHeight(_ context.Context, height *big.Int) (uint64, error) {
return 0, errors.New("failed")
}
func (f *faultyPOWChainService) BlockNumberByTimestamp(_ context.Context, _ uint64) (*big.Int, error) {
return big.NewInt(0), nil
}
func (f *faultyPOWChainService) DepositRoot() [32]byte {
return [32]byte{}
}
func (f *faultyPOWChainService) DepositTrie() *trieutil.MerkleTrie {
return &trieutil.MerkleTrie{}
}
func (f *faultyPOWChainService) ChainStartDeposits() []*ethpb.Deposit {
return []*ethpb.Deposit{}
}
func (f *faultyPOWChainService) ChainStartDepositHashes() ([][]byte, error) {
return [][]byte{}, errors.New("hashing failed")
}
func (f *faultyPOWChainService) ChainStartETH1Data() *ethpb.Eth1Data {
return &ethpb.Eth1Data{}
}
type mockPOWChainService struct {
chainStartFeed *event.Feed
latestBlockNumber *big.Int
hashesByHeight map[int][]byte
blockTimeByHeight map[int]uint64
blockNumberByHeight map[uint64]*big.Int
eth1Data *ethpb.Eth1Data
genesisEth1Block *big.Int
}
func (m *mockPOWChainService) HasChainStarted() bool {
return true
}
func (m *mockPOWChainService) ETH2GenesisTime() (uint64, *big.Int) {
blk := m.genesisEth1Block
if blk == nil {
blk = big.NewInt(0)
}
return uint64(time.Unix(0, 0).Unix()), blk
}
func (m *mockPOWChainService) ChainStartFeed() *event.Feed {
return m.chainStartFeed
}
func (m *mockPOWChainService) LatestBlockHeight() *big.Int {
return m.latestBlockNumber
}
func (m *mockPOWChainService) DepositTrie() *trieutil.MerkleTrie {
return &trieutil.MerkleTrie{}
}
func (m *mockPOWChainService) BlockExists(_ context.Context, hash common.Hash) (bool, *big.Int, error) {
// Reverse the map of heights by hash.
heightsByHash := make(map[[32]byte]int)
for k, v := range m.hashesByHeight {
h := bytesutil.ToBytes32(v)
heightsByHash[h] = k
}
val, ok := heightsByHash[hash]
if !ok {
return false, nil, fmt.Errorf("could not fetch height for hash: %#x", hash)
}
return true, big.NewInt(int64(val)), nil
}
func (m *mockPOWChainService) BlockHashByHeight(_ context.Context, height *big.Int) (common.Hash, error) {
k := int(height.Int64())
val, ok := m.hashesByHeight[k]
if !ok {
return [32]byte{}, fmt.Errorf("could not fetch hash for height: %v", height)
}
return bytesutil.ToBytes32(val), nil
}
func (m *mockPOWChainService) BlockTimeByHeight(_ context.Context, height *big.Int) (uint64, error) {
h := int(height.Int64())
return m.blockTimeByHeight[h], nil
}
func (m *mockPOWChainService) BlockNumberByTimestamp(_ context.Context, time uint64) (*big.Int, error) {
return m.blockNumberByHeight[time], nil
}
func (m *mockPOWChainService) DepositRoot() [32]byte {
root := []byte("depositroot")
return bytesutil.ToBytes32(root)
}
func (m *mockPOWChainService) ChainStartDeposits() []*ethpb.Deposit {
return []*ethpb.Deposit{}
}
func (m *mockPOWChainService) ChainStartDepositHashes() ([][]byte, error) {
return [][]byte{}, nil
}
func (m *mockPOWChainService) ChainStartETH1Data() *ethpb.Eth1Data {
return m.eth1Data
}
func TestWaitForChainStart_ContextClosed(t *testing.T) { func TestWaitForChainStart_ContextClosed(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
beaconServer := &BeaconServer{ beaconServer := &BeaconServer{
ctx: ctx, ctx: ctx,
powChainService: &faultyPOWChainService{ chainStartFetcher: &mockPOW.FaultyMockPOWChain{
chainStartFeed: new(event.Feed), ChainFeed: new(event.Feed),
}, },
chainService: &mockClient.ChainService{}, eth1InfoFetcher: &mockPOW.POWChain{},
stateFeedListener: &mockChain.ChainService{},
} }
exitRoutine := make(chan bool) exitRoutine := make(chan bool)
ctrl := gomock.NewController(t) ctrl := gomock.NewController(t)
defer ctrl.Finish() defer ctrl.Finish()
mockStream := mockRPC.NewMockBeaconService_WaitForChainStartServer(ctrl) mockStream := mockRPC.NewMockBeaconService_WaitForChainStartServer(ctrl)
go func(tt *testing.T) { go func(tt *testing.T) {
if err := beaconServer.WaitForChainStart(&ptypes.Empty{}, mockStream); !strings.Contains(err.Error(), closedContext) { if err := beaconServer.WaitForChainStart(&ptypes.Empty{}, mockStream); !strings.Contains(err.Error(), "context closed") {
tt.Errorf("Could not call RPC method: %v", err) tt.Errorf("Could not call RPC method: %v", err)
} }
<-exitRoutine <-exitRoutine
@@ -193,10 +44,11 @@ func TestWaitForChainStart_ContextClosed(t *testing.T) {
func TestWaitForChainStart_AlreadyStarted(t *testing.T) { func TestWaitForChainStart_AlreadyStarted(t *testing.T) {
beaconServer := &BeaconServer{ beaconServer := &BeaconServer{
ctx: context.Background(), ctx: context.Background(),
powChainService: &mockPOWChainService{ chainStartFetcher: &mockPOW.POWChain{
chainStartFeed: new(event.Feed), ChainFeed: new(event.Feed),
}, },
chainService: &mockClient.ChainService{}, eth1InfoFetcher: &mockPOW.POWChain{},
stateFeedListener: &mockChain.ChainService{},
} }
ctrl := gomock.NewController(t) ctrl := gomock.NewController(t)
defer ctrl.Finish() defer ctrl.Finish()
@@ -217,10 +69,11 @@ func TestWaitForChainStart_NotStartedThenLogFired(t *testing.T) {
beaconServer := &BeaconServer{ beaconServer := &BeaconServer{
ctx: context.Background(), ctx: context.Background(),
chainStartChan: make(chan time.Time, 1), chainStartChan: make(chan time.Time, 1),
powChainService: &faultyPOWChainService{ chainStartFetcher: &mockPOW.FaultyMockPOWChain{
chainStartFeed: new(event.Feed), ChainFeed: new(event.Feed),
}, },
chainService: &mockClient.ChainService{}, eth1InfoFetcher: &mockPOW.POWChain{},
stateFeedListener: &mockChain.ChainService{},
} }
exitRoutine := make(chan bool) exitRoutine := make(chan bool)
ctrl := gomock.NewController(t) ctrl := gomock.NewController(t)

View File

@@ -7,15 +7,19 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prysmaticlabs/go-ssz" "github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/operations"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params" "github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/trieutil" "github.com/prysmaticlabs/prysm/shared/trieutil"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@@ -27,9 +31,13 @@ import (
// beacon blocks to a beacon node, and more. // beacon blocks to a beacon node, and more.
type ProposerServer struct { type ProposerServer struct {
beaconDB db.Database beaconDB db.Database
chainService chainService headFetcher blockchain.HeadFetcher
powChainService powChainService blockReceiver blockchain.BlockReceiver
operationService operationService mockEth1Votes bool
chainStartFetcher powchain.ChainStartFetcher
eth1InfoFetcher powchain.ChainInfoFetcher
eth1BlockFetcher powchain.POWBlockFetcher
pool operations.Pool
canonicalStateChan chan *pbp2p.BeaconState canonicalStateChan chan *pbp2p.BeaconState
depositCache *depositcache.DepositCache depositCache *depositcache.DepositCache
} }
@@ -42,15 +50,13 @@ func (ps *ProposerServer) RequestBlock(ctx context.Context, req *pb.BlockRequest
span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot))) span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot)))
// Retrieve the parent block as the current head of the canonical chain // Retrieve the parent block as the current head of the canonical chain
parent := ps.chainService.HeadBlock() parent := ps.headFetcher.HeadBlock()
parentRoot, err := ssz.SigningRoot(parent) parentRoot, err := ssz.SigningRoot(parent)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get parent block signing root") return nil, errors.Wrap(err, "could not get parent block signing root")
} }
// Construct block body
// Pack ETH1 deposits which have not been included in the beacon chain
eth1Data, err := ps.eth1Data(ctx, req.Slot) eth1Data, err := ps.eth1Data(ctx, req.Slot)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get ETH1 data") return nil, errors.Wrap(err, "could not get ETH1 data")
@@ -114,8 +120,7 @@ func (ps *ProposerServer) ProposeBlock(ctx context.Context, blk *ethpb.BeaconBlo
} }
log.WithField("blockRoot", fmt.Sprintf("%#x", bytesutil.Trunc(root[:]))).Debugf( log.WithField("blockRoot", fmt.Sprintf("%#x", bytesutil.Trunc(root[:]))).Debugf(
"Block proposal received via RPC") "Block proposal received via RPC")
if err := ps.blockReceiver.ReceiveBlock(ctx, blk); err != nil {
if err := ps.chainService.ReceiveBlock(ctx, blk); err != nil {
return nil, errors.Wrap(err, "could not process beacon block") return nil, errors.Wrap(err, "could not process beacon block")
} }
@@ -128,15 +133,15 @@ func (ps *ProposerServer) ProposeBlock(ctx context.Context, blk *ethpb.BeaconBlo
// attestations which are ready for inclusion. That is, attestations that satisfy: // attestations which are ready for inclusion. That is, attestations that satisfy:
// attestation.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot. // attestation.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot.
func (ps *ProposerServer) attestations(ctx context.Context, expectedSlot uint64) ([]*ethpb.Attestation, error) { func (ps *ProposerServer) attestations(ctx context.Context, expectedSlot uint64) ([]*ethpb.Attestation, error) {
headState := ps.chainService.HeadState() beaconState := ps.headFetcher.HeadState()
atts, err := ps.operationService.AttestationPool(ctx, expectedSlot) atts, err := ps.pool.AttestationPool(ctx, expectedSlot)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not retrieve pending attestations from operations service") return nil, errors.Wrap(err, "could not retrieve pending attestations from operations service")
} }
// advance slot, if it is behind // advance slot, if it is behind
if headState.Slot < expectedSlot { if beaconState.Slot < expectedSlot {
headState, err = state.ProcessSlots(ctx, headState, expectedSlot) beaconState, err = state.ProcessSlots(ctx, beaconState, expectedSlot)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -144,24 +149,24 @@ func (ps *ProposerServer) attestations(ctx context.Context, expectedSlot uint64)
var attsReadyForInclusion []*ethpb.Attestation var attsReadyForInclusion []*ethpb.Attestation
for _, att := range atts { for _, att := range atts {
slot, err := helpers.AttestationDataSlot(headState, att.Data) slot, err := helpers.AttestationDataSlot(beaconState, att.Data)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get attestation slot") return nil, errors.Wrap(err, "could not get attestation slot")
} }
if slot+params.BeaconConfig().MinAttestationInclusionDelay <= headState.Slot && if slot+params.BeaconConfig().MinAttestationInclusionDelay <= beaconState.Slot &&
headState.Slot <= slot+params.BeaconConfig().SlotsPerEpoch { beaconState.Slot <= slot+params.BeaconConfig().SlotsPerEpoch {
attsReadyForInclusion = append(attsReadyForInclusion, att) attsReadyForInclusion = append(attsReadyForInclusion, att)
} }
} }
validAtts := make([]*ethpb.Attestation, 0, len(attsReadyForInclusion)) validAtts := make([]*ethpb.Attestation, 0, len(attsReadyForInclusion))
for _, att := range attsReadyForInclusion { for _, att := range attsReadyForInclusion {
slot, err := helpers.AttestationDataSlot(headState, att.Data) slot, err := helpers.AttestationDataSlot(beaconState, att.Data)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get attestation slot") return nil, errors.Wrap(err, "could not get attestation slot")
} }
if _, err := blocks.ProcessAttestationNoVerify(headState, att); err != nil { if _, err := blocks.ProcessAttestationNoVerify(beaconState, att); err != nil {
if ctx.Err() != nil { if ctx.Err() != nil {
return nil, ctx.Err() return nil, ctx.Err()
} }
@@ -175,7 +180,6 @@ func (ps *ProposerServer) attestations(ctx context.Context, expectedSlot uint64)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := ps.beaconDB.DeleteAttestation(ctx, root); err != nil { if err := ps.beaconDB.DeleteAttestation(ctx, root); err != nil {
return nil, errors.Wrap(err, "could not delete failed attestation") return nil, errors.Wrap(err, "could not delete failed attestation")
} }
@@ -194,11 +198,39 @@ func (ps *ProposerServer) attestations(ctx context.Context, expectedSlot uint64)
// - Subtract that eth1block.number by ETH1_FOLLOW_DISTANCE. // - Subtract that eth1block.number by ETH1_FOLLOW_DISTANCE.
// - This is the eth1block to use for the block proposal. // - This is the eth1block to use for the block proposal.
func (ps *ProposerServer) eth1Data(ctx context.Context, slot uint64) (*ethpb.Eth1Data, error) { func (ps *ProposerServer) eth1Data(ctx context.Context, slot uint64) (*ethpb.Eth1Data, error) {
eth1VotingPeriodStartTime, _ := ps.powChainService.ETH2GenesisTime() if ps.mockEth1Votes {
// If a mock eth1 data votes is specified, we use the following for the
// eth1data we provide to every proposer based on https://github.com/ethereum/eth2.0-pm/issues/62:
//
// slot_in_voting_period = current_slot % SLOTS_PER_ETH1_VOTING_PERIOD
// Eth1Data(
// DepositRoot = hash(current_epoch + slot_in_voting_period),
// DepositCount = state.eth1_deposit_index,
// BlockHash = hash(hash(current_epoch + slot_in_voting_period)),
// )
slotInVotingPeriod := slot % params.BeaconConfig().SlotsPerEth1VotingPeriod
headState, err := ps.beaconDB.HeadState(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not get head state")
}
enc, err := ssz.Marshal(helpers.SlotToEpoch(slot) + slotInVotingPeriod)
if err != nil {
return nil, err
}
depRoot := hashutil.Hash(enc)
blockHash := hashutil.Hash(depRoot[:])
return &ethpb.Eth1Data{
DepositRoot: depRoot[:],
DepositCount: headState.Eth1DepositIndex,
BlockHash: blockHash[:],
}, nil
}
eth1VotingPeriodStartTime, _ := ps.eth1InfoFetcher.Eth2GenesisPowchainInfo()
eth1VotingPeriodStartTime += (slot - (slot % params.BeaconConfig().SlotsPerEth1VotingPeriod)) * params.BeaconConfig().SecondsPerSlot eth1VotingPeriodStartTime += (slot - (slot % params.BeaconConfig().SlotsPerEth1VotingPeriod)) * params.BeaconConfig().SecondsPerSlot
// Look up most recent block up to timestamp // Look up most recent block up to timestamp
blockNumber, err := ps.powChainService.BlockNumberByTimestamp(ctx, eth1VotingPeriodStartTime) blockNumber, err := ps.eth1BlockFetcher.BlockNumberByTimestamp(ctx, eth1VotingPeriodStartTime)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -239,14 +271,13 @@ func (ps *ProposerServer) computeStateRoot(ctx context.Context, block *ethpb.Bea
func (ps *ProposerServer) deposits(ctx context.Context, currentVote *ethpb.Eth1Data) ([]*ethpb.Deposit, error) { func (ps *ProposerServer) deposits(ctx context.Context, currentVote *ethpb.Eth1Data) ([]*ethpb.Deposit, error) {
// Need to fetch if the deposits up to the state's latest eth 1 data matches // Need to fetch if the deposits up to the state's latest eth 1 data matches
// the number of all deposits in this RPC call. If not, then we return nil. // the number of all deposits in this RPC call. If not, then we return nil.
headState := ps.chainService.HeadState() beaconState := ps.headFetcher.HeadState()
canonicalEth1Data, latestEth1DataHeight, err := ps.canonicalEth1Data(ctx, beaconState, currentVote)
canonicalEth1Data, latestEth1DataHeight, err := ps.canonicalEth1Data(ctx, headState, currentVote)
if err != nil { if err != nil {
return nil, err return nil, err
} }
_, genesisEth1Block := ps.powChainService.ETH2GenesisTime() _, genesisEth1Block := ps.eth1InfoFetcher.Eth2GenesisPowchainInfo()
if genesisEth1Block.Cmp(latestEth1DataHeight) == 0 { if genesisEth1Block.Cmp(latestEth1DataHeight) == 0 {
return []*ethpb.Deposit{}, nil return []*ethpb.Deposit{}, nil
} }
@@ -272,7 +303,7 @@ func (ps *ProposerServer) deposits(ctx context.Context, currentVote *ethpb.Eth1D
// deposits are sorted from lowest to highest. // deposits are sorted from lowest to highest.
var pendingDeps []*depositcache.DepositContainer var pendingDeps []*depositcache.DepositContainer
for _, dep := range allPendingContainers { for _, dep := range allPendingContainers {
if uint64(dep.Index) >= headState.Eth1DepositIndex && uint64(dep.Index) < canonicalEth1Data.DepositCount { if uint64(dep.Index) >= beaconState.Eth1DepositIndex && uint64(dep.Index) < canonicalEth1Data.DepositCount {
pendingDeps = append(pendingDeps, dep) pendingDeps = append(pendingDeps, dep)
} }
} }
@@ -313,7 +344,7 @@ func (ps *ProposerServer) canonicalEth1Data(ctx context.Context, beaconState *pb
canonicalEth1Data = beaconState.Eth1Data canonicalEth1Data = beaconState.Eth1Data
eth1BlockHash = bytesutil.ToBytes32(beaconState.Eth1Data.BlockHash) eth1BlockHash = bytesutil.ToBytes32(beaconState.Eth1Data.BlockHash)
} }
_, latestEth1DataHeight, err := ps.powChainService.BlockExists(ctx, eth1BlockHash) _, latestEth1DataHeight, err := ps.eth1BlockFetcher.BlockExists(ctx, eth1BlockHash)
if err != nil { if err != nil {
return nil, nil, errors.Wrap(err, "could not fetch eth1data height") return nil, nil, errors.Wrap(err, "could not fetch eth1data height")
} }
@@ -327,14 +358,14 @@ func (ps *ProposerServer) canonicalEth1Data(ctx context.Context, beaconState *pb
func (ps *ProposerServer) defaultEth1DataResponse(ctx context.Context, currentHeight *big.Int) (*ethpb.Eth1Data, error) { func (ps *ProposerServer) defaultEth1DataResponse(ctx context.Context, currentHeight *big.Int) (*ethpb.Eth1Data, error) {
eth1FollowDistance := int64(params.BeaconConfig().Eth1FollowDistance) eth1FollowDistance := int64(params.BeaconConfig().Eth1FollowDistance)
ancestorHeight := big.NewInt(0).Sub(currentHeight, big.NewInt(eth1FollowDistance)) ancestorHeight := big.NewInt(0).Sub(currentHeight, big.NewInt(eth1FollowDistance))
blockHash, err := ps.powChainService.BlockHashByHeight(ctx, ancestorHeight) blockHash, err := ps.eth1BlockFetcher.BlockHashByHeight(ctx, ancestorHeight)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not fetch ETH1_FOLLOW_DISTANCE ancestor") return nil, errors.Wrap(err, "could not fetch ETH1_FOLLOW_DISTANCE ancestor")
} }
// Fetch all historical deposits up to an ancestor height. // Fetch all historical deposits up to an ancestor height.
depositsTillHeight, depositRoot := ps.depositCache.DepositsNumberAndRootAtHeight(ctx, ancestorHeight) depositsTillHeight, depositRoot := ps.depositCache.DepositsNumberAndRootAtHeight(ctx, ancestorHeight)
if depositsTillHeight == 0 { if depositsTillHeight == 0 {
return ps.powChainService.ChainStartETH1Data(), nil return ps.chainStartFetcher.ChainStartEth1Data(), nil
} }
return &ethpb.Eth1Data{ return &ethpb.Eth1Data{
DepositRoot: depositRoot[:], DepositRoot: depositRoot[:],

View File

@@ -17,9 +17,12 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
mockOps "github.com/prysmaticlabs/prysm/beacon-chain/operations/testing"
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls" "github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params" "github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil" "github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/trieutil" "github.com/prysmaticlabs/prysm/shared/trieutil"
@@ -60,9 +63,12 @@ func TestProposeBlock_OK(t *testing.T) {
} }
proposerServer := &ProposerServer{ proposerServer := &ProposerServer{
beaconDB: db, beaconDB: db,
powChainService: &mockPOWChainService{}, chainStartFetcher: &mockPOW.POWChain{},
chainService: &mock.ChainService{}, eth1InfoFetcher: &mockPOW.POWChain{},
eth1BlockFetcher: &mockPOW.POWChain{},
blockReceiver: &mock.ChainService{},
headFetcher: &mock.ChainService{},
} }
req := &ethpb.BeaconBlock{ req := &ethpb.BeaconBlock{
Slot: 5, Slot: 5,
@@ -113,8 +119,10 @@ func TestComputeStateRoot_OK(t *testing.T) {
} }
proposerServer := &ProposerServer{ proposerServer := &ProposerServer{
beaconDB: db, beaconDB: db,
powChainService: &mockPOWChainService{}, chainStartFetcher: &mockPOW.POWChain{},
eth1InfoFetcher: &mockPOW.POWChain{},
eth1BlockFetcher: &mockPOW.POWChain{},
} }
req := &ethpb.BeaconBlock{ req := &ethpb.BeaconBlock{
@@ -256,10 +264,11 @@ func TestPendingAttestations_FiltersWithinInclusionDelay(t *testing.T) {
} }
proposerServer := &ProposerServer{ proposerServer := &ProposerServer{
operationService: &mockOperationService{ pool: &mockOps.Operations{
pendingAttestations: []*ethpb.Attestation{att}, Attestations: []*ethpb.Attestation{att},
}, },
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
} }
atts, err := proposerServer.attestations(context.Background(), stateSlot) atts, err := proposerServer.attestations(context.Background(), stateSlot)
@@ -375,8 +384,8 @@ func TestPendingAttestations_FiltersExpiredAttestations(t *testing.T) {
att2 := proto.Clone(att).(*ethpb.Attestation) att2 := proto.Clone(att).(*ethpb.Attestation)
att3 := proto.Clone(att).(*ethpb.Attestation) att3 := proto.Clone(att).(*ethpb.Attestation)
opService := &mockOperationService{ opService := &mockOps.Operations{
pendingAttestations: []*ethpb.Attestation{ Attestations: []*ethpb.Attestation{
//Expired attestations //Expired attestations
{ {
Data: &ethpb.AttestationData{ Data: &ethpb.AttestationData{
@@ -448,9 +457,10 @@ func TestPendingAttestations_FiltersExpiredAttestations(t *testing.T) {
expectedNumberOfAttestations := 3 expectedNumberOfAttestations := 3
proposerServer := &ProposerServer{ proposerServer := &ProposerServer{
beaconDB: db, beaconDB: db,
operationService: opService, pool: opService,
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
} }
atts, err := proposerServer.attestations(context.Background(), currentSlot+params.BeaconConfig().MinAttestationInclusionDelay+1) atts, err := proposerServer.attestations(context.Background(), currentSlot+params.BeaconConfig().MinAttestationInclusionDelay+1)
@@ -507,9 +517,9 @@ func TestPendingDeposits_Eth1DataVoteOK(t *testing.T) {
height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)) height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance))
newHeight := big.NewInt(height.Int64() + 11000) newHeight := big.NewInt(height.Int64() + 11000)
p := &mockPOWChainService{ p := &mockPOW.POWChain{
latestBlockNumber: height, LatestBlockNumber: height,
hashesByHeight: map[int][]byte{ HashesByHeight: map[int][]byte{
int(height.Int64()): []byte("0x0"), int(height.Int64()): []byte("0x0"),
int(newHeight.Int64()): []byte("0x1"), int(newHeight.Int64()): []byte("0x1"),
}, },
@@ -544,12 +554,15 @@ func TestPendingDeposits_Eth1DataVoteOK(t *testing.T) {
} }
bs := &ProposerServer{ bs := &ProposerServer{
powChainService: p, chainStartFetcher: p,
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, eth1InfoFetcher: p,
eth1BlockFetcher: p,
blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
} }
// It should also return the recent deposits after their follow window. // It should also return the recent deposits after their follow window.
p.latestBlockNumber = big.NewInt(0).Add(p.latestBlockNumber, big.NewInt(10000)) p.LatestBlockNumber = big.NewInt(0).Add(p.LatestBlockNumber, big.NewInt(10000))
_, eth1Height, err := bs.canonicalEth1Data(ctx, beaconState, &ethpb.Eth1Data{}) _, eth1Height, err := bs.canonicalEth1Data(ctx, beaconState, &ethpb.Eth1Data{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -596,9 +609,9 @@ func TestPendingDeposits_OutsideEth1FollowWindow(t *testing.T) {
ctx := context.Background() ctx := context.Background()
height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)) height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance))
p := &mockPOWChainService{ p := &mockPOW.POWChain{
latestBlockNumber: height, LatestBlockNumber: height,
hashesByHeight: map[int][]byte{ HashesByHeight: map[int][]byte{
int(height.Int64()): []byte("0x0"), int(height.Int64()): []byte("0x0"),
}, },
} }
@@ -690,9 +703,12 @@ func TestPendingDeposits_OutsideEth1FollowWindow(t *testing.T) {
} }
bs := &ProposerServer{ bs := &ProposerServer{
powChainService: p, chainStartFetcher: p,
depositCache: depositCache, eth1InfoFetcher: p,
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, eth1BlockFetcher: p,
depositCache: depositCache,
blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
} }
deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{}) deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{})
@@ -705,7 +721,7 @@ func TestPendingDeposits_OutsideEth1FollowWindow(t *testing.T) {
// It should not return the recent deposits after their follow window. // It should not return the recent deposits after their follow window.
// as latest block number makes no difference in retrieval of deposits // as latest block number makes no difference in retrieval of deposits
p.latestBlockNumber = big.NewInt(0).Add(p.latestBlockNumber, big.NewInt(10000)) p.LatestBlockNumber = big.NewInt(0).Add(p.LatestBlockNumber, big.NewInt(10000))
deposits, err = bs.deposits(ctx, &ethpb.Eth1Data{}) deposits, err = bs.deposits(ctx, &ethpb.Eth1Data{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -724,9 +740,9 @@ func TestPendingDeposits_FollowsCorrectEth1Block(t *testing.T) {
height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)) height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance))
newHeight := big.NewInt(height.Int64() + 11000) newHeight := big.NewInt(height.Int64() + 11000)
p := &mockPOWChainService{ p := &mockPOW.POWChain{
latestBlockNumber: height, LatestBlockNumber: height,
hashesByHeight: map[int][]byte{ HashesByHeight: map[int][]byte{
int(height.Int64()): []byte("0x0"), int(height.Int64()): []byte("0x0"),
int(newHeight.Int64()): []byte("0x1"), int(newHeight.Int64()): []byte("0x1"),
}, },
@@ -830,9 +846,12 @@ func TestPendingDeposits_FollowsCorrectEth1Block(t *testing.T) {
} }
bs := &ProposerServer{ bs := &ProposerServer{
powChainService: p, chainStartFetcher: p,
depositCache: depositCache, eth1InfoFetcher: p,
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, eth1BlockFetcher: p,
depositCache: depositCache,
blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
} }
deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{}) deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{})
@@ -844,7 +863,7 @@ func TestPendingDeposits_FollowsCorrectEth1Block(t *testing.T) {
} }
// It should also return the recent deposits after their follow window. // It should also return the recent deposits after their follow window.
p.latestBlockNumber = big.NewInt(0).Add(p.latestBlockNumber, big.NewInt(10000)) p.LatestBlockNumber = big.NewInt(0).Add(p.LatestBlockNumber, big.NewInt(10000))
// we should get our pending deposits once this vote pushes the vote tally to include // we should get our pending deposits once this vote pushes the vote tally to include
// the updated eth1 data. // the updated eth1 data.
deposits, err = bs.deposits(ctx, vote) deposits, err = bs.deposits(ctx, vote)
@@ -863,9 +882,9 @@ func TestPendingDeposits_FollowsCorrectEth1Block(t *testing.T) {
func TestPendingDeposits_CantReturnBelowStateEth1DepositIndex(t *testing.T) { func TestPendingDeposits_CantReturnBelowStateEth1DepositIndex(t *testing.T) {
ctx := context.Background() ctx := context.Background()
height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)) height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance))
p := &mockPOWChainService{ p := &mockPOW.POWChain{
latestBlockNumber: height, LatestBlockNumber: height,
hashesByHeight: map[int][]byte{ HashesByHeight: map[int][]byte{
int(height.Int64()): []byte("0x0"), int(height.Int64()): []byte("0x0"),
}, },
} }
@@ -943,13 +962,16 @@ func TestPendingDeposits_CantReturnBelowStateEth1DepositIndex(t *testing.T) {
} }
bs := &ProposerServer{ bs := &ProposerServer{
powChainService: p, chainStartFetcher: p,
depositCache: depositCache, eth1InfoFetcher: p,
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, eth1BlockFetcher: p,
depositCache: depositCache,
blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
} }
// It should also return the recent deposits after their follow window. // It should also return the recent deposits after their follow window.
p.latestBlockNumber = big.NewInt(0).Add(p.latestBlockNumber, big.NewInt(10000)) p.LatestBlockNumber = big.NewInt(0).Add(p.LatestBlockNumber, big.NewInt(10000))
deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{}) deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -969,9 +991,9 @@ func TestPendingDeposits_CantReturnMoreThanMax(t *testing.T) {
ctx := context.Background() ctx := context.Background()
height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)) height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance))
p := &mockPOWChainService{ p := &mockPOW.POWChain{
latestBlockNumber: height, LatestBlockNumber: height,
hashesByHeight: map[int][]byte{ HashesByHeight: map[int][]byte{
int(height.Int64()): []byte("0x0"), int(height.Int64()): []byte("0x0"),
}, },
} }
@@ -1048,13 +1070,16 @@ func TestPendingDeposits_CantReturnMoreThanMax(t *testing.T) {
} }
bs := &ProposerServer{ bs := &ProposerServer{
powChainService: p, chainStartFetcher: p,
depositCache: depositCache, eth1InfoFetcher: p,
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, eth1BlockFetcher: p,
depositCache: depositCache,
blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
} }
// It should also return the recent deposits after their follow window. // It should also return the recent deposits after their follow window.
p.latestBlockNumber = big.NewInt(0).Add(p.latestBlockNumber, big.NewInt(10000)) p.LatestBlockNumber = big.NewInt(0).Add(p.LatestBlockNumber, big.NewInt(10000))
deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{}) deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -1072,9 +1097,9 @@ func TestPendingDeposits_CantReturnMoreDepositCount(t *testing.T) {
ctx := context.Background() ctx := context.Background()
height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)) height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance))
p := &mockPOWChainService{ p := &mockPOW.POWChain{
latestBlockNumber: height, LatestBlockNumber: height,
hashesByHeight: map[int][]byte{ HashesByHeight: map[int][]byte{
int(height.Int64()): []byte("0x0"), int(height.Int64()): []byte("0x0"),
}, },
} }
@@ -1151,13 +1176,16 @@ func TestPendingDeposits_CantReturnMoreDepositCount(t *testing.T) {
} }
bs := &ProposerServer{ bs := &ProposerServer{
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
powChainService: p, headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
depositCache: depositCache, chainStartFetcher: p,
eth1InfoFetcher: p,
eth1BlockFetcher: p,
depositCache: depositCache,
} }
// It should also return the recent deposits after their follow window. // It should also return the recent deposits after their follow window.
p.latestBlockNumber = big.NewInt(0).Add(p.latestBlockNumber, big.NewInt(10000)) p.LatestBlockNumber = big.NewInt(0).Add(p.LatestBlockNumber, big.NewInt(10000))
deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{}) deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -1178,11 +1206,15 @@ func TestEth1Data_EmptyVotesFetchBlockHashFailure(t *testing.T) {
}, },
Eth1DataVotes: []*ethpb.Eth1Data{}, Eth1DataVotes: []*ethpb.Eth1Data{},
} }
p := &mockPOW.FaultyMockPOWChain{
HashesByHeight: make(map[int][]byte),
}
proposerServer := &ProposerServer{ proposerServer := &ProposerServer{
powChainService: &faultyPOWChainService{ chainStartFetcher: p,
hashesByHeight: make(map[int][]byte), eth1InfoFetcher: p,
}, eth1BlockFetcher: p,
chainService: &mock.ChainService{State: beaconState}, blockReceiver: &mock.ChainService{State: beaconState},
headFetcher: &mock.ChainService{State: beaconState},
} }
want := "could not fetch ETH1_FOLLOW_DISTANCE ancestor" want := "could not fetch ETH1_FOLLOW_DISTANCE ancestor"
if _, err := proposerServer.eth1Data(context.Background(), beaconState.Slot+1); !strings.Contains(err.Error(), want) { if _, err := proposerServer.eth1Data(context.Background(), beaconState.Slot+1); !strings.Contains(err.Error(), want) {
@@ -1201,8 +1233,8 @@ func TestDefaultEth1Data_NoBlockExists(t *testing.T) {
Deposit: &ethpb.Deposit{ Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{ Data: &ethpb.Deposit_Data{
PublicKey: []byte("a"), PublicKey: []byte("a"),
Signature: mockSig[:], Signature: make([]byte, 96),
WithdrawalCredentials: mockCreds[:], WithdrawalCredentials: make([]byte, 32),
}}, }},
}, },
{ {
@@ -1211,8 +1243,8 @@ func TestDefaultEth1Data_NoBlockExists(t *testing.T) {
Deposit: &ethpb.Deposit{ Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{ Data: &ethpb.Deposit_Data{
PublicKey: []byte("b"), PublicKey: []byte("b"),
Signature: mockSig[:], Signature: make([]byte, 96),
WithdrawalCredentials: mockCreds[:], WithdrawalCredentials: make([]byte, 32),
}}, }},
}, },
} }
@@ -1225,16 +1257,18 @@ func TestDefaultEth1Data_NoBlockExists(t *testing.T) {
depositCache.InsertDeposit(context.Background(), dp.Deposit, dp.Block, dp.Index, depositTrie.Root()) depositCache.InsertDeposit(context.Background(), dp.Deposit, dp.Block, dp.Index, depositTrie.Root())
} }
powChainService := &mockPOWChainService{ p := &mockPOW.POWChain{
latestBlockNumber: height, LatestBlockNumber: height,
hashesByHeight: map[int][]byte{ HashesByHeight: map[int][]byte{
0: []byte("hash0"), 0: []byte("hash0"),
476: []byte("hash1024"), 476: []byte("hash1024"),
}, },
} }
proposerServer := &ProposerServer{ proposerServer := &ProposerServer{
powChainService: powChainService, chainStartFetcher: p,
depositCache: depositCache, eth1InfoFetcher: p,
eth1BlockFetcher: p,
depositCache: depositCache,
} }
defEth1Data := &ethpb.Eth1Data{ defEth1Data := &ethpb.Eth1Data{
@@ -1243,7 +1277,7 @@ func TestDefaultEth1Data_NoBlockExists(t *testing.T) {
DepositRoot: []byte{'r', 'o', 'o', 't'}, DepositRoot: []byte{'r', 'o', 'o', 't'},
} }
powChainService.eth1Data = defEth1Data p.Eth1Data = defEth1Data
result, err := proposerServer.defaultEth1DataResponse(ctx, big.NewInt(1500)) result, err := proposerServer.defaultEth1DataResponse(ctx, big.NewInt(1500))
if err != nil { if err != nil {
@@ -1260,19 +1294,22 @@ func TestEth1Data(t *testing.T) {
slot := uint64(10000) slot := uint64(10000)
ps := &ProposerServer{ p := &mockPOW.POWChain{
powChainService: &mockPOWChainService{ BlockNumberByHeight: map[uint64]*big.Int{
blockNumberByHeight: map[uint64]*big.Int{ 60000: big.NewInt(4096),
60000: big.NewInt(4096),
},
hashesByHeight: map[int][]byte{
3072: []byte("3072"),
},
eth1Data: &ethpb.Eth1Data{
DepositCount: 55,
},
}, },
depositCache: depositcache.NewDepositCache(), HashesByHeight: map[int][]byte{
3072: []byte("3072"),
},
Eth1Data: &ethpb.Eth1Data{
DepositCount: 55,
},
}
ps := &ProposerServer{
chainStartFetcher: p,
eth1InfoFetcher: p,
eth1BlockFetcher: p,
depositCache: depositcache.NewDepositCache(),
} }
ctx := context.Background() ctx := context.Background()
@@ -1286,6 +1323,57 @@ func TestEth1Data(t *testing.T) {
} }
} }
func TestEth1Data_MockEnabled(t *testing.T) {
db := dbutil.SetupDB(t)
defer dbutil.TeardownDB(t, db)
// If a mock eth1 data votes is specified, we use the following for the
// eth1data we provide to every proposer based on https://github.com/ethereum/eth2.0-pm/issues/62:
//
// slot_in_voting_period = current_slot % SLOTS_PER_ETH1_VOTING_PERIOD
// Eth1Data(
// DepositRoot = hash(current_epoch + slot_in_voting_period),
// DepositCount = state.eth1_deposit_index,
// BlockHash = hash(hash(current_epoch + slot_in_voting_period)),
// )
ctx := context.Background()
ps := &ProposerServer{
headFetcher: &mock.ChainService{},
beaconDB: db,
mockEth1Votes: true,
}
headBlockRoot := [32]byte{1, 2, 3}
headState := &pbp2p.BeaconState{
Eth1DepositIndex: 64,
}
if err := db.SaveHeadBlockRoot(ctx, headBlockRoot); err != nil {
t.Fatal(err)
}
if err := db.SaveState(ctx, headState, headBlockRoot); err != nil {
t.Fatal(err)
}
eth1Data, err := ps.eth1Data(ctx, 100)
if err != nil {
t.Fatal(err)
}
wantedSlot := 100 % params.BeaconConfig().SlotsPerEth1VotingPeriod
currentEpoch := helpers.SlotToEpoch(100)
enc, err := ssz.Marshal(currentEpoch + wantedSlot)
if err != nil {
t.Fatal(err)
}
depRoot := hashutil.Hash(enc)
blockHash := hashutil.Hash(depRoot[:])
want := &ethpb.Eth1Data{
DepositRoot: depRoot[:],
DepositCount: 64,
BlockHash: blockHash[:],
}
if !proto.Equal(eth1Data, want) {
t.Errorf("Wanted %v, received %v", want, eth1Data)
}
}
func Benchmark_Eth1Data(b *testing.B) { func Benchmark_Eth1Data(b *testing.B) {
ctx := context.Background() ctx := context.Background()
@@ -1347,13 +1435,17 @@ func Benchmark_Eth1Data(b *testing.B) {
} }
currentHeight := params.BeaconConfig().Eth1FollowDistance + 5 currentHeight := params.BeaconConfig().Eth1FollowDistance + 5
p := &mockPOW.POWChain{
LatestBlockNumber: big.NewInt(int64(currentHeight)),
HashesByHeight: hashesByHeight,
}
proposerServer := &ProposerServer{ proposerServer := &ProposerServer{
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
powChainService: &mockPOWChainService{ headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
latestBlockNumber: big.NewInt(int64(currentHeight)), chainStartFetcher: p,
hashesByHeight: hashesByHeight, eth1InfoFetcher: p,
}, eth1BlockFetcher: p,
depositCache: depositCache, depositCache: depositCache,
} }
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@@ -1368,12 +1460,12 @@ func TestDeposits_ReturnsEmptyList_IfLatestEth1DataEqGenesisEth1Block(t *testing
ctx := context.Background() ctx := context.Background()
height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)) height := big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance))
p := &mockPOWChainService{ p := &mockPOW.POWChain{
latestBlockNumber: height, LatestBlockNumber: height,
hashesByHeight: map[int][]byte{ HashesByHeight: map[int][]byte{
int(height.Int64()): []byte("0x0"), int(height.Int64()): []byte("0x0"),
}, },
genesisEth1Block: height, GenesisEth1Block: height,
} }
beaconState := &pbp2p.BeaconState{ beaconState := &pbp2p.BeaconState{
@@ -1448,13 +1540,16 @@ func TestDeposits_ReturnsEmptyList_IfLatestEth1DataEqGenesisEth1Block(t *testing
} }
bs := &ProposerServer{ bs := &ProposerServer{
chainService: &mock.ChainService{State: beaconState, Root: blkRoot[:]}, blockReceiver: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
powChainService: p, headFetcher: &mock.ChainService{State: beaconState, Root: blkRoot[:]},
depositCache: depositCache, chainStartFetcher: p,
eth1InfoFetcher: p,
eth1BlockFetcher: p,
depositCache: depositCache,
} }
// It should also return the recent deposits after their follow window. // It should also return the recent deposits after their follow window.
p.latestBlockNumber = big.NewInt(0).Add(p.latestBlockNumber, big.NewInt(10000)) p.LatestBlockNumber = big.NewInt(0).Add(p.LatestBlockNumber, big.NewInt(10000))
deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{}) deposits, err := bs.deposits(ctx, &ethpb.Eth1Data{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View File

@@ -4,12 +4,9 @@ package rpc
import ( import (
"context" "context"
"fmt" "fmt"
"math/big"
"net" "net"
"time" "time"
"github.com/ethereum/go-ethereum/common"
"github.com/gogo/protobuf/proto"
middleware "github.com/grpc-ecosystem/go-grpc-middleware" middleware "github.com/grpc-ecosystem/go-grpc-middleware"
recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
@@ -19,13 +16,12 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/operations" "github.com/prysmaticlabs/prysm/beacon-chain/operations"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
"github.com/prysmaticlabs/prysm/beacon-chain/sync" "github.com/prysmaticlabs/prysm/beacon-chain/sync"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/params" "github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/trieutil"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opencensus.io/plugin/ocgrpc" "go.opencensus.io/plugin/ocgrpc"
"google.golang.org/grpc" "google.golang.org/grpc"
@@ -39,43 +35,19 @@ func init() {
log = logrus.WithField("prefix", "rpc") log = logrus.WithField("prefix", "rpc")
} }
type chainService interface {
blockchain.HeadRetriever
blockchain.AttestationReceiver
blockchain.BlockReceiver
StateInitializedFeed() *event.Feed
}
type operationService interface {
operations.Pool
HandleAttestation(context.Context, proto.Message) error
IncomingAttFeed() *event.Feed
}
type powChainService interface {
HasChainStarted() bool
ETH2GenesisTime() (uint64, *big.Int)
ChainStartFeed() *event.Feed
LatestBlockHeight() *big.Int
BlockExists(ctx context.Context, hash common.Hash) (bool, *big.Int, error)
BlockHashByHeight(ctx context.Context, height *big.Int) (common.Hash, error)
BlockTimeByHeight(ctx context.Context, height *big.Int) (uint64, error)
BlockNumberByTimestamp(ctx context.Context, time uint64) (*big.Int, error)
DepositRoot() [32]byte
DepositTrie() *trieutil.MerkleTrie
ChainStartDepositHashes() ([][]byte, error)
ChainStartDeposits() []*ethpb.Deposit
ChainStartETH1Data() *ethpb.Eth1Data
}
// Service defining an RPC server for a beacon node. // Service defining an RPC server for a beacon node.
type Service struct { type Service struct {
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
beaconDB db.Database beaconDB db.Database
chainService chainService stateFeedListener blockchain.ChainFeeds
powChainService powChainService headFetcher blockchain.HeadFetcher
operationService operationService attestationReceiver blockchain.AttestationReceiver
blockReceiver blockchain.BlockReceiver
powChainService powchain.Chain
mockEth1Votes bool
attestationsPool operations.Pool
operationsHandler operations.Handler
syncService sync.Checker syncService sync.Checker
port string port string
listener net.Listener listener net.Listener
@@ -91,16 +63,21 @@ type Service struct {
// Config options for the beacon node RPC server. // Config options for the beacon node RPC server.
type Config struct { type Config struct {
Port string Port string
CertFlag string CertFlag string
KeyFlag string KeyFlag string
BeaconDB db.Database BeaconDB db.Database
ChainService chainService StateFeedListener blockchain.ChainFeeds
POWChainService powChainService HeadFetcher blockchain.HeadFetcher
OperationService operationService AttestationReceiver blockchain.AttestationReceiver
SyncService sync.Checker BlockReceiver blockchain.BlockReceiver
Broadcaster p2p.Broadcaster POWChainService powchain.Chain
DepositCache *depositcache.DepositCache MockEth1Votes bool
OperationsHandler operations.Handler
AttestationsPool operations.Pool
SyncService sync.Checker
Broadcaster p2p.Broadcaster
DepositCache *depositcache.DepositCache
} }
// NewService instantiates a new RPC service instance that will // NewService instantiates a new RPC service instance that will
@@ -111,10 +88,15 @@ func NewService(ctx context.Context, cfg *Config) *Service {
ctx: ctx, ctx: ctx,
cancel: cancel, cancel: cancel,
beaconDB: cfg.BeaconDB, beaconDB: cfg.BeaconDB,
stateFeedListener: cfg.StateFeedListener,
headFetcher: cfg.HeadFetcher,
attestationReceiver: cfg.AttestationReceiver,
blockReceiver: cfg.BlockReceiver,
p2p: cfg.Broadcaster, p2p: cfg.Broadcaster,
chainService: cfg.ChainService,
powChainService: cfg.POWChainService, powChainService: cfg.POWChainService,
operationService: cfg.OperationService, mockEth1Votes: cfg.MockEth1Votes,
attestationsPool: cfg.AttestationsPool,
operationsHandler: cfg.OperationsHandler,
syncService: cfg.SyncService, syncService: cfg.SyncService,
port: cfg.Port, port: cfg.Port,
withCert: cfg.CertFlag, withCert: cfg.CertFlag,
@@ -163,34 +145,41 @@ func (s *Service) Start() {
beaconServer := &BeaconServer{ beaconServer := &BeaconServer{
beaconDB: s.beaconDB, beaconDB: s.beaconDB,
ctx: s.ctx, ctx: s.ctx,
powChainService: s.powChainService, chainStartFetcher: s.powChainService,
chainService: s.chainService, eth1InfoFetcher: s.powChainService,
operationService: s.operationService, headFetcher: s.headFetcher,
stateFeedListener: s.stateFeedListener,
incomingAttestation: s.incomingAttestation, incomingAttestation: s.incomingAttestation,
canonicalStateChan: s.canonicalStateChan, canonicalStateChan: s.canonicalStateChan,
chainStartChan: make(chan time.Time, 1), chainStartChan: make(chan time.Time, 1),
} }
proposerServer := &ProposerServer{ proposerServer := &ProposerServer{
beaconDB: s.beaconDB, beaconDB: s.beaconDB,
chainService: s.chainService, headFetcher: s.headFetcher,
powChainService: s.powChainService, blockReceiver: s.blockReceiver,
operationService: s.operationService, chainStartFetcher: s.powChainService,
eth1InfoFetcher: s.powChainService,
eth1BlockFetcher: s.powChainService,
mockEth1Votes: s.mockEth1Votes,
pool: s.attestationsPool,
canonicalStateChan: s.canonicalStateChan, canonicalStateChan: s.canonicalStateChan,
depositCache: s.depositCache, depositCache: s.depositCache,
} }
attesterServer := &AttesterServer{ attesterServer := &AttesterServer{
beaconDB: s.beaconDB, p2p: s.p2p,
operationService: s.operationService, beaconDB: s.beaconDB,
p2p: s.p2p, operationsHandler: s.operationsHandler,
chainService: s.chainService, attReceiver: s.attestationReceiver,
cache: cache.NewAttestationCache(), headFetcher: s.headFetcher,
depositCache: cache.NewAttestationCache(),
} }
validatorServer := &ValidatorServer{ validatorServer := &ValidatorServer{
ctx: s.ctx, ctx: s.ctx,
beaconDB: s.beaconDB, beaconDB: s.beaconDB,
chainService: s.chainService, headFetcher: s.headFetcher,
canonicalStateChan: s.canonicalStateChan, canonicalStateChan: s.canonicalStateChan,
powChainService: s.powChainService, blockFetcher: s.powChainService,
chainStartFetcher: s.powChainService,
depositCache: s.depositCache, depositCache: s.depositCache,
} }
nodeServer := &NodeServer{ nodeServer := &NodeServer{
@@ -199,9 +188,9 @@ func (s *Service) Start() {
syncChecker: s.syncService, syncChecker: s.syncService,
} }
beaconChainServer := &BeaconChainServer{ beaconChainServer := &BeaconChainServer{
beaconDB: s.beaconDB, beaconDB: s.beaconDB,
pool: s.operationService, pool: s.attestationsPool,
chainService: s.chainService, headFetcher: s.headFetcher,
} }
pb.RegisterBeaconServiceServer(s.grpcServer, beaconServer) pb.RegisterBeaconServiceServer(s.grpcServer, beaconServer)
pb.RegisterProposerServiceServer(s.grpcServer, proposerServer) pb.RegisterProposerServiceServer(s.grpcServer, proposerServer)

View File

@@ -7,11 +7,8 @@ import (
"io/ioutil" "io/ioutil"
"testing" "testing"
"github.com/gogo/protobuf/proto"
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/testing"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil" "github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
logTest "github.com/sirupsen/logrus/hooks/test" logTest "github.com/sirupsen/logrus/hooks/test"
@@ -22,80 +19,17 @@ func init() {
logrus.SetOutput(ioutil.Discard) logrus.SetOutput(ioutil.Discard)
} }
type mockOperationService struct {
pendingAttestations []*ethpb.Attestation
}
func (ms *mockOperationService) IncomingAttFeed() *event.Feed {
return new(event.Feed)
}
func (ms *mockOperationService) IncomingExitFeed() *event.Feed {
return new(event.Feed)
}
func (ms *mockOperationService) HandleAttestation(_ context.Context, _ proto.Message) error {
return nil
}
func (ms *mockOperationService) IsAttCanonical(_ context.Context, att *ethpb.Attestation) (bool, error) {
return true, nil
}
func (ms *mockOperationService) AttestationPool(_ context.Context, expectedSlot uint64) ([]*ethpb.Attestation, error) {
if ms.pendingAttestations != nil {
return ms.pendingAttestations, nil
}
return []*ethpb.Attestation{
{
AggregationBits: []byte{0xC0},
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: params.BeaconConfig().SlotsPerEpoch,
DataRoot: params.BeaconConfig().ZeroHash[:],
},
},
},
{
AggregationBits: []byte{0xC1},
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: params.BeaconConfig().SlotsPerEpoch,
DataRoot: params.BeaconConfig().ZeroHash[:],
},
},
},
{
AggregationBits: []byte{0xC2},
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: params.BeaconConfig().SlotsPerEpoch,
DataRoot: params.BeaconConfig().ZeroHash[:],
},
},
},
}, nil
}
type mockSyncService struct {
}
func (ms *mockSyncService) Status() error {
return nil
}
func (ms *mockSyncService) Syncing() bool {
return false
}
func TestLifecycle_OK(t *testing.T) { func TestLifecycle_OK(t *testing.T) {
hook := logTest.NewGlobal() hook := logTest.NewGlobal()
rpcService := NewService(context.Background(), &Config{ rpcService := NewService(context.Background(), &Config{
Port: "7348", Port: "7348",
CertFlag: "alice.crt", CertFlag: "alice.crt",
KeyFlag: "alice.key", KeyFlag: "alice.key",
SyncService: &mockSyncService{}, SyncService: &mockSync.Sync{IsSyncing: false},
ChainService: &mock.ChainService{}, BlockReceiver: &mock.ChainService{},
AttestationReceiver: &mock.ChainService{},
HeadFetcher: &mock.ChainService{},
StateFeedListener: &mock.ChainService{},
}) })
rpcService.Start() rpcService.Start()
@@ -112,9 +46,12 @@ func TestRPC_BadEndpoint(t *testing.T) {
hook := logTest.NewGlobal() hook := logTest.NewGlobal()
rpcService := NewService(context.Background(), &Config{ rpcService := NewService(context.Background(), &Config{
Port: "ralph merkle!!!", Port: "ralph merkle!!!",
SyncService: &mockSyncService{}, SyncService: &mockSync.Sync{IsSyncing: false},
ChainService: &mock.ChainService{}, BlockReceiver: &mock.ChainService{},
AttestationReceiver: &mock.ChainService{},
HeadFetcher: &mock.ChainService{},
StateFeedListener: &mock.ChainService{},
}) })
testutil.AssertLogsDoNotContain(t, hook, "Could not listen to port in Start()") testutil.AssertLogsDoNotContain(t, hook, "Could not listen to port in Start()")
@@ -141,9 +78,12 @@ func TestStatus_CredentialError(t *testing.T) {
func TestRPC_InsecureEndpoint(t *testing.T) { func TestRPC_InsecureEndpoint(t *testing.T) {
hook := logTest.NewGlobal() hook := logTest.NewGlobal()
rpcService := NewService(context.Background(), &Config{ rpcService := NewService(context.Background(), &Config{
Port: "7777", Port: "7777",
SyncService: &mockSyncService{}, SyncService: &mockSync.Sync{IsSyncing: false},
ChainService: &mock.ChainService{}, BlockReceiver: &mock.ChainService{},
AttestationReceiver: &mock.ChainService{},
HeadFetcher: &mock.ChainService{},
StateFeedListener: &mock.ChainService{},
}) })
rpcService.Start() rpcService.Start()

View File

@@ -8,11 +8,13 @@ import (
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state/stateutils" "github.com/prysmaticlabs/prysm/beacon-chain/core/state/stateutils"
"github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
@@ -29,9 +31,10 @@ import (
type ValidatorServer struct { type ValidatorServer struct {
ctx context.Context ctx context.Context
beaconDB db.Database beaconDB db.Database
chainService chainService headFetcher blockchain.HeadFetcher
canonicalStateChan chan *pbp2p.BeaconState canonicalStateChan chan *pbp2p.BeaconState
powChainService powChainService blockFetcher powchain.POWBlockFetcher
chainStartFetcher powchain.ChainStartFetcher
depositCache *depositcache.DepositCache depositCache *depositcache.DepositCache
} }
@@ -103,7 +106,7 @@ func (vs *ValidatorServer) ValidatorPerformance(
if !ok { if !ok {
return nil, status.Errorf(codes.Internal, "could not find validator index for public key %#x not found", req.PublicKey) return nil, status.Errorf(codes.Internal, "could not find validator index for public key %#x not found", req.PublicKey)
} }
headState := vs.chainService.HeadState() headState := vs.headFetcher.HeadState()
activeCount, err := helpers.ActiveValidatorCount(headState, helpers.SlotToEpoch(req.Slot)) activeCount, err := helpers.ActiveValidatorCount(headState, helpers.SlotToEpoch(req.Slot))
if err != nil { if err != nil {
@@ -133,7 +136,7 @@ func (vs *ValidatorServer) ValidatorPerformance(
// 4.) The bool signaling if the validator is expected to propose a block at the assigned slot. // 4.) The bool signaling if the validator is expected to propose a block at the assigned slot.
func (vs *ValidatorServer) CommitteeAssignment(ctx context.Context, req *pb.AssignmentRequest) (*pb.AssignmentResponse, error) { func (vs *ValidatorServer) CommitteeAssignment(ctx context.Context, req *pb.AssignmentRequest) (*pb.AssignmentResponse, error) {
var err error var err error
s := vs.chainService.HeadState() s := vs.headFetcher.HeadState()
// Advance state with empty transitions up to the requested epoch start slot. // Advance state with empty transitions up to the requested epoch start slot.
if epochStartSlot := helpers.StartSlot(req.EpochStart); s.Slot < epochStartSlot { if epochStartSlot := helpers.StartSlot(req.EpochStart); s.Slot < epochStartSlot {
@@ -226,9 +229,9 @@ func (vs *ValidatorServer) assignment(
func (vs *ValidatorServer) ValidatorStatus( func (vs *ValidatorServer) ValidatorStatus(
ctx context.Context, ctx context.Context,
req *pb.ValidatorIndexRequest) (*pb.ValidatorStatusResponse, error) { req *pb.ValidatorIndexRequest) (*pb.ValidatorStatusResponse, error) {
headState := vs.chainService.HeadState() headState := vs.headFetcher.HeadState()
chainStarted := vs.powChainService.HasChainStarted() chainStarted := vs.chainStartFetcher.HasChainStarted()
chainStartKeys := vs.chainStartPubkeys() chainStartKeys := vs.chainStartPubkeys()
validatorIndexMap := stateutils.ValidatorIndexMap(headState) validatorIndexMap := stateutils.ValidatorIndexMap(headState)
return vs.validatorStatus(ctx, req.PublicKey, chainStarted, chainStartKeys, validatorIndexMap, headState), nil return vs.validatorStatus(ctx, req.PublicKey, chainStarted, chainStartKeys, validatorIndexMap, headState), nil
@@ -239,13 +242,13 @@ func (vs *ValidatorServer) ValidatorStatus(
func (vs *ValidatorServer) MultipleValidatorStatus( func (vs *ValidatorServer) MultipleValidatorStatus(
ctx context.Context, ctx context.Context,
pubkeys [][]byte) (bool, []*pb.ValidatorActivationResponse_Status, error) { pubkeys [][]byte) (bool, []*pb.ValidatorActivationResponse_Status, error) {
chainStarted := vs.powChainService.HasChainStarted() chainStarted := vs.chainStartFetcher.HasChainStarted()
if !chainStarted { if !chainStarted {
return false, nil, nil return false, nil, nil
} }
activeValidatorExists := false activeValidatorExists := false
statusResponses := make([]*pb.ValidatorActivationResponse_Status, len(pubkeys)) statusResponses := make([]*pb.ValidatorActivationResponse_Status, len(pubkeys))
headState := vs.chainService.HeadState() headState := vs.headFetcher.HeadState()
chainStartKeys := vs.chainStartPubkeys() chainStartKeys := vs.chainStartPubkeys()
validatorIndexMap := stateutils.ValidatorIndexMap(headState) validatorIndexMap := stateutils.ValidatorIndexMap(headState)
@@ -425,7 +428,7 @@ func (vs *ValidatorServer) lookupValidatorStatus(validatorIdx uint64, beaconStat
func (vs *ValidatorServer) depositBlockSlot(ctx context.Context, currentSlot uint64, func (vs *ValidatorServer) depositBlockSlot(ctx context.Context, currentSlot uint64,
eth1BlockNumBigInt *big.Int, beaconState *pbp2p.BeaconState) (uint64, error) { eth1BlockNumBigInt *big.Int, beaconState *pbp2p.BeaconState) (uint64, error) {
blockTimeStamp, err := vs.powChainService.BlockTimeByHeight(ctx, eth1BlockNumBigInt) blockTimeStamp, err := vs.blockFetcher.BlockTimeByHeight(ctx, eth1BlockNumBigInt)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@@ -449,7 +452,7 @@ func (vs *ValidatorServer) depositBlockSlot(ctx context.Context, currentSlot uin
func (vs *ValidatorServer) chainStartPubkeys() map[[96]byte]bool { func (vs *ValidatorServer) chainStartPubkeys() map[[96]byte]bool {
pubkeys := make(map[[96]byte]bool) pubkeys := make(map[[96]byte]bool)
deposits := vs.powChainService.ChainStartDeposits() deposits := vs.chainStartFetcher.ChainStartDeposits()
for _, dep := range deposits { for _, dep := range deposits {
pubkeys[bytesutil.ToBytes96(dep.Data.PublicKey)] = true pubkeys[bytesutil.ToBytes96(dep.Data.PublicKey)] = true
} }
@@ -458,7 +461,7 @@ func (vs *ValidatorServer) chainStartPubkeys() map[[96]byte]bool {
// DomainData fetches the current domain version information from the beacon state. // DomainData fetches the current domain version information from the beacon state.
func (vs *ValidatorServer) DomainData(ctx context.Context, request *pb.DomainRequest) (*pb.DomainResponse, error) { func (vs *ValidatorServer) DomainData(ctx context.Context, request *pb.DomainRequest) (*pb.DomainResponse, error) {
headState := vs.chainService.HeadState() headState := vs.headFetcher.HeadState()
dv := helpers.Domain(headState, request.Epoch, request.Domain) dv := helpers.Domain(headState, request.Epoch, request.Domain)
return &pb.DomainResponse{ return &pb.DomainResponse{
SignatureDomain: dv, SignatureDomain: dv,

View File

@@ -20,7 +20,8 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/testing" mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
internal "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testing"
mockRPC "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testing" mockRPC "github.com/prysmaticlabs/prysm/beacon-chain/rpc/testing"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
@@ -78,8 +79,8 @@ func TestNextEpochCommitteeAssignment_WrongPubkeyLength(t *testing.T) {
} }
validatorServer := &ValidatorServer{ validatorServer := &ValidatorServer{
beaconDB: db, beaconDB: db,
chainService: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]}, headFetcher: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]},
} }
req := &pb.AssignmentRequest{ req := &pb.AssignmentRequest{
PublicKeys: [][]byte{{1}}, PublicKeys: [][]byte{{1}},
@@ -107,7 +108,7 @@ func TestNextEpochCommitteeAssignment_CantFindValidatorIdx(t *testing.T) {
} }
vs := &ValidatorServer{ vs := &ValidatorServer{
chainService: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]}, headFetcher: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]},
} }
pubKey := make([]byte, 96) pubKey := make([]byte, 96)
@@ -159,8 +160,8 @@ func TestCommitteeAssignment_OK(t *testing.T) {
} }
vs := &ValidatorServer{ vs := &ValidatorServer{
beaconDB: db, beaconDB: db,
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
// Test the first validator in registry. // Test the first validator in registry.
@@ -241,8 +242,8 @@ func TestCommitteeAssignment_CurrentEpoch_ShouldNotFail(t *testing.T) {
} }
vs := &ValidatorServer{ vs := &ValidatorServer{
beaconDB: db, beaconDB: db,
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
// Test the first validator in registry. // Test the first validator in registry.
@@ -295,8 +296,8 @@ func TestCommitteeAssignment_MultipleKeys_OK(t *testing.T) {
} }
vs := &ValidatorServer{ vs := &ValidatorServer{
beaconDB: db, beaconDB: db,
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
pubkey0 := deposits[0].Data.PublicKey pubkey0 := deposits[0].Data.PublicKey
@@ -367,15 +368,17 @@ func TestValidatorStatus_PendingActive(t *testing.T) {
depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root()) depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root())
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix() height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
vs := &ValidatorServer{ p := &mockPOW.POWChain{
beaconDB: db, TimesByHeight: map[int]uint64{
powChainService: &mockPOWChainService{ 0: uint64(height),
blockTimeByHeight: map[int]uint64{
0: uint64(height),
},
}, },
depositCache: depositCache, }
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, vs := &ValidatorServer{
beaconDB: db,
chainStartFetcher: p,
blockFetcher: p,
depositCache: depositCache,
headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
req := &pb.ValidatorIndexRequest{ req := &pb.ValidatorIndexRequest{
PublicKey: pubKey, PublicKey: pubKey,
@@ -440,15 +443,17 @@ func TestValidatorStatus_Active(t *testing.T) {
}} }}
timestamp := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix() timestamp := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
vs := &ValidatorServer{ p := &mockPOW.POWChain{
beaconDB: db, TimesByHeight: map[int]uint64{
powChainService: &mockPOWChainService{ int(params.BeaconConfig().Eth1FollowDistance): uint64(timestamp),
blockTimeByHeight: map[int]uint64{
int(params.BeaconConfig().Eth1FollowDistance): uint64(timestamp),
},
}, },
depositCache: depositCache, }
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, vs := &ValidatorServer{
beaconDB: db,
chainStartFetcher: p,
blockFetcher: p,
depositCache: depositCache,
headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
req := &pb.ValidatorIndexRequest{ req := &pb.ValidatorIndexRequest{
PublicKey: pubKey, PublicKey: pubKey,
@@ -517,15 +522,17 @@ func TestValidatorStatus_InitiatedExit(t *testing.T) {
depositCache := depositcache.NewDepositCache() depositCache := depositcache.NewDepositCache()
depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root()) depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root())
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix() height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
vs := &ValidatorServer{ p := &mockPOW.POWChain{
beaconDB: db, TimesByHeight: map[int]uint64{
powChainService: &mockPOWChainService{ 0: uint64(height),
blockTimeByHeight: map[int]uint64{
0: uint64(height),
},
}, },
depositCache: depositCache, }
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, vs := &ValidatorServer{
beaconDB: db,
chainStartFetcher: p,
blockFetcher: p,
depositCache: depositCache,
headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
req := &pb.ValidatorIndexRequest{ req := &pb.ValidatorIndexRequest{
PublicKey: pubKey, PublicKey: pubKey,
@@ -584,15 +591,17 @@ func TestValidatorStatus_Withdrawable(t *testing.T) {
depositCache := depositcache.NewDepositCache() depositCache := depositcache.NewDepositCache()
depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root()) depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root())
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix() height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
vs := &ValidatorServer{ p := &mockPOW.POWChain{
beaconDB: db, TimesByHeight: map[int]uint64{
powChainService: &mockPOWChainService{ 0: uint64(height),
blockTimeByHeight: map[int]uint64{
0: uint64(height),
},
}, },
depositCache: depositCache, }
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, vs := &ValidatorServer{
beaconDB: db,
chainStartFetcher: p,
blockFetcher: p,
depositCache: depositCache,
headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
req := &pb.ValidatorIndexRequest{ req := &pb.ValidatorIndexRequest{
PublicKey: pubKey, PublicKey: pubKey,
@@ -651,15 +660,17 @@ func TestValidatorStatus_ExitedSlashed(t *testing.T) {
depositCache := depositcache.NewDepositCache() depositCache := depositcache.NewDepositCache()
depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root()) depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root())
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix() height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
vs := &ValidatorServer{ p := &mockPOW.POWChain{
beaconDB: db, TimesByHeight: map[int]uint64{
powChainService: &mockPOWChainService{ 0: uint64(height),
blockTimeByHeight: map[int]uint64{
0: uint64(height),
},
}, },
depositCache: depositCache, }
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, vs := &ValidatorServer{
beaconDB: db,
chainStartFetcher: p,
depositCache: depositCache,
blockFetcher: p,
headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
req := &pb.ValidatorIndexRequest{ req := &pb.ValidatorIndexRequest{
PublicKey: pubKey, PublicKey: pubKey,
@@ -719,15 +730,17 @@ func TestValidatorStatus_Exited(t *testing.T) {
depositCache := depositcache.NewDepositCache() depositCache := depositcache.NewDepositCache()
depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root()) depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root())
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix() height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
vs := &ValidatorServer{ p := &mockPOW.POWChain{
beaconDB: db, TimesByHeight: map[int]uint64{
powChainService: &mockPOWChainService{ 0: uint64(height),
blockTimeByHeight: map[int]uint64{
0: uint64(height),
},
}, },
depositCache: depositCache, }
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, vs := &ValidatorServer{
beaconDB: db,
chainStartFetcher: p,
blockFetcher: p,
depositCache: depositCache,
headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
req := &pb.ValidatorIndexRequest{ req := &pb.ValidatorIndexRequest{
PublicKey: pubKey, PublicKey: pubKey,
@@ -782,15 +795,17 @@ func TestValidatorStatus_UnknownStatus(t *testing.T) {
depositCache := depositcache.NewDepositCache() depositCache := depositcache.NewDepositCache()
depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root()) depositCache.InsertDeposit(ctx, deposit, big.NewInt(0) /*blockNum*/, 0, depositTrie.Root())
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix() height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
vs := &ValidatorServer{ p := &mockPOW.POWChain{
beaconDB: db, TimesByHeight: map[int]uint64{
powChainService: &mockPOWChainService{ 0: uint64(height),
blockTimeByHeight: map[int]uint64{
0: uint64(height),
},
}, },
depositCache: depositCache, }
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, vs := &ValidatorServer{
beaconDB: db,
chainStartFetcher: p,
blockFetcher: p,
depositCache: depositCache,
headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
req := &pb.ValidatorIndexRequest{ req := &pb.ValidatorIndexRequest{
PublicKey: pubKey, PublicKey: pubKey,
@@ -826,10 +841,11 @@ func TestWaitForActivation_ContextClosed(t *testing.T) {
vs := &ValidatorServer{ vs := &ValidatorServer{
beaconDB: db, beaconDB: db,
ctx: ctx, ctx: ctx,
powChainService: &mockPOWChainService{}, chainStartFetcher: &mockPOW.POWChain{},
blockFetcher: &mockPOW.POWChain{},
canonicalStateChan: make(chan *pbp2p.BeaconState, 1), canonicalStateChan: make(chan *pbp2p.BeaconState, 1),
depositCache: depositcache.NewDepositCache(), depositCache: depositcache.NewDepositCache(),
chainService: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]}, headFetcher: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]},
} }
req := &pb.ValidatorActivationRequest{ req := &pb.ValidatorActivationRequest{
PublicKeys: [][]byte{[]byte("A")}, PublicKeys: [][]byte{[]byte("A")},
@@ -929,9 +945,10 @@ func TestWaitForActivation_ValidatorOriginallyExists(t *testing.T) {
beaconDB: db, beaconDB: db,
ctx: context.Background(), ctx: context.Background(),
canonicalStateChan: make(chan *pbp2p.BeaconState, 1), canonicalStateChan: make(chan *pbp2p.BeaconState, 1),
powChainService: &mockPOWChainService{}, chainStartFetcher: &mockPOW.POWChain{},
blockFetcher: &mockPOW.POWChain{},
depositCache: depositCache, depositCache: depositCache,
chainService: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]}, headFetcher: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]},
} }
req := &pb.ValidatorActivationRequest{ req := &pb.ValidatorActivationRequest{
PublicKeys: [][]byte{pubKey1, pubKey2}, PublicKeys: [][]byte{pubKey1, pubKey2},
@@ -1042,9 +1059,10 @@ func TestMultipleValidatorStatus_OK(t *testing.T) {
beaconDB: db, beaconDB: db,
ctx: context.Background(), ctx: context.Background(),
canonicalStateChan: make(chan *pbp2p.BeaconState, 1), canonicalStateChan: make(chan *pbp2p.BeaconState, 1),
powChainService: &mockPOWChainService{}, chainStartFetcher: &mockPOW.POWChain{},
blockFetcher: &mockPOW.POWChain{},
depositCache: depositCache, depositCache: depositCache,
chainService: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]}, headFetcher: &mockChain.ChainService{State: beaconState, Root: genesisRoot[:]},
} }
activeExists, response, err := vs.MultipleValidatorStatus(context.Background(), pubKeys) activeExists, response, err := vs.MultipleValidatorStatus(context.Background(), pubKeys)
if err != nil { if err != nil {
@@ -1108,8 +1126,8 @@ func BenchmarkAssignment(b *testing.B) {
} }
vs := &ValidatorServer{ vs := &ValidatorServer{
beaconDB: db, beaconDB: db,
chainService: &mockChain.ChainService{State: state, Root: genesisRoot[:]}, headFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
} }
// Set up request for 100 public keys at a time // Set up request for 100 public keys at a time

View File

@@ -23,7 +23,7 @@ var _ = shared.Service(&InitialSync{})
type blockchainService interface { type blockchainService interface {
blockchain.BlockReceiver blockchain.BlockReceiver
blockchain.HeadRetriever blockchain.HeadFetcher
blockchain.ChainFeeds blockchain.ChainFeeds
} }

View File

@@ -26,8 +26,8 @@ type Config struct {
// This defines the interface for interacting with block chain service // This defines the interface for interacting with block chain service
type blockchainService interface { type blockchainService interface {
blockchain.BlockReceiver blockchain.BlockReceiver
blockchain.HeadRetriever blockchain.HeadFetcher
blockchain.FinalizationRetriever blockchain.FinalizationFetcher
blockchain.AttestationReceiver blockchain.AttestationReceiver
} }

View File

@@ -0,0 +1,9 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
testonly = True,
srcs = ["mock.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/sync/testing",
visibility = ["//beacon-chain:__subpackages__"],
)

View File

@@ -0,0 +1,16 @@
package testing
// Sync defines a mock for the sync service.
type Sync struct {
IsSyncing bool
}
// Syncing --
func (s *Sync) Syncing() bool {
return s.IsSyncing
}
// Status --
func (s *Sync) Status() error {
return nil
}

View File

@@ -75,6 +75,8 @@ var appHelpFlagGroups = []flagGroup{
Name: "beacon-chain", Name: "beacon-chain",
Flags: []cli.Flag{ Flags: []cli.Flag{
flags.NoCustomConfigFlag, flags.NoCustomConfigFlag,
flags.InteropMockEth1DataVotesFlag,
flags.InteropGenesisStateFlag,
flags.DepositContractFlag, flags.DepositContractFlag,
flags.Web3ProviderFlag, flags.Web3ProviderFlag,
flags.RPCPort, flags.RPCPort,
@@ -83,7 +85,6 @@ var appHelpFlagGroups = []flagGroup{
flags.EnableDBCleanup, flags.EnableDBCleanup,
flags.GRPCGatewayPort, flags.GRPCGatewayPort,
flags.HTTPWeb3ProviderFlag, flags.HTTPWeb3ProviderFlag,
flags.GenesisState,
}, },
}, },
{ {