From 5cb1b41440209b03a1c5ec6c639207fd336e67e3 Mon Sep 17 00:00:00 2001
From: zelig <viktor.tron@gmail.com>
Date: Thu, 2 Apr 2015 16:30:48 +0100
Subject: proper locking to prevent "parent unknown" INVALID blocks due to race
 in peer head info update

---
 blockpool/peers.go | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/blockpool/peers.go b/blockpool/peers.go
index 802081780..285fa45b1 100644
--- a/blockpool/peers.go
+++ b/blockpool/peers.go
@@ -133,13 +133,10 @@ func (self *peer) addError(code int, format string, params ...interface{}) {
 	self.addToBlacklist(self.id)
 }
 
+// caller must hold peer lock
 func (self *peer) setChainInfo(td *big.Int, c common.Hash) {
-	self.lock.Lock()
-	defer self.lock.Unlock()
-
 	self.td = td
 	self.currentBlockHash = c
-
 	self.currentBlock = nil
 	self.parentHash = common.Hash{}
 	self.headSection = nil
@@ -171,7 +168,7 @@ func (self *peers) requestBlocks(attempts int, hashes []common.Hash) {
 	defer self.lock.RUnlock()
 	peerCount := len(self.peers)
 	// on first attempt use the best peer
-	if attempts == 0 {
+	if attempts == 0 && self.best != nil {
 		plog.DebugDetailf("request %v missing blocks from best peer <%s>", len(hashes), self.best.id)
 		self.best.requestBlocks(hashes)
 		return
@@ -224,6 +221,7 @@ func (self *peers) addPeer(
 	if found {
 		// when called on an already connected peer, it means a newBlockMsg is received
 		// peer head info is updated
+		p.lock.Lock()
 		if p.currentBlockHash != currentBlockHash {
 			previousBlockHash = p.currentBlockHash
 			plog.Debugf("addPeer: Update peer <%s> with td %v and current block %s (was %v)", id, td, hex(currentBlockHash), hex(previousBlockHash))
@@ -233,6 +231,7 @@ func (self *peers) addPeer(
 			self.status.values.NewBlocks++
 			self.status.lock.Unlock()
 		}
+		p.lock.Unlock()
 	} else {
 		p = self.newPeer(td, currentBlockHash, id, requestBlockHashes, requestBlocks, peerError)
 
-- 
cgit v1.2.3