- follow up locks and fix them
- chainManager: call SetQueued for parentErr future blocks, uncomment TD checks, unskip test
- make ErrIncorrectTD non-fatal to be forgiving to genuine mistaken nodes (temp) but demote them to guard against stuck best peers.
- add purging to bounded nodeCache (config nodeCacheSize)
- use nodeCache when creating blockpool entries and let non-best peers add blocks (performance boost)
- minor error in addError
- reduce idleBestPeerTimeout to 1 minute
- correct status counts and unskip status passing status test
- glogified logging
// if we reach the blockchain we stop reading further blockhashes
// if we reach the blockchain we stop reading further blockhashes
ifself.hasBlock(hash){
ifself.hasBlock(hash){
// check if known block connecting the downloaded chain to our blockchain
// check if known block connecting the downloaded chain to our blockchain
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) found block %s in the blockchain",peerId,hex(bestpeer.currentBlockHash),hex(hash))
glog.V(logger.Detail).Infof("AddBlockHashes: peer <%s> (head: %s) found block %s in the blockchain",peerId,hex(bestpeer.currentBlockHash),hex(hash))
iflen(nodes)==1{
iflen(nodes)==1{
plog.DebugDetailf("AddBlockHashes: singleton section pushed to blockchain peer <%s> (head: %s) found block %s in the blockchain",peerId,hex(bestpeer.currentBlockHash),hex(hash))
glog.V(logger.Detail).Infof("AddBlockHashes: singleton section pushed to blockchain peer <%s> (head: %s) found block %s in the blockchain",peerId,hex(bestpeer.currentBlockHash),hex(hash))
// create new section if needed and push it to the blockchain
// create new section if needed and push it to the blockchain
sec=self.newSection(nodes)
sec=self.newSection(nodes)
@ -470,7 +474,7 @@ LOOP:
andtdtogetherwithblockByarerecordedonthenode
andtdtogetherwithblockByarerecordedonthenode
*/
*/
iflen(nodes)==0&&child!=nil{
iflen(nodes)==0&&child!=nil{
plog.DebugDetailf("AddBlockHashes: child section [%s] pushed to blockchain peer <%s> (head: %s) found block %s in the blockchain",sectionhex(child),peerId,hex(bestpeer.currentBlockHash),hex(hash))
glog.V(logger.Detail).Infof("AddBlockHashes: child section [%s] pushed to blockchain peer <%s> (head: %s) found block %s in the blockchain",sectionhex(child),peerId,hex(bestpeer.currentBlockHash),hex(hash))
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) found head block [%s] as root of connecting child section [%s] skipping",peerId,hex(bestpeer.currentBlockHash),hex(hash),sectionhex(entry.section))
glog.V(logger.Detail).Infof("AddBlockHashes: peer <%s> (head: %s) found head block [%s] as root of connecting child section [%s] skipping",peerId,hex(bestpeer.currentBlockHash),hex(hash),sectionhex(entry.section))
// record the entry's chain section as child section
// record the entry's chain section as child section
child=entry.section
child=entry.section
continueLOOP
continueLOOP
}
}
// otherwise record entry's chain section as parent connecting it to the pool
// otherwise record entry's chain section as parent connecting it to the pool
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) found block [%s] in section [%s]. Connected to pool.",peerId,hex(bestpeer.currentBlockHash),hex(hash),sectionhex(entry.section))
glog.V(logger.Detail).Infof("AddBlockHashes: peer <%s> (head: %s) found block [%s] in section [%s]. Connected to pool.",peerId,hex(bestpeer.currentBlockHash),hex(hash),sectionhex(entry.section))
parent=entry.section
parent=entry.section
breakLOOP
breakLOOP
}
}
// finally if node for block hash does not exist, create it and append node to section nodes
// finally if node for block hash does not exist, create it and append node to section nodes
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) no longer best: delay requesting blocks for section [%s]",peerId,hex(bestpeer.currentBlockHash),sectionhex(sec))
glog.V(logger.Detail).Infof("AddBlockHashes: peer <%s> (head: %s) no longer best: delay requesting blocks for section [%s]",peerId,hex(bestpeer.currentBlockHash),sectionhex(sec))
sec.deactivate()
sec.deactivate()
}
}
}
}
@ -589,7 +586,7 @@ LOOP:
// If we are processing peer's head section, signal it to headSection process that it is created.
// If we are processing peer's head section, signal it to headSection process that it is created.
ifheadSection{
ifheadSection{
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) head section registered on head section process",peerId,hex(bestpeer.currentBlockHash))
glog.V(logger.Detail).Infof("AddBlockHashes: peer <%s> (head: %s) head section registered on head section process",peerId,hex(bestpeer.currentBlockHash))
varheadSec*section
varheadSec*section
switch{
switch{
@ -601,7 +598,7 @@ LOOP:
headSec=parent
headSec=parent
}
}
if!peerswitch{
if!peerswitch{
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) head section [%s] created signalled to head section process",peerId,hex(bestpeer.currentBlockHash),sectionhex(headSec))
glog.V(logger.Detail).Infof("AddBlockHashes: peer <%s> (head: %s) head section [%s] created signalled to head section process",peerId,hex(bestpeer.currentBlockHash),sectionhex(headSec))
plog.DebugDetailf("AddBlock: block %s from peer <%s> (head: %s) already sent by <%s> ",hex(hash),peerId,hex(sender.currentBlockHash),bnode.blockBy)
glog.V(logger.Detail).Infof("AddBlock: block %s from peer <%s> (head: %s) already sent by <%s> ",hex(hash),peerId,hex(sender.currentBlockHash),bnode.blockBy)
glog.V(logger.Detail).Infof("AddBlock: set td on node %s from peer <%s> (head: %s) to %v (was %v) ",hex(hash),peerId,hex(sender.currentBlockHash),bnode.td,tdFromCurrentHead)
bnode.td=tdFromCurrentHead
bnode.td=tdFromCurrentHead
self.status.lock.Lock()
self.status.lock.Lock()
self.status.values.Blocks++
self.status.values.Blocks++
self.status.values.BlocksInPool++
self.status.values.BlocksInPool++
self.status.lock.Unlock()
self.status.lock.Unlock()
}
}
bnode.lock.Unlock()
currentBlockC:=sender.currentBlockC
switchC:=sender.switchC
sender.lock.Unlock()
// this must be called without peerlock.
// peerlock held can halt the loop and block on select forever
plog.Debugf("addPeer: Update peer <%s> with td %v and current block %s (was %v)",self.id,td,hex(currentBlockHash),hex(previousBlockHash))
glog.V(logger.Debug).Infof("addPeer: Update peer <%s> with td %v (was %v) and current block %s (was %v)",self.id,td,self.td,hex(currentBlockHash),hex(previousBlockHash))
plog.DebugDetailf("HeadSection: <%s> (head: %s) head section received [%s]-[%s]",self.id,hex(self.currentBlockHash),sectionhex(self.headSection),sectionhex(sec))
glog.V(logger.Detail).Infof("HeadSection: <%s> (head: %s) head section received [%s]-[%s]",self.id,hex(self.currentBlockHash),sectionhex(self.headSection),sectionhex(sec))
plog.DebugDetailf("HeadSection: <%s> head block %s received (parent: %s)",self.id,hex(self.currentBlockHash),hex(currentBlock.ParentHash()))
glog.V(logger.Detail).Infof("HeadSection: <%s> head block %s received (parent: %s)",self.id,hex(self.currentBlockHash),hex(currentBlock.ParentHash()))
}
}
self.lock.Lock()
deferself.lock.Unlock()
self.currentBlock=currentBlock
self.currentBlock=currentBlock
self.parentHash=currentBlock.ParentHash()
self.parentHash=currentBlock.ParentHash()
plog.DebugDetailf("HeadSection: <%s> head block %s found (parent: %s)... requesting hashes",self.id,hex(self.currentBlockHash),hex(self.parentHash))
glog.V(logger.Detail).Infof("HeadSection: <%s> head block %s found (parent: %s)... requesting hashes",self.id,hex(self.currentBlockHash),hex(self.parentHash))
plog.Debugf("HeadSection: <%s> section with head %s, idle: %v",self.id,hex(self.currentBlockHash),self.idle)
glog.V(logger.Detail).Infof("HeadSection: <%s> section with head %s, idle: %v",self.id,hex(self.currentBlockHash),self.idle)
// signal from AddBlockHashes that head section for current best peer is created
// signal from AddBlockHashes that head section for current best peer is created
// if sec == nil, it signals that chain info has updated (new block message)
// if sec == nil, it signals that chain info has updated (new block message)
@ -614,12 +609,12 @@ LOOP:
// there is no persistence here, so GC will just take care of cleaning up
// there is no persistence here, so GC will just take care of cleaning up
// signal for peer switch, quit
// signal for peer switch, quit
case<-switchC:
case<-self.switchC:
varcomplete="incomplete "
varcomplete="incomplete "
ifself.idle{
ifself.idle{
complete="complete"
complete="complete"
}
}
plog.Debugf("HeadSection: <%s> section with head %s %s... quit request loop due to peer switch",self.id,hex(self.currentBlockHash),complete)
glog.V(logger.Detail).Infof("HeadSection: <%s> section with head %s %s... quit request loop due to peer switch",self.id,hex(self.currentBlockHash),complete)
breakLOOP
breakLOOP
// global quit for blockpool
// global quit for blockpool
@ -633,7 +628,7 @@ LOOP:
self.bp.status.lock.Lock()
self.bp.status.lock.Lock()
self.bp.status.badPeers[self.id]++
self.bp.status.badPeers[self.id]++
self.bp.status.lock.Unlock()
self.bp.status.lock.Unlock()
plog.Debugf("HeadSection: <%s> (headsection [%s]) quit channel closed : timed out without providing new blocks...quitting",self.id,sectionhex(self.headSection))
glog.V(logger.Detail).Infof("HeadSection: <%s> (headsection [%s]) quit channel closed : timed out without providing new blocks...quitting",self.id,sectionhex(self.headSection))
plog.DebugDetailf("[%s] got parent head block hash %s...checking",sectionhex(self),hex(self.parentHash))
glog.V(logger.Detail).Infof("[%s] got parent head block hash %s...checking",sectionhex(self),hex(self.parentHash))
self.blockHashesRequest()
self.blockHashesRequest()
}
}
}
}
}
}
ifself.initialised&&self.step==self.lastMissing{
ifself.initialised&&self.step==self.lastMissing{
plog.DebugDetailf("[%s] check if new blocks arrived (attempt %v): missing %v/%v/%v",sectionhex(self),self.blocksRequests,self.missing,self.lastMissing,self.depth)
glog.V(logger.Detail).Infof("[%s] check if new blocks arrived (attempt %v): missing %v/%v/%v",sectionhex(self),self.blocksRequests,self.missing,self.lastMissing,self.depth)
self.checkRound()
self.checkRound()
checking=false
checking=false
}
}
@ -347,7 +346,7 @@ LOOP:
self.bp.wg.Done()
self.bp.wg.Done()
}
}
plog.DebugDetailf("[%s] section process terminated: %v blocks retrieved (%v attempts), hash requests complete on root (%v attempts).",sectionhex(self),self.depth,self.blocksRequests,self.blockHashesRequests)
glog.V(logger.Detail).Infof("[%s] section process terminated: %v blocks retrieved (%v attempts), hash requests complete on root (%v attempts).",sectionhex(self),self.depth,self.blocksRequests,self.blockHashesRequests)
plog.DebugDetailf("[%s] section checked: got all blocks. process complete (%v total blocksRequests): missing %v/%v/%v",sectionhex(self),self.blocksRequests,self.missing,self.lastMissing,self.depth)
glog.V(logger.Detail).Infof("[%s] section checked: got all blocks. process complete (%v total blocksRequests): missing %v/%v/%v",sectionhex(self),self.blocksRequests,self.missing,self.lastMissing,self.depth)