3d57e377a4
- follow up locks and fix them - chainManager: call SetQueued for parentErr future blocks, uncomment TD checks, unskip test - make ErrIncorrectTD non-fatal to be forgiving to genuine mistaken nodes (temp) but demote them to guard against stuck best peers. - add purging to bounded nodeCache (config nodeCacheSize) - use nodeCache when creating blockpool entries and let non-best peers add blocks (performance boost) - minor error in addError - reduce idleBestPeerTimeout to 1 minute - correct status counts and unskip status passing status test - glogified logging
225 lines
5.9 KiB
Go
225 lines
5.9 KiB
Go
package blockpool
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/pow"
|
|
)
|
|
|
|
func TestInvalidBlock(t *testing.T) {
|
|
_, blockPool, blockPoolTester := newTestBlockPool(t)
|
|
blockPoolTester.blockChain[0] = nil
|
|
blockPoolTester.initRefBlockChain(2)
|
|
blockPoolTester.refBlockChain[2] = []int{}
|
|
|
|
blockPool.Start()
|
|
|
|
peer1 := blockPoolTester.newPeer("peer1", 1, 3)
|
|
peer1.AddPeer()
|
|
go peer1.serveBlocks(2, 3)
|
|
go peer1.serveBlockHashes(3, 2, 1, 0)
|
|
peer1.serveBlocks(0, 1, 2)
|
|
|
|
blockPool.Wait(waitTimeout)
|
|
blockPool.Stop()
|
|
blockPoolTester.refBlockChain[2] = []int{}
|
|
blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain)
|
|
if len(peer1.peerErrors) == 1 {
|
|
if peer1.peerErrors[0] != ErrInvalidBlock {
|
|
t.Errorf("wrong error, got %v, expected %v", peer1.peerErrors[0], ErrInvalidBlock)
|
|
}
|
|
} else {
|
|
t.Errorf("expected %v error, got %v", ErrInvalidBlock, peer1.peerErrors)
|
|
}
|
|
}
|
|
|
|
func TestVerifyPoW(t *testing.T) {
|
|
t.Skip() // :FIXME:
|
|
|
|
_, blockPool, blockPoolTester := newTestBlockPool(t)
|
|
blockPoolTester.blockChain[0] = nil
|
|
blockPoolTester.initRefBlockChain(3)
|
|
first := false
|
|
blockPoolTester.blockPool.verifyPoW = func(b pow.Block) bool {
|
|
bb, _ := b.(*types.Block)
|
|
indexes := blockPoolTester.hashPool.HashesToIndexes([]common.Hash{bb.Hash()})
|
|
if indexes[0] == 2 && !first {
|
|
first = true
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
|
|
}
|
|
|
|
blockPool.Start()
|
|
|
|
peer1 := blockPoolTester.newPeer("peer1", 1, 3)
|
|
peer2 := blockPoolTester.newPeer("peer2", 1, 3)
|
|
peer1.AddPeer()
|
|
peer2.AddPeer()
|
|
go peer1.serveBlocks(2, 3)
|
|
go peer1.serveBlockHashes(3, 2, 1, 0)
|
|
peer1.serveBlocks(0, 1, 2, 3)
|
|
blockPoolTester.blockPool.verifyPoW = func(b pow.Block) bool {
|
|
return true
|
|
}
|
|
peer2.serveBlocks(1, 2)
|
|
|
|
blockPool.Wait(waitTimeout)
|
|
blockPool.Stop()
|
|
blockPoolTester.refBlockChain[3] = []int{}
|
|
blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain)
|
|
if len(peer1.peerErrors) == 1 {
|
|
if peer1.peerErrors[0] != ErrInvalidPoW {
|
|
t.Errorf("wrong error, expected %v, got %v", ErrInvalidPoW, peer1.peerErrors[0])
|
|
}
|
|
} else {
|
|
t.Errorf("expected %v error, got %v", ErrInvalidPoW, peer1.peerErrors)
|
|
}
|
|
}
|
|
|
|
func TestUnrequestedBlock(t *testing.T) {
|
|
t.Skip() // :FIXME:
|
|
|
|
_, blockPool, blockPoolTester := newTestBlockPool(t)
|
|
blockPoolTester.blockChain[0] = nil
|
|
blockPool.Start()
|
|
|
|
peer1 := blockPoolTester.newPeer("peer1", 1, 3)
|
|
peer1.AddPeer()
|
|
peer1.sendBlocks(1, 2)
|
|
|
|
blockPool.Stop()
|
|
if len(peer1.peerErrors) == 1 {
|
|
if peer1.peerErrors[0] != ErrUnrequestedBlock {
|
|
t.Errorf("wrong error, got %v, expected %v", peer1.peerErrors[0], ErrUnrequestedBlock)
|
|
}
|
|
} else {
|
|
t.Errorf("expected %v error, got %v", ErrUnrequestedBlock, peer1.peerErrors)
|
|
}
|
|
}
|
|
|
|
func TestErrInsufficientChainInfo(t *testing.T) {
|
|
_, blockPool, blockPoolTester := newTestBlockPool(t)
|
|
blockPool.Config.BlockHashesTimeout = 100 * time.Millisecond
|
|
blockPool.Start()
|
|
|
|
peer1 := blockPoolTester.newPeer("peer1", 1, 3)
|
|
peer1.AddPeer()
|
|
|
|
blockPool.Wait(waitTimeout)
|
|
blockPool.Stop()
|
|
if len(peer1.peerErrors) == 1 {
|
|
if peer1.peerErrors[0] != ErrInsufficientChainInfo {
|
|
t.Errorf("wrong error, got %v, expected %v", peer1.peerErrors[0], ErrInsufficientChainInfo)
|
|
}
|
|
} else {
|
|
t.Errorf("expected %v error, got %v", ErrInsufficientChainInfo, peer1.peerErrors)
|
|
}
|
|
}
|
|
|
|
func TestIncorrectTD(t *testing.T) {
|
|
_, blockPool, blockPoolTester := newTestBlockPool(t)
|
|
blockPoolTester.blockChain[0] = nil
|
|
blockPoolTester.initRefBlockChain(3)
|
|
|
|
blockPool.Start()
|
|
|
|
peer1 := blockPoolTester.newPeer("peer1", 1, 3)
|
|
peer1.AddPeer()
|
|
go peer1.serveBlocks(2, 3)
|
|
go peer1.serveBlockHashes(3, 2, 1, 0)
|
|
peer1.serveBlocks(0, 1, 2)
|
|
|
|
blockPool.Wait(waitTimeout)
|
|
blockPool.Stop()
|
|
blockPoolTester.refBlockChain[3] = []int{}
|
|
blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain)
|
|
if len(peer1.peerErrors) == 1 {
|
|
if peer1.peerErrors[0] != ErrIncorrectTD {
|
|
t.Errorf("wrong error, got %v, expected %v", peer1.peerErrors[0], ErrIncorrectTD)
|
|
}
|
|
} else {
|
|
t.Errorf("expected %v error, got %v", ErrIncorrectTD, peer1.peerErrors)
|
|
}
|
|
}
|
|
|
|
func TestSkipIncorrectTDonFutureBlocks(t *testing.T) {
|
|
_, blockPool, blockPoolTester := newTestBlockPool(t)
|
|
blockPoolTester.blockChain[0] = nil
|
|
blockPoolTester.initRefBlockChain(3)
|
|
|
|
blockPool.insertChain = func(blocks types.Blocks) error {
|
|
err := blockPoolTester.insertChain(blocks)
|
|
if err == nil {
|
|
for _, block := range blocks {
|
|
if block.Td.Cmp(common.Big3) == 0 {
|
|
block.Td = common.Big3
|
|
block.SetQueued(true)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
|
|
blockPool.Start()
|
|
|
|
peer1 := blockPoolTester.newPeer("peer1", 3, 3)
|
|
peer1.AddPeer()
|
|
go peer1.serveBlocks(2, 3)
|
|
go peer1.serveBlockHashes(3, 2, 1, 0)
|
|
peer1.serveBlocks(0, 1, 2)
|
|
|
|
blockPool.Wait(waitTimeout)
|
|
blockPool.Stop()
|
|
blockPoolTester.refBlockChain[3] = []int{}
|
|
blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain)
|
|
if len(peer1.peerErrors) > 0 {
|
|
t.Errorf("expected no error, got %v (1 of %v)", peer1.peerErrors[0], len(peer1.peerErrors))
|
|
}
|
|
}
|
|
|
|
func TestPeerSuspension(t *testing.T) {
|
|
_, blockPool, blockPoolTester := newTestBlockPool(t)
|
|
blockPool.Config.PeerSuspensionInterval = 100 * time.Millisecond
|
|
|
|
blockPool.Start()
|
|
|
|
peer1 := blockPoolTester.newPeer("peer1", 3, 3)
|
|
peer1.AddPeer()
|
|
bestpeer, _ := blockPool.peers.getPeer("peer1")
|
|
if bestpeer == nil {
|
|
t.Errorf("peer1 not best peer")
|
|
return
|
|
}
|
|
peer1.serveBlocks(2, 3)
|
|
|
|
blockPool.peers.peerError("peer1", 0, "")
|
|
bestpeer, _ = blockPool.peers.getPeer("peer1")
|
|
if bestpeer != nil {
|
|
t.Errorf("peer1 not removed on error")
|
|
return
|
|
}
|
|
peer1.AddPeer()
|
|
bestpeer, _ = blockPool.peers.getPeer("peer1")
|
|
if bestpeer != nil {
|
|
t.Errorf("peer1 not removed on reconnect")
|
|
return
|
|
}
|
|
time.Sleep(100 * time.Millisecond)
|
|
peer1.AddPeer()
|
|
|
|
bestpeer, _ = blockPool.peers.getPeer("peer1")
|
|
if bestpeer == nil {
|
|
t.Errorf("peer1 not connected after PeerSuspensionInterval")
|
|
return
|
|
}
|
|
blockPool.Stop()
|
|
|
|
}
|