prysm-pulse/beacon-chain/blockchain/service_test.go

783 lines
23 KiB
Go
Raw Normal View History

package blockchain
import (
"context"
"io/ioutil"
"math/big"
"testing"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
gethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/prysmaticlabs/prysm/beacon-chain/params"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
"github.com/prysmaticlabs/prysm/beacon-chain/types"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/database"
"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 mockClient struct{}
func (f *mockClient) SubscribeNewHead(ctx context.Context, ch chan<- *gethTypes.Header) (ethereum.Subscription, error) {
return new(event.Feed).Subscribe(ch), nil
}
func (f *mockClient) BlockByHash(ctx context.Context, hash common.Hash) (*gethTypes.Block, error) {
head := &gethTypes.Header{Number: big.NewInt(0), Difficulty: big.NewInt(100)}
return gethTypes.NewBlockWithHeader(head), nil
}
func (f *mockClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- gethTypes.Log) (ethereum.Subscription, error) {
return new(event.Feed).Subscribe(ch), nil
}
func (f *mockClient) LatestBlockHash() common.Hash {
return common.BytesToHash([]byte{'A'})
}
func init() {
logrus.SetLevel(logrus.DebugLevel)
}
func TestStartStop(t *testing.T) {
ctx := context.Background()
config := &database.DBConfig{DataDir: "", Name: "", InMemory: true}
db, err := database.NewDB(config)
if err != nil {
t.Fatalf("could not setup beaconDB: %v", err)
}
endpoint := "ws://127.0.0.1"
client := &mockClient{}
web3Service, err := powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{Endpoint: endpoint, Pubkey: "", VrcAddr: common.Address{}}, client, client, client)
if err != nil {
t.Fatalf("unable to set up web3 service: %v", err)
}
beaconChain, err := NewBeaconChain(db.DB())
cfg := &Config{
BeaconBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
}
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
chainService, err := NewChainService(ctx, cfg)
if err != nil {
t.Fatalf("unable to setup chain service: %v", err)
}
chainService.Start()
cfg = &Config{
BeaconBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
Web3Service: web3Service,
}
chainService, err = NewChainService(ctx, cfg)
if err != nil {
t.Fatalf("unable to setup chain service: %v", err)
}
chainService.Start()
if len(chainService.CurrentActiveState().RecentBlockHashes()) != 128 {
t.Errorf("incorrect recent block hashes")
}
if len(chainService.CurrentCrystallizedState().Validators()) != params.BootstrappedValidatorsCount {
t.Errorf("incorrect default validator size")
}
blockExists, err := chainService.ContainsBlock([32]byte{})
if err != nil {
t.Fatalf("unable to check if block exists: %v", err)
}
if blockExists {
t.Errorf("chain is not empty")
}
hasState, err := chainService.HasStoredState()
if err != nil {
t.Fatalf("calling HasStoredState failed")
}
if hasState {
t.Errorf("has stored state should return false")
}
chainService.CanonicalBlockFeed()
chainService.CanonicalCrystallizedStateFeed()
chainService, _ = NewChainService(ctx, cfg)
active := types.NewActiveState(&pb.ActiveState{RecentBlockHashes: [][]byte{{'A'}}}, make(map[[32]byte]*types.VoteCache))
activeStateHash, err := active.Hash()
if err != nil {
t.Fatalf("Cannot hash active state: %v", err)
}
chainService.chain.SetActiveState(active)
crystallized := types.NewCrystallizedState(&pb.CrystallizedState{LastStateRecalc: 10000})
crystallizedStateHash, err := crystallized.Hash()
if err != nil {
t.Fatalf("Cannot hash crystallized state: %v", err)
}
chainService.chain.SetCrystallizedState(crystallized)
parentBlock := types.NewBlock(nil)
parentHash, _ := parentBlock.Hash()
block := types.NewBlock(&pb.BeaconBlock{
SlotNumber: 2,
ActiveStateHash: activeStateHash[:],
CrystallizedStateHash: crystallizedStateHash[:],
ParentHash: parentHash[:],
PowChainRef: []byte("a"),
})
if err := chainService.SaveBlock(block); err != nil {
t.Errorf("save block should have failed")
}
// Save states so HasStoredState state should return true.
chainService.chain.SetActiveState(types.NewActiveState(&pb.ActiveState{}, make(map[[32]byte]*types.VoteCache)))
chainService.chain.SetCrystallizedState(types.NewCrystallizedState(&pb.CrystallizedState{}))
hasState, _ = chainService.HasStoredState()
if !hasState {
t.Errorf("has stored state should return false")
}
if err := chainService.Stop(); err != nil {
t.Fatalf("unable to stop chain service: %v", err)
}
// The context should have been canceled.
if chainService.ctx.Err() == nil {
t.Error("context was not canceled")
}
}
func TestFaultyStop(t *testing.T) {
ctx := context.Background()
config := &database.DBConfig{DataDir: "", Name: "", InMemory: true}
db, err := database.NewDB(config)
if err != nil {
t.Fatalf("could not setup beaconDB: %v", err)
}
endpoint := "ws://127.0.0.1"
client := &mockClient{}
web3Service, err := powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{Endpoint: endpoint, Pubkey: "", VrcAddr: common.Address{}}, client, client, client)
if err != nil {
t.Fatalf("unable to set up web3 service: %v", err)
}
beaconChain, err := NewBeaconChain(db.DB())
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
cfg := &Config{
BeaconBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
Web3Service: web3Service,
}
chainService, err := NewChainService(ctx, cfg)
if err != nil {
t.Fatalf("unable to setup chain service: %v", err)
}
chainService.Start()
chainService.chain.SetActiveState(types.NewActiveState(nil, make(map[[32]byte]*types.VoteCache)))
err = chainService.Stop()
if err == nil {
t.Errorf("chain stop should have failed with persist active state")
}
chainService.chain.SetActiveState(types.NewActiveState(&pb.ActiveState{}, make(map[[32]byte]*types.VoteCache)))
chainService.chain.SetCrystallizedState(types.NewCrystallizedState(nil))
err = chainService.Stop()
if err == nil {
t.Errorf("chain stop should have failed with persist crystallized state")
}
}
func TestRunningChainService(t *testing.T) {
hook := logTest.NewGlobal()
ctx := context.Background()
config := &database.DBConfig{DataDir: "", Name: "", InMemory: true}
db, err := database.NewDB(config)
if err != nil {
t.Fatalf("could not setup beaconDB: %v", err)
}
endpoint := "ws://127.0.0.1"
client := &mockClient{}
web3Service, err := powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{Endpoint: endpoint, Pubkey: "", VrcAddr: common.Address{}}, client, client, client)
if err != nil {
t.Fatalf("unable to set up web3 service: %v", err)
}
beaconChain, err := NewBeaconChain(db.DB())
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
active := types.NewGenesisActiveState()
crystallized, err := types.NewGenesisCrystallizedState()
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
activeStateHash, _ := active.Hash()
crystallizedStateHash, _ := crystallized.Hash()
cfg := &Config{
BeaconBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
Web3Service: web3Service,
}
chainService, _ := NewChainService(ctx, cfg)
genesis, err := beaconChain.GenesisBlock()
if err != nil {
t.Fatalf("unable to get canonical head: %v", err)
}
parentHash, err := genesis.Hash()
if err != nil {
t.Fatalf("unable to get hash of canonical head: %v", err)
}
block := types.NewBlock(&pb.BeaconBlock{
SlotNumber: 1,
ActiveStateHash: activeStateHash[:],
CrystallizedStateHash: crystallizedStateHash[:],
ParentHash: parentHash[:],
PowChainRef: []byte("a"),
Attestations: []*pb.AggregatedAttestation{{
Slot: 0,
AttesterBitfield: []byte{128, 0},
ShardId: 0,
}},
})
exitRoutine := make(chan bool)
go func() {
chainService.blockProcessing(chainService.ctx.Done())
<-exitRoutine
}()
if err := chainService.SaveBlock(block); err != nil {
t.Fatal(err)
}
chainService.incomingBlockChan <- block
chainService.cancel()
exitRoutine <- true
hash, err := block.Hash()
if err != nil {
t.Fatal("Can not hash the block")
}
slot, err := chainService.GetBlockSlotNumber(hash)
if err != nil {
t.Fatal("Can not get block slot number")
}
if slot != block.SlotNumber() {
t.Errorf("Block slot number mismatched, wanted 1, got slot %d", block.SlotNumber())
}
if _, err := chainService.GetBlockSlotNumber([32]byte{}); err == nil {
t.Fatal("Get block slot number should have failed with nil hash")
}
testutil.AssertLogsContain(t, hook, "Finished processing state for candidate block")
}
func TestUpdateHead(t *testing.T) {
hook := logTest.NewGlobal()
ctx := context.Background()
config := &database.DBConfig{DataDir: "", Name: "", InMemory: true}
db, err := database.NewDB(config)
if err != nil {
t.Fatalf("could not setup beaconDB: %v", err)
}
endpoint := "ws://127.0.0.1"
client := &mockClient{}
web3Service, err := powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{Endpoint: endpoint, Pubkey: "", VrcAddr: common.Address{}}, client, client, client)
if err != nil {
t.Fatalf("unable to set up web3 service: %v", err)
}
beaconChain, err := NewBeaconChain(db.DB())
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
cfg := &Config{
BeaconBlockBuf: 0,
IncomingBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
Web3Service: web3Service,
}
chainService, _ := NewChainService(ctx, cfg)
active := types.NewGenesisActiveState()
crystallized, err := types.NewGenesisCrystallizedState()
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
activeStateHash, _ := active.Hash()
crystallizedStateHash, _ := crystallized.Hash()
parentHash := [32]byte{'a'}
block := types.NewBlock(&pb.BeaconBlock{
SlotNumber: 64,
ActiveStateHash: activeStateHash[:],
CrystallizedStateHash: crystallizedStateHash[:],
ParentHash: parentHash[:],
PowChainRef: []byte("a"),
})
chainService.candidateBlock = block
chainService.candidateActiveState = active
chainService.candidateCrystallizedState = crystallized
chainService.updateHead()
testutil.AssertLogsContain(t, hook, "Canonical block determined")
if chainService.candidateBlock != nilBlock {
t.Error("Candidate Block unable to be reset")
}
}
func TestProcessingBlocks(t *testing.T) {
ctx := context.Background()
config := &database.DBConfig{DataDir: "", Name: "", InMemory: true}
db, err := database.NewDB(config)
if err != nil {
t.Fatalf("could not setup beaconDB: %v", err)
}
endpoint := "ws://127.0.0.1"
client := &mockClient{}
web3Service, err := powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{Endpoint: endpoint, Pubkey: "", VrcAddr: common.Address{}}, client, client, client)
if err != nil {
t.Fatalf("unable to set up web3 service: %v", err)
}
beaconChain, err := NewBeaconChain(db.DB())
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
cfg := &Config{
BeaconBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
Web3Service: web3Service,
}
chainService, _ := NewChainService(ctx, cfg)
active := types.NewGenesisActiveState()
crystallized, err := types.NewGenesisCrystallizedState()
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
activeStateHash, _ := active.Hash()
crystallizedStateHash, _ := crystallized.Hash()
2018-09-14 05:07:30 +00:00
exitRoutine := make(chan bool)
go func() {
chainService.blockProcessing(chainService.ctx.Done())
<-exitRoutine
}()
2018-09-14 05:07:30 +00:00
block0 := types.NewBlock(&pb.BeaconBlock{
SlotNumber: 3,
})
if saveErr := beaconChain.saveBlock(block0); saveErr != nil {
t.Fatalf("Cannot save block: %v", saveErr)
}
block0Hash, err := block0.Hash()
if err != nil {
2018-09-14 05:07:30 +00:00
t.Fatalf("Failed to compute block's hash: %v", err)
}
block1 := types.NewBlock(&pb.BeaconBlock{
2018-09-14 05:07:30 +00:00
ParentHash: block0Hash[:],
SlotNumber: 4,
ActiveStateHash: activeStateHash[:],
CrystallizedStateHash: crystallizedStateHash[:],
Attestations: []*pb.AggregatedAttestation{{
Slot: 0,
AttesterBitfield: []byte{16, 0},
ShardId: 0,
}},
})
block1Hash, err := block1.Hash()
if err != nil {
t.Fatalf("unable to get hash of block 1: %v", err)
}
// Add 1 more attestation field for slot2
block2 := types.NewBlock(&pb.BeaconBlock{
ParentHash: block1Hash[:],
2018-09-14 05:07:30 +00:00
SlotNumber: 5,
Attestations: []*pb.AggregatedAttestation{
{Slot: 0, AttesterBitfield: []byte{8, 0}, ShardId: 0},
{Slot: 1, AttesterBitfield: []byte{8, 0}, ShardId: 0},
}})
block2Hash, err := block2.Hash()
if err != nil {
t.Fatalf("unable to get hash of block 1: %v", err)
}
// Add 1 more attestation field for slot3
block3 := types.NewBlock(&pb.BeaconBlock{
ParentHash: block2Hash[:],
2018-09-14 05:07:30 +00:00
SlotNumber: 6,
Attestations: []*pb.AggregatedAttestation{
{Slot: 0, AttesterBitfield: []byte{4, 0}, ShardId: 0},
{Slot: 1, AttesterBitfield: []byte{4, 0}, ShardId: 0},
{Slot: 2, AttesterBitfield: []byte{4, 0}, ShardId: 0},
}})
2018-09-14 05:07:30 +00:00
chainService.incomingBlockChan <- block1
chainService.incomingBlockChan <- block2
chainService.incomingBlockChan <- block3
chainService.cancel()
exitRoutine <- true
// We should have 3 pending attestations from blocks 1 and 2
if len(beaconChain.ActiveState().PendingAttestations()) != 3 {
t.Fatalf("Active state should have 3 pending attestation: %d", len(beaconChain.ActiveState().PendingAttestations()))
}
// Check that there are 6 pending attestations for the candidate state
if len(chainService.candidateActiveState.PendingAttestations()) != 6 {
t.Fatalf("Candidate active state should have 6 pending attestations: %d", len(chainService.candidateActiveState.PendingAttestations()))
}
}
func TestProcessAttestationBadBlock(t *testing.T) {
hook := logTest.NewGlobal()
ctx := context.Background()
config := &database.DBConfig{DataDir: "", Name: "", InMemory: true}
db, err := database.NewDB(config)
if err != nil {
t.Fatalf("could not setup beaconDB: %v", err)
}
endpoint := "ws://127.0.0.1"
client := &mockClient{}
web3Service, err := powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{Endpoint: endpoint, Pubkey: "", VrcAddr: common.Address{}}, client, client, client)
if err != nil {
t.Fatalf("unable to set up web3 service: %v", err)
}
beaconChain, err := NewBeaconChain(db.DB())
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
cfg := &Config{
BeaconBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
Web3Service: web3Service,
}
chainService, _ := NewChainService(ctx, cfg)
active := types.NewGenesisActiveState()
crystallized, err := types.NewGenesisCrystallizedState()
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
activeStateHash, _ := active.Hash()
crystallizedStateHash, _ := crystallized.Hash()
2018-09-14 05:07:30 +00:00
block0 := types.NewBlock(&pb.BeaconBlock{
SlotNumber: 5,
})
if saveErr := beaconChain.saveBlock(block0); saveErr != nil {
t.Fatalf("Cannot save block: %v", saveErr)
}
2018-09-14 05:07:30 +00:00
parentHash, err := block0.Hash()
if err != nil {
2018-09-14 05:07:30 +00:00
t.Fatalf("Failed to compute block's hash: %v", err)
}
block1 := types.NewBlock(&pb.BeaconBlock{
ParentHash: parentHash[:],
SlotNumber: 1,
ActiveStateHash: activeStateHash[:],
CrystallizedStateHash: crystallizedStateHash[:],
Attestations: []*pb.AggregatedAttestation{{
Slot: 10,
AttesterBitfield: []byte{},
ShardId: 0,
}},
})
exitRoutine := make(chan bool)
go func() {
chainService.blockProcessing(chainService.ctx.Done())
<-exitRoutine
}()
chainService.incomingBlockChan <- block1
chainService.cancel()
exitRoutine <- true
2018-09-14 05:07:30 +00:00
testutil.AssertLogsContain(t, hook, "attestation slot number can't be higher than parent block's slot number. Found: 10, Needed lower than: 5")
}
func TestEnterCycleTransition(t *testing.T) {
hook := logTest.NewGlobal()
ctx := context.Background()
config := &database.DBConfig{DataDir: "", Name: "", InMemory: true}
db, err := database.NewDB(config)
if err != nil {
t.Fatalf("could not setup beaconDB: %v", err)
}
endpoint := "ws://127.0.0.1"
client := &mockClient{}
web3Service, err := powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{Endpoint: endpoint, Pubkey: "", VrcAddr: common.Address{}}, client, client, client)
if err != nil {
t.Fatalf("unable to set up web3 service: %v", err)
}
beaconChain, err := NewBeaconChain(db.DB())
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
cfg := &Config{
BeaconBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
Web3Service: web3Service,
}
chainService, _ := NewChainService(ctx, cfg)
genesisBlock, _ := beaconChain.GenesisBlock()
active := beaconChain.ActiveState()
crystallized := beaconChain.CrystallizedState()
parentHash, _ := genesisBlock.Hash()
activeStateHash, _ := active.Hash()
crystallizedStateHash, _ := crystallized.Hash()
block1 := types.NewBlock(&pb.BeaconBlock{
ParentHash: parentHash[:],
SlotNumber: 64,
ActiveStateHash: activeStateHash[:],
CrystallizedStateHash: crystallizedStateHash[:],
Attestations: []*pb.AggregatedAttestation{{
Slot: 0,
AttesterBitfield: []byte{128, 0},
ShardId: 0,
}},
})
exitRoutine := make(chan bool)
go func() {
chainService.blockProcessing(chainService.ctx.Done())
<-exitRoutine
}()
chainService.incomingBlockChan <- block1
chainService.cancel()
exitRoutine <- true
testutil.AssertLogsContain(t, hook, "Entering cycle transition")
}
func TestEnterDynastyTransition(t *testing.T) {
hook := logTest.NewGlobal()
ctx := context.Background()
config := &database.DBConfig{DataDir: "", Name: "", InMemory: true}
db, err := database.NewDB(config)
if err != nil {
t.Fatalf("could not setup beaconDB: %v", err)
}
endpoint := "ws://127.0.0.1"
client := &mockClient{}
web3Service, err := powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{Endpoint: endpoint, Pubkey: "", VrcAddr: common.Address{}}, client, client, client)
if err != nil {
t.Fatalf("unable to set up web3 service: %v", err)
}
beaconChain, err := NewBeaconChain(db.DB())
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
cfg := &Config{
BeaconBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
Web3Service: web3Service,
}
var shardCommitteeForSlots []*pb.ShardAndCommitteeArray
for i := 0; i < 300; i++ {
shardCommittee := &pb.ShardAndCommitteeArray{
ArrayShardAndCommittee: []*pb.ShardAndCommittee{
{ShardId: 0, Committee: []uint32{0, 1, 2, 3}},
{ShardId: 1, Committee: []uint32{0, 1, 2, 3}},
{ShardId: 2, Committee: []uint32{0, 1, 2, 3}},
{ShardId: 3, Committee: []uint32{0, 1, 2, 3}},
},
}
shardCommitteeForSlots = append(shardCommitteeForSlots, shardCommittee)
}
var validators []*pb.ValidatorRecord
for i := 0; i < 5; i++ {
validators = append(validators, &pb.ValidatorRecord{StartDynasty: 0, EndDynasty: params.DefaultEndDynasty})
}
chainService, _ := NewChainService(ctx, cfg)
crystallized := types.NewCrystallizedState(
&pb.CrystallizedState{
DynastyStart: 1,
LastFinalizedSlot: 2,
ShardAndCommitteesForSlots: shardCommitteeForSlots,
Validators: validators,
LastStateRecalc: 150,
CrosslinkRecords: []*pb.CrosslinkRecord{
{Slot: 2},
{Slot: 2},
{Slot: 2},
{Slot: 2},
},
},
)
var recentBlockhashes [][]byte
for i := 0; i < 257; i++ {
recentBlockhashes = append(recentBlockhashes, []byte{'A'})
}
active := types.NewActiveState(
&pb.ActiveState{
RecentBlockHashes: recentBlockhashes,
PendingAttestations: []*pb.AggregatedAttestation{
{Slot: 100, AttesterBitfield: []byte{0}},
{Slot: 101, AttesterBitfield: []byte{0}},
{Slot: 102, AttesterBitfield: []byte{0}},
{Slot: 103, AttesterBitfield: []byte{0}},
},
}, nil,
)
2018-09-14 05:07:30 +00:00
block0 := types.NewBlock(&pb.BeaconBlock{
SlotNumber: 202,
})
if saveErr := beaconChain.saveBlock(block0); saveErr != nil {
t.Fatalf("Cannot save block: %v", saveErr)
}
block0Hash, err := block0.Hash()
if err != nil {
t.Fatalf("Failed to compute block's hash: %v", err)
}
activeStateHash, _ := active.Hash()
crystallizedStateHash, _ := crystallized.Hash()
if err := chainService.chain.SetCrystallizedState(crystallized); err != nil {
t.Fatalf("unable to save crystallized state %v", err)
}
if err := chainService.chain.SetActiveState(active); err != nil {
t.Fatalf("unable to save active state %v", err)
}
block1 := types.NewBlock(&pb.BeaconBlock{
2018-09-14 05:07:30 +00:00
ParentHash: block0Hash[:],
SlotNumber: params.MinDynastyLength + 1,
ActiveStateHash: activeStateHash[:],
CrystallizedStateHash: crystallizedStateHash[:],
Attestations: []*pb.AggregatedAttestation{{
Slot: 200,
AttesterBitfield: []byte{32},
ShardId: 0,
}},
})
exitRoutine := make(chan bool)
go func() {
chainService.blockProcessing(chainService.ctx.Done())
<-exitRoutine
}()
chainService.incomingBlockChan <- block1
chainService.cancel()
exitRoutine <- true
testutil.AssertLogsContain(t, hook, "Entering dynasty transition")
}
func TestIncomingAttestation(t *testing.T) {
hook := logTest.NewGlobal()
ctx := context.Background()
config := &database.DBConfig{DataDir: "", Name: "", InMemory: true}
db, err := database.NewDB(config)
if err != nil {
t.Fatalf("could not setup beaconDB: %v", err)
}
endpoint := "ws://127.0.0.1"
client := &mockClient{}
web3Service, err := powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{Endpoint: endpoint, Pubkey: "", VrcAddr: common.Address{}}, client, client, client)
if err != nil {
t.Fatalf("unable to set up web3 service: %v", err)
}
beaconChain, err := NewBeaconChain(db.DB())
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
cfg := &Config{
BeaconBlockBuf: 0,
BeaconDB: db.DB(),
Chain: beaconChain,
Web3Service: web3Service,
}
chainService, _ := NewChainService(ctx, cfg)
exitRoutine := make(chan bool)
go func() {
chainService.blockProcessing(chainService.ctx.Done())
<-exitRoutine
}()
attestation := types.NewAttestation(
&pb.AggregatedAttestation{
Slot: 1,
ShardId: 1,
ShardBlockHash: []byte{'A'},
})
chainService.incomingAttestationChan <- attestation
chainService.cancel()
exitRoutine <- true
testutil.AssertLogsContain(t, hook, "Relaying attestation")
}