// lastPoolNode is nil if and only if the node with stored root hash is already cleaned up
// after valid block insertion, therefore in this case the blockpool active chain is connected to the blockchain, so no need to request further hashes or request blocks
ifbottom==nil{// the chain section is being created or killed
break
}
// register this section with the peer
ifpeer!=nil{
peer.addSection(bottom.hash,bottom.section)
ifon{
bottom.section.start()
}else{
bottom.section.start()
}
}
ifbottom.parent==nil{
node=bottom
break
}
// if peer demoted stop activation
select{
case<-peer.quitC:
break
default:
}
node=bottom.parent
bottom.sectionRUnlock()
}
// remember root for this peer
peer.addRoot(node)
self.wg.Done()
}()
}
// main worker thread on each section in the poolchain
// - kills the section if there are blocks missing after an absolute time
// - kills the section if there are maxIdleRounds of idle rounds of block requests with no response
// - periodically polls the chain section for missing blocks which are then requested from peers
// - registers the process controller on the peer so that if the peer is promoted as best peer the second time (after a disconnect of a better one), all active processes are switched back on unless they expire and killed ()
// - when turned off (if peer disconnects and new peer connects with alternative chain), no blockrequests are made but absolute expiry timer is ticking
// - when turned back on it recursively calls itself on the root of the next chain section
poolLogger.Debugf("[%x] block requests had %v idle rounds (%v total attempts): missing %v/%v/%v\ngiving up...",hash[0:4],idle,blocksRequests,missing,total,depth)
self.killChain(node,nil)
break
}
}else{
idle=0
}
same=true
}else{
ifmissing==0{
// no missing nodes
poolLogger.Debugf("block request process complete on section %x... (%v total blocksRequests): missing %v/%v/%v",hash[0:4],blockHashesRequests,blocksRequests,missing,total,depth)
node.Lock()
orignode.complete=true
node.Unlock()
blocksRequestTimer=nil
ifblockHashesRequestTimer==nil{
// not waiting for hashes any more
poolLogger.Debugf("hash request on root %x... successful (%v total attempts)\nquitting...",hash[0:4],blockHashesRequests)
break
}// otherwise suicide if no hashes coming
}
same=false
}
lastMissing=missing
i=0
missing=0
// ready for next round
done=true
}
ifdone&&alarm{
poolLogger.Debugf("start checking if new blocks arrived (attempt %v): missing %v/%v/%v",blocksRequests,missing,total,depth)
// if same peer gave different chain before, this will overwrite it
// if currentPoolNode existed as a non-leaf node the earlier fork is delinked
// if same parent hash is found, we can abort, we do not allow the same peer to change minds about parent of same hash, if errored first time round, will get penalized.
// if lastPoolNode had a different parent the earlier parent (with entire subtree) is delinked, this situation cannot normally arise though
// just in case reset lastPoolNode as non-root (unlikely)