Commit 50661f0e authored by zelig's avatar zelig

peer suspension to disallow reconnect after disconnect on fatal error for set...

 peer suspension to disallow reconnect after disconnect on fatal error for set period (PeerSuspensionInterval)
parent 01ff0b31
...@@ -33,7 +33,8 @@ var ( ...@@ -33,7 +33,8 @@ var (
// timeout interval: max time allowed for peer without sending a block // timeout interval: max time allowed for peer without sending a block
blocksTimeout = 60 * time.Second blocksTimeout = 60 * time.Second
// //
idleBestPeerTimeout = 120 * time.Second idleBestPeerTimeout = 120 * time.Second
peerSuspensionInterval = 300 * time.Second
) )
// config embedded in components, by default fall back to constants // config embedded in components, by default fall back to constants
...@@ -48,6 +49,7 @@ type Config struct { ...@@ -48,6 +49,7 @@ type Config struct {
BlockHashesTimeout time.Duration BlockHashesTimeout time.Duration
BlocksTimeout time.Duration BlocksTimeout time.Duration
IdleBestPeerTimeout time.Duration IdleBestPeerTimeout time.Duration
PeerSuspensionInterval time.Duration
} }
// blockpool errors // blockpool errors
...@@ -96,6 +98,9 @@ func (self *Config) init() { ...@@ -96,6 +98,9 @@ func (self *Config) init() {
if self.IdleBestPeerTimeout == 0 { if self.IdleBestPeerTimeout == 0 {
self.IdleBestPeerTimeout = idleBestPeerTimeout self.IdleBestPeerTimeout = idleBestPeerTimeout
} }
if self.PeerSuspensionInterval == 0 {
self.PeerSuspensionInterval = peerSuspensionInterval
}
} }
// node is the basic unit of the internal model of block chain/tree in the blockpool // node is the basic unit of the internal model of block chain/tree in the blockpool
...@@ -188,9 +193,10 @@ func (self *BlockPool) Start() { ...@@ -188,9 +193,10 @@ func (self *BlockPool) Start() {
Errors: errorToString, Errors: errorToString,
Level: severity, Level: severity,
}, },
peers: make(map[string]*peer), peers: make(map[string]*peer),
status: self.status, blacklist: make(map[string]time.Time),
bp: self, status: self.status,
bp: self,
} }
timer := time.NewTicker(3 * time.Second) timer := time.NewTicker(3 * time.Second)
go func() { go func() {
...@@ -267,7 +273,8 @@ func (self *BlockPool) AddPeer( ...@@ -267,7 +273,8 @@ func (self *BlockPool) AddPeer(
requestBlocks func([]common.Hash) error, requestBlocks func([]common.Hash) error,
peerError func(*errs.Error), peerError func(*errs.Error),
) (best bool) { ) (best bool, suspended bool) {
return self.peers.addPeer(td, currentBlockHash, peerId, requestBlockHashes, requestBlocks, peerError) return self.peers.addPeer(td, currentBlockHash, peerId, requestBlockHashes, requestBlocks, peerError)
} }
......
...@@ -5,8 +5,8 @@ import ( ...@@ -5,8 +5,8 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/blockpool/test" "github.com/ethereum/go-ethereum/blockpool/test"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
) )
func TestPeerWithKnownBlock(t *testing.T) { func TestPeerWithKnownBlock(t *testing.T) {
...@@ -69,8 +69,8 @@ func TestPeerPromotionByOptionalTdOnBlock(t *testing.T) { ...@@ -69,8 +69,8 @@ func TestPeerPromotionByOptionalTdOnBlock(t *testing.T) {
hashes := blockPoolTester.hashPool.IndexesToHashes([]int{2, 3}) hashes := blockPoolTester.hashPool.IndexesToHashes([]int{2, 3})
peer1.waitBlocksRequests(3) peer1.waitBlocksRequests(3)
blockPool.AddBlock(&types.Block{ blockPool.AddBlock(&types.Block{
HeaderHash: common.Bytes(hashes[1]), HeaderHash: common.Hash(hashes[1]),
ParentHeaderHash: common.Bytes(hashes[0]), ParentHeaderHash: common.Hash(hashes[0]),
Td: common.Big3, Td: common.Big3,
}, "peer1") }, "peer1")
......
...@@ -8,9 +8,9 @@ import ( ...@@ -8,9 +8,9 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/blockpool/test" "github.com/ethereum/go-ethereum/blockpool/test"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/errs" "github.com/ethereum/go-ethereum/errs"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/pow"
) )
...@@ -63,10 +63,10 @@ func (self *blockPoolTester) Errorf(format string, params ...interface{}) { ...@@ -63,10 +63,10 @@ func (self *blockPoolTester) Errorf(format string, params ...interface{}) {
// blockPoolTester implements the 3 callbacks needed by the blockPool: // blockPoolTester implements the 3 callbacks needed by the blockPool:
// hasBlock, insetChain, verifyPoW // hasBlock, insetChain, verifyPoW
func (self *blockPoolTester) hasBlock(block []byte) (ok bool) { func (self *blockPoolTester) hasBlock(block common.Hash) (ok bool) {
self.lock.RLock() self.lock.RLock()
defer self.lock.RUnlock() defer self.lock.RUnlock()
indexes := self.hashPool.HashesToIndexes([][]byte{block}) indexes := self.hashPool.HashesToIndexes([]common.Hash{block})
i := indexes[0] i := indexes[0]
_, ok = self.blockChain[i] _, ok = self.blockChain[i]
fmt.Printf("has block %v (%x...): %v\n", i, block[0:4], ok) fmt.Printf("has block %v (%x...): %v\n", i, block[0:4], ok)
...@@ -80,13 +80,13 @@ func (self *blockPoolTester) insertChain(blocks types.Blocks) error { ...@@ -80,13 +80,13 @@ func (self *blockPoolTester) insertChain(blocks types.Blocks) error {
var children, refChildren []int var children, refChildren []int
var ok bool var ok bool
for _, block := range blocks { for _, block := range blocks {
child = self.hashPool.HashesToIndexes([][]byte{block.Hash()})[0] child = self.hashPool.HashesToIndexes([]common.Hash{block.Hash()})[0]
_, ok = self.blockChain[child] _, ok = self.blockChain[child]
if ok { if ok {
fmt.Printf("block %v already in blockchain\n", child) fmt.Printf("block %v already in blockchain\n", child)
continue // already in chain continue // already in chain
} }
parent = self.hashPool.HashesToIndexes([][]byte{block.ParentHeaderHash})[0] parent = self.hashPool.HashesToIndexes([]common.Hash{block.ParentHeaderHash})[0]
children, ok = self.blockChain[parent] children, ok = self.blockChain[parent]
if !ok { if !ok {
return fmt.Errorf("parent %v not in blockchain ", parent) return fmt.Errorf("parent %v not in blockchain ", parent)
...@@ -274,9 +274,10 @@ func (self *blockPoolTester) initRefBlockChain(n int) { ...@@ -274,9 +274,10 @@ func (self *blockPoolTester) initRefBlockChain(n int) {
// peerTester functions that mimic protocol calls to the blockpool // peerTester functions that mimic protocol calls to the blockpool
// registers the peer with the blockPool // registers the peer with the blockPool
func (self *peerTester) AddPeer() bool { func (self *peerTester) AddPeer() (best bool) {
hash := self.hashPool.IndexesToHashes([]int{self.currentBlock})[0] hash := self.hashPool.IndexesToHashes([]int{self.currentBlock})[0]
return self.blockPool.AddPeer(big.NewInt(int64(self.td)), hash, self.id, self.requestBlockHashes, self.requestBlocks, self.peerError) best, _ = self.blockPool.AddPeer(big.NewInt(int64(self.td)), hash, self.id, self.requestBlockHashes, self.requestBlocks, self.peerError)
return
} }
// peer sends blockhashes if and when gets a request // peer sends blockhashes if and when gets a request
...@@ -291,7 +292,7 @@ func (self *peerTester) sendBlockHashes(indexes ...int) { ...@@ -291,7 +292,7 @@ func (self *peerTester) sendBlockHashes(indexes ...int) {
fmt.Printf("adding block hashes %v\n", indexes) fmt.Printf("adding block hashes %v\n", indexes)
hashes := self.hashPool.IndexesToHashes(indexes) hashes := self.hashPool.IndexesToHashes(indexes)
i := 1 i := 1
next := func() (hash []byte, ok bool) { next := func() (hash common.Hash, ok bool) {
if i < len(hashes) { if i < len(hashes) {
hash = hashes[i] hash = hashes[i]
ok = true ok = true
...@@ -315,15 +316,15 @@ func (self *peerTester) sendBlocks(indexes ...int) { ...@@ -315,15 +316,15 @@ func (self *peerTester) sendBlocks(indexes ...int) {
hashes := self.hashPool.IndexesToHashes(indexes) hashes := self.hashPool.IndexesToHashes(indexes)
for i := 1; i < len(hashes); i++ { for i := 1; i < len(hashes); i++ {
fmt.Printf("adding block %v %x\n", indexes[i], hashes[i][:4]) fmt.Printf("adding block %v %x\n", indexes[i], hashes[i][:4])
self.blockPool.AddBlock(&types.Block{HeaderHash: common.Bytes(hashes[i]), ParentHeaderHash: common.Bytes(hashes[i-1])}, self.id) self.blockPool.AddBlock(&types.Block{HeaderHash: hashes[i], ParentHeaderHash: hashes[i-1]}, self.id)
} }
} }
// peer callbacks // peer callbacks
// -1 is special: not found (a hash never seen) // -1 is special: not found (a hash never seen)
// records block hashes requests by the blockPool // records block hashes requests by the blockPool
func (self *peerTester) requestBlockHashes(hash []byte) error { func (self *peerTester) requestBlockHashes(hash common.Hash) error {
indexes := self.hashPool.HashesToIndexes([][]byte{hash}) indexes := self.hashPool.HashesToIndexes([]common.Hash{hash})
fmt.Printf("[%s] block hash request %v %x\n", self.id, indexes[0], hash[:4]) fmt.Printf("[%s] block hash request %v %x\n", self.id, indexes[0], hash[:4])
self.lock.Lock() self.lock.Lock()
defer self.lock.Unlock() defer self.lock.Unlock()
...@@ -332,7 +333,7 @@ func (self *peerTester) requestBlockHashes(hash []byte) error { ...@@ -332,7 +333,7 @@ func (self *peerTester) requestBlockHashes(hash []byte) error {
} }
// records block requests by the blockPool // records block requests by the blockPool
func (self *peerTester) requestBlocks(hashes [][]byte) error { func (self *peerTester) requestBlocks(hashes []common.Hash) error {
indexes := self.hashPool.HashesToIndexes(hashes) indexes := self.hashPool.HashesToIndexes(hashes)
fmt.Printf("blocks request %v %x...\n", indexes, hashes[0][:4]) fmt.Printf("blocks request %v %x...\n", indexes, hashes[0][:4])
self.bt.reqlock.Lock() self.bt.reqlock.Lock()
...@@ -347,4 +348,9 @@ func (self *peerTester) requestBlocks(hashes [][]byte) error { ...@@ -347,4 +348,9 @@ func (self *peerTester) requestBlocks(hashes [][]byte) error {
// records the error codes of all the peerErrors found the blockPool // records the error codes of all the peerErrors found the blockPool
func (self *peerTester) peerError(err *errs.Error) { func (self *peerTester) peerError(err *errs.Error) {
self.peerErrors = append(self.peerErrors, err.Code) self.peerErrors = append(self.peerErrors, err.Code)
fmt.Printf("Error %v on peer %v\n", err, self.id)
if err.Fatal() {
fmt.Printf("Error %v is fatal, removing peer %v\n", err, self.id)
self.blockPool.RemovePeer(self.id)
}
} }
...@@ -21,12 +21,13 @@ func TestBlockPoolConfig(t *testing.T) { ...@@ -21,12 +21,13 @@ func TestBlockPoolConfig(t *testing.T) {
test.CheckDuration("BlockHashesTimeout", c.BlockHashesTimeout, blockHashesTimeout, t) test.CheckDuration("BlockHashesTimeout", c.BlockHashesTimeout, blockHashesTimeout, t)
test.CheckDuration("BlocksTimeout", c.BlocksTimeout, blocksTimeout, t) test.CheckDuration("BlocksTimeout", c.BlocksTimeout, blocksTimeout, t)
test.CheckDuration("IdleBestPeerTimeout", c.IdleBestPeerTimeout, idleBestPeerTimeout, t) test.CheckDuration("IdleBestPeerTimeout", c.IdleBestPeerTimeout, idleBestPeerTimeout, t)
test.CheckDuration("PeerSuspensionInterval", c.PeerSuspensionInterval, peerSuspensionInterval, t)
} }
func TestBlockPoolOverrideConfig(t *testing.T) { func TestBlockPoolOverrideConfig(t *testing.T) {
test.LogInit() test.LogInit()
blockPool := &BlockPool{Config: &Config{}} blockPool := &BlockPool{Config: &Config{}}
c := &Config{128, 32, 1, 0, 300 * time.Millisecond, 100 * time.Millisecond, 90 * time.Second, 0, 30 * time.Second} c := &Config{128, 32, 1, 0, 300 * time.Millisecond, 100 * time.Millisecond, 90 * time.Second, 0, 30 * time.Second, 30 * time.Second}
blockPool.Config = c blockPool.Config = c
blockPool.Start() blockPool.Start()
...@@ -39,4 +40,5 @@ func TestBlockPoolOverrideConfig(t *testing.T) { ...@@ -39,4 +40,5 @@ func TestBlockPoolOverrideConfig(t *testing.T) {
test.CheckDuration("BlockHashesTimeout", c.BlockHashesTimeout, 90*time.Second, t) test.CheckDuration("BlockHashesTimeout", c.BlockHashesTimeout, 90*time.Second, t)
test.CheckDuration("BlocksTimeout", c.BlocksTimeout, blocksTimeout, t) test.CheckDuration("BlocksTimeout", c.BlocksTimeout, blocksTimeout, t)
test.CheckDuration("IdleBestPeerTimeout", c.IdleBestPeerTimeout, 30*time.Second, t) test.CheckDuration("IdleBestPeerTimeout", c.IdleBestPeerTimeout, 30*time.Second, t)
test.CheckDuration("PeerSuspensionInterval", c.PeerSuspensionInterval, 30*time.Second, t)
} }
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/blockpool/test" "github.com/ethereum/go-ethereum/blockpool/test"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/pow"
) )
...@@ -45,7 +46,7 @@ func TestVerifyPoW(t *testing.T) { ...@@ -45,7 +46,7 @@ func TestVerifyPoW(t *testing.T) {
first := false first := false
blockPoolTester.blockPool.verifyPoW = func(b pow.Block) bool { blockPoolTester.blockPool.verifyPoW = func(b pow.Block) bool {
bb, _ := b.(*types.Block) bb, _ := b.(*types.Block)
indexes := blockPoolTester.hashPool.HashesToIndexes([][]byte{bb.Hash()}) indexes := blockPoolTester.hashPool.HashesToIndexes([]common.Hash{bb.Hash()})
if indexes[0] == 2 && !first { if indexes[0] == 2 && !first {
first = true first = true
return false return false
...@@ -122,3 +123,33 @@ func TestErrInsufficientChainInfo(t *testing.T) { ...@@ -122,3 +123,33 @@ func TestErrInsufficientChainInfo(t *testing.T) {
t.Errorf("expected %v error, got %v", ErrInsufficientChainInfo, peer1.peerErrors) t.Errorf("expected %v error, got %v", ErrInsufficientChainInfo, peer1.peerErrors)
} }
} }
func TestPeerSuspension(t *testing.T) {
test.LogInit()
_, blockPool, blockPoolTester := newTestBlockPool(t)
blockPool.Config.PeerSuspensionInterval = 100 * time.Millisecond
blockPool.Start()
peer1 := blockPoolTester.newPeer("peer1", 1, 3)
peer1.AddPeer()
blockPool.peers.peerError("peer1", 0, "")
bestpeer, _ := blockPool.peers.getPeer("peer1")
if bestpeer != nil {
t.Errorf("peer1 not removed on error")
}
peer1.AddPeer()
bestpeer, _ = blockPool.peers.getPeer("peer1")
if bestpeer != nil {
t.Errorf("peer1 not removed on reconnect")
}
time.Sleep(100 * time.Millisecond)
peer1.AddPeer()
bestpeer, _ = blockPool.peers.getPeer("peer1")
if bestpeer == nil {
t.Errorf("peer1 not connected after PeerSuspensionInterval")
}
// blockPool.Wait(waitTimeout)
blockPool.Stop()
}
...@@ -47,6 +47,8 @@ type peer struct { ...@@ -47,6 +47,8 @@ type peer struct {
blocksRequestTimer <-chan time.Time blocksRequestTimer <-chan time.Time
suicideC <-chan time.Time suicideC <-chan time.Time
addToBlacklist func(id string)
idle bool idle bool
} }
...@@ -55,11 +57,12 @@ type peer struct { ...@@ -55,11 +57,12 @@ type peer struct {
type peers struct { type peers struct {
lock sync.RWMutex lock sync.RWMutex
bp *BlockPool bp *BlockPool
errors *errs.Errors errors *errs.Errors
peers map[string]*peer peers map[string]*peer
best *peer best *peer
status *status status *status
blacklist map[string]time.Time
} }
// peer constructor // peer constructor
...@@ -84,26 +87,46 @@ func (self *peers) newPeer( ...@@ -84,26 +87,46 @@ func (self *peers) newPeer(
headSectionC: make(chan *section), headSectionC: make(chan *section),
bp: self.bp, bp: self.bp,
idle: true, idle: true,
addToBlacklist: self.addToBlacklist,
} }
// at creation the peer is recorded in the peer pool // at creation the peer is recorded in the peer pool
self.peers[id] = p self.peers[id] = p
return return
} }
// dispatches an error to a peer if still connected // dispatches an error to a peer if still connected, adds it to the blacklist
func (self *peers) peerError(id string, code int, format string, params ...interface{}) { func (self *peers) peerError(id string, code int, format string, params ...interface{}) {
self.lock.RLock() self.lock.RLock()
defer self.lock.RUnlock()
peer, ok := self.peers[id] peer, ok := self.peers[id]
self.lock.RUnlock()
if ok { if ok {
peer.addError(code, format, params) peer.addError(code, format, params)
} }
// blacklisting comes here self.addToBlacklist(id)
}
func (self *peers) addToBlacklist(id string) {
self.lock.Lock()
defer self.lock.Unlock()
self.blacklist[id] = time.Now()
}
func (self *peers) suspended(id string) (s bool) {
self.lock.Lock()
defer self.lock.Unlock()
if suspendedAt, ok := self.blacklist[id]; ok {
if s = suspendedAt.Add(self.bp.Config.PeerSuspensionInterval).After(time.Now()); !s {
// no longer suspended, delete entry
delete(self.blacklist, id)
}
}
return
} }
func (self *peer) addError(code int, format string, params ...interface{}) { func (self *peer) addError(code int, format string, params ...interface{}) {
err := self.errors.New(code, format, params...) err := self.errors.New(code, format, params...)
self.peerError(err) self.peerError(err)
self.addToBlacklist(self.id)
} }
func (self *peer) setChainInfo(td *big.Int, c common.Hash) { func (self *peer) setChainInfo(td *big.Int, c common.Hash) {
...@@ -182,9 +205,13 @@ func (self *peers) addPeer( ...@@ -182,9 +205,13 @@ func (self *peers) addPeer(
requestBlockHashes func(common.Hash) error, requestBlockHashes func(common.Hash) error,
requestBlocks func([]common.Hash) error, requestBlocks func([]common.Hash) error,
peerError func(*errs.Error), peerError func(*errs.Error),
) (best bool) { ) (best bool, suspended bool) {
var previousBlockHash common.Hash var previousBlockHash common.Hash
if self.suspended(id) {
suspended = true
return
}
self.lock.Lock() self.lock.Lock()
p, found := self.peers[id] p, found := self.peers[id]
if found { if found {
...@@ -213,7 +240,7 @@ func (self *peers) addPeer( ...@@ -213,7 +240,7 @@ func (self *peers) addPeer(
if self.bp.hasBlock(currentBlockHash) { if self.bp.hasBlock(currentBlockHash) {
// peer not ahead // peer not ahead
plog.Debugf("addPeer: peer <%v> with td %v and current block %s is behind", id, td, hex(currentBlockHash)) plog.Debugf("addPeer: peer <%v> with td %v and current block %s is behind", id, td, hex(currentBlockHash))
return false return false, false
} }
if self.best == p { if self.best == p {
...@@ -248,8 +275,10 @@ func (self *peers) addPeer( ...@@ -248,8 +275,10 @@ func (self *peers) addPeer(
// removePeer is called (via RemovePeer) by the eth protocol when the peer disconnects // removePeer is called (via RemovePeer) by the eth protocol when the peer disconnects
func (self *peers) removePeer(id string) { func (self *peers) removePeer(id string) {
plog.Debugf("addPeer: remove peer 0 <%v>", id)
self.lock.Lock() self.lock.Lock()
defer self.lock.Unlock() defer self.lock.Unlock()
plog.Debugf("addPeer: remove peer 1 <%v>", id)
p, found := self.peers[id] p, found := self.peers[id]
if !found { if !found {
......
...@@ -3,6 +3,7 @@ package test ...@@ -3,6 +3,7 @@ package test
import ( import (
"sync" "sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
...@@ -13,9 +14,9 @@ func NewHashPool() *TestHashPool { ...@@ -13,9 +14,9 @@ func NewHashPool() *TestHashPool {
return &TestHashPool{intToHash: make(intToHash), hashToInt: make(hashToInt)} return &TestHashPool{intToHash: make(intToHash), hashToInt: make(hashToInt)}
} }
type intToHash map[int][]byte type intToHash map[int]common.Hash
type hashToInt map[string]int type hashToInt map[common.Hash]int
// hashPool is a test helper, that allows random hashes to be referred to by integers // hashPool is a test helper, that allows random hashes to be referred to by integers
type TestHashPool struct { type TestHashPool struct {
...@@ -24,11 +25,11 @@ type TestHashPool struct { ...@@ -24,11 +25,11 @@ type TestHashPool struct {
lock sync.Mutex lock sync.Mutex
} }
func newHash(i int) []byte { func newHash(i int) common.Hash {
return crypto.Sha3([]byte(string(i))) return common.BytesToHash(crypto.Sha3([]byte(string(i))))
} }
func (self *TestHashPool) IndexesToHashes(indexes []int) (hashes [][]byte) { func (self *TestHashPool) IndexesToHashes(indexes []int) (hashes []common.Hash) {
self.lock.Lock() self.lock.Lock()
defer self.lock.Unlock() defer self.lock.Unlock()
for _, i := range indexes { for _, i := range indexes {
...@@ -36,18 +37,18 @@ func (self *TestHashPool) IndexesToHashes(indexes []int) (hashes [][]byte) { ...@@ -36,18 +37,18 @@ func (self *TestHashPool) IndexesToHashes(indexes []int) (hashes [][]byte) {
if !found { if !found {
hash = newHash(i) hash = newHash(i)
self.intToHash[i] = hash self.intToHash[i] = hash
self.hashToInt[string(hash)] = i self.hashToInt[hash] = i
} }
hashes = append(hashes, hash) hashes = append(hashes, hash)
} }
return return
} }
func (self *TestHashPool) HashesToIndexes(hashes [][]byte) (indexes []int) { func (self *TestHashPool) HashesToIndexes(hashes []common.Hash) (indexes []int) {
self.lock.Lock() self.lock.Lock()
defer self.lock.Unlock() defer self.lock.Unlock()
for _, hash := range hashes { for _, hash := range hashes {
i, found := self.hashToInt[string(hash)] i, found := self.hashToInt[hash]
if !found { if !found {
i = -1 i = -1
} }
......
...@@ -42,6 +42,7 @@ const ( ...@@ -42,6 +42,7 @@ const (
ErrGenesisBlockMismatch ErrGenesisBlockMismatch
ErrNoStatusMsg ErrNoStatusMsg
ErrExtraStatusMsg ErrExtraStatusMsg
ErrSuspendedPeer
) )
var errorToString = map[int]string{ var errorToString = map[int]string{
...@@ -53,6 +54,7 @@ var errorToString = map[int]string{ ...@@ -53,6 +54,7 @@ var errorToString = map[int]string{
ErrGenesisBlockMismatch: "Genesis block mismatch", ErrGenesisBlockMismatch: "Genesis block mismatch",
ErrNoStatusMsg: "No status message", ErrNoStatusMsg: "No status message",
ErrExtraStatusMsg: "Extra status message", ErrExtraStatusMsg: "Extra status message",
ErrSuspendedPeer: "Suspended peer",
} }
// ethProtocol represents the ethereum wire protocol // ethProtocol represents the ethereum wire protocol
...@@ -85,7 +87,7 @@ type chainManager interface { ...@@ -85,7 +87,7 @@ type chainManager interface {
type blockPool interface { type blockPool interface {
AddBlockHashes(next func() (common.Hash, bool), peerId string) AddBlockHashes(next func() (common.Hash, bool), peerId string)
AddBlock(block *types.Block, peerId string) AddBlock(block *types.Block, peerId string)
AddPeer(td *big.Int, currentBlock common.Hash, peerId string, requestHashes func(common.Hash) error, requestBlocks func([]common.Hash) error, peerError func(*errs.Error)) (best bool) AddPeer(td *big.Int, currentBlock common.Hash, peerId string, requestHashes func(common.Hash) error, requestBlocks func([]common.Hash) error, peerError func(*errs.Error)) (best bool, suspended bool)
RemovePeer(peerId string) RemovePeer(peerId string)
} }
...@@ -288,7 +290,7 @@ func (self *ethProtocol) handle() error { ...@@ -288,7 +290,7 @@ func (self *ethProtocol) handle() error {
// to simplify backend interface adding a new block // to simplify backend interface adding a new block
// uses AddPeer followed by AddBlock only if peer is the best peer // uses AddPeer followed by AddBlock only if peer is the best peer
// (or selected as new best peer) // (or selected as new best peer)
if self.blockPool.AddPeer(request.TD, hash, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect) { if best, _ := self.blockPool.AddPeer(request.TD, hash, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect); best {
self.blockPool.AddBlock(request.Block, self.id) self.blockPool.AddBlock(request.Block, self.id)
} }
...@@ -334,9 +336,12 @@ func (self *ethProtocol) handleStatus() error { ...@@ -334,9 +336,12 @@ func (self *ethProtocol) handleStatus() error {
return self.protoError(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, self.protocolVersion) return self.protoError(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, self.protocolVersion)
} }
self.peer.Infof("Peer is [eth] capable (%d/%d). TD=%v H=%x\n", status.ProtocolVersion, status.NetworkId, status.TD, status.CurrentBlock[:4]) _, suspended := self.blockPool.AddPeer(status.TD, status.CurrentBlock, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect)
if suspended {
return self.protoError(ErrSuspendedPeer, "")
}
self.blockPool.AddPeer(status.TD, status.CurrentBlock, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect) self.peer.Infof("Peer is [eth] capable (%d/%d). TD=%v H=%x\n", status.ProtocolVersion, status.NetworkId, status.TD, status.CurrentBlock[:4])
return nil return nil
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment