mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 21:07:18 +00:00
2624cd2b3c
Former-commit-id: b853fd1c3ea2284d30d7f3032cf83287c7198c10 [formerly c012daacceec9cb3497f1d066ee3ca2d20aa5b14] Former-commit-id: 0a5a60c296f878c7057b25fc759dec2487363d30
219 lines
6.2 KiB
Go
219 lines
6.2 KiB
Go
package simulator
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/prysmaticlabs/geth-sharding/sharding/mainchain"
|
|
|
|
ethereum "github.com/ethereum/go-ethereum"
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/prysmaticlabs/geth-sharding/sharding/p2p/messages"
|
|
|
|
"github.com/ethereum/go-ethereum/log"
|
|
internal "github.com/prysmaticlabs/geth-sharding/sharding/internal"
|
|
"github.com/prysmaticlabs/geth-sharding/sharding/p2p"
|
|
"github.com/prysmaticlabs/geth-sharding/sharding/params"
|
|
"github.com/prysmaticlabs/geth-sharding/sharding/types"
|
|
)
|
|
|
|
var _ = types.Service(&Simulator{})
|
|
|
|
type faultyReader struct{}
|
|
type goodReader struct{}
|
|
|
|
type faultySMCCaller struct{}
|
|
type goodSMCCaller struct{}
|
|
|
|
func (f *faultySMCCaller) CollationRecords(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (struct {
|
|
ChunkRoot [32]byte
|
|
Proposer common.Address
|
|
IsElected bool
|
|
Signature [32]byte
|
|
}, error) {
|
|
res := new(struct {
|
|
ChunkRoot [32]byte
|
|
Proposer common.Address
|
|
IsElected bool
|
|
Signature [32]byte
|
|
})
|
|
return *res, errors.New("error fetching collation record")
|
|
}
|
|
|
|
func (g *goodSMCCaller) CollationRecords(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (struct {
|
|
ChunkRoot [32]byte
|
|
Proposer common.Address
|
|
IsElected bool
|
|
Signature [32]byte
|
|
}, error) {
|
|
res := new(struct {
|
|
ChunkRoot [32]byte
|
|
Proposer common.Address
|
|
IsElected bool
|
|
Signature [32]byte
|
|
})
|
|
body := []byte{1, 2, 3, 4, 5}
|
|
res.ChunkRoot = [32]byte(gethTypes.DeriveSha(types.Chunks(body)))
|
|
res.Proposer = common.BytesToAddress([]byte{})
|
|
res.IsElected = false
|
|
return *res, nil
|
|
}
|
|
|
|
func (f *faultyReader) BlockByNumber(ctx context.Context, number *big.Int) (*gethTypes.Block, error) {
|
|
return nil, fmt.Errorf("cannot fetch block by number")
|
|
}
|
|
|
|
func (f *faultyReader) SubscribeNewHead(ctx context.Context, ch chan<- *gethTypes.Header) (ethereum.Subscription, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (g *goodReader) BlockByNumber(ctx context.Context, number *big.Int) (*gethTypes.Block, error) {
|
|
return gethTypes.NewBlock(&gethTypes.Header{Number: big.NewInt(0)}, nil, nil, nil), nil
|
|
}
|
|
|
|
func (g *goodReader) SubscribeNewHead(ctx context.Context, ch chan<- *gethTypes.Header) (ethereum.Subscription, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func TestStartStop(t *testing.T) {
|
|
h := internal.NewLogHandler(t)
|
|
log.Root().SetHandler(h)
|
|
|
|
shardID := 0
|
|
server, err := p2p.NewServer()
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup p2p server: %v", err)
|
|
}
|
|
|
|
simulator, err := NewSimulator(params.DefaultConfig, &mainchain.SMCClient{}, server, shardID, 0)
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup simulator service: %v", err)
|
|
}
|
|
|
|
if err := simulator.Stop(); err != nil {
|
|
t.Fatalf("Unable to stop simulator service: %v", err)
|
|
}
|
|
|
|
h.VerifyLogMsg("Stopping simulator service")
|
|
|
|
// The context should have been canceled.
|
|
if simulator.ctx.Err() == nil {
|
|
t.Error("Context was not canceled")
|
|
}
|
|
}
|
|
|
|
// This test uses a faulty chain reader in order to trigger an error
|
|
// in the simulateNotaryRequests goroutine when reading the block number from
|
|
// the mainchain via RPC.
|
|
func TestSimulateNotaryRequests_FaultyReader(t *testing.T) {
|
|
h := internal.NewLogHandler(t)
|
|
log.Root().SetHandler(h)
|
|
|
|
shardID := 0
|
|
server, err := p2p.NewServer()
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup p2p server: %v", err)
|
|
}
|
|
|
|
simulator, err := NewSimulator(params.DefaultConfig, &mainchain.SMCClient{}, server, shardID, 0)
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup simulator service: %v", err)
|
|
}
|
|
|
|
simulator.requestFeed = server.Feed(messages.CollationBodyRequest{})
|
|
|
|
delayChan := make(chan time.Time)
|
|
doneChan := make(chan struct{})
|
|
exitRoutine := make(chan bool)
|
|
go func() {
|
|
simulator.simulateNotaryRequests(&goodSMCCaller{}, &faultyReader{}, delayChan, doneChan)
|
|
<-exitRoutine
|
|
}()
|
|
|
|
delayChan <- time.Time{}
|
|
doneChan <- struct{}{}
|
|
h.VerifyLogMsg("Could not fetch current block number: cannot fetch block by number")
|
|
|
|
exitRoutine <- true
|
|
h.VerifyLogMsg("Simulator context closed, exiting goroutine")
|
|
}
|
|
|
|
// This test uses a faulty SMCCaller in order to trigger an error
|
|
// in the simulateNotaryRequests goroutine when reading the collation records
|
|
// from the SMC.
|
|
func TestSimulateNotaryRequests_FaultyCaller(t *testing.T) {
|
|
h := internal.NewLogHandler(t)
|
|
log.Root().SetHandler(h)
|
|
|
|
shardID := 0
|
|
server, err := p2p.NewServer()
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup p2p server: %v", err)
|
|
}
|
|
|
|
simulator, err := NewSimulator(params.DefaultConfig, &mainchain.SMCClient{}, server, shardID, 0)
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup simulator service: %v", err)
|
|
}
|
|
|
|
simulator.requestFeed = server.Feed(messages.CollationBodyRequest{})
|
|
|
|
delayChan := make(chan time.Time)
|
|
doneChan := make(chan struct{})
|
|
exitRoutine := make(chan bool)
|
|
go func() {
|
|
simulator.simulateNotaryRequests(&faultySMCCaller{}, &goodReader{}, delayChan, doneChan)
|
|
<-exitRoutine
|
|
}()
|
|
|
|
delayChan <- time.Time{}
|
|
doneChan <- struct{}{}
|
|
h.VerifyLogMsg("Error constructing collation body request: could not fetch collation record from SMC: error fetching collation record")
|
|
|
|
exitRoutine <- true
|
|
h.VerifyLogMsg("Simulator context closed, exiting goroutine")
|
|
}
|
|
|
|
// This test checks the proper functioning of the simulateNotaryRequests goroutine
|
|
// by listening to the requestSent channel which occurs after successful
|
|
// construction and sending of a request via p2p.
|
|
func TestSimulateNotaryRequests(t *testing.T) {
|
|
h := internal.NewLogHandler(t)
|
|
log.Root().SetHandler(h)
|
|
|
|
shardID := 0
|
|
server, err := p2p.NewServer()
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup p2p server: %v", err)
|
|
}
|
|
|
|
simulator, err := NewSimulator(params.DefaultConfig, &mainchain.SMCClient{}, server, shardID, 0)
|
|
if err != nil {
|
|
t.Fatalf("Unable to setup simulator service: %v", err)
|
|
}
|
|
|
|
simulator.requestFeed = server.Feed(messages.CollationBodyRequest{})
|
|
delayChan := make(chan time.Time)
|
|
doneChan := make(chan struct{})
|
|
exitRoutine := make(chan bool)
|
|
|
|
go func() {
|
|
simulator.simulateNotaryRequests(&goodSMCCaller{}, &goodReader{}, delayChan, doneChan)
|
|
<-exitRoutine
|
|
}()
|
|
|
|
delayChan <- time.Time{}
|
|
doneChan <- struct{}{}
|
|
|
|
h.VerifyLogMsg("Sent request for collation body via a shardp2p feed")
|
|
|
|
exitRoutine <- true
|
|
h.VerifyLogMsg("Simulator context closed, exiting goroutine")
|
|
}
|