From 29b0480cfb2f2bd6c350fdce0063312ad691d7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Thu, 28 May 2015 13:06:10 +0300 Subject: [PATCH] core, eth/downloader: expose the bad hashes, check in downloader --- core/blocks.go | 7 ++++--- core/chain_manager.go | 2 +- core/manager.go | 6 ------ eth/downloader/downloader.go | 16 ++++++++++++++++ eth/sync.go | 3 +-- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/core/blocks.go b/core/blocks.go index d09242a07..35e170af3 100644 --- a/core/blocks.go +++ b/core/blocks.go @@ -2,7 +2,8 @@ package core import "github.com/ethereum/go-ethereum/common" -var badHashes = []common.Hash{ - common.HexToHash("f269c503aed286caaa0d114d6a5320e70abbc2febe37953207e76a2873f2ba79"), - common.HexToHash("38f5bbbffd74804820ffa4bab0cd540e9de229725afb98c1a7e57936f4a714bc"), +// Set of manually tracked bad hashes (usually hard forks) +var BadHashes = map[common.Hash]bool{ + common.HexToHash("f269c503aed286caaa0d114d6a5320e70abbc2febe37953207e76a2873f2ba79"): true, + common.HexToHash("38f5bbbffd74804820ffa4bab0cd540e9de229725afb98c1a7e57936f4a714bc"): true, } diff --git a/core/chain_manager.go b/core/chain_manager.go index ee73145c1..edf8825f3 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -121,7 +121,7 @@ func NewChainManager(blockDb, stateDb common.Database, pow pow.PoW, mux *event.T 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 - for _, hash := range badHashes { + for hash, _ := range BadHashes { 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]) block = bc.GetBlock(block.ParentHash()) diff --git a/core/manager.go b/core/manager.go index 695f0e99c..ba0ecf9d1 100644 --- a/core/manager.go +++ b/core/manager.go @@ -3,9 +3,7 @@ package core import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/p2p" ) // TODO move this to types? @@ -14,11 +12,7 @@ type Backend interface { BlockProcessor() *BlockProcessor ChainManager() *ChainManager TxPool() *TxPool - PeerCount() int - IsListening() bool - Peers() []*p2p.Peer BlockDb() common.Database StateDb() common.Database EventMux() *event.TypeMux - Downloader() *downloader.Downloader } diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 421c336f2..85531ce15 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -7,7 +7,10 @@ import ( "sync/atomic" "time" + "gopkg.in/fatih/set.v0" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" @@ -75,6 +78,7 @@ type Downloader struct { 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 // Callbacks hasBlock hashCheckFn @@ -100,6 +104,7 @@ type Block struct { } func New(mux *event.TypeMux, hasBlock hashCheckFn, getBlock getBlockFn) *Downloader { + // Create the base downloader downloader := &Downloader{ mux: mux, queue: newQueue(), @@ -110,6 +115,11 @@ func New(mux *event.TypeMux, hasBlock hashCheckFn, getBlock getBlockFn) *Downloa hashCh: make(chan hashPack, 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 } @@ -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) 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 done, index := false, 0 for index, head = range hashPack.hashes { diff --git a/eth/sync.go b/eth/sync.go index cf549f852..76e137630 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -70,6 +70,7 @@ func (pm *ProtocolManager) processBlocks() error { // Try to inset the blocks, drop the originating peer if there's an error index, err := pm.chainman.InsertChain(raw) if err != nil { + glog.V(logger.Debug).Infoln("Downloaded block import failed:", err) pm.removePeer(blocks[index].OriginPeer) pm.downloader.Cancel() return err @@ -84,12 +85,10 @@ func (pm *ProtocolManager) processBlocks() error { func (pm *ProtocolManager) synchronise(peer *peer) { // Short circuit if no peers are available if peer == nil { - glog.V(logger.Debug).Infoln("Synchronisation canceled: no peers available") return } // Make sure the peer's TD is higher than our own. If not drop. if peer.td.Cmp(pm.chainman.Td()) <= 0 { - glog.V(logger.Debug).Infoln("Synchronisation canceled: peer's total difficulty is too small") return } // FIXME if we have the hash in our chain and the TD of the peer is