diff --git a/core/blockchain.go b/core/blockchain.go index f14ff363c..cea346e38 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -411,11 +411,14 @@ func (self *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error { // insert injects a new head block into the current block chain. This method // assumes that the block is indeed a true head. It will also reset the head -// header and the head fast sync block to this very same block to prevent them -// from pointing to a possibly old canonical chain (i.e. side chain by now). +// header and the head fast sync block to this very same block if they are older +// or if they are on a different side chain. // // Note, this function assumes that the `mu` mutex is held! func (bc *BlockChain) insert(block *types.Block) { + // If the block is on a side chain or an unknown one, force other heads onto it too + updateHeads := GetCanonicalHash(bc.chainDb, block.NumberU64()) != block.Hash() + // Add the block to the canonical chain number scheme and mark as the head if err := WriteCanonicalHash(bc.chainDb, block.Hash(), block.NumberU64()); err != nil { glog.Fatalf("failed to insert block number: %v", err) @@ -423,16 +426,20 @@ func (bc *BlockChain) insert(block *types.Block) { if err := WriteHeadBlockHash(bc.chainDb, block.Hash()); err != nil { glog.Fatalf("failed to insert head block hash: %v", err) } - if err := WriteHeadHeaderHash(bc.chainDb, block.Hash()); err != nil { - glog.Fatalf("failed to insert head header hash: %v", err) - } - if err := WriteHeadFastBlockHash(bc.chainDb, block.Hash()); err != nil { - glog.Fatalf("failed to insert head fast block hash: %v", err) - } - // Update the internal state with the head block bc.currentBlock = block - bc.currentHeader = block.Header() - bc.currentFastBlock = block + + // If the block is better than out head or is on a different chain, force update heads + if updateHeads { + if err := WriteHeadHeaderHash(bc.chainDb, block.Hash()); err != nil { + glog.Fatalf("failed to insert head header hash: %v", err) + } + bc.currentHeader = block.Header() + + if err := WriteHeadFastBlockHash(bc.chainDb, block.Hash()); err != nil { + glog.Fatalf("failed to insert head fast block hash: %v", err) + } + bc.currentFastBlock = block + } } // Accessors diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 4bcbd8557..153427ee4 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -248,10 +248,11 @@ func (d *Downloader) UnregisterPeer(id string) error { // Synchronise tries to sync up our local block chain with a remote peer, both // adding various sanity checks as well as wrapping it with various log entries. -func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) { +func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) error { glog.V(logger.Detail).Infof("Attempting synchronisation: %v, head [%x…], TD %v", id, head[:4], td) - switch err := d.synchronise(id, head, td, mode); err { + err := d.synchronise(id, head, td, mode) + switch err { case nil: glog.V(logger.Detail).Infof("Synchronisation completed") @@ -268,6 +269,7 @@ func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode default: glog.V(logger.Warn).Infof("Synchronisation failed: %v", err) } + return err } // synchronise will select the peer and use it for synchronising. If an empty string is given diff --git a/eth/sync.go b/eth/sync.go index b69a24556..bbf2abc04 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -170,13 +170,16 @@ func (pm *ProtocolManager) synchronise(peer *peer) { if pm.fastSync { mode = downloader.FastSync } - pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), mode) - + if err := pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), mode); err != nil { + return + } // If fast sync was enabled, and we synced up, disable it if pm.fastSync { + // Wait until all pending imports finish processing for pm.downloader.Synchronising() { time.Sleep(100 * time.Millisecond) } + // Disable fast sync if we indeed have something in our chain if pm.blockchain.CurrentBlock().NumberU64() > 0 { glog.V(logger.Info).Infof("fast sync complete, auto disabling") pm.fastSync = false