core, eth/downloader: expose the bad hashes, check in downloader

This commit is contained in:
Péter Szilágyi 2015-05-28 13:06:10 +03:00
parent 27e0d2a973
commit 29b0480cfb
5 changed files with 22 additions and 12 deletions

View File

@ -2,7 +2,8 @@ package core
import "github.com/ethereum/go-ethereum/common" import "github.com/ethereum/go-ethereum/common"
var badHashes = []common.Hash{ // Set of manually tracked bad hashes (usually hard forks)
common.HexToHash("f269c503aed286caaa0d114d6a5320e70abbc2febe37953207e76a2873f2ba79"), var BadHashes = map[common.Hash]bool{
common.HexToHash("38f5bbbffd74804820ffa4bab0cd540e9de229725afb98c1a7e57936f4a714bc"), common.HexToHash("f269c503aed286caaa0d114d6a5320e70abbc2febe37953207e76a2873f2ba79"): true,
common.HexToHash("38f5bbbffd74804820ffa4bab0cd540e9de229725afb98c1a7e57936f4a714bc"): true,
} }

View File

@ -121,7 +121,7 @@ func NewChainManager(blockDb, stateDb common.Database, pow pow.PoW, mux *event.T
bc.setLastState() bc.setLastState()
// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
for _, hash := range badHashes { for hash, _ := range BadHashes {
if block := bc.GetBlock(hash); block != nil { if block := bc.GetBlock(hash); block != nil {
glog.V(logger.Error).Infof("Found bad hash. Reorganising chain to state %x\n", block.ParentHash().Bytes()[:4]) glog.V(logger.Error).Infof("Found bad hash. Reorganising chain to state %x\n", block.ParentHash().Bytes()[:4])
block = bc.GetBlock(block.ParentHash()) block = bc.GetBlock(block.ParentHash())

View File

@ -3,9 +3,7 @@ package core
import ( import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
) )
// TODO move this to types? // TODO move this to types?
@ -14,11 +12,7 @@ type Backend interface {
BlockProcessor() *BlockProcessor BlockProcessor() *BlockProcessor
ChainManager() *ChainManager ChainManager() *ChainManager
TxPool() *TxPool TxPool() *TxPool
PeerCount() int
IsListening() bool
Peers() []*p2p.Peer
BlockDb() common.Database BlockDb() common.Database
StateDb() common.Database StateDb() common.Database
EventMux() *event.TypeMux EventMux() *event.TypeMux
Downloader() *downloader.Downloader
} }

View File

@ -7,7 +7,10 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"gopkg.in/fatih/set.v0"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
@ -75,6 +78,7 @@ type Downloader struct {
queue *queue // Scheduler for selecting the hashes to download queue *queue // Scheduler for selecting the hashes to download
peers *peerSet // Set of active peers from which download can proceed peers *peerSet // Set of active peers from which download can proceed
checks map[common.Hash]*crossCheck // Pending cross checks to verify a hash chain checks map[common.Hash]*crossCheck // Pending cross checks to verify a hash chain
banned *set.SetNonTS // Set of hashes we've received and banned
// Callbacks // Callbacks
hasBlock hashCheckFn hasBlock hashCheckFn
@ -100,6 +104,7 @@ type Block struct {
} }
func New(mux *event.TypeMux, hasBlock hashCheckFn, getBlock getBlockFn) *Downloader { func New(mux *event.TypeMux, hasBlock hashCheckFn, getBlock getBlockFn) *Downloader {
// Create the base downloader
downloader := &Downloader{ downloader := &Downloader{
mux: mux, mux: mux,
queue: newQueue(), queue: newQueue(),
@ -110,6 +115,11 @@ func New(mux *event.TypeMux, hasBlock hashCheckFn, getBlock getBlockFn) *Downloa
hashCh: make(chan hashPack, 1), hashCh: make(chan hashPack, 1),
blockCh: make(chan blockPack, 1), blockCh: make(chan blockPack, 1),
} }
// Inject all the known bad hashes
downloader.banned = set.NewNonTS()
for hash, _ := range core.BadHashes {
downloader.banned.Add(hash)
}
return downloader return downloader
} }
@ -280,6 +290,12 @@ func (d *Downloader) fetchHashes(p *peer, h common.Hash) error {
glog.V(logger.Debug).Infof("Peer (%s) responded with empty hash set\n", active.id) glog.V(logger.Debug).Infof("Peer (%s) responded with empty hash set\n", active.id)
return errEmptyHashSet return errEmptyHashSet
} }
for _, hash := range hashPack.hashes {
if d.banned.Has(hash) {
glog.V(logger.Debug).Infof("Peer (%s) sent a known invalid chain\n", active.id)
return ErrInvalidChain
}
}
// Determine if we're done fetching hashes (queue up all pending), and continue if not done // Determine if we're done fetching hashes (queue up all pending), and continue if not done
done, index := false, 0 done, index := false, 0
for index, head = range hashPack.hashes { for index, head = range hashPack.hashes {

View File

@ -70,6 +70,7 @@ func (pm *ProtocolManager) processBlocks() error {
// Try to inset the blocks, drop the originating peer if there's an error // Try to inset the blocks, drop the originating peer if there's an error
index, err := pm.chainman.InsertChain(raw) index, err := pm.chainman.InsertChain(raw)
if err != nil { if err != nil {
glog.V(logger.Debug).Infoln("Downloaded block import failed:", err)
pm.removePeer(blocks[index].OriginPeer) pm.removePeer(blocks[index].OriginPeer)
pm.downloader.Cancel() pm.downloader.Cancel()
return err return err
@ -84,12 +85,10 @@ func (pm *ProtocolManager) processBlocks() error {
func (pm *ProtocolManager) synchronise(peer *peer) { func (pm *ProtocolManager) synchronise(peer *peer) {
// Short circuit if no peers are available // Short circuit if no peers are available
if peer == nil { if peer == nil {
glog.V(logger.Debug).Infoln("Synchronisation canceled: no peers available")
return return
} }
// Make sure the peer's TD is higher than our own. If not drop. // Make sure the peer's TD is higher than our own. If not drop.
if peer.td.Cmp(pm.chainman.Td()) <= 0 { if peer.td.Cmp(pm.chainman.Td()) <= 0 {
glog.V(logger.Debug).Infoln("Synchronisation canceled: peer's total difficulty is too small")
return return
} }
// FIXME if we have the hash in our chain and the TD of the peer is // FIXME if we have the hash in our chain and the TD of the peer is