eth/downloader: reject peer registration if head is banned

This commit is contained in:
Péter Szilágyi 2015-06-08 14:46:31 +03:00
parent 63c6cedb14
commit c4f224932f

@ -36,6 +36,7 @@ var (
errUnknownPeer = errors.New("peer is unknown or unhealthy")
ErrBadPeer = errors.New("action from bad peer ignored")
ErrStallingPeer = errors.New("peer is stalling")
errBannedHead = errors.New("peer head hash already banned")
errNoPeers = errors.New("no peers to keep download active")
ErrPendingQueue = errors.New("pending items in queue")
ErrTimeout = errors.New("timeout")
@ -72,11 +73,10 @@ type crossCheck struct {
type Downloader struct {
mux *event.TypeMux
mu sync.RWMutex
queue *queue // Scheduler for selecting the hashes to download
peers *peerSet // Set of active peers from which download can proceed
checks map[common.Hash]*crossCheck // Pending cross checks to verify a hash chain
banned *set.SetNonTS // Set of hashes we've received and banned
banned *set.Set // Set of hashes we've received and banned
// Callbacks
hasBlock hashCheckFn
@ -114,7 +114,7 @@ func New(mux *event.TypeMux, hasBlock hashCheckFn, getBlock getBlockFn) *Downloa
blockCh: make(chan blockPack, 1),
}
// Inject all the known bad hashes
downloader.banned = set.NewNonTS()
downloader.banned = set.New()
for hash, _ := range core.BadHashes {
downloader.banned.Add(hash)
}
@ -133,6 +133,12 @@ func (d *Downloader) Synchronising() bool {
// RegisterPeer injects a new download peer into the set of block source to be
// used for fetching hashes and blocks from.
func (d *Downloader) RegisterPeer(id string, head common.Hash, getHashes hashFetcherFn, getBlocks blockFetcherFn) error {
// If the peer wants to send a banned hash, reject
if d.banned.Has(head) {
glog.V(logger.Debug).Infoln("Register rejected, head hash banned:", id)
return errBannedHead
}
// Otherwise try to construct and register the peer
glog.V(logger.Detail).Infoln("Registering peer", id)
if err := d.peers.Register(newPeer(id, head, getHashes, getBlocks)); err != nil {
glog.V(logger.Error).Infoln("Register failed:", err)
@ -199,6 +205,8 @@ func (d *Downloader) TakeBlocks() []*Block {
return d.queue.TakeBlocks()
}
// Has checks if the downloader knows about a particular hash, meaning that its
// either already downloaded of pending retrieval.
func (d *Downloader) Has(hash common.Hash) bool {
return d.queue.Has(hash)
}
@ -604,14 +612,17 @@ func (d *Downloader) banBlocks(peerId string, head common.Hash) error {
// Ban the head hash and phase out any excess
d.banned.Add(blocks[index].Hash())
for d.banned.Size() > maxBannedHashes {
var evacuate common.Hash
d.banned.Each(func(item interface{}) bool {
// Skip any hard coded bans
if core.BadHashes[item.(common.Hash)] {
return true
}
d.banned.Remove(item)
evacuate = item.(common.Hash)
return false
})
d.banned.Remove(evacuate)
}
glog.V(logger.Debug).Infof("Banned %d blocks from: %s", index+1, peerId)
return nil