Black listing of bad peers
This commit is contained in:
parent
b55e017e62
commit
a75c92000f
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/ethereum/eth-go/ethchain"
|
"github.com/ethereum/eth-go/ethchain"
|
||||||
"github.com/ethereum/eth-go/ethlog"
|
"github.com/ethereum/eth-go/ethlog"
|
||||||
"github.com/ethereum/eth-go/ethutil"
|
"github.com/ethereum/eth-go/ethutil"
|
||||||
|
"github.com/ethereum/eth-go/ethwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
var poollogger = ethlog.NewLogger("BPOOL")
|
var poollogger = ethlog.NewLogger("BPOOL")
|
||||||
@ -38,6 +39,8 @@ type BlockPool struct {
|
|||||||
downloadStartedAt time.Time
|
downloadStartedAt time.Time
|
||||||
|
|
||||||
ChainLength, BlocksProcessed int
|
ChainLength, BlocksProcessed int
|
||||||
|
|
||||||
|
peer *Peer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBlockPool(eth *Ethereum) *BlockPool {
|
func NewBlockPool(eth *Ethereum) *BlockPool {
|
||||||
@ -74,6 +77,27 @@ func (self *BlockPool) Blocks() (blocks ethchain.Blocks) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *BlockPool) FetchHashes(peer *Peer) {
|
||||||
|
highestTd := self.eth.HighestTDPeer()
|
||||||
|
|
||||||
|
if (self.peer == nil && peer.td.Cmp(highestTd) >= 0) || (self.peer != nil && peer.td.Cmp(self.peer.td) >= 0) || self.peer == peer {
|
||||||
|
if self.peer != peer {
|
||||||
|
poollogger.Debugf("Found better suitable peer (%v vs %v)\n", self.td, peer.td)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.peer = peer
|
||||||
|
self.td = peer.td
|
||||||
|
|
||||||
|
if !self.HasLatestHash() {
|
||||||
|
peer.doneFetchingHashes = false
|
||||||
|
|
||||||
|
const amount = 256
|
||||||
|
peerlogger.Debugf("Fetching hashes (%d)\n", amount)
|
||||||
|
peer.QueueMessage(ethwire.NewMessage(ethwire.MsgGetBlockHashesTy, []interface{}{peer.lastReceivedHash, uint32(amount)}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *BlockPool) AddHash(hash []byte, peer *Peer) {
|
func (self *BlockPool) AddHash(hash []byte, peer *Peer) {
|
||||||
self.mut.Lock()
|
self.mut.Lock()
|
||||||
defer self.mut.Unlock()
|
defer self.mut.Unlock()
|
||||||
@ -99,7 +123,7 @@ func (self *BlockPool) Add(b *ethchain.Block, peer *Peer) {
|
|||||||
|
|
||||||
if !self.eth.BlockChain().HasBlock(b.PrevHash) && self.pool[string(b.PrevHash)] == nil && !self.fetchingHashes {
|
if !self.eth.BlockChain().HasBlock(b.PrevHash) && self.pool[string(b.PrevHash)] == nil && !self.fetchingHashes {
|
||||||
poollogger.Infof("Unknown block, requesting parent (%x...)\n", b.PrevHash[0:4])
|
poollogger.Infof("Unknown block, requesting parent (%x...)\n", b.PrevHash[0:4])
|
||||||
//peer.QueueMessage(ethwire.NewMessage(ethwire.MsgGetBlockHashesTy, []interface{}{b.Hash(), uint32(256)}))
|
peer.QueueMessage(ethwire.NewMessage(ethwire.MsgGetBlockHashesTy, []interface{}{b.Hash(), uint32(256)}))
|
||||||
}
|
}
|
||||||
} else if self.pool[hash] != nil {
|
} else if self.pool[hash] != nil {
|
||||||
self.pool[hash].block = b
|
self.pool[hash].block = b
|
||||||
@ -227,7 +251,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *BlockPool) chainThread() {
|
func (self *BlockPool) chainThread() {
|
||||||
procTimer := time.NewTicker(500 * time.Millisecond)
|
procTimer := time.NewTicker(1000 * time.Millisecond)
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -237,6 +261,14 @@ out:
|
|||||||
blocks := self.Blocks()
|
blocks := self.Blocks()
|
||||||
ethchain.BlockBy(ethchain.Number).Sort(blocks)
|
ethchain.BlockBy(ethchain.Number).Sort(blocks)
|
||||||
|
|
||||||
|
// Find common block
|
||||||
|
for i, block := range blocks {
|
||||||
|
if self.eth.BlockChain().HasBlock(block.PrevHash) {
|
||||||
|
blocks = blocks[i:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(blocks) > 0 {
|
if len(blocks) > 0 {
|
||||||
if self.eth.BlockChain().HasBlock(blocks[0].PrevHash) {
|
if self.eth.BlockChain().HasBlock(blocks[0].PrevHash) {
|
||||||
for i, block := range blocks[1:] {
|
for i, block := range blocks[1:] {
|
||||||
@ -253,13 +285,51 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle in batches of 4k
|
if len(blocks) > 0 {
|
||||||
max := int(math.Min(4000, float64(len(blocks))))
|
self.eth.Eventer().Post("blocks", blocks)
|
||||||
for _, block := range blocks[:max] {
|
|
||||||
self.eth.Eventer().Post("block", block)
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
for i, block := range blocks {
|
||||||
|
//self.eth.Eventer().Post("block", block)
|
||||||
|
err = self.eth.StateManager().Process(block, false)
|
||||||
|
if err != nil {
|
||||||
|
poollogger.Infoln(err)
|
||||||
|
poollogger.Debugf("Block #%v failed (%x...)\n", block.Number, block.Hash()[0:4])
|
||||||
|
poollogger.Debugln(block)
|
||||||
|
|
||||||
|
blocks = blocks[i:]
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
self.Remove(block.Hash())
|
self.Remove(block.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// Remove this bad chain
|
||||||
|
for _, block := range blocks {
|
||||||
|
self.Remove(block.Hash())
|
||||||
|
}
|
||||||
|
|
||||||
|
poollogger.Debugf("Punishing peer for supplying bad chain (%v)\n", self.peer.conn.RemoteAddr())
|
||||||
|
// This peer gave us bad hashes and made us fetch a bad chain, therefor he shall be punished.
|
||||||
|
self.eth.BlacklistPeer(self.peer)
|
||||||
|
self.peer.StopWithReason(DiscBadPeer)
|
||||||
|
self.td = ethutil.Big0
|
||||||
|
self.peer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Handle in batches of 4k
|
||||||
|
//max := int(math.Min(4000, float64(len(blocks))))
|
||||||
|
for _, block := range blocks {
|
||||||
|
self.eth.Eventer().Post("block", block)
|
||||||
|
|
||||||
|
self.Remove(block.Hash())
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,8 @@ type Ethereum struct {
|
|||||||
Addr net.Addr
|
Addr net.Addr
|
||||||
Port string
|
Port string
|
||||||
|
|
||||||
|
blacklist [][]byte
|
||||||
|
|
||||||
peerMut sync.Mutex
|
peerMut sync.Mutex
|
||||||
|
|
||||||
// Capabilities for outgoing peers
|
// Capabilities for outgoing peers
|
||||||
@ -211,6 +213,10 @@ func (s *Ethereum) HighestTDPeer() (td *big.Int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Ethereum) BlacklistPeer(peer *Peer) {
|
||||||
|
self.blacklist = append(self.blacklist, peer.pubkey)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Ethereum) AddPeer(conn net.Conn) {
|
func (s *Ethereum) AddPeer(conn net.Conn) {
|
||||||
peer := NewPeer(conn, s, true)
|
peer := NewPeer(conn, s, true)
|
||||||
|
|
||||||
|
65
peer.go
65
peer.go
@ -39,15 +39,15 @@ const (
|
|||||||
// Values are given explicitly instead of by iota because these values are
|
// Values are given explicitly instead of by iota because these values are
|
||||||
// defined by the wire protocol spec; it is easier for humans to ensure
|
// defined by the wire protocol spec; it is easier for humans to ensure
|
||||||
// correctness when values are explicit.
|
// correctness when values are explicit.
|
||||||
DiscReRequested = 0x00
|
DiscRequested DiscReason = iota
|
||||||
DiscReTcpSysErr = 0x01
|
DiscReTcpSysErr
|
||||||
DiscBadProto = 0x02
|
DiscBadProto
|
||||||
DiscBadPeer = 0x03
|
DiscBadPeer
|
||||||
DiscTooManyPeers = 0x04
|
DiscTooManyPeers
|
||||||
DiscConnDup = 0x05
|
DiscConnDup
|
||||||
DiscGenesisErr = 0x06
|
DiscGenesisErr
|
||||||
DiscProtoErr = 0x07
|
DiscProtoErr
|
||||||
DiscQuitting = 0x08
|
DiscQuitting
|
||||||
)
|
)
|
||||||
|
|
||||||
var discReasonToString = []string{
|
var discReasonToString = []string{
|
||||||
@ -554,19 +554,22 @@ func (self *Peer) FetchBlocks(hashes [][]byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *Peer) FetchHashes() {
|
func (self *Peer) FetchHashes() {
|
||||||
self.doneFetchingHashes = false
|
|
||||||
|
|
||||||
blockPool := self.ethereum.blockPool
|
blockPool := self.ethereum.blockPool
|
||||||
|
blockPool.FetchHashes(self)
|
||||||
|
|
||||||
if self.td.Cmp(self.ethereum.HighestTDPeer()) >= 0 {
|
/*
|
||||||
blockPool.td = self.td
|
if self.td.Cmp(self.ethereum.HighestTDPeer()) >= 0 {
|
||||||
|
blockPool.td = self.td
|
||||||
|
|
||||||
if !blockPool.HasLatestHash() {
|
if !blockPool.HasLatestHash() {
|
||||||
const amount = 256
|
self.doneFetchingHashes = false
|
||||||
peerlogger.Debugf("Fetching hashes (%d)\n", amount)
|
|
||||||
self.QueueMessage(ethwire.NewMessage(ethwire.MsgGetBlockHashesTy, []interface{}{self.lastReceivedHash, uint32(amount)}))
|
const amount = 256
|
||||||
|
peerlogger.Debugf("Fetching hashes (%d)\n", amount)
|
||||||
|
self.QueueMessage(ethwire.NewMessage(ethwire.MsgGetBlockHashesTy, []interface{}{self.lastReceivedHash, uint32(amount)}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Peer) FetchingHashes() bool {
|
func (self *Peer) FetchingHashes() bool {
|
||||||
@ -631,18 +634,22 @@ func (p *Peer) Start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Peer) Stop() {
|
func (p *Peer) Stop() {
|
||||||
|
p.StopWithReason(DiscRequested)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Peer) StopWithReason(reason DiscReason) {
|
||||||
if atomic.AddInt32(&p.disconnect, 1) != 1 {
|
if atomic.AddInt32(&p.disconnect, 1) != 1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
close(p.quit)
|
|
||||||
if atomic.LoadInt32(&p.connected) != 0 {
|
|
||||||
p.writeMessage(ethwire.NewMessage(ethwire.MsgDiscTy, ""))
|
|
||||||
p.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-emptively remove the peer; don't wait for reaping. We already know it's dead if we are here
|
// Pre-emptively remove the peer; don't wait for reaping. We already know it's dead if we are here
|
||||||
p.ethereum.RemovePeer(p)
|
p.ethereum.RemovePeer(p)
|
||||||
|
|
||||||
|
close(p.quit)
|
||||||
|
if atomic.LoadInt32(&p.connected) != 0 {
|
||||||
|
p.writeMessage(ethwire.NewMessage(ethwire.MsgDiscTy, reason))
|
||||||
|
p.conn.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Peer) peersMessage() *ethwire.Msg {
|
func (p *Peer) peersMessage() *ethwire.Msg {
|
||||||
@ -764,6 +771,16 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for blacklisting
|
||||||
|
for _, pk := range p.ethereum.blacklist {
|
||||||
|
if bytes.Compare(pk, pub) == 0 {
|
||||||
|
peerlogger.Debugf("Blacklisted peer tried to connect (%x...)\n", pubkey[0:4])
|
||||||
|
p.StopWithReason(DiscBadPeer)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
usedPub := 0
|
usedPub := 0
|
||||||
// This peer is already added to the peerlist so we expect to find a double pubkey at least once
|
// This peer is already added to the peerlist so we expect to find a double pubkey at least once
|
||||||
eachPeer(p.ethereum.Peers(), func(peer *Peer, e *list.Element) {
|
eachPeer(p.ethereum.Peers(), func(peer *Peer, e *list.Element) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user