2016-11-09 02:01:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Copyright 2016 The go-ethereum Authors  
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// This file is part of the go-ethereum library.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The go-ethereum library is free software: you can redistribute it and/or modify  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// it under the terms of the GNU Lesser General Public License as published by  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the Free Software Foundation, either version 3 of the License, or  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// (at your option) any later version.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The go-ethereum library is distributed in the hope that it will be useful,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// but WITHOUT ANY WARRANTY; without even the implied warranty of  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GNU Lesser General Public License for more details.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// You should have received a copy of the GNU Lesser General Public License  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.  
						 
					
						
							
								
									
										
										
										
											2016-11-09 02:01:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  light  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2017-03-22 18:20:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"math/big" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"sync" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"sync/atomic" 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-22 20:44:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/common" 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-05 01:16:29 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/consensus" 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/core" 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-07 14:35:06 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/core/rawdb" 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/core/state" 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/core/types" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/ethdb" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/event" 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-22 14:10:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/log" 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-20 13:36:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/params" 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/ethereum/go-ethereum/rlp" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/hashicorp/golang-lru" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bodyCacheLimit   =  256 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blockCacheLimit  =  256 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// LightChain represents a canonical chain that by default only handles block  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// headers, downloading block bodies and receipts on demand through an ODR  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// interface. It only does header validation during chain insertion.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  LightChain  struct  {  
						 
					
						
							
								
									
										
										
										
											2017-08-18 18:58:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hc             * core . HeaderChain 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-28 15:08:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									indexerConfig  * IndexerConfig 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-18 18:58:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									chainDb        ethdb . Database 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									odr            OdrBackend 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chainFeed      event . Feed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chainSideFeed  event . Feed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chainHeadFeed  event . Feed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									scope          event . SubscriptionScope 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									genesisBlock   * types . Block 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mu       sync . RWMutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chainmu  sync . RWMutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bodyCache     * lru . Cache  // Cache for the most recent block bodies 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bodyRLPCache  * lru . Cache  // Cache for the most recent block bodies in RLP encoded format 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blockCache    * lru . Cache  // Cache for the most recent entire blocks 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									quit     chan  struct { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									running  int32  // running must be called automically 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// procInterrupt must be atomically called 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									procInterrupt  int32  // interrupt signaler for block processing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									wg             sync . WaitGroup 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-05 01:16:29 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									engine  consensus . Engine 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// NewLightChain returns a fully initialised light chain using information  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// available in the database. It initialises the default Ethereum header  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// validator.  
						 
					
						
							
								
									
										
										
										
											2017-08-18 18:58:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  NewLightChain ( odr  OdrBackend ,  config  * params . ChainConfig ,  engine  consensus . Engine )  ( * LightChain ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									bodyCache ,  _  :=  lru . New ( bodyCacheLimit ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bodyRLPCache ,  _  :=  lru . New ( bodyCacheLimit ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blockCache ,  _  :=  lru . New ( blockCacheLimit ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc  :=  & LightChain { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-28 15:08:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										chainDb :        odr . Database ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										indexerConfig :  odr . IndexerConfig ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										odr :            odr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										quit :           make ( chan  struct { } ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bodyCache :      bodyCache , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bodyRLPCache :   bodyRLPCache , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										blockCache :     blockCache , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										engine :         engine , 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  err  error 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-05 01:16:29 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bc . hc ,  err  =  core . NewHeaderChain ( odr . Database ( ) ,  config ,  bc . engine ,  bc . getProcInterrupt ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . genesisBlock ,  _  =  bc . GetBlockByNumber ( NoOdr ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  bc . genesisBlock  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-02 14:03:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  core . ErrNoGenesis 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  cp ,  ok  :=  trustedCheckpoints [ bc . genesisBlock . Hash ( ) ] ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bc . addTrustedCheckpoint ( cp ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-11 23:36:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  :=  bc . loadLastState ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 15:52:03 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  hash  :=  range  core . BadHashes  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  header  :=  bc . GetHeaderByHash ( hash ) ;  header  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-03 11:41:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											log . Error ( "Found bad hash, rewinding chain" ,  "number" ,  header . Number ,  "hash" ,  header . ParentHash ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											bc . SetHead ( header . Number . Uint64 ( )  -  1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-03 11:41:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											log . Error ( "Chain rewind was successful, resuming normal operation" ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bc ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// addTrustedCheckpoint adds a trusted checkpoint to the blockchain  
						 
					
						
							
								
									
										
										
										
											2018-09-20 14:11:14 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * LightChain )  addTrustedCheckpoint ( cp  * params . TrustedCheckpoint )  {  
						 
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  self . odr . ChtIndexer ( )  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-20 14:11:14 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										StoreChtRoot ( self . chainDb ,  cp . SectionIndex ,  cp . SectionHead ,  cp . CHTRoot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . odr . ChtIndexer ( ) . AddCheckpoint ( cp . SectionIndex ,  cp . SectionHead ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  self . odr . BloomTrieIndexer ( )  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-20 14:11:14 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										StoreBloomTrieRoot ( self . chainDb ,  cp . SectionIndex ,  cp . SectionHead ,  cp . BloomRoot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . odr . BloomTrieIndexer ( ) . AddCheckpoint ( cp . SectionIndex ,  cp . SectionHead ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  self . odr . BloomIndexer ( )  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-20 14:11:14 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self . odr . BloomIndexer ( ) . AddCheckpoint ( cp . SectionIndex ,  cp . SectionHead ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-20 14:11:14 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									log . Info ( "Added trusted checkpoint" ,  "chain" ,  cp . Name ,  "block" ,  ( cp . SectionIndex + 1 ) * self . indexerConfig . ChtSize - 1 ,  "hash" ,  cp . SectionHead ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  getProcInterrupt ( )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  atomic . LoadInt32 ( & self . procInterrupt )  ==  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Odr returns the ODR backend of the chain  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  Odr ( )  OdrBackend  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . odr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// loadLastState loads the last known chain state from the database. This method  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// assumes that the chain manager mutex is held.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  loadLastState ( )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-05-07 14:35:06 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  head  :=  rawdb . ReadHeadHeaderHash ( self . chainDb ) ;  head  ==  ( common . Hash { } )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// Corrupt or empty database, init from scratch 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . Reset ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  header  :=  self . GetHeaderByHash ( head ) ;  header  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . hc . SetCurrentHeader ( header ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Issue a status log and return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									header  :=  self . hc . CurrentHeader ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									headerTd  :=  self . GetTd ( header . Hash ( ) ,  header . Number . Uint64 ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-20 11:41:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									log . Info ( "Loaded most recent local header" ,  "number" ,  header . Number ,  "hash" ,  header . Hash ( ) ,  "td" ,  headerTd ,  "age" ,  common . PrettyAge ( time . Unix ( header . Time . Int64 ( ) ,  0 ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SetHead rewinds the local chain to a new head. Everything above the new  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// head will be deleted and the new one set.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  SetHead ( head  uint64 )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  bc . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . hc . SetHead ( head ,  nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . loadLastState ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GasLimit returns the gas limit of the current HEAD block.  
						 
					
						
							
								
									
										
										
										
											2017-11-13 13:47:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GasLimit ( )  uint64  {  
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  self . hc . CurrentHeader ( ) . GasLimit 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Reset purges the entire blockchain, restoring it to its genesis state.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  Reset ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . ResetWithGenesisBlock ( bc . genesisBlock ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ResetWithGenesisBlock purges the entire blockchain, restoring it to the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// specified genesis state.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  ResetWithGenesisBlock ( genesis  * types . Block )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Dump the entire block chain and purge the caches 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . SetHead ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  bc . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Prepare the genesis block and reinitialise the chain 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-07 14:35:06 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									rawdb . WriteTd ( bc . chainDb ,  genesis . Hash ( ) ,  genesis . NumberU64 ( ) ,  genesis . Difficulty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rawdb . WriteBlock ( bc . chainDb ,  genesis ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									bc . genesisBlock  =  genesis 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . hc . SetGenesis ( bc . genesisBlock . Header ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . hc . SetCurrentHeader ( bc . genesisBlock . Header ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Accessors  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-12 16:38:31 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Engine retrieves the light chain's consensus engine.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  Engine ( )  consensus . Engine  {  return  bc . engine  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// Genesis returns the genesis block  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  Genesis ( )  * types . Block  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bc . genesisBlock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// State returns a new mutable state based on the current HEAD block.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  State ( )  ( * state . StateDB ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil ,  errors . New ( "not implemented, needs client/server interface split" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// GetBody retrieves a block body (transactions and uncles) from the database  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// or ODR service by hash, caching it if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetBody ( ctx  context . Context ,  hash  common . Hash )  ( * types . Body ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Short circuit if the body's already in the cache, retrieve otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  cached ,  ok  :=  self . bodyCache . Get ( hash ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										body  :=  cached . ( * types . Body ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  body ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-07 14:35:06 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									number  :=  self . hc . GetBlockNumber ( hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  number  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errors . New ( "unknown block" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									body ,  err  :=  GetBody ( ctx ,  self . odr ,  hash ,  * number ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Cache the found body for next time and return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . bodyCache . Add ( hash ,  body ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  body ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetBodyRLP retrieves a block body in RLP encoding from the database or  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ODR service by hash, caching it if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetBodyRLP ( ctx  context . Context ,  hash  common . Hash )  ( rlp . RawValue ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Short circuit if the body's already in the cache, retrieve otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  cached ,  ok  :=  self . bodyRLPCache . Get ( hash ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  cached . ( rlp . RawValue ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-07 14:35:06 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									number  :=  self . hc . GetBlockNumber ( hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  number  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errors . New ( "unknown block" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									body ,  err  :=  GetBodyRLP ( ctx ,  self . odr ,  hash ,  * number ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Cache the found body for next time and return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . bodyRLPCache . Add ( hash ,  body ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  body ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// HasBlock checks if a block is fully present in the database or not, caching  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// it if present.  
						 
					
						
							
								
									
										
										
										
											2017-09-09 18:03:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  HasBlock ( hash  common . Hash ,  number  uint64 )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blk ,  _  :=  bc . GetBlock ( NoOdr ,  hash ,  number ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  blk  !=  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetBlock retrieves a block from the database or ODR service by hash and number,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// caching it if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetBlock ( ctx  context . Context ,  hash  common . Hash ,  number  uint64 )  ( * types . Block ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Short circuit if the block's already in the cache, retrieve otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  block ,  ok  :=  self . blockCache . Get ( hash ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  block . ( * types . Block ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									block ,  err  :=  GetBlock ( ctx ,  self . odr ,  hash ,  number ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Cache the found block for next time and return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . blockCache . Add ( block . Hash ( ) ,  block ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  block ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetBlockByHash retrieves a block from the database or ODR service by hash,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// caching it if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetBlockByHash ( ctx  context . Context ,  hash  common . Hash )  ( * types . Block ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-05-07 14:35:06 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									number  :=  self . hc . GetBlockNumber ( hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  number  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errors . New ( "unknown block" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . GetBlock ( ctx ,  hash ,  * number ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetBlockByNumber retrieves a block from the database or ODR service by  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// number, caching it (associated with its hash) if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetBlockByNumber ( ctx  context . Context ,  number  uint64 )  ( * types . Block ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash ,  err  :=  GetCanonicalHash ( ctx ,  self . odr ,  number ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  hash  ==  ( common . Hash { } )  ||  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . GetBlock ( ctx ,  hash ,  number ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Stop stops the blockchain service. If any imports are currently in progress  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// it will abort them using the procInterrupt.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  Stop ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! atomic . CompareAndSwapInt32 ( & bc . running ,  0 ,  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									close ( bc . quit ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									atomic . StoreInt32 ( & bc . procInterrupt ,  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . wg . Wait ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-03 11:41:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									log . Info ( "Blockchain manager stopped" ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Rollback is designed to remove a chain of links from the database that aren't  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// certain enough to be valid.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  Rollback ( chain  [ ] common . Hash )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  len ( chain )  -  1 ;  i  >=  0 ;  i --  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash  :=  chain [ i ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  head  :=  self . hc . CurrentHeader ( ) ;  head . Hash ( )  ==  hash  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . hc . SetCurrentHeader ( self . GetHeader ( head . ParentHash ,  head . Number . Uint64 ( ) - 1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// postChainEvents iterates over the events generated by a chain insertion and  
						 
					
						
							
								
									
										
										
										
											2017-08-18 18:58:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// posts them into the event feed.  
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  postChainEvents ( events  [ ] interface { } )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  event  :=  range  events  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-18 18:58:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										switch  ev  :=  event . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  core . ChainEvent : 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 18:39:32 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  self . CurrentHeader ( ) . Hash ( )  ==  ev . Hash  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-18 18:58:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												self . chainHeadFeed . Send ( core . ChainHeadEvent { Block :  ev . Block } ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-18 18:58:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											self . chainFeed . Send ( ev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  core . ChainSideEvent : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self . chainSideFeed . Send ( ev ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// InsertHeaderChain attempts to insert the given header chain in to the local  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// chain, possibly creating a reorg. If an error is returned, it will return the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// index number of the failing header as well an error describing what went wrong.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The verify parameter can be used to fine tune whether nonce verification  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// should be done or not. The reason behind the optional check is because some  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// of the header retrieval mechanisms already need to verfy nonces, as well as  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// because nonces can be verified sparsely, not needing to check each.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// In the case of a light chain, InsertHeaderChain also creates and posts light  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// chain events when necessary.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  InsertHeaderChain ( chain  [ ] * types . Header ,  checkFreq  int )  ( int ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2017-03-22 20:44:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									start  :=  time . Now ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  i ,  err  :=  self . hc . ValidateHeaderChain ( chain ,  checkFreq ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  i ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Make sure only one thread manipulates the chain at once 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . chainmu . Lock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-22 20:44:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . chainmu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										time . Sleep ( time . Millisecond  *  10 )  // ugly hack; do not hog chain lock in case syncing is CPU-limited by validation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . wg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  self . wg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  events  [ ] interface { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									whFunc  :=  func ( header  * types . Header )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										defer  self . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status ,  err  :=  self . hc . WriteHeader ( header ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  status  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  core . CanonStatTy : 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-03 11:41:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											log . Debug ( "Inserted new header" ,  "number" ,  header . Number ,  "hash" ,  header . Hash ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											events  =  append ( events ,  core . ChainEvent { Block :  types . NewBlockWithHeader ( header ) ,  Hash :  header . Hash ( ) } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  core . SideStatTy : 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-03 11:41:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											log . Debug ( "Inserted forked header" ,  "number" ,  header . Number ,  "hash" ,  header . Hash ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											events  =  append ( events ,  core . ChainSideEvent { Block :  types . NewBlockWithHeader ( header ) } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-22 20:44:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									i ,  err  :=  self . hc . InsertHeaderChain ( chain ,  whFunc ,  start ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-23 12:10:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self . postChainEvents ( events ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  i ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// CurrentHeader retrieves the current head header of the canonical chain. The  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// header is retrieved from the HeaderChain's internal cache.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  CurrentHeader ( )  * types . Header  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . hc . CurrentHeader ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetTd retrieves a block's total difficulty in the canonical chain from the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// database by hash and number, caching it if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetTd ( hash  common . Hash ,  number  uint64 )  * big . Int  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . hc . GetTd ( hash ,  number ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetTdByHash retrieves a block's total difficulty in the canonical chain from the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// database by hash, caching it if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetTdByHash ( hash  common . Hash )  * big . Int  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . hc . GetTdByHash ( hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetHeader retrieves a block header from the database by hash and number,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// caching it if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetHeader ( hash  common . Hash ,  number  uint64 )  * types . Header  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . hc . GetHeader ( hash ,  number ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetHeaderByHash retrieves a block header from the database by hash, caching it if  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetHeaderByHash ( hash  common . Hash )  * types . Header  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . hc . GetHeaderByHash ( hash ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// HasHeader checks if a block header is present in the database or not, caching  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// it if present.  
						 
					
						
							
								
									
										
										
										
											2017-09-09 18:03:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  HasHeader ( hash  common . Hash ,  number  uint64 )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bc . hc . HasHeader ( hash ,  number ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetBlockHashesFromHash retrieves a number of block hashes starting at a given  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// hash, fetching towards the genesis block.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetBlockHashesFromHash ( hash  common . Hash ,  max  uint64 )  [ ] common . Hash  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . hc . GetBlockHashesFromHash ( hash ,  max ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-06-12 15:52:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// number of blocks to be individually checked before we reach the canonical chain.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note: ancestor == 0 returns the same block, 1 returns its parent and so on.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( bc  * LightChain )  GetAncestor ( hash  common . Hash ,  number ,  ancestor  uint64 ,  maxNonCanonical  * uint64 )  ( common . Hash ,  uint64 )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bc . chainmu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  bc . chainmu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bc . hc . GetAncestor ( hash ,  number ,  ancestor ,  maxNonCanonical ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// GetHeaderByNumber retrieves a block header from the database by number,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// caching it (associated with its hash) if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetHeaderByNumber ( number  uint64 )  * types . Header  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . hc . GetHeaderByNumber ( number ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetHeaderByNumberOdr retrieves a block header from the database or network  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// by number, caching it (associated with its hash) if found.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  GetHeaderByNumberOdr ( ctx  context . Context ,  number  uint64 )  ( * types . Header ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  header  :=  self . hc . GetHeaderByNumber ( number ) ;  header  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  header ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  GetHeaderByNumber ( ctx ,  self . odr ,  number ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-28 15:18:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Config retrieves the header chain's chain configuration.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  Config ( )  * params . ChainConfig  {  return  self . hc . Config ( )  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  SyncCht ( ctx  context . Context )  bool  {  
						 
					
						
							
								
									
										
										
										
											2018-08-21 14:39:28 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// If we don't have a CHT indexer, abort 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  self . odr . ChtIndexer ( )  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-21 14:39:28 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Ensure the remote CHT head is ahead of us 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									head  :=  self . CurrentHeader ( ) . Number . Uint64 ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sections ,  _ ,  _  :=  self . odr . ChtIndexer ( ) . Sections ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-28 15:08:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									latest  :=  sections * self . indexerConfig . ChtSize  -  1 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-21 14:39:28 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  clique  :=  self . hc . Config ( ) . Clique ;  clique  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latest  -=  latest  %  clique . Epoch  // epoch snapshot for clique 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  head  >=  latest  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Retrieve the latest useful header and update to it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  header ,  err  :=  GetHeaderByNumber ( ctx ,  self . odr ,  latest ) ;  header  !=  nil  &&  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										defer  self . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Ensure the chain didn't move past the latest block while retrieving it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  self . hc . CurrentHeader ( ) . Number . Uint64 ( )  <  header . Number . Uint64 ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-20 11:41:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											log . Info ( "Updated latest header based on CHT" ,  "number" ,  header . Number ,  "hash" ,  header . Hash ( ) ,  "age" ,  common . PrettyAge ( time . Unix ( header . Time . Int64 ( ) ,  0 ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-21 14:39:28 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											self . hc . SetCurrentHeader ( header ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-21 14:39:28 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  true 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-14 05:47:09 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2016-11-30 06:02:08 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// LockChain locks the chain mutex for reading so that multiple canonical hashes can be  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// retrieved while it is guaranteed that they belong to the same version of the chain  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  LockChain ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . chainmu . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// UnlockChain unlocks the chain mutex  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  UnlockChain ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self . chainmu . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2017-08-18 18:58:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SubscribeChainEvent registers a subscription of ChainEvent.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  SubscribeChainEvent ( ch  chan <-  core . ChainEvent )  event . Subscription  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . scope . Track ( self . chainFeed . Subscribe ( ch ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SubscribeChainHeadEvent registers a subscription of ChainHeadEvent.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  SubscribeChainHeadEvent ( ch  chan <-  core . ChainHeadEvent )  event . Subscription  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . scope . Track ( self . chainHeadFeed . Subscribe ( ch ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SubscribeChainSideEvent registers a subscription of ChainSideEvent.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  SubscribeChainSideEvent ( ch  chan <-  core . ChainSideEvent )  event . Subscription  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . scope . Track ( self . chainSideFeed . Subscribe ( ch ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SubscribeLogsEvent implements the interface of filters.Backend  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// LightChain does not send logs events, so return an empty subscription.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  SubscribeLogsEvent ( ch  chan <-  [ ] * types . Log )  event . Subscription  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . scope . Track ( new ( event . Feed ) . Subscribe ( ch ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SubscribeRemovedLogsEvent implements the interface of filters.Backend  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// LightChain does not send core.RemovedLogsEvent, so return an empty subscription.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( self  * LightChain )  SubscribeRemovedLogsEvent ( ch  chan <-  core . RemovedLogsEvent )  event . Subscription  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  self . scope . Track ( new ( event . Feed ) . Subscribe ( ch ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}