mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-10 03:31:20 +00:00
1ddb19bba6
sharding: create a syncer and a simulator package Former-commit-id: b392885510ba5a96e61278cbbe2c0ec6f9722ee8 [formerly 3a435eaf6805d02beae55656f155b2c3a66ee663] Former-commit-id: 0f6f3f2053ae77711e2072848b727b0dc9b92276
233 lines
5.9 KiB
Go
233 lines
5.9 KiB
Go
package syncer
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/sharding/mainchain"
|
|
|
|
"github.com/ethereum/go-ethereum/sharding/p2p/messages"
|
|
|
|
"github.com/ethereum/go-ethereum/log"
|
|
|
|
"github.com/ethereum/go-ethereum/sharding"
|
|
"github.com/ethereum/go-ethereum/sharding/database"
|
|
internal "github.com/ethereum/go-ethereum/sharding/internal"
|
|
"github.com/ethereum/go-ethereum/sharding/p2p"
|
|
"github.com/ethereum/go-ethereum/sharding/params"
|
|
)
|
|
|
|
var _ = sharding.Service(&Syncer{})
|
|
|
|
func TestStartStop(t *testing.T) {
|
|
h := internal.NewLogHandler(t)
|
|
log.Root().SetHandler(h)
|
|
|
|
shardChainDB := database.NewShardKV()
|
|
shardID := 0
|
|
server, err := p2p.NewServer()
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup p2p server: %v", err)
|
|
}
|
|
|
|
syncer, err := NewSyncer(params.DefaultConfig, &mainchain.SMCClient{}, server, shardChainDB, shardID)
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup sync service: %v", err)
|
|
}
|
|
|
|
syncer.Start()
|
|
|
|
h.VerifyLogMsg("Starting sync service")
|
|
|
|
if err := syncer.Stop(); err != nil {
|
|
t.Fatalf("Unable to stop sync service: %v", err)
|
|
}
|
|
|
|
h.VerifyLogMsg("Stopping sync service")
|
|
|
|
// The context should have been canceled.
|
|
if syncer.ctx.Err() == nil {
|
|
t.Error("Context was not canceled")
|
|
}
|
|
}
|
|
|
|
// This test uses a faulty Signer interface in order to trigger an error
|
|
// in the simulateNotaryRequests goroutine when attempting to sign
|
|
// a collation header within the goroutine's internals.
|
|
func TestHandleCollationBodyRequests_FaultySigner(t *testing.T) {
|
|
h := internal.NewLogHandler(t)
|
|
log.Root().SetHandler(h)
|
|
|
|
shardChainDB := database.NewShardKV()
|
|
shardID := 0
|
|
server, err := p2p.NewServer()
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup p2p server: %v", err)
|
|
}
|
|
|
|
syncer, err := NewSyncer(params.DefaultConfig, &mainchain.SMCClient{}, server, shardChainDB, shardID)
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup syncer service: %v", err)
|
|
}
|
|
|
|
feed := server.Feed(messages.CollationBodyRequest{})
|
|
|
|
go syncer.handleCollationBodyRequests(&faultySigner{}, feed)
|
|
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-syncer.ctx.Done():
|
|
return
|
|
default:
|
|
msg := p2p.Message{
|
|
Peer: p2p.Peer{},
|
|
Data: messages.CollationBodyRequest{},
|
|
}
|
|
feed.Send(msg)
|
|
}
|
|
}
|
|
}()
|
|
|
|
receivedErr := <-syncer.errChan
|
|
expectedErr := "could not construct response"
|
|
if !strings.Contains(receivedErr.Error(), expectedErr) {
|
|
t.Errorf("Expected error did not match. want: %v, got: %v", expectedErr, receivedErr)
|
|
}
|
|
syncer.cancel()
|
|
// The context should have been canceled.
|
|
if syncer.ctx.Err() == nil {
|
|
t.Fatal("Context was not canceled")
|
|
}
|
|
}
|
|
|
|
// This test checks the proper functioning of the handleCollationBodyRequests goroutine
|
|
// by listening to the responseSent channel which occurs after successful
|
|
// construction and sending of a response via p2p.
|
|
func TestHandleCollationBodyRequests(t *testing.T) {
|
|
h := internal.NewLogHandler(t)
|
|
log.Root().SetHandler(h)
|
|
|
|
shardChainDB := database.NewShardKV()
|
|
server, err := p2p.NewServer()
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup p2p server: %v", err)
|
|
}
|
|
|
|
body := []byte{1, 2, 3, 4, 5}
|
|
shardID := big.NewInt(0)
|
|
chunkRoot := types.DeriveSha(sharding.Chunks(body))
|
|
period := big.NewInt(0)
|
|
proposerAddress := common.BytesToAddress([]byte{})
|
|
signer := &mockSigner{}
|
|
|
|
header := sharding.NewCollationHeader(shardID, &chunkRoot, period, &proposerAddress, nil)
|
|
sig, err := signer.Sign(header.Hash())
|
|
if err != nil {
|
|
t.Fatalf("Could not sign header: %v", err)
|
|
}
|
|
|
|
// Adds the signature to the header before calculating the hash used for db lookups.
|
|
header.AddSig(sig)
|
|
|
|
// Stores the collation into the inmemory kv store shardChainDB.
|
|
collation := sharding.NewCollation(header, body, nil)
|
|
|
|
shard := sharding.NewShard(shardID, shardChainDB)
|
|
|
|
if err := shard.SaveCollation(collation); err != nil {
|
|
t.Fatalf("Could not store collation in shardChainDB: %v", err)
|
|
}
|
|
|
|
syncer, err := NewSyncer(params.DefaultConfig, &mainchain.SMCClient{}, server, shardChainDB, 0)
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup syncer service: %v", err)
|
|
}
|
|
|
|
feed := server.Feed(messages.CollationBodyRequest{})
|
|
|
|
go syncer.handleCollationBodyRequests(&mockSigner{}, feed)
|
|
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-syncer.ctx.Done():
|
|
return
|
|
default:
|
|
msg := p2p.Message{
|
|
Peer: p2p.Peer{},
|
|
Data: messages.CollationBodyRequest{
|
|
ChunkRoot: &chunkRoot,
|
|
ShardID: shardID,
|
|
Period: period,
|
|
Proposer: &proposerAddress,
|
|
},
|
|
}
|
|
feed.Send(msg)
|
|
}
|
|
}
|
|
}()
|
|
|
|
<-syncer.responseSent
|
|
h.VerifyLogMsg(fmt.Sprintf("Received p2p request of type: %T", p2p.Message{}))
|
|
h.VerifyLogMsg(fmt.Sprintf("Responding to p2p request with collation with headerHash: %v", header.Hash().Hex()))
|
|
syncer.cancel()
|
|
// The context should have been canceled.
|
|
if syncer.ctx.Err() == nil {
|
|
t.Fatal("Context was not canceled")
|
|
}
|
|
}
|
|
|
|
// TODO: Move this to the utils package along with the handleServiceErrors
|
|
// function.
|
|
func TestHandleServiceErrors(t *testing.T) {
|
|
|
|
h := internal.NewLogHandler(t)
|
|
log.Root().SetHandler(h)
|
|
|
|
shardChainDB := database.NewShardKV()
|
|
shardID := 0
|
|
server, err := p2p.NewServer()
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup p2p server: %v", err)
|
|
}
|
|
|
|
syncer, err := NewSyncer(params.DefaultConfig, &mainchain.SMCClient{}, server, shardChainDB, shardID)
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup syncer service: %v", err)
|
|
}
|
|
|
|
go syncer.handleServiceErrors()
|
|
|
|
expectedErr := "testing the error channel"
|
|
complete := make(chan int)
|
|
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-syncer.ctx.Done():
|
|
return
|
|
default:
|
|
syncer.errChan <- errors.New(expectedErr)
|
|
complete <- 1
|
|
}
|
|
}
|
|
}()
|
|
|
|
<-complete
|
|
syncer.cancel()
|
|
|
|
// The context should have been canceled.
|
|
if syncer.ctx.Err() == nil {
|
|
t.Fatal("Context was not canceled")
|
|
}
|
|
time.Sleep(time.Millisecond * 500)
|
|
h.VerifyLogMsg(fmt.Sprintf("Sync service error: %v", expectedErr))
|
|
}
|