@ -117,45 +117,45 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.
}
// addTrustedCheckpoint adds a trusted checkpoint to the blockchain
func ( self * LightChain ) addTrustedCheckpoint ( cp * params . TrustedCheckpoint ) {
if self . odr . ChtIndexer ( ) != nil {
StoreChtRoot ( self . chainDb , cp . SectionIndex , cp . SectionHead , cp . CHTRoot )
self . odr . ChtIndexer ( ) . AddCheckpoint ( cp . SectionIndex , cp . SectionHead )
func ( lc * LightChain ) addTrustedCheckpoint ( cp * params . TrustedCheckpoint ) {
if lc . odr . ChtIndexer ( ) != nil {
StoreChtRoot ( lc . chainDb , cp . SectionIndex , cp . SectionHead , cp . CHTRoot )
lc . odr . ChtIndexer ( ) . AddCheckpoint ( cp . SectionIndex , cp . SectionHead )
}
if self . odr . BloomTrieIndexer ( ) != nil {
StoreBloomTrieRoot ( self . chainDb , cp . SectionIndex , cp . SectionHead , cp . BloomRoot )
self . odr . BloomTrieIndexer ( ) . AddCheckpoint ( cp . SectionIndex , cp . SectionHead )
if lc . odr . BloomTrieIndexer ( ) != nil {
StoreBloomTrieRoot ( lc . chainDb , cp . SectionIndex , cp . SectionHead , cp . BloomRoot )
lc . odr . BloomTrieIndexer ( ) . AddCheckpoint ( cp . SectionIndex , cp . SectionHead )
}
if self . odr . BloomIndexer ( ) != nil {
self . odr . BloomIndexer ( ) . AddCheckpoint ( cp . SectionIndex , cp . SectionHead )
if lc . odr . BloomIndexer ( ) != nil {
lc . odr . BloomIndexer ( ) . AddCheckpoint ( cp . SectionIndex , cp . SectionHead )
}
log . Info ( "Added trusted checkpoint" , "chain" , cp . Name , "block" , ( cp . SectionIndex + 1 ) * self . indexerConfig . ChtSize - 1 , "hash" , cp . SectionHead )
log . Info ( "Added trusted checkpoint" , "chain" , cp . Name , "block" , ( cp . SectionIndex + 1 ) * lc . indexerConfig . ChtSize - 1 , "hash" , cp . SectionHead )
}
func ( self * LightChain ) getProcInterrupt ( ) bool {
return atomic . LoadInt32 ( & self . procInterrupt ) == 1
func ( lc * LightChain ) getProcInterrupt ( ) bool {
return atomic . LoadInt32 ( & lc . procInterrupt ) == 1
}
// Odr returns the ODR backend of the chain
func ( self * LightChain ) Odr ( ) OdrBackend {
return self . odr
func ( lc * LightChain ) Odr ( ) OdrBackend {
return lc . 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 {
if head := rawdb . ReadHeadHeaderHash ( self . chainDb ) ; head == ( common . Hash { } ) {
func ( lc * LightChain ) loadLastState ( ) error {
if head := rawdb . ReadHeadHeaderHash ( lc . chainDb ) ; head == ( common . Hash { } ) {
// Corrupt or empty database, init from scratch
self . Reset ( )
lc . Reset ( )
} else {
if header := self . GetHeaderByHash ( head ) ; header != nil {
self . hc . SetCurrentHeader ( header )
if header := lc . GetHeaderByHash ( head ) ; header != nil {
lc . hc . SetCurrentHeader ( header )
}
}
// Issue a status log and return
header := self . hc . CurrentHeader ( )
headerTd := self . GetTd ( header . Hash ( ) , header . Number . Uint64 ( ) )
header := lc . hc . CurrentHeader ( )
headerTd := lc . GetTd ( header . Hash ( ) , header . Number . Uint64 ( ) )
log . Info ( "Loaded most recent local header" , "number" , header . Number , "hash" , header . Hash ( ) , "td" , headerTd , "age" , common . PrettyAge ( time . Unix ( header . Time . Int64 ( ) , 0 ) ) )
return nil
@ -163,181 +163,181 @@ func (self *LightChain) loadLastState() error {
// SetHead rewinds the local chain to a new head. Everything above the new
// head will be deleted and the new one set.
func ( b c * LightChain ) SetHead ( head uint64 ) {
b c. chainmu . Lock ( )
defer b c. chainmu . Unlock ( )
func ( l c * LightChain ) SetHead ( head uint64 ) {
l c. chainmu . Lock ( )
defer l c. chainmu . Unlock ( )
b c. hc . SetHead ( head , nil )
b c. loadLastState ( )
l c. hc . SetHead ( head , nil )
l c. loadLastState ( )
}
// GasLimit returns the gas limit of the current HEAD block.
func ( self * LightChain ) GasLimit ( ) uint64 {
return self . hc . CurrentHeader ( ) . GasLimit
func ( lc * LightChain ) GasLimit ( ) uint64 {
return lc . hc . CurrentHeader ( ) . GasLimit
}
// Reset purges the entire blockchain, restoring it to its genesis state.
func ( b c * LightChain ) Reset ( ) {
b c. ResetWithGenesisBlock ( b c. genesisBlock )
func ( l c * LightChain ) Reset ( ) {
l c. ResetWithGenesisBlock ( l c. genesisBlock )
}
// ResetWithGenesisBlock purges the entire blockchain, restoring it to the
// specified genesis state.
func ( b c * LightChain ) ResetWithGenesisBlock ( genesis * types . Block ) {
func ( l c * LightChain ) ResetWithGenesisBlock ( genesis * types . Block ) {
// Dump the entire block chain and purge the caches
b c. SetHead ( 0 )
l c. SetHead ( 0 )
b c. chainmu . Lock ( )
defer b c. chainmu . Unlock ( )
l c. chainmu . Lock ( )
defer l c. chainmu . Unlock ( )
// Prepare the genesis block and reinitialise the chain
rawdb . WriteTd ( b c. chainDb , genesis . Hash ( ) , genesis . NumberU64 ( ) , genesis . Difficulty ( ) )
rawdb . WriteBlock ( b c. chainDb , genesis )
rawdb . WriteTd ( l c. chainDb , genesis . Hash ( ) , genesis . NumberU64 ( ) , genesis . Difficulty ( ) )
rawdb . WriteBlock ( l c. chainDb , genesis )
b c. genesisBlock = genesis
b c. hc . SetGenesis ( b c. genesisBlock . Header ( ) )
b c. hc . SetCurrentHeader ( b c. genesisBlock . Header ( ) )
l c. genesisBlock = genesis
l c. hc . SetGenesis ( l c. genesisBlock . Header ( ) )
l c. hc . SetCurrentHeader ( l c. genesisBlock . Header ( ) )
}
// Accessors
// Engine retrieves the light chain's consensus engine.
func ( b c * LightChain ) Engine ( ) consensus . Engine { return b c. engine }
func ( l c * LightChain ) Engine ( ) consensus . Engine { return l c. engine }
// Genesis returns the genesis block
func ( b c * LightChain ) Genesis ( ) * types . Block {
return b c. genesisBlock
func ( l c * LightChain ) Genesis ( ) * types . Block {
return l c. genesisBlock
}
// State returns a new mutable state based on the current HEAD block.
func ( b c * LightChain ) State ( ) ( * state . StateDB , error ) {
func ( l c * LightChain ) State ( ) ( * state . StateDB , error ) {
return nil , errors . New ( "not implemented, needs client/server interface split" )
}
// 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 ) {
func ( lc * 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 {
if cached , ok := lc . bodyCache . Get ( hash ) ; ok {
body := cached . ( * types . Body )
return body , nil
}
number := self . hc . GetBlockNumber ( hash )
number := lc . hc . GetBlockNumber ( hash )
if number == nil {
return nil , errors . New ( "unknown block" )
}
body , err := GetBody ( ctx , self . odr , hash , * number )
body , err := GetBody ( ctx , lc . odr , hash , * number )
if err != nil {
return nil , err
}
// Cache the found body for next time and return
self . bodyCache . Add ( hash , body )
lc . 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 ) {
func ( lc * 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 {
if cached , ok := lc . bodyRLPCache . Get ( hash ) ; ok {
return cached . ( rlp . RawValue ) , nil
}
number := self . hc . GetBlockNumber ( hash )
number := lc . hc . GetBlockNumber ( hash )
if number == nil {
return nil , errors . New ( "unknown block" )
}
body , err := GetBodyRLP ( ctx , self . odr , hash , * number )
body , err := GetBodyRLP ( ctx , lc . odr , hash , * number )
if err != nil {
return nil , err
}
// Cache the found body for next time and return
self . bodyRLPCache . Add ( hash , body )
lc . bodyRLPCache . Add ( hash , body )
return body , nil
}
// HasBlock checks if a block is fully present in the database or not, caching
// it if present.
func ( b c * LightChain ) HasBlock ( hash common . Hash , number uint64 ) bool {
blk , _ := b c. GetBlock ( NoOdr , hash , number )
func ( l c * LightChain ) HasBlock ( hash common . Hash , number uint64 ) bool {
blk , _ := l c. GetBlock ( NoOdr , hash , number )
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 ) {
func ( lc * 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 {
if block , ok := lc . blockCache . Get ( hash ) ; ok {
return block . ( * types . Block ) , nil
}
block , err := GetBlock ( ctx , self . odr , hash , number )
block , err := GetBlock ( ctx , lc . odr , hash , number )
if err != nil {
return nil , err
}
// Cache the found block for next time and return
self . blockCache . Add ( block . Hash ( ) , block )
lc . 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 ) {
number := self . hc . GetBlockNumber ( hash )
func ( lc * LightChain ) GetBlockByHash ( ctx context . Context , hash common . Hash ) ( * types . Block , error ) {
number := lc . hc . GetBlockNumber ( hash )
if number == nil {
return nil , errors . New ( "unknown block" )
}
return self . GetBlock ( ctx , hash , * number )
return lc . GetBlock ( ctx , hash , * number )
}
// 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 )
func ( lc * LightChain ) GetBlockByNumber ( ctx context . Context , number uint64 ) ( * types . Block , error ) {
hash , err := GetCanonicalHash ( ctx , lc . odr , number )
if hash == ( common . Hash { } ) || err != nil {
return nil , err
}
return self . GetBlock ( ctx , hash , number )
return lc . GetBlock ( ctx , hash , number )
}
// Stop stops the blockchain service. If any imports are currently in progress
// it will abort them using the procInterrupt.
func ( b c * LightChain ) Stop ( ) {
if ! atomic . CompareAndSwapInt32 ( & b c. running , 0 , 1 ) {
func ( l c * LightChain ) Stop ( ) {
if ! atomic . CompareAndSwapInt32 ( & l c. running , 0 , 1 ) {
return
}
close ( b c. quit )
atomic . StoreInt32 ( & b c. procInterrupt , 1 )
close ( l c. quit )
atomic . StoreInt32 ( & l c. procInterrupt , 1 )
b c. wg . Wait ( )
l c. wg . Wait ( )
log . Info ( "Blockchain manager stopped" )
}
// 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 . chainmu . Lock ( )
defer self . chainmu . Unlock ( )
func ( lc * LightChain ) Rollback ( chain [ ] common . Hash ) {
lc . chainmu . Lock ( )
defer lc . chainmu . 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 ) )
if head := lc . hc . CurrentHeader ( ) ; head . Hash ( ) == hash {
lc . hc . SetCurrentHeader ( lc . GetHeader ( head . ParentHash , head . Number . Uint64 ( ) - 1 ) )
}
}
}
// postChainEvents iterates over the events generated by a chain insertion and
// posts them into the event feed.
func ( self * LightChain ) postChainEvents ( events [ ] interface { } ) {
func ( lc * LightChain ) postChainEvents ( events [ ] interface { } ) {
for _ , event := range events {
switch ev := event . ( type ) {
case core . ChainEvent :
if self . CurrentHeader ( ) . Hash ( ) == ev . Hash {
self . chainHeadFeed . Send ( core . ChainHeadEvent { Block : ev . Block } )
if lc . CurrentHeader ( ) . Hash ( ) == ev . Hash {
lc . chainHeadFeed . Send ( core . ChainHeadEvent { Block : ev . Block } )
}
self . chainFeed . Send ( ev )
lc . chainFeed . Send ( ev )
case core . ChainSideEvent :
self . chainSideFeed . Send ( ev )
lc . chainSideFeed . Send ( ev )
}
}
}
@ -353,25 +353,25 @@ func (self *LightChain) postChainEvents(events []interface{}) {
//
// 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 ) {
if atomic . LoadInt32 ( & self . disableCheckFreq ) == 1 {
func ( lc * LightChain ) InsertHeaderChain ( chain [ ] * types . Header , checkFreq int ) ( int , error ) {
if atomic . LoadInt32 ( & lc . disableCheckFreq ) == 1 {
checkFreq = 0
}
start := time . Now ( )
if i , err := self . hc . ValidateHeaderChain ( chain , checkFreq ) ; err != nil {
if i , err := lc . hc . ValidateHeaderChain ( chain , checkFreq ) ; err != nil {
return i , err
}
// Make sure only one thread manipulates the chain at once
self . chainmu . Lock ( )
defer self . chainmu . Unlock ( )
lc . chainmu . Lock ( )
defer lc . chainmu . Unlock ( )
self . wg . Add ( 1 )
defer self . wg . Done ( )
lc . wg . Add ( 1 )
defer lc . wg . Done ( )
var events [ ] interface { }
whFunc := func ( header * types . Header ) error {
status , err := self . hc . WriteHeader ( header )
status , err := lc . hc . WriteHeader ( header )
switch status {
case core . CanonStatTy :
@ -384,51 +384,51 @@ func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
}
return err
}
i , err := self . hc . InsertHeaderChain ( chain , whFunc , start )
self . postChainEvents ( events )
i , err := lc . hc . InsertHeaderChain ( chain , whFunc , start )
lc . postChainEvents ( events )
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 ( )
func ( lc * LightChain ) CurrentHeader ( ) * types . Header {
return lc . 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 )
func ( lc * LightChain ) GetTd ( hash common . Hash , number uint64 ) * big . Int {
return lc . 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 )
func ( lc * LightChain ) GetTdByHash ( hash common . Hash ) * big . Int {
return lc . 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 )
func ( lc * LightChain ) GetHeader ( hash common . Hash , number uint64 ) * types . Header {
return lc . 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 )
func ( lc * LightChain ) GetHeaderByHash ( hash common . Hash ) * types . Header {
return lc . hc . GetHeaderByHash ( hash )
}
// HasHeader checks if a block header is present in the database or not, caching
// it if present.
func ( b c * LightChain ) HasHeader ( hash common . Hash , number uint64 ) bool {
return b c. hc . HasHeader ( hash , number )
func ( l c * LightChain ) HasHeader ( hash common . Hash , number uint64 ) bool {
return l c. hc . HasHeader ( hash , number )
}
// 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 )
func ( lc * LightChain ) GetBlockHashesFromHash ( hash common . Hash , max uint64 ) [ ] common . Hash {
return lc . hc . GetBlockHashesFromHash ( hash , max )
}
// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or
@ -436,56 +436,56 @@ func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []c
// 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 ( b c * LightChain ) GetAncestor ( hash common . Hash , number , ancestor uint64 , maxNonCanonical * uint64 ) ( common . Hash , uint64 ) {
b c. chainmu . RLock ( )
defer b c. chainmu . RUnlock ( )
func ( l c * LightChain ) GetAncestor ( hash common . Hash , number , ancestor uint64 , maxNonCanonical * uint64 ) ( common . Hash , uint64 ) {
l c. chainmu . RLock ( )
defer l c. chainmu . RUnlock ( )
return b c. hc . GetAncestor ( hash , number , ancestor , maxNonCanonical )
return l c. hc . GetAncestor ( hash , number , ancestor , maxNonCanonical )
}
// 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 )
func ( lc * LightChain ) GetHeaderByNumber ( number uint64 ) * types . Header {
return lc . 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 {
func ( lc * LightChain ) GetHeaderByNumberOdr ( ctx context . Context , number uint64 ) ( * types . Header , error ) {
if header := lc . hc . GetHeaderByNumber ( number ) ; header != nil {
return header , nil
}
return GetHeaderByNumber ( ctx , self . odr , number )
return GetHeaderByNumber ( ctx , lc . odr , number )
}
// Config retrieves the header chain's chain configuration.
func ( self * LightChain ) Config ( ) * params . ChainConfig { return self . hc . Config ( ) }
func ( lc * LightChain ) Config ( ) * params . ChainConfig { return lc . hc . Config ( ) }
func ( self * LightChain ) SyncCht ( ctx context . Context ) bool {
func ( lc * LightChain ) SyncCht ( ctx context . Context ) bool {
// If we don't have a CHT indexer, abort
if self . odr . ChtIndexer ( ) == nil {
if lc . odr . ChtIndexer ( ) == nil {
return false
}
// Ensure the remote CHT head is ahead of us
head := self . CurrentHeader ( ) . Number . Uint64 ( )
sections , _ , _ := self . odr . ChtIndexer ( ) . Sections ( )
head := lc . CurrentHeader ( ) . Number . Uint64 ( )
sections , _ , _ := lc . odr . ChtIndexer ( ) . Sections ( )
latest := sections * self . indexerConfig . ChtSize - 1
if clique := self . hc . Config ( ) . Clique ; clique != nil {
latest := sections * lc . indexerConfig . ChtSize - 1
if clique := lc . 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 . chainmu . Lock ( )
defer self . chainmu . Unlock ( )
if header , err := GetHeaderByNumber ( ctx , lc . odr , latest ) ; header != nil && err == nil {
lc . chainmu . Lock ( )
defer lc . chainmu . Unlock ( )
// Ensure the chain didn't move past the latest block while retrieving it
if self . hc . CurrentHeader ( ) . Number . Uint64 ( ) < header . Number . Uint64 ( ) {
if lc . hc . CurrentHeader ( ) . Number . Uint64 ( ) < header . Number . Uint64 ( ) {
log . Info ( "Updated latest header based on CHT" , "number" , header . Number , "hash" , header . Hash ( ) , "age" , common . PrettyAge ( time . Unix ( header . Time . Int64 ( ) , 0 ) ) )
self . hc . SetCurrentHeader ( header )
lc . hc . SetCurrentHeader ( header )
}
return true
}
@ -494,48 +494,48 @@ func (self *LightChain) SyncCht(ctx context.Context) bool {
// 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 ( )
func ( lc * LightChain ) LockChain ( ) {
lc . chainmu . RLock ( )
}
// UnlockChain unlocks the chain mutex
func ( self * LightChain ) UnlockChain ( ) {
self . chainmu . RUnlock ( )
func ( lc * LightChain ) UnlockChain ( ) {
lc . chainmu . RUnlock ( )
}
// SubscribeChainEvent registers a subscription of ChainEvent.
func ( self * LightChain ) SubscribeChainEvent ( ch chan <- core . ChainEvent ) event . Subscription {
return self . scope . Track ( self . chainFeed . Subscribe ( ch ) )
func ( lc * LightChain ) SubscribeChainEvent ( ch chan <- core . ChainEvent ) event . Subscription {
return lc . scope . Track ( lc . 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 ) )
func ( lc * LightChain ) SubscribeChainHeadEvent ( ch chan <- core . ChainHeadEvent ) event . Subscription {
return lc . scope . Track ( lc . 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 ) )
func ( lc * LightChain ) SubscribeChainSideEvent ( ch chan <- core . ChainSideEvent ) event . Subscription {
return lc . scope . Track ( lc . 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 ) )
func ( lc * LightChain ) SubscribeLogsEvent ( ch chan <- [ ] * types . Log ) event . Subscription {
return lc . 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 ) )
func ( lc * LightChain ) SubscribeRemovedLogsEvent ( ch chan <- core . RemovedLogsEvent ) event . Subscription {
return lc . scope . Track ( new ( event . Feed ) . Subscribe ( ch ) )
}
// DisableCheckFreq disables header validation. This is used for ultralight mode.
func ( self * LightChain ) DisableCheckFreq ( ) {
atomic . StoreInt32 ( & self . disableCheckFreq , 1 )
func ( lc * LightChain ) DisableCheckFreq ( ) {
atomic . StoreInt32 ( & lc . disableCheckFreq , 1 )
}
// EnableCheckFreq enables header validation.
func ( self * LightChain ) EnableCheckFreq ( ) {
atomic . StoreInt32 ( & self . disableCheckFreq , 0 )
func ( lc * LightChain ) EnableCheckFreq ( ) {
atomic . StoreInt32 ( & lc . disableCheckFreq , 0 )
}