mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 19:50:36 +00:00
198 lines
5.9 KiB
Go
198 lines
5.9 KiB
Go
package sentry
|
|
|
|
import (
|
|
"context"
|
|
"math/big"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/holiman/uint256"
|
|
"github.com/ledgerwatch/erigon-lib/chain"
|
|
"github.com/ledgerwatch/erigon-lib/common/datadir"
|
|
"github.com/ledgerwatch/erigon-lib/direct"
|
|
"github.com/ledgerwatch/erigon-lib/gointerfaces"
|
|
proto_sentry "github.com/ledgerwatch/erigon-lib/gointerfaces/sentry"
|
|
"github.com/ledgerwatch/erigon-lib/kv"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
|
"github.com/ledgerwatch/erigon/core"
|
|
"github.com/ledgerwatch/erigon/core/forkid"
|
|
"github.com/ledgerwatch/erigon/core/rawdb"
|
|
"github.com/ledgerwatch/erigon/core/state/temporal"
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
"github.com/ledgerwatch/erigon/p2p"
|
|
)
|
|
|
|
func testSentryServer(db kv.Getter, genesis *types.Genesis, genesisHash libcommon.Hash) *GrpcServer {
|
|
s := &GrpcServer{
|
|
ctx: context.Background(),
|
|
}
|
|
|
|
head := rawdb.ReadCurrentHeader(db)
|
|
headTd, err := rawdb.ReadTd(db, head.Hash(), head.Number.Uint64())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
headTd256 := new(uint256.Int)
|
|
headTd256.SetFromBig(headTd)
|
|
heightForks, timeForks := forkid.GatherForks(genesis.Config, genesis.Timestamp)
|
|
s.statusData = &proto_sentry.StatusData{
|
|
NetworkId: 1,
|
|
TotalDifficulty: gointerfaces.ConvertUint256IntToH256(headTd256),
|
|
BestHash: gointerfaces.ConvertHashToH256(head.Hash()),
|
|
MaxBlockHeight: head.Number.Uint64(),
|
|
MaxBlockTime: head.Time,
|
|
ForkData: &proto_sentry.Forks{
|
|
Genesis: gointerfaces.ConvertHashToH256(genesisHash),
|
|
HeightForks: heightForks,
|
|
TimeForks: timeForks,
|
|
},
|
|
}
|
|
return s
|
|
|
|
}
|
|
|
|
func startHandshake(
|
|
ctx context.Context,
|
|
status *proto_sentry.StatusData,
|
|
pipe *p2p.MsgPipeRW,
|
|
protocolVersion uint,
|
|
errChan chan *p2p.PeerError,
|
|
) {
|
|
go func() {
|
|
_, err := handShake(ctx, status, pipe, protocolVersion, protocolVersion)
|
|
errChan <- err
|
|
}()
|
|
}
|
|
|
|
// Tests that peers are correctly accepted (or rejected) based on the advertised
|
|
// fork IDs in the protocol handshake.
|
|
func TestForkIDSplit66(t *testing.T) { testForkIDSplit(t, direct.ETH66) }
|
|
|
|
func testForkIDSplit(t *testing.T, protocol uint) {
|
|
var (
|
|
ctx = context.Background()
|
|
configNoFork = &chain.Config{HomesteadBlock: big.NewInt(1), ChainID: big.NewInt(1)}
|
|
configProFork = &chain.Config{
|
|
ChainID: big.NewInt(1),
|
|
HomesteadBlock: big.NewInt(1),
|
|
TangerineWhistleBlock: big.NewInt(2),
|
|
SpuriousDragonBlock: big.NewInt(2),
|
|
ByzantiumBlock: big.NewInt(3),
|
|
}
|
|
_, dbNoFork, _ = temporal.NewTestDB(t, datadir.New(t.TempDir()), nil)
|
|
_, dbProFork, _ = temporal.NewTestDB(t, datadir.New(t.TempDir()), nil)
|
|
|
|
gspecNoFork = &types.Genesis{Config: configNoFork}
|
|
gspecProFork = &types.Genesis{Config: configProFork}
|
|
|
|
genesisNoFork = core.MustCommitGenesis(gspecNoFork, dbNoFork, "")
|
|
genesisProFork = core.MustCommitGenesis(gspecProFork, dbProFork, "")
|
|
)
|
|
|
|
var s1, s2 *GrpcServer
|
|
|
|
err := dbNoFork.Update(context.Background(), func(tx kv.RwTx) error {
|
|
s1 = testSentryServer(tx, gspecNoFork, genesisNoFork.Hash())
|
|
return nil
|
|
})
|
|
require.NoError(t, err)
|
|
err = dbProFork.Update(context.Background(), func(tx kv.RwTx) error {
|
|
s2 = testSentryServer(tx, gspecProFork, genesisProFork.Hash())
|
|
return nil
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Both nodes should allow the other to connect (same genesis, next fork is the same)
|
|
p2pNoFork, p2pProFork := p2p.MsgPipe()
|
|
defer p2pNoFork.Close()
|
|
defer p2pProFork.Close()
|
|
|
|
errc := make(chan *p2p.PeerError, 2)
|
|
startHandshake(ctx, s1.GetStatus(), p2pNoFork, protocol, errc)
|
|
startHandshake(ctx, s2.GetStatus(), p2pProFork, protocol, errc)
|
|
|
|
for i := 0; i < 2; i++ {
|
|
select {
|
|
case err := <-errc:
|
|
if err != nil {
|
|
t.Fatalf("frontier nofork <-> profork failed: %v", err)
|
|
}
|
|
case <-time.After(250 * time.Millisecond):
|
|
t.Fatalf("frontier nofork <-> profork handler timeout")
|
|
}
|
|
}
|
|
|
|
// Progress into Homestead. Fork's match, so we don't care what the future holds
|
|
s1.statusData.MaxBlockHeight = 1
|
|
s2.statusData.MaxBlockHeight = 1
|
|
|
|
startHandshake(ctx, s1.GetStatus(), p2pNoFork, protocol, errc)
|
|
startHandshake(ctx, s2.GetStatus(), p2pProFork, protocol, errc)
|
|
|
|
for i := 0; i < 2; i++ {
|
|
select {
|
|
case err := <-errc:
|
|
if err != nil {
|
|
t.Fatalf("homestead nofork <-> profork failed: %v", err)
|
|
}
|
|
case <-time.After(250 * time.Millisecond):
|
|
t.Fatalf("frontier nofork <-> profork handler timeout")
|
|
}
|
|
}
|
|
|
|
// Progress into Spurious. Forks mismatch, signalling differing chains, reject
|
|
s1.statusData.MaxBlockHeight = 2
|
|
s2.statusData.MaxBlockHeight = 2
|
|
|
|
// Both nodes should allow the other to connect (same genesis, next fork is the same)
|
|
startHandshake(ctx, s1.GetStatus(), p2pNoFork, protocol, errc)
|
|
startHandshake(ctx, s2.GetStatus(), p2pProFork, protocol, errc)
|
|
|
|
var successes int
|
|
for i := 0; i < 2; i++ {
|
|
select {
|
|
case err := <-errc:
|
|
if err == nil {
|
|
successes++
|
|
if successes == 2 { // Only one side disconnects
|
|
t.Fatalf("fork ID rejection didn't happen")
|
|
}
|
|
}
|
|
case <-time.After(250 * time.Millisecond):
|
|
t.Fatalf("split peers not rejected")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSentryServerImpl_SetStatusInitPanic(t *testing.T) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
t.Fatalf("panic during server initialization")
|
|
}
|
|
}()
|
|
|
|
configNoFork := &chain.Config{HomesteadBlock: big.NewInt(1), ChainID: big.NewInt(1)}
|
|
_, dbNoFork, _ := temporal.NewTestDB(t, datadir.New(t.TempDir()), nil)
|
|
gspecNoFork := &types.Genesis{Config: configNoFork}
|
|
genesisNoFork := core.MustCommitGenesis(gspecNoFork, dbNoFork, "")
|
|
ss := &GrpcServer{p2p: &p2p.Config{}}
|
|
|
|
_, err := ss.SetStatus(context.Background(), &proto_sentry.StatusData{
|
|
ForkData: &proto_sentry.Forks{Genesis: gointerfaces.ConvertHashToH256(genesisNoFork.Hash())},
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("error expected")
|
|
}
|
|
|
|
// Should not panic here.
|
|
_, err = ss.SetStatus(context.Background(), &proto_sentry.StatusData{
|
|
ForkData: &proto_sentry.Forks{Genesis: gointerfaces.ConvertHashToH256(genesisNoFork.Hash())},
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("error expected")
|
|
}
|
|
}
|