2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  eth  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"bytes" 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"math" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"math/big" 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"math/rand" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"sort" 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"sync" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/core/types" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/ethutil" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ethlogger  "github.com/ethereum/go-ethereum/logger" 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/pow" 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  poolLogger  =  ethlogger . NewLogger ( "Blockpool" )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									blockHashesBatchSize        =  256 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blockBatchSize              =  64 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									blocksRequestInterval       =  500  // ms 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									blocksRequestRepetition     =  1 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									blockHashesRequestInterval  =  500  // ms 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blocksRequestMaxIdleRounds  =  100 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									blockHashesTimeout          =  60   // seconds 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blocksTimeout               =  120  // seconds 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  poolNode  struct  {  
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									lock     sync . RWMutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash     [ ] byte 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									td       * big . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									block    * types . Block 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									parent   * poolNode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									peer     string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blockBy  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  poolEntry  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									node     * poolNode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									section  * section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									index    int 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  BlockPool  struct  {  
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									lock       sync . RWMutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chainLock  sync . RWMutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pool  map [ string ] * poolEntry 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									peersLock  sync . RWMutex 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									peers      map [ string ] * peerInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									peer       * peerInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									quit     chan  bool 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									purgeC   chan  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									flushC   chan  bool 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									wg       sync . WaitGroup 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									procWg   sync . WaitGroup 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									running  bool 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// the minimal interface with blockchain 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hasBlock     func ( hash  [ ] byte )  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									insertChain  func ( types . Blocks )  error 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									verifyPoW    func ( pow . Block )  bool 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  peerInfo  struct  {  
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									lock  sync . RWMutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									td                * big . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									currentBlockHash  [ ] byte 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									currentBlock      * types . Block 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									currentBlockC     chan  * types . Block 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									parentHash        [ ] byte 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									headSection       * section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									headSectionC      chan  * section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									id                string 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									requestBlockHashes  func ( [ ] byte )  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									requestBlocks       func ( [ ] [ ] byte )  error 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									peerError           func ( int ,  string ,  ... interface { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									sections  map [ string ] * section 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									quitC  chan  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// structure to store long range links on chain to skip along  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  section  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									lock         sync . RWMutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									parent       * section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									child        * section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									top          * poolNode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bottom       * poolNode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									nodes        [ ] * poolNode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									controlC     chan  * peerInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									suicideC     chan  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blockChainC  chan  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									forkC        chan  chan  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									offC         chan  bool 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  NewBlockPool ( hasBlock  func ( hash  [ ] byte )  bool ,  insertChain  func ( types . Blocks )  error ,  verifyPoW  func ( pow . Block )  bool ,  
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  * BlockPool  {  
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  & BlockPool { 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hasBlock :     hasBlock , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										insertChain :  insertChain , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										verifyPoW :    verifyPoW , 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// allows restart  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  Start ( )  {  
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									self . lock . Lock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  self . running  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . running  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . quit  =  make ( chan  bool ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . flushC  =  make ( chan  bool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . pool  =  make ( map [ string ] * poolEntry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . peersLock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . peers  =  make ( map [ string ] * peerInfo ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . peersLock . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									poolLogger . Infoln ( "Started" ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  Stop ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! self . running  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . lock . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . running  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									poolLogger . Infoln ( "Stopping..." ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									close ( self . quit ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:15:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									//self.wg.Wait() 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									self . peersLock . Lock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . peers  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . peer  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									self . peersLock . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . pool  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolLogger . Infoln ( "Stopped" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  Purge ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! self . running  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolLogger . Infoln ( "Purging..." ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									close ( self . purgeC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . wg . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . purgeC  =  make ( chan  bool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									poolLogger . Infoln ( "Stopped" ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  Wait ( t  time . Duration )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! self . running  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolLogger . Infoln ( "Waiting for processes to complete..." ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									close ( self . flushC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									w  :=  make ( chan  bool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									go  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . procWg . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										close ( w ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  <- w : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Infoln ( "Processes complete" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  <- time . After ( t ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Warnf ( "Timeout" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . flushC  =  make ( chan  bool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// AddPeer is called by the eth protocol instance running on the peer after  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the status message has been received with total difficulty and current block hash  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// AddPeer can only be used once, RemovePeer needs to be called when the peer disconnects  
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  AddPeer ( td  * big . Int ,  currentBlockHash  [ ] byte ,  peerId  string ,  requestBlockHashes  func ( [ ] byte )  error ,  requestBlocks  func ( [ ] [ ] byte )  error ,  peerError  func ( int ,  string ,  ... interface { } ) )  ( best  bool )  {  
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									self . peersLock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . peersLock . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									peer ,  ok  :=  self . peers [ peerId ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  bytes . Compare ( peer . currentBlockHash ,  currentBlockHash )  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . Debugf ( "Update peer %v with td %v and current block %s" ,  peerId ,  td ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer . td  =  td 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer . currentBlockHash  =  currentBlockHash 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer . currentBlock  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer . parentHash  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer . headSection  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer  =  & peerInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											td :                  td , 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											currentBlockHash :    currentBlockHash , 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											id :                  peerId ,  //peer.Identity().Pubkey() 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											requestBlockHashes :  requestBlockHashes , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											requestBlocks :       requestBlocks , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peerError :           peerError , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											sections :            make ( map [ string ] * section ) , 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											currentBlockC :       make ( chan  * types . Block ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											headSectionC :        make ( chan  * section ) , 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . peers [ peerId ]  =  peer 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										poolLogger . Debugf ( "add new peer %v with td %v and current block %x" ,  peerId ,  td ,  currentBlockHash [ : 4 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// check peer current head 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  self . hasBlock ( currentBlockHash )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// peer not ahead 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  self . peer  ==  peer  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// new block update 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// peer is already active best peer, request hashes 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										poolLogger . Debugf ( "[%s] already the best peer. Request new head section info from %s" ,  peerId ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer . headSectionC  <-  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										best  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										currentTD  :=  ethutil . Big0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  self . peer  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											currentTD  =  self . peer . td 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  td . Cmp ( currentTD )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . Debugf ( "peer %v promoted best peer" ,  peerId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . switchPeer ( self . peer ,  peer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . peer  =  peer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											best  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  requestHeadSection ( peer  * peerInfo )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . wg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . procWg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolLogger . Debugf ( "[%s] head section at [%s] requesting info" ,  peer . id ,  name ( peer . currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									go  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  idle  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer . lock . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										quitC  :=  peer . quitC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										currentBlockHash  :=  peer . currentBlockHash 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer . lock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										blockHashesRequestTimer  :=  time . NewTimer ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										blocksRequestTimer  :=  time . NewTimer ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										suicide  :=  time . NewTimer ( blockHashesTimeout  *  time . Second ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										blockHashesRequestTimer . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										defer  blockHashesRequestTimer . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										defer  blocksRequestTimer . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										entry  :=  self . get ( currentBlockHash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  entry  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											entry . node . lock . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											currentBlock  :=  entry . node . block 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											entry . node . lock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  currentBlock  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . currentBlock  =  currentBlock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . parentHash  =  currentBlock . ParentHash ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												poolLogger . Debugf ( "[%s] head block [%s] found" ,  peer . id ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blockHashesRequestTimer . Reset ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blocksRequestTimer . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									LOOP : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- self . quit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- quitC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												poolLogger . Debugf ( "[%s] head section at [%s] incomplete - quit request loop" ,  peer . id ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  headSection  :=  <- peer . headSectionC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . headSection  =  headSection 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  headSection  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													oldBlockHash  :=  currentBlockHash 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													currentBlockHash  =  peer . currentBlockHash 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													poolLogger . Debugf ( "[%s] head section changed [%s] -> [%s]" ,  peer . id ,  name ( oldBlockHash ) ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  idle  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														idle  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														suicide . Reset ( blockHashesTimeout  *  time . Second ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . procWg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													blocksRequestTimer . Reset ( blocksRequestInterval  *  time . Millisecond ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													poolLogger . DebugDetailf ( "[%s] head section at [%s] created" ,  peer . id ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  ! idle  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														idle  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														suicide . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . procWg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blockHashesRequestTimer . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- blockHashesRequestTimer . C : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												poolLogger . DebugDetailf ( "[%s] head section at [%s] not found, requesting block hashes" ,  peer . id ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . requestBlockHashes ( currentBlockHash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blockHashesRequestTimer . Reset ( blockHashesRequestInterval  *  time . Millisecond ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  currentBlock  :=  <- peer . currentBlockC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . currentBlock  =  currentBlock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . parentHash  =  currentBlock . ParentHash ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												poolLogger . DebugDetailf ( "[%s] head block [%s] found" ,  peer . id ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  self . hasBlock ( currentBlock . ParentHash ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  err  :=  self . insertChain ( types . Blocks ( [ ] * types . Block { currentBlock } ) ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														peer . peerError ( ErrInvalidBlock ,  "%v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  ! idle  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														idle  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														suicide . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . procWg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													blockHashesRequestTimer . Reset ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blocksRequestTimer . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- blocksRequestTimer . C : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . lock . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												poolLogger . DebugDetailf ( "[%s] head block [%s] not found, requesting" ,  peer . id ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . requestBlocks ( [ ] [ ] byte { peer . currentBlockHash } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . lock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blocksRequestTimer . Reset ( blocksRequestInterval  *  time . Millisecond ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- suicide . C : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer . peerError ( ErrInsufficientChainInfo ,  "peer failed to provide block hashes or head block for block hash %x" ,  currentBlockHash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . wg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! idle  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . procWg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// RemovePeer is called by the eth protocol when the peer disconnects  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  RemovePeer ( peerId  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . peersLock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . peersLock . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									peer ,  ok  :=  self . peers [ peerId ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									delete ( self . peers ,  peerId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolLogger . Debugf ( "remove peer %v" ,  peerId ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// if current best peer is removed, need find a better one 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  self . peer  ==  peer  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										var  newPeer  * peerInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										max  :=  ethutil . Big0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// peer with the highest self-acclaimed TD is chosen 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  info  :=  range  self . peers  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  info . td . Cmp ( max )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												max  =  info . td 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												newPeer  =  info 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  newPeer  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											poolLogger . Debugf ( "peer %v with td %v promoted to best peer" ,  newPeer . id ,  newPeer . td ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											poolLogger . Warnln ( "no peers" ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self . peer  =  newPeer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . switchPeer ( peer ,  newPeer ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Entry point for eth protocol to add block hashes received via BlockHashesMsg  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// only hashes from the best peer is handled  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// this method is always responsible to initiate further hash requests until  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// a known parent is reached unless cancelled by a peerChange event  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// this process also launches all request processes on each chain section  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// this function needs to run asynchronously for one peer since the message is discarded???  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  AddBlockHashes ( next  func ( )  ( [ ] byte ,  bool ) ,  peerId  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// register with peer manager loop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									peer ,  best  :=  self . getPeer ( peerId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! best  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// peer is still the best 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  size ,  n  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  hash  [ ] byte 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  ok ,  headSection  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  sec ,  child ,  parent  * section 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  entry  * poolEntry 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  nodes  [ ] * poolNode 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bestPeer  :=  peer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash ,  ok  =  next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									peer . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  bytes . Compare ( peer . parentHash ,  hash )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  self . hasBlock ( peer . currentBlockHash )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Debugf ( "adding hashes at chain head for best peer %s starting from [%s]" ,  peerId ,  name ( peer . currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										headSection  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  entry  :=  self . get ( peer . currentBlockHash ) ;  entry  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											node  :=  & poolNode { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												hash :     peer . currentBlockHash , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												block :    peer . currentBlock , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer :     peerId , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blockBy :  peerId , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  size  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												sec  =  newSection ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											nodes  =  append ( nodes ,  node ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											size ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											n ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											child  =  entry . section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Debugf ( "adding hashes for best peer %s starting from [%s]" ,  peerId ,  name ( hash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									quitC  :=  peer . quitC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									peer . lock . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								LOOP :  
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// iterate using next (rlp stream lazy decoder) feeding hashesC 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ;  ok ;  hash ,  ok  =  next ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										n ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  <- self . quit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  <- quitC : 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// if the peer is demoted, no more hashes taken 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											bestPeer  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  self . hasBlock ( hash )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// check if known block connecting the downloaded chain to our blockchain 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . DebugDetailf ( "[%s] known block" ,  name ( hash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// mark child as absolute pool root with parent known to blockchain 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  sec  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												self . connectToBlockChain ( sec ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  child  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													self . connectToBlockChain ( child ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break  LOOP 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// look up node in pool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										entry  =  self . get ( hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  entry  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// reached a known chain in the pool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  entry . node  ==  entry . section . bottom  &&  n  ==  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// the first block hash received is an orphan in the pool, so rejoice and continue 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												poolLogger . DebugDetailf ( "[%s] connecting child section" ,  sectionName ( entry . section ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												child  =  entry . section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . DebugDetailf ( "[%s] reached blockpool chain" ,  name ( hash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											parent  =  entry . section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break  LOOP 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// if node for block hash does not exist, create it and index in the pool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										node  :=  & poolNode { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											hash :  hash , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer :  peerId , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  size  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											sec  =  newSection ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nodes  =  append ( nodes ,  node ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										size ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  //for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . chainLock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolLogger . DebugDetailf ( "added %v hashes sent by %s" ,  n ,  peerId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  parent  !=  nil  &&  entry  !=  nil  &&  entry . node  !=  parent . top  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . DebugDetailf ( "[%s] split section at fork" ,  sectionName ( parent ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										parent . controlC  <-  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										waiter  :=  make ( chan  bool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										parent . forkC  <-  waiter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chain  :=  parent . nodes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										parent . nodes  =  chain [ entry . index : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										parent . top  =  parent . nodes [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										orphan  :=  newSection ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . link ( orphan ,  parent . child ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . processSection ( orphan ,  chain [ 0 : entry . index ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										orphan . controlC  <-  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										close ( waiter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  size  >  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self . processSection ( sec ,  nodes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . DebugDetailf ( "[%s]->[%s](%v)->[%s] new chain section" ,  sectionName ( parent ) ,  sectionName ( sec ) ,  size ,  sectionName ( child ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . link ( parent ,  sec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . link ( sec ,  child ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . DebugDetailf ( "[%s]->[%s] connecting known sections" ,  sectionName ( parent ) ,  sectionName ( child ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . link ( parent ,  child ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . chainLock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  parent  !=  nil  &&  bestPeer  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self . activateChain ( parent ,  peer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Debugf ( "[%s] activate parent section [%s]" ,  name ( parent . top . hash ) ,  sectionName ( parent ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  sec  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer . addSection ( sec . top . hash ,  sec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// request next section here once, only repeat if bottom block arrives, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// otherwise no way to check if it arrived 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer . requestBlockHashes ( sec . bottom . hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sec . controlC  <-  bestPeer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Debugf ( "[%s] activate new section" ,  sectionName ( sec ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  headSection  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  headSec  * section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  sec  !=  nil : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											headSec  =  sec 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  child  !=  nil : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											headSec  =  child 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											headSec  =  parent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer . headSectionC  <-  headSec 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  name ( hash  [ ] byte )  ( name  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  hash  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										name  =  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										name  =  fmt . Sprintf ( "%x" ,  hash [ : 4 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  sectionName ( section  * section )  ( name  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  section  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										name  =  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										name  =  fmt . Sprintf ( "%x-%x" ,  section . bottom . hash [ : 4 ] ,  section . top . hash [ : 4 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// AddBlock is the entry point for the eth protocol when blockmsg is received upon requests  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// It has a strict interpretation of the protocol in that if the block received has not been requested, it results in an error (which can be ignored)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// block is checked for PoW  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// only the first PoW-valid block for a hash is considered legit  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  AddBlock ( block  * types . Block ,  peerId  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash  :=  block . Hash ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . peersLock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									peer  :=  self . peer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . peersLock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									entry  :=  self . get ( hash ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  bytes . Compare ( hash ,  peer . currentBlockHash )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Debugf ( "add head block [%s] for peer %s" ,  name ( hash ) ,  peerId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer . currentBlockC  <-  block 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  entry  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . Warnf ( "unrequested block [%s] by peer %s" ,  name ( hash ) ,  peerId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . peerError ( peerId ,  ErrUnrequestedBlock ,  "%x" ,  hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  entry  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									node  :=  entry . node 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									node . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  node . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// check if block already present 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  node . block  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										poolLogger . DebugDetailf ( "block [%s] already sent by %s" ,  name ( hash ) ,  node . blockBy ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  self . hasBlock ( hash )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . DebugDetailf ( "block [%s] already known" ,  name ( hash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// validate block for PoW 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! self . verifyPoW ( block )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-02 20:02:00 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											poolLogger . Warnf ( "invalid pow on block [%s %v] by peer %s" ,  name ( hash ) ,  block . Number ( ) ,  peerId ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											self . peerError ( peerId ,  ErrInvalidPoW ,  "%x" ,  hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-02 20:02:00 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									poolLogger . DebugDetailf ( "added block [%s] sent by peer %s" ,  name ( hash ) ,  peerId ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									node . block  =  block 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									node . blockBy  =  peerId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  connectToBlockChain ( section  * section )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  <- section . offC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . addSectionToBlockChain ( section ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  <- section . blockChainC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										close ( section . blockChainC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  addSectionToBlockChain ( section  * section )  ( rest  int ,  err  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  blocks  types . Blocks 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  node  * poolNode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  keys  [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rest  =  len ( section . nodes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  rest  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rest -- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										node  =  section . nodes [ rest ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										node . lock . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										block  :=  node . block 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										node . lock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  block  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										keys  =  append ( keys ,  string ( node . hash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										blocks  =  append ( blocks ,  block ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  key  :=  range  keys  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										delete ( self . pool ,  key ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolLogger . Infof ( "insert %v blocks into blockchain" ,  len ( blocks ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  =  self . insertChain ( blocks ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// TODO: not clear which peer we need to address 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// peerError should dispatch to peer if still connected and disconnect 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . peerError ( node . blockBy ,  ErrInvalidBlock ,  "%v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Warnf ( "invalid block %x" ,  node . hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Warnf ( "penalise peers %v (hash), %v (block)" ,  node . peer ,  node . blockBy ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// penalise peer in node.blockBy 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// self.disconnect() 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  activateChain ( section  * section ,  peer  * peerInfo )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolLogger . DebugDetailf ( "[%s] activate known chain for peer %s" ,  sectionName ( section ) ,  peer . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									i  :=  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LOOP :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  section  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// register this section with the peer and quit if registered 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . DebugDetailf ( "[%s] register section with peer %s" ,  sectionName ( section ) ,  peer . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  peer . addSection ( section . top . hash ,  section )  ==  section  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . DebugDetailf ( "[%s] activate section process" ,  sectionName ( section ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  section . controlC  <-  peer : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  <- section . offC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										i ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										section  =  self . getParent ( section ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  <- peer . quitC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  <- self . quit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// 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  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// - when exits, signals to  
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  processSection ( sec  * section ,  nodes  [ ] * poolNode )  {  
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  node  :=  range  nodes  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										entry  :=  & poolEntry { node :  node ,  section :  sec ,  index :  i } 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self . set ( node . hash ,  entry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									sec . bottom  =  nodes [ len ( nodes ) - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sec . top  =  nodes [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sec . nodes  =  nodes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolLogger . DebugDetailf ( "[%s] setup section process" ,  sectionName ( sec ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . wg . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									go  func ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// absolute time after which sub-chain is killed if not complete (some blocks are missing) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										suicideTimer  :=  time . After ( blocksTimeout  *  time . Second ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  peer ,  newPeer  * peerInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  blocksRequestTimer ,  blockHashesRequestTimer  <- chan  time . Time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  blocksRequestTime ,  blockHashesRequestTime  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  blocksRequests ,  blockHashesRequests  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  blocksRequestsComplete ,  blockHashesRequestsComplete  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// node channels for the section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  missingC ,  processC ,  offC  chan  * poolNode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// container for missing block hashes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  hashes  [ ] [ ] byte 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  i ,  missing ,  lastMissing ,  depth  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  idle  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  init ,  done ,  same ,  ready  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  insertChain  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  quitC  chan  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  blockChainC  =  sec . blockChainC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  parentHash  [ ] byte 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									LOOP : 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  insertChain  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												insertChain  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												rest ,  err  :=  self . addSectionToBlockChain ( sec ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													close ( sec . suicideC ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													continue  LOOP 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  rest  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													blocksRequestsComplete  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													child  :=  self . getChild ( sec ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													if  child  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . connectToBlockChain ( child ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  blockHashesRequestsComplete  &&  blocksRequestsComplete  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// not waiting for hashes any more 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												poolLogger . Debugf ( "[%s] section complete %v blocks retrieved (%v attempts), hash requests complete on root (%v attempts)" ,  sectionName ( sec ) ,  depth ,  blocksRequests ,  blockHashesRequests ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												break  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  // otherwise suicide if no hashes coming 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  done  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// went through all blocks in section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  missing  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													// no missing blocks 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													poolLogger . DebugDetailf ( "[%s] got all blocks. process complete (%v total blocksRequests): missing %v/%v/%v" ,  sectionName ( sec ) ,  blocksRequests ,  missing ,  lastMissing ,  depth ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													blocksRequestsComplete  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													blocksRequestTimer  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													blocksRequestTime  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													poolLogger . DebugDetailf ( "[%s] section checked: missing %v/%v/%v" ,  sectionName ( sec ) ,  missing ,  lastMissing ,  depth ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													// some missing blocks 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													blocksRequests ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  len ( hashes )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														// send block requests to peers 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . requestBlocks ( blocksRequests ,  hashes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														hashes  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  missing  ==  lastMissing  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														// idle round 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  same  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															// more than once 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															idle ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															// too many idle rounds 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															if  idle  >=  blocksRequestMaxIdleRounds  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
																poolLogger . DebugDetailf ( "[%s] block requests had %v idle rounds (%v total attempts): missing %v/%v/%v\ngiving up..." ,  sectionName ( sec ) ,  idle ,  blocksRequests ,  missing ,  lastMissing ,  depth ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																close ( sec . suicideC ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
															} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															idle  =  0 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														same  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														same  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												lastMissing  =  missing 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ready  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												done  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// save a new processC (blocks still missing) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												offC  =  missingC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												missingC  =  processC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// put processC offline 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												processC  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ready  &&  blocksRequestTime  &&  ! blocksRequestsComplete  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												poolLogger . DebugDetailf ( "[%s] check if new blocks arrived (attempt %v): missing %v/%v/%v" ,  sectionName ( sec ) ,  blocksRequests ,  missing ,  lastMissing ,  depth ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												blocksRequestTimer  =  time . After ( blocksRequestInterval  *  time . Millisecond ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blocksRequestTime  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												processC  =  offC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  blockHashesRequestTime  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												var  parentSection  =  self . getParent ( sec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  parentSection  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  parent  :=  self . get ( parentHash ) ;  parent  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														parentSection  =  parent . section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . chainLock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . link ( parentSection ,  sec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . chainLock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  self . hasBlock ( parentHash )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															insertChain  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															blockHashesRequestTime  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															blockHashesRequestTimer  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															blockHashesRequestsComplete  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															continue  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  parentSection  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													// if not root of chain, switch off 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													poolLogger . DebugDetailf ( "[%s] parent found, hash requests deactivated (after %v total attempts)\n" ,  sectionName ( sec ) ,  blockHashesRequests ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													blockHashesRequestTimer  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													blockHashesRequestsComplete  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													blockHashesRequests ++ 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													poolLogger . Debugf ( "[%s] hash request on root (%v total attempts)\n" ,  sectionName ( sec ) ,  blockHashesRequests ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													peer . requestBlockHashes ( sec . bottom . hash ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													blockHashesRequestTimer  =  time . After ( blockHashesRequestInterval  *  time . Millisecond ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												blockHashesRequestTime  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- self . quit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- quitC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// peer quit or demoted, put section in idle mode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												quitC  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												go  func ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													sec . controlC  <-  nil 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- self . purgeC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												suicideTimer  =  time . After ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- suicideTimer : 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												close ( sec . suicideC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												poolLogger . Debugf ( "[%s] timeout. (%v total attempts): missing %v/%v/%v" ,  sectionName ( sec ) ,  blocksRequests ,  missing ,  lastMissing ,  depth ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											case  <- sec . suicideC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												poolLogger . Debugf ( "[%s] suicide" ,  sectionName ( sec ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// first delink from child and parent under chainlock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												self . chainLock . Lock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												self . link ( nil ,  sec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												self . link ( sec ,  nil ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												self . chainLock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// delete node entries from pool index under pool lock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												self . lock . Lock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												for  _ ,  node  :=  range  sec . nodes  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													delete ( self . pool ,  string ( node . hash ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- blocksRequestTimer : 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												poolLogger . DebugDetailf ( "[%s] block request time" ,  sectionName ( sec ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												blocksRequestTime  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- blockHashesRequestTimer : 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												poolLogger . DebugDetailf ( "[%s] hash request time" ,  sectionName ( sec ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												blockHashesRequestTime  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											case  newPeer  =  <- sec . controlC : 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// active -> idle 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  peer  !=  nil  &&  newPeer  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													self . procWg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  init  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														poolLogger . Debugf ( "[%s] idle mode (%v total attempts): missing %v/%v/%v" ,  sectionName ( sec ) ,  blocksRequests ,  missing ,  lastMissing ,  depth ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													blocksRequestTime  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													blocksRequestTimer  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													blockHashesRequestTime  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													blockHashesRequestTimer  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													if  processC  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														offC  =  processC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														processC  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// idle -> active 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  peer  ==  nil  &&  newPeer  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													self . procWg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													poolLogger . Debugf ( "[%s] active mode" ,  sectionName ( sec ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													if  ! blocksRequestsComplete  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														blocksRequestTime  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													if  ! blockHashesRequestsComplete  &&  parentHash  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														blockHashesRequestTime  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													if  ! init  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														processC  =  make ( chan  * poolNode ,  blockHashesBatchSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														missingC  =  make ( chan  * poolNode ,  blockHashesBatchSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														i  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														missing  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . wg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														self . procWg . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														depth  =  len ( sec . nodes ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														lastMissing  =  depth 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														// if not run at least once fully, launch iterator 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														go  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															var  node  * poolNode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														IT : 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
															for  _ ,  node  =  range  sec . nodes  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
																select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																case  processC  <-  node : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																case  <- self . quit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																	break  IT 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															close ( processC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															self . wg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															self . procWg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														poolLogger . Debugf ( "[%s] restore earlier state" ,  sectionName ( sec ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														processC  =  offC 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// reset quitC to current best peer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  newPeer  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													quitC  =  newPeer . quitC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer  =  newPeer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											case  waiter  :=  <- sec . forkC : 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// this case just blocks the process until section is split at the fork 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												<- waiter 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												init  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												done  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ready  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											case  node ,  ok  :=  <- processC : 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ! ok  &&  ! init  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													// channel closed, first iteration finished 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													init  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													done  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													processC  =  make ( chan  * poolNode ,  missing ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													poolLogger . DebugDetailf ( "[%s] section initalised: missing %v/%v/%v" ,  sectionName ( sec ) ,  missing ,  lastMissing ,  depth ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													continue  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ready  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													i  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													missing  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ready  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												i ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// if node has no block 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												node . lock . RLock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												block  :=  node . block 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												node . lock . RUnlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  block  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													missing ++ 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													hashes  =  append ( hashes ,  node . hash ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													if  len ( hashes )  ==  blockBatchSize  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														poolLogger . Debugf ( "[%s] request %v missing blocks" ,  sectionName ( sec ) ,  len ( hashes ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														self . requestBlocks ( blocksRequests ,  hashes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														hashes  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													missingC  <-  node 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													if  i  ==  lastMissing  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  blockChainC  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															insertChain  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															if  parentHash  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																parentHash  =  block . ParentHash ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																poolLogger . Debugf ( "[%s] found root block [%s]" ,  sectionName ( sec ) ,  name ( parentHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																blockHashesRequestTime  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  i  ==  lastMissing  &&  init  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													done  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- blockChainC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// closed blockChain channel indicates that the blockpool is reached 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// connected to the blockchain, insert the longest chain of blocks 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												poolLogger . Debugf ( "[%s] reached blockchain" ,  sectionName ( sec ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												blockChainC  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// switch off hash requests in case they were on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blockHashesRequestTime  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blockHashesRequestTimer  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												blockHashesRequestsComplete  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// section root has block 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  len ( sec . nodes )  >  0  &&  sec . nodes [ len ( sec . nodes ) - 1 ] . block  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													insertChain  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue  LOOP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  // select 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  // for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										close ( sec . offC ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . wg . Done ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  peer  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . procWg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  peerError ( peerId  string ,  code  int ,  format  string ,  params  ... interface { } )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . peersLock . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . peersLock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									peer ,  ok  :=  self . peers [ peerId ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer . peerError ( code ,  format ,  params ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  requestBlocks ( attempts  int ,  hashes  [ ] [ ] byte )  {  
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . wg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . procWg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									go  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// distribute block request among known peers 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . peersLock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										defer  self . peersLock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peerCount  :=  len ( self . peers ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// on first attempt use the best peer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  attempts  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . Debugf ( "request %v missing blocks from best peer %s" ,  len ( hashes ) ,  self . peer . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . peer . requestBlocks ( hashes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										repetitions  :=  int ( math . Min ( float64 ( peerCount ) ,  float64 ( blocksRequestRepetition ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										i  :=  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										indexes  :=  rand . Perm ( peerCount ) [ 0 : repetitions ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sort . Ints ( indexes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poolLogger . Debugf ( "request %v missing blocks from %v/%v peers: chosen %v" ,  len ( hashes ) ,  repetitions ,  peerCount ,  indexes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  peer  :=  range  self . peers  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  i  ==  indexes [ 0 ]  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-28 21:34:08 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												poolLogger . Debugf ( "request %v missing blocks [%x/%x] from peer %s" ,  len ( hashes ) ,  hashes [ 0 ] [ : 4 ] ,  hashes [ len ( hashes ) - 1 ] [ : 4 ] ,  peer . id ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												peer . requestBlocks ( hashes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												indexes  =  indexes [ 1 : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  len ( indexes )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											i ++ 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self . wg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . procWg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  getPeer ( peerId  string )  ( * peerInfo ,  bool )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . peersLock . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . peersLock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  self . peer  !=  nil  &&  self . peer . id  ==  peerId  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  self . peer ,  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									info ,  ok  :=  self . peers [ peerId ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  false 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  info ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * peerInfo )  addSection ( hash  [ ] byte ,  section  * section )  ( found  * section )  {  
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . lock . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									key  :=  string ( hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									found  =  self . sections [ key ] 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									poolLogger . DebugDetailf ( "[%s] section process stored for %s" ,  sectionName ( section ) ,  self . id ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . sections [ key ]  =  section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  switchPeer ( oldPeer ,  newPeer  * peerInfo )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  newPeer  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										newPeer . quitC  =  make ( chan  bool ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										poolLogger . DebugDetailf ( "[%s] activate section processes" ,  newPeer . id ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  addSections  [ ] * section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  hash ,  section  :=  range  newPeer . sections  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// split sections get reorganised here 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  string ( section . top . hash )  !=  hash  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												addSections  =  append ( addSections ,  section ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  entry  :=  self . get ( [ ] byte ( hash ) ) ;  entry  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													addSections  =  append ( addSections ,  entry . section ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  section  :=  range  addSections  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											newPeer . sections [ string ( section . top . hash ) ]  =  section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  hash ,  section  :=  range  newPeer . sections  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// this will block if section process is waiting for peer lock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- section . offC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												poolLogger . DebugDetailf ( "[%s][%x] section process complete - remove" ,  newPeer . id ,  hash [ : 4 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												delete ( newPeer . sections ,  hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  section . controlC  <-  newPeer : 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												poolLogger . DebugDetailf ( "[%s][%x] activates section [%s]" ,  newPeer . id ,  hash [ : 4 ] ,  sectionName ( section ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										newPeer . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										headSection  :=  newPeer . headSection 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										currentBlockHash  :=  newPeer . currentBlockHash 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										newPeer . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  headSection  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . DebugDetailf ( "[%s] head section for [%s] not created, requesting info" ,  newPeer . id ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . requestHeadSection ( newPeer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  entry  :=  self . get ( currentBlockHash ) ;  entry  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												headSection  =  entry . section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . DebugDetailf ( "[%s] activate chain at head section [%s] for current head [%s]" ,  newPeer . id ,  sectionName ( headSection ) ,  name ( currentBlockHash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . activateChain ( headSection ,  newPeer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  oldPeer  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 06:03:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										poolLogger . DebugDetailf ( "[%s] quit section processes" ,  oldPeer . id ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										close ( oldPeer . quitC ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  getParent ( sec  * section )  * section  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . chainLock . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . chainLock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  sec . parent 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  getChild ( sec  * section )  * section  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . chainLock . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . chainLock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  sec . child 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  newSection ( )  ( sec  * section )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sec  =  & section { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										controlC :     make ( chan  * peerInfo ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										suicideC :     make ( chan  bool ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										blockChainC :  make ( chan  bool ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										offC :         make ( chan  bool ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										forkC :        make ( chan  chan  bool ) , 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// link should only be called under chainLock  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  link ( parent  * section ,  child  * section )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  parent  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										exChild  :=  parent . child 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										parent . child  =  child 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  exChild  !=  nil  &&  exChild  !=  child  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . Debugf ( "[%s] chain fork [%s] -> [%s]" ,  sectionName ( parent ) ,  sectionName ( exChild ) ,  sectionName ( child ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											exChild . parent  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  child  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										exParent  :=  child . parent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  exParent  !=  nil  &&  exParent  !=  parent  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											poolLogger . Debugf ( "[%s] chain reverse fork [%s] -> [%s]" ,  sectionName ( child ) ,  sectionName ( exParent ) ,  sectionName ( parent ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											exParent . child  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-10 04:12:25 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										child . parent  =  parent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  get ( hash  [ ] byte )  ( node  * poolEntry )  {  
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . lock . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . lock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . pool [ string ( hash ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-05 17:10:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * BlockPool )  set ( hash  [ ] byte ,  node  * poolEntry )  {  
						 
					
						
							
								
									
										
										
										
											2014-12-14 18:08:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . lock . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . lock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . pool [ string ( hash ) ]  =  node 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}