mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-05 17:22:18 +00:00
4a1b5db07b
* begin with a block/state dag approach in prep for fork choice * add TODOs for fork choice items, add data structure for forks * remove syncing and processing states for incoming block sync * simulator only broadcasts blocks now, no more state simulation * fix sim tests, no more state sim * bazel rerun * naive fork choice * split update head routine * pesky race conditions * fork choice rule works * dag + fork choice working * canonical head storage across sessions * todo: save dag * no more stalling after 10 blocks, using event feeds * address review * sync instead uses event feed * refactored pure funcs into casper package * tests pass * fix lint * refactor get blockhash * refactor blockhashforslot * event feed for incoming blocks in chainservice * use config * addressed all comments * fix typo * address yutaro comment * using db interface * check if parent hash in previous slot DAG * works * tests * drop ffg suffix * bazel gazelle * full cov validators by height shard * gazelle * state tests * all state tests * 100% cov types and 99% cover casper * cov up * 80% blockchain cov * fix lint
222 lines
7.4 KiB
Go
222 lines
7.4 KiB
Go
package rpc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"testing"
|
|
|
|
"github.com/ethereum/go-ethereum/event"
|
|
"github.com/golang/mock/gomock"
|
|
"github.com/golang/protobuf/ptypes/empty"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/types"
|
|
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
|
"github.com/sirupsen/logrus"
|
|
logTest "github.com/sirupsen/logrus/hooks/test"
|
|
)
|
|
|
|
func init() {
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
logrus.SetOutput(ioutil.Discard)
|
|
}
|
|
|
|
type mockAnnouncer struct {
|
|
blockFeed *event.Feed
|
|
stateFeed *event.Feed
|
|
}
|
|
|
|
func newMockAnnouncer() *mockAnnouncer {
|
|
return &mockAnnouncer{
|
|
blockFeed: new(event.Feed),
|
|
stateFeed: new(event.Feed),
|
|
}
|
|
}
|
|
|
|
func (m *mockAnnouncer) CanonicalBlockFeed() *event.Feed {
|
|
return m.blockFeed
|
|
}
|
|
|
|
func (m *mockAnnouncer) CanonicalCrystallizedStateFeed() *event.Feed {
|
|
return m.stateFeed
|
|
}
|
|
|
|
func TestLifecycle(t *testing.T) {
|
|
hook := logTest.NewGlobal()
|
|
announcer := newMockAnnouncer()
|
|
rpcService := NewRPCService(context.Background(), &Config{Port: "7348", CertFlag: "alice.crt", KeyFlag: "alice.key"}, announcer)
|
|
|
|
rpcService.Start()
|
|
|
|
testutil.AssertLogsContain(t, hook, "Starting service")
|
|
testutil.AssertLogsContain(t, hook, fmt.Sprintf("RPC server listening on port :%s", rpcService.port))
|
|
|
|
rpcService.Stop()
|
|
testutil.AssertLogsContain(t, hook, "Stopping service")
|
|
}
|
|
|
|
func TestBadEndpoint(t *testing.T) {
|
|
hook := logTest.NewGlobal()
|
|
announcer := newMockAnnouncer()
|
|
rpcService := NewRPCService(context.Background(), &Config{Port: "ralph merkle!!!"}, announcer)
|
|
|
|
rpcService.Start()
|
|
|
|
testutil.AssertLogsContain(t, hook, "Starting service")
|
|
testutil.AssertLogsContain(t, hook, fmt.Sprintf("Could not listen to port :%s", rpcService.port))
|
|
|
|
rpcService.Stop()
|
|
testutil.AssertLogsContain(t, hook, "Stopping service")
|
|
}
|
|
|
|
func TestInsecureEndpoint(t *testing.T) {
|
|
hook := logTest.NewGlobal()
|
|
announcer := newMockAnnouncer()
|
|
rpcService := NewRPCService(context.Background(), &Config{Port: "7777"}, announcer)
|
|
|
|
rpcService.Start()
|
|
|
|
testutil.AssertLogsContain(t, hook, "Starting service")
|
|
testutil.AssertLogsContain(t, hook, fmt.Sprintf("RPC server listening on port :%s", rpcService.port))
|
|
testutil.AssertLogsContain(t, hook, "You are using an insecure gRPC connection")
|
|
|
|
rpcService.Stop()
|
|
testutil.AssertLogsContain(t, hook, "Stopping service")
|
|
}
|
|
|
|
func TestRPCMethods(t *testing.T) {
|
|
announcer := newMockAnnouncer()
|
|
rpcService := NewRPCService(context.Background(), &Config{Port: "7362"}, announcer)
|
|
if _, err := rpcService.ProposeBlock(context.Background(), nil); err == nil {
|
|
t.Error("Wanted error: unimplemented, received nil")
|
|
}
|
|
if _, err := rpcService.SignBlock(context.Background(), nil); err == nil {
|
|
t.Error("Wanted error: unimplemented, received nil")
|
|
}
|
|
}
|
|
|
|
func TestFetchShuffledValidatorIndices(t *testing.T) {
|
|
announcer := newMockAnnouncer()
|
|
rpcService := NewRPCService(context.Background(), &Config{Port: "6372"}, announcer)
|
|
res, err := rpcService.FetchShuffledValidatorIndices(context.Background(), &pb.ShuffleRequest{})
|
|
if err != nil {
|
|
t.Fatalf("Could not call RPC method: %v", err)
|
|
}
|
|
if len(res.ShuffledValidatorIndices) != 100 {
|
|
t.Errorf("Expected 100 validators in the shuffled indices, received %d", len(res.ShuffledValidatorIndices))
|
|
}
|
|
}
|
|
|
|
func TestLatestBeaconBlockContextClosed(t *testing.T) {
|
|
hook := logTest.NewGlobal()
|
|
announcer := newMockAnnouncer()
|
|
rpcService := NewRPCService(context.Background(), &Config{Port: "6663", SubscriptionBuf: 0}, announcer)
|
|
exitRoutine := make(chan bool)
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
mockStream := internal.NewMockBeaconService_LatestBeaconBlockServer(ctrl)
|
|
go func(tt *testing.T) {
|
|
if err := rpcService.LatestBeaconBlock(&empty.Empty{}, mockStream); err != nil {
|
|
tt.Errorf("Could not call RPC method: %v", err)
|
|
}
|
|
<-exitRoutine
|
|
}(t)
|
|
rpcService.cancel()
|
|
exitRoutine <- true
|
|
testutil.AssertLogsContain(t, hook, "RPC context closed, exiting goroutine")
|
|
}
|
|
|
|
func TestLatestBeaconBlock(t *testing.T) {
|
|
hook := logTest.NewGlobal()
|
|
announcer := newMockAnnouncer()
|
|
rpcService := NewRPCService(context.Background(), &Config{Port: "7771", SubscriptionBuf: 0}, announcer)
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
exitRoutine := make(chan bool)
|
|
|
|
mockStream := internal.NewMockBeaconService_LatestBeaconBlockServer(ctrl)
|
|
mockStream.EXPECT().Send(&pbp2p.BeaconBlock{}).Return(errors.New("something wrong"))
|
|
// Tests a faulty stream.
|
|
go func(tt *testing.T) {
|
|
if err := rpcService.LatestBeaconBlock(&empty.Empty{}, mockStream); err.Error() != "something wrong" {
|
|
tt.Errorf("Faulty stream should throw correct error, wanted 'something wrong', got %v", err)
|
|
}
|
|
<-exitRoutine
|
|
}(t)
|
|
rpcService.canonicalBlockChan <- types.NewBlock(&pbp2p.BeaconBlock{})
|
|
|
|
mockStream = internal.NewMockBeaconService_LatestBeaconBlockServer(ctrl)
|
|
mockStream.EXPECT().Send(&pbp2p.BeaconBlock{}).Return(nil)
|
|
|
|
// Tests a good stream.
|
|
go func(tt *testing.T) {
|
|
if err := rpcService.LatestBeaconBlock(&empty.Empty{}, mockStream); err != nil {
|
|
tt.Errorf("Could not call RPC method: %v", err)
|
|
}
|
|
<-exitRoutine
|
|
}(t)
|
|
rpcService.canonicalBlockChan <- types.NewBlock(&pbp2p.BeaconBlock{})
|
|
testutil.AssertLogsContain(t, hook, "Sending latest canonical block to RPC clients")
|
|
rpcService.cancel()
|
|
exitRoutine <- true
|
|
}
|
|
|
|
func TestLatestCrystallizedStateContextClosed(t *testing.T) {
|
|
hook := logTest.NewGlobal()
|
|
announcer := newMockAnnouncer()
|
|
rpcService := NewRPCService(context.Background(), &Config{Port: "8777", SubscriptionBuf: 0}, announcer)
|
|
exitRoutine := make(chan bool)
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
mockStream := internal.NewMockBeaconService_LatestCrystallizedStateServer(ctrl)
|
|
go func(tt *testing.T) {
|
|
if err := rpcService.LatestCrystallizedState(&empty.Empty{}, mockStream); err != nil {
|
|
tt.Errorf("Could not call RPC method: %v", err)
|
|
}
|
|
<-exitRoutine
|
|
}(t)
|
|
rpcService.cancel()
|
|
exitRoutine <- true
|
|
testutil.AssertLogsContain(t, hook, "RPC context closed, exiting goroutine")
|
|
}
|
|
|
|
func TestLatestCrystallizedState(t *testing.T) {
|
|
hook := logTest.NewGlobal()
|
|
announcer := newMockAnnouncer()
|
|
rpcService := NewRPCService(context.Background(), &Config{Port: "8773", SubscriptionBuf: 0}, announcer)
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
exitRoutine := make(chan bool)
|
|
|
|
mockStream := internal.NewMockBeaconService_LatestCrystallizedStateServer(ctrl)
|
|
mockStream.EXPECT().Send(&pbp2p.CrystallizedState{}).Return(errors.New("something wrong"))
|
|
// Tests a faulty stream.
|
|
go func(tt *testing.T) {
|
|
if err := rpcService.LatestCrystallizedState(&empty.Empty{}, mockStream); err.Error() != "something wrong" {
|
|
tt.Errorf("Faulty stream should throw correct error, wanted 'something wrong', got %v", err)
|
|
}
|
|
<-exitRoutine
|
|
}(t)
|
|
rpcService.canonicalStateChan <- types.NewCrystallizedState(&pbp2p.CrystallizedState{})
|
|
|
|
mockStream = internal.NewMockBeaconService_LatestCrystallizedStateServer(ctrl)
|
|
mockStream.EXPECT().Send(&pbp2p.CrystallizedState{}).Return(nil)
|
|
|
|
// Tests a good stream.
|
|
go func(tt *testing.T) {
|
|
if err := rpcService.LatestCrystallizedState(&empty.Empty{}, mockStream); err != nil {
|
|
tt.Errorf("Could not call RPC method: %v", err)
|
|
}
|
|
<-exitRoutine
|
|
}(t)
|
|
rpcService.canonicalStateChan <- types.NewCrystallizedState(&pbp2p.CrystallizedState{})
|
|
testutil.AssertLogsContain(t, hook, "Sending crystallized state to RPC clients")
|
|
rpcService.cancel()
|
|
exitRoutine <- true
|
|
}
|