github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/les/sync.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package les
    18  
    19  import (
    20  	"context"
    21  	"time"
    22  
    23  	"github.com/ethereum/go-ethereum/core/rawdb"
    24  	"github.com/ethereum/go-ethereum/eth/downloader"
    25  	"github.com/ethereum/go-ethereum/light"
    26  	"github.com/ethereum/go-ethereum/log"
    27  )
    28  
    29  // syncer is responsible for periodically synchronising with the network, both
    30  // downloading hashes and blocks as well as handling the announcement handler.
    31  func (pm *ProtocolManager) syncer() {
    32  	// Start and ensure cleanup of sync mechanisms
    33  	//pm.fetcher.Start()
    34  	//defer pm.fetcher.Stop()
    35  	defer pm.downloader.Terminate()
    36  
    37  	// Wait for different events to fire synchronisation operations
    38  	//forceSync := time.Tick(forceSyncCycle)
    39  	for {
    40  		select {
    41  		case <-pm.newPeerCh:
    42  			/*			// Make sure we have peers to select from, then sync
    43  						if pm.peers.Len() < minDesiredPeerCount {
    44  							break
    45  						}
    46  						go pm.synchronise(pm.peers.BestPeer())
    47  			*/
    48  		/*case <-forceSync:
    49  		// Force a sync even if not enough peers are present
    50  		go pm.synchronise(pm.peers.BestPeer())
    51  		*/
    52  		case <-pm.noMorePeers:
    53  			return
    54  		}
    55  	}
    56  }
    57  
    58  func (pm *ProtocolManager) needToSync(peerHead blockInfo, mode downloader.SyncMode) bool {
    59  	head := pm.blockchain.CurrentHeader()
    60  	if !mode.SyncFullHeaderChain() {
    61  		// This is true only for the ultralight sync mode.
    62  		// In the ultralight mode used for IBFT, each block has a difficulty of 1, so, block number
    63  		// corresponds to the difficulty level.
    64  		currentHead := head.Number.Uint64()
    65  		log.Debug("needToSync", "currentHead", currentHead, "peerHead", peerHead.Number)
    66  		return peerHead.Number > currentHead
    67  	} else {
    68  		currentTd := rawdb.ReadTd(pm.chainDb, head.Hash(), head.Number.Uint64())
    69  		log.Debug("needToSync", "currentTd", currentTd, "peerHead.Td", peerHead.Td)
    70  		return currentTd != nil && peerHead.Td.Cmp(currentTd) > 0
    71  	}
    72  }
    73  
    74  // synchronise tries to sync up our local block chain with a remote peer.
    75  func (pm *ProtocolManager) synchronise(peer *peer, mode downloader.SyncMode) {
    76  	// Short circuit if no peers are available
    77  	if peer == nil {
    78  		log.Debug("Synchronise no peer available")
    79  		return
    80  	}
    81  
    82  	// Make sure the peer's TD is higher than our own.
    83  	if !pm.needToSync(peer.headBlockInfo(), mode) {
    84  		log.Debug("synchronise no need to sync")
    85  		return
    86  	}
    87  
    88  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
    89  	defer cancel()
    90  	pm.blockchain.(*light.LightChain).SyncCht(ctx)
    91  	pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), mode)
    92  }