eth, eth/downloader: handle a potential unknown parent attack

This commit is contained in:
Péter Szilágyi
2015-05-14 15:24:18 +03:00
parent 7cb0e24245
commit a4246c2da6
3 changed files with 112 additions and 31 deletions

View File

@ -2,6 +2,7 @@ package eth
import (
"math"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/eth/downloader"
@ -14,6 +15,7 @@ import (
func (pm *ProtocolManager) update() {
forceSync := time.Tick(forceSyncCycle)
blockProc := time.Tick(blockProcCycle)
blockProcPend := int32(0)
for {
select {
@ -36,7 +38,14 @@ func (pm *ProtocolManager) update() {
}
case <-blockProc:
// Try to pull some blocks from the downloaded
go pm.processBlocks()
if atomic.CompareAndSwapInt32(&blockProcPend, 0, 1) {
go func() {
if err := pm.processBlocks(); err != nil {
pm.downloader.Cancel()
}
atomic.StoreInt32(&blockProcPend, 0)
}()
}
case <-pm.quitSync:
return
@ -52,8 +61,12 @@ func (pm *ProtocolManager) processBlocks() error {
pm.wg.Add(1)
defer pm.wg.Done()
// Take a batch of blocks (will return nil if a previous batch has not reached the chain yet)
blocks := pm.downloader.TakeBlocks()
// Take a batch of blocks, but abort if there's an invalid head or if the chain's empty
blocks, err := pm.downloader.TakeBlocks()
if err != nil {
glog.V(logger.Warn).Infof("Block processing failed: %v", err)
return err
}
if len(blocks) == 0 {
return nil
}
@ -63,9 +76,7 @@ func (pm *ProtocolManager) processBlocks() error {
max := int(math.Min(float64(len(blocks)), float64(blockProcAmount)))
_, err := pm.chainman.InsertChain(blocks[:max])
if err != nil {
// cancel download process
pm.downloader.Cancel()
glog.V(logger.Warn).Infof("Block insertion failed: %v", err)
return err
}
blocks = blocks[max:]