github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/neatptc/downloader/downloader.go (about)

     1  package downloader
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/big"
     7  	"sync"
     8  	"sync/atomic"
     9  	"time"
    10  
    11  	"github.com/neatio-net/neatio"
    12  	"github.com/neatio-net/neatio/chain/core/rawdb"
    13  	"github.com/neatio-net/neatio/chain/core/types"
    14  	"github.com/neatio-net/neatio/chain/log"
    15  	"github.com/neatio-net/neatio/neatdb"
    16  	"github.com/neatio-net/neatio/params"
    17  	"github.com/neatio-net/neatio/utilities/common"
    18  	"github.com/neatio-net/neatio/utilities/event"
    19  	"github.com/neatio-net/neatio/utilities/metrics"
    20  )
    21  
    22  var (
    23  	MaxHashFetch    = 512
    24  	MaxBlockFetch   = 128
    25  	MaxHeaderFetch  = 192
    26  	MaxSkeletonSize = 128
    27  	MaxBodyFetch    = 128
    28  	MaxReceiptFetch = 256
    29  	MaxStateFetch   = 384
    30  
    31  	MaxForkAncestry  = 3 * params.EpochDuration
    32  	rttMinEstimate   = 2 * time.Second
    33  	rttMaxEstimate   = 20 * time.Second
    34  	rttMinConfidence = 0.1
    35  	ttlScaling       = 3
    36  	ttlLimit         = time.Minute
    37  
    38  	qosTuningPeers   = 5
    39  	qosConfidenceCap = 10
    40  	qosTuningImpact  = 0.25
    41  
    42  	maxQueuedHeaders  = 32 * 1024
    43  	maxHeadersProcess = 2048
    44  	maxResultsProcess = 2048
    45  
    46  	fsHeaderCheckFrequency = 100
    47  	fsHeaderSafetyNet      = 2048
    48  	fsHeaderForceVerify    = 24
    49  	fsHeaderContCheck      = 3 * time.Second
    50  	fsMinFullBlocks        = 64
    51  )
    52  
    53  var (
    54  	errBusy                    = errors.New("busy")
    55  	errUnknownPeer             = errors.New("peer is unknown or unhealthy")
    56  	errBadPeer                 = errors.New("action from bad peer ignored")
    57  	errStallingPeer            = errors.New("peer is stalling")
    58  	errNoPeers                 = errors.New("no peers to keep download active")
    59  	errTimeout                 = errors.New("timeout")
    60  	errEmptyHeaderSet          = errors.New("empty header set by peer")
    61  	errPeersUnavailable        = errors.New("no peers available or all tried for download")
    62  	errInvalidAncestor         = errors.New("retrieved ancestor is invalid")
    63  	errInvalidChain            = errors.New("retrieved hash chain is invalid")
    64  	errInvalidBlock            = errors.New("retrieved block is invalid")
    65  	errInvalidBody             = errors.New("retrieved block body is invalid")
    66  	errInvalidReceipt          = errors.New("retrieved receipt is invalid")
    67  	errCancelBlockFetch        = errors.New("block download canceled (requested)")
    68  	errCancelHeaderFetch       = errors.New("block header download canceled (requested)")
    69  	errCancelBodyFetch         = errors.New("block body download canceled (requested)")
    70  	errCancelReceiptFetch      = errors.New("receipt download canceled (requested)")
    71  	errCancelStateFetch        = errors.New("state data download canceled (requested)")
    72  	errCancelHeaderProcessing  = errors.New("header processing canceled (requested)")
    73  	errCancelContentProcessing = errors.New("content processing canceled (requested)")
    74  	errNoSyncActive            = errors.New("no sync active")
    75  	errTooOld                  = errors.New("peer doesn't speak recent enough protocol version (need version >= 62)")
    76  )
    77  
    78  type Downloader struct {
    79  	mode SyncMode
    80  	mux  *event.TypeMux
    81  
    82  	queue   *queue
    83  	peers   *peerSet
    84  	stateDB neatdb.Database
    85  
    86  	rttEstimate   uint64
    87  	rttConfidence uint64
    88  
    89  	syncStatsChainOrigin uint64
    90  	syncStatsChainHeight uint64
    91  	syncStatsState       stateSyncStats
    92  	syncStatsLock        sync.RWMutex
    93  
    94  	lightchain LightChain
    95  	blockchain BlockChain
    96  
    97  	dropPeer peerDropFn
    98  
    99  	synchroniseMock func(id string, hash common.Hash) error
   100  	synchronising   int32
   101  	notified        int32
   102  	committed       int32
   103  
   104  	headerCh      chan dataPack
   105  	bodyCh        chan dataPack
   106  	receiptCh     chan dataPack
   107  	bodyWakeCh    chan bool
   108  	receiptWakeCh chan bool
   109  	headerProcCh  chan []*types.Header
   110  
   111  	stateSyncStart chan *stateSync
   112  	trackStateReq  chan *stateReq
   113  	stateCh        chan dataPack
   114  
   115  	cancelPeer string
   116  	cancelCh   chan struct{}
   117  	cancelLock sync.RWMutex
   118  
   119  	quitCh   chan struct{}
   120  	quitLock sync.RWMutex
   121  
   122  	syncInitHook     func(uint64, uint64)
   123  	bodyFetchHook    func([]*types.Header)
   124  	receiptFetchHook func([]*types.Header)
   125  	chainInsertHook  func([]*fetchResult)
   126  
   127  	logger log.Logger
   128  }
   129  
   130  type LightChain interface {
   131  	HasHeader(common.Hash, uint64) bool
   132  
   133  	GetHeaderByHash(common.Hash) *types.Header
   134  
   135  	CurrentHeader() *types.Header
   136  
   137  	GetTd(common.Hash, uint64) *big.Int
   138  
   139  	InsertHeaderChain([]*types.Header, int) (int, error)
   140  
   141  	Rollback([]common.Hash)
   142  }
   143  
   144  type BlockChain interface {
   145  	LightChain
   146  
   147  	HasBlock(common.Hash, uint64) bool
   148  
   149  	GetBlockByHash(common.Hash) *types.Block
   150  
   151  	CurrentBlock() *types.Block
   152  
   153  	CurrentFastBlock() *types.Block
   154  
   155  	FastSyncCommitHead(common.Hash) error
   156  
   157  	InsertChain(types.Blocks) (int, error)
   158  
   159  	InsertReceiptChain(types.Blocks, []types.Receipts) (int, error)
   160  }
   161  
   162  func New(mode SyncMode, stateDb neatdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, logger log.Logger) *Downloader {
   163  	if lightchain == nil {
   164  		lightchain = chain
   165  	}
   166  
   167  	dl := &Downloader{
   168  		mode:           mode,
   169  		stateDB:        stateDb,
   170  		mux:            mux,
   171  		queue:          newQueue(),
   172  		peers:          newPeerSet(),
   173  		rttEstimate:    uint64(rttMaxEstimate),
   174  		rttConfidence:  uint64(1000000),
   175  		blockchain:     chain,
   176  		lightchain:     lightchain,
   177  		dropPeer:       dropPeer,
   178  		headerCh:       make(chan dataPack, 1),
   179  		bodyCh:         make(chan dataPack, 1),
   180  		receiptCh:      make(chan dataPack, 1),
   181  		bodyWakeCh:     make(chan bool, 1),
   182  		receiptWakeCh:  make(chan bool, 1),
   183  		headerProcCh:   make(chan []*types.Header, 1),
   184  		quitCh:         make(chan struct{}),
   185  		stateCh:        make(chan dataPack),
   186  		stateSyncStart: make(chan *stateSync),
   187  		syncStatsState: stateSyncStats{
   188  			processed: rawdb.ReadFastTrieProgress(stateDb),
   189  		},
   190  		trackStateReq: make(chan *stateReq),
   191  
   192  		logger: logger,
   193  	}
   194  	go dl.qosTuner()
   195  	go dl.stateFetcher()
   196  	return dl
   197  }
   198  
   199  func (d *Downloader) Progress() neatio.SyncProgress {
   200  
   201  	d.syncStatsLock.RLock()
   202  	defer d.syncStatsLock.RUnlock()
   203  
   204  	current := uint64(0)
   205  	switch d.mode {
   206  	case FullSync:
   207  		current = d.blockchain.CurrentBlock().NumberU64()
   208  	case FastSync:
   209  		current = d.blockchain.CurrentFastBlock().NumberU64()
   210  	}
   211  	return neatio.SyncProgress{
   212  		StartingBlock: d.syncStatsChainOrigin,
   213  		CurrentBlock:  current,
   214  		HighestBlock:  d.syncStatsChainHeight,
   215  		PulledStates:  d.syncStatsState.processed,
   216  		KnownStates:   d.syncStatsState.processed + d.syncStatsState.pending,
   217  	}
   218  }
   219  
   220  func (d *Downloader) Synchronising() bool {
   221  	return atomic.LoadInt32(&d.synchronising) > 0
   222  }
   223  
   224  func (d *Downloader) RegisterPeer(id string, version int, peer Peer) error {
   225  	logger := d.logger.New("peer", id)
   226  	logger.Trace("Registering sync peer")
   227  	if err := d.peers.Register(newPeerConnection(id, version, peer, logger)); err != nil {
   228  		logger.Error("Failed to register sync peer", "err", err)
   229  		return err
   230  	}
   231  	d.qosReduceConfidence()
   232  
   233  	return nil
   234  }
   235  
   236  func (d *Downloader) RegisterLightPeer(id string, version int, peer LightPeer) error {
   237  	return d.RegisterPeer(id, version, &lightPeerWrapper{peer})
   238  }
   239  
   240  func (d *Downloader) UnregisterPeer(id string) error {
   241  
   242  	logger := d.logger.New("peer", id)
   243  	logger.Trace("Unregistering sync peer")
   244  	if err := d.peers.Unregister(id); err != nil {
   245  		logger.Error("Failed to unregister sync peer", "err", err)
   246  		return err
   247  	}
   248  	d.queue.Revoke(id)
   249  
   250  	d.cancelLock.RLock()
   251  	master := id == d.cancelPeer
   252  	d.cancelLock.RUnlock()
   253  
   254  	if master {
   255  		d.Cancel()
   256  	}
   257  	return nil
   258  }
   259  
   260  func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) error {
   261  	err := d.synchronise(id, head, td, mode)
   262  	switch err {
   263  	case nil:
   264  	case errBusy:
   265  
   266  	case errTimeout, errBadPeer, errStallingPeer,
   267  		errEmptyHeaderSet, errPeersUnavailable, errTooOld,
   268  		errInvalidAncestor, errInvalidChain:
   269  		d.logger.Warn("Synchronisation failed, dropping peer", "peer", id, "err", err)
   270  		if d.dropPeer == nil {
   271  
   272  			d.logger.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", id)
   273  		} else {
   274  			d.dropPeer(id)
   275  		}
   276  	default:
   277  		d.logger.Warn("Synchronisation failed, retrying", "err", err)
   278  	}
   279  	return err
   280  }
   281  
   282  func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode SyncMode) error {
   283  
   284  	if d.synchroniseMock != nil {
   285  		return d.synchroniseMock(id, hash)
   286  	}
   287  
   288  	if !atomic.CompareAndSwapInt32(&d.synchronising, 0, 1) {
   289  		return errBusy
   290  	}
   291  	defer atomic.StoreInt32(&d.synchronising, 0)
   292  
   293  	if atomic.CompareAndSwapInt32(&d.notified, 0, 1) {
   294  		d.logger.Info("Block synchronisation started")
   295  	}
   296  
   297  	d.queue.Reset()
   298  	d.peers.Reset()
   299  
   300  	for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} {
   301  		select {
   302  		case <-ch:
   303  		default:
   304  		}
   305  	}
   306  	for _, ch := range []chan dataPack{d.headerCh, d.bodyCh, d.receiptCh} {
   307  		for empty := false; !empty; {
   308  			select {
   309  			case <-ch:
   310  			default:
   311  				empty = true
   312  			}
   313  		}
   314  	}
   315  	for empty := false; !empty; {
   316  		select {
   317  		case <-d.headerProcCh:
   318  		default:
   319  			empty = true
   320  		}
   321  	}
   322  
   323  	d.cancelLock.Lock()
   324  	d.cancelCh = make(chan struct{})
   325  	d.cancelPeer = id
   326  	d.cancelLock.Unlock()
   327  
   328  	defer d.Cancel()
   329  
   330  	d.mode = mode
   331  
   332  	p := d.peers.Peer(id)
   333  	if p == nil {
   334  		return errUnknownPeer
   335  	}
   336  	return d.syncWithPeer(p, hash, td)
   337  }
   338  
   339  func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.Int) (err error) {
   340  	d.mux.Post(StartEvent{})
   341  	defer func() {
   342  
   343  		if err != nil {
   344  			d.mux.Post(FailedEvent{err})
   345  		} else {
   346  			d.mux.Post(DoneEvent{})
   347  		}
   348  	}()
   349  	if p.version < 62 {
   350  		return errTooOld
   351  	}
   352  
   353  	d.logger.Debug("Synchronising with the network", "peer", p.id, "eth", p.version, "head", hash, "td", td, "mode", d.mode)
   354  	defer func(start time.Time) {
   355  		d.logger.Debug("Synchronisation terminated", "elapsed", time.Since(start))
   356  	}(time.Now())
   357  
   358  	latest, err := d.fetchHeight(p)
   359  	if err != nil {
   360  		return err
   361  	}
   362  	height := latest.Number.Uint64()
   363  
   364  	origin, err := d.findAncestor(p, height)
   365  	if err != nil {
   366  		return err
   367  	}
   368  	d.syncStatsLock.Lock()
   369  	if d.syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin {
   370  		d.syncStatsChainOrigin = origin
   371  	}
   372  	d.syncStatsChainHeight = height
   373  	d.syncStatsLock.Unlock()
   374  
   375  	pivot := uint64(0)
   376  	if d.mode == FastSync {
   377  		if height <= uint64(fsMinFullBlocks) {
   378  			origin = 0
   379  		} else {
   380  			pivot = height - uint64(fsMinFullBlocks)
   381  			if pivot <= origin {
   382  				origin = pivot - 1
   383  			}
   384  		}
   385  	}
   386  	d.committed = 1
   387  	if d.mode == FastSync && pivot != 0 {
   388  		d.committed = 0
   389  	}
   390  
   391  	d.queue.Prepare(origin+1, d.mode)
   392  	if d.syncInitHook != nil {
   393  		d.syncInitHook(origin, height)
   394  	}
   395  
   396  	fetchers := []func() error{
   397  		func() error { return d.fetchHeaders(p, origin+1, pivot) },
   398  		func() error { return d.fetchBodies(origin + 1) },
   399  		func() error { return d.fetchReceipts(origin + 1) },
   400  		func() error { return d.processHeaders(origin+1, pivot, td) },
   401  	}
   402  	if d.mode == FastSync {
   403  		fetchers = append(fetchers, func() error { return d.processFastSyncContent(latest) })
   404  	} else if d.mode == FullSync {
   405  		fetchers = append(fetchers, d.processFullSyncContent)
   406  	}
   407  	return d.spawnSync(fetchers)
   408  }
   409  
   410  func (d *Downloader) spawnSync(fetchers []func() error) error {
   411  	var wg sync.WaitGroup
   412  	errc := make(chan error, len(fetchers))
   413  	wg.Add(len(fetchers))
   414  	for _, fn := range fetchers {
   415  		fn := fn
   416  		go func() { defer wg.Done(); errc <- fn() }()
   417  	}
   418  
   419  	var err error
   420  	for i := 0; i < len(fetchers); i++ {
   421  		if i == len(fetchers)-1 {
   422  
   423  			d.queue.Close()
   424  		}
   425  		if err = <-errc; err != nil {
   426  			break
   427  		}
   428  	}
   429  	d.queue.Close()
   430  	d.Cancel()
   431  	wg.Wait()
   432  	return err
   433  }
   434  
   435  func (d *Downloader) Cancel() {
   436  
   437  	d.cancelLock.Lock()
   438  	if d.cancelCh != nil {
   439  		select {
   440  		case <-d.cancelCh:
   441  
   442  		default:
   443  			close(d.cancelCh)
   444  		}
   445  	}
   446  	d.cancelLock.Unlock()
   447  }
   448  
   449  func (d *Downloader) Terminate() {
   450  
   451  	d.quitLock.Lock()
   452  	select {
   453  	case <-d.quitCh:
   454  	default:
   455  		close(d.quitCh)
   456  	}
   457  	d.quitLock.Unlock()
   458  
   459  	d.Cancel()
   460  }
   461  
   462  func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) {
   463  	p.log.Debug("Retrieving remote chain height")
   464  
   465  	head, _ := p.peer.Head()
   466  	go p.peer.RequestHeadersByHash(head, 1, 0, false)
   467  
   468  	ttl := d.requestTTL()
   469  	timeout := time.After(ttl)
   470  	for {
   471  		select {
   472  		case <-d.cancelCh:
   473  			return nil, errCancelBlockFetch
   474  
   475  		case packet := <-d.headerCh:
   476  
   477  			if packet.PeerId() != p.id {
   478  				d.logger.Debug("Received headers from incorrect peer", "peer", packet.PeerId())
   479  				break
   480  			}
   481  
   482  			headers := packet.(*headerPack).headers
   483  			if len(headers) != 1 {
   484  				p.log.Debug("Multiple headers for single request", "headers", len(headers))
   485  				return nil, errBadPeer
   486  			}
   487  			head := headers[0]
   488  			p.log.Debug("Remote head header identified", "number", head.Number, "hash", head.Hash())
   489  			return head, nil
   490  
   491  		case <-timeout:
   492  			p.log.Debug("Waiting for head header timed out", "elapsed", ttl)
   493  			return nil, errTimeout
   494  
   495  		case <-d.bodyCh:
   496  		case <-d.receiptCh:
   497  
   498  		}
   499  	}
   500  }
   501  
   502  func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, error) {
   503  
   504  	floor, ceil := int64(-1), d.lightchain.CurrentHeader().Number.Uint64()
   505  
   506  	if d.mode == FullSync {
   507  		ceil = d.blockchain.CurrentBlock().NumberU64()
   508  	} else if d.mode == FastSync {
   509  		ceil = d.blockchain.CurrentFastBlock().NumberU64()
   510  	}
   511  	if ceil >= MaxForkAncestry {
   512  		floor = int64(ceil - MaxForkAncestry)
   513  	}
   514  	p.log.Debug("Looking for common ancestor", "local", ceil, "remote", height)
   515  
   516  	head := ceil
   517  	if head > height {
   518  		head = height
   519  	}
   520  	from := int64(head) - int64(MaxHeaderFetch)
   521  	if from < 0 {
   522  		from = 0
   523  	}
   524  
   525  	limit := 2 * MaxHeaderFetch / 16
   526  	count := 1 + int((int64(ceil)-from)/16)
   527  	if count > limit {
   528  		count = limit
   529  	}
   530  	go p.peer.RequestHeadersByNumber(uint64(from), count, 15, false)
   531  
   532  	number, hash := uint64(0), common.Hash{}
   533  
   534  	ttl := d.requestTTL()
   535  	timeout := time.After(ttl)
   536  
   537  	for finished := false; !finished; {
   538  		select {
   539  		case <-d.cancelCh:
   540  			return 0, errCancelHeaderFetch
   541  
   542  		case packet := <-d.headerCh:
   543  
   544  			if packet.PeerId() != p.id {
   545  				d.logger.Debug("Received headers from incorrect peer", "peer", packet.PeerId())
   546  				break
   547  			}
   548  
   549  			headers := packet.(*headerPack).headers
   550  			if len(headers) == 0 {
   551  				p.log.Warn("Empty head header set")
   552  				return 0, errEmptyHeaderSet
   553  			}
   554  
   555  			for i := 0; i < len(headers); i++ {
   556  				if number := headers[i].Number.Int64(); number != from+int64(i)*16 {
   557  					p.log.Warn("Head headers broke chain ordering", "index", i, "requested", from+int64(i)*16, "received", number)
   558  					return 0, errInvalidChain
   559  				}
   560  			}
   561  
   562  			finished = true
   563  			for i := len(headers) - 1; i >= 0; i-- {
   564  
   565  				if headers[i].Number.Int64() < from || headers[i].Number.Uint64() > ceil {
   566  					continue
   567  				}
   568  
   569  				if (d.mode == FullSync && d.blockchain.HasBlock(headers[i].Hash(), headers[i].Number.Uint64())) || (d.mode != FullSync && d.lightchain.HasHeader(headers[i].Hash(), headers[i].Number.Uint64())) {
   570  					number, hash = headers[i].Number.Uint64(), headers[i].Hash()
   571  
   572  					if number > height && i == limit-1 {
   573  						p.log.Warn("Lied about chain head", "reported", height, "found", number)
   574  						return 0, errStallingPeer
   575  					}
   576  					break
   577  				}
   578  			}
   579  
   580  		case <-timeout:
   581  			p.log.Debug("Waiting for head header timed out", "elapsed", ttl)
   582  			return 0, errTimeout
   583  
   584  		case <-d.bodyCh:
   585  		case <-d.receiptCh:
   586  
   587  		}
   588  	}
   589  
   590  	if !common.EmptyHash(hash) {
   591  		if int64(number) <= floor {
   592  			p.log.Warn("Ancestor below allowance", "number", number, "hash", hash, "allowance", floor)
   593  			return 0, errInvalidAncestor
   594  		}
   595  		p.log.Debug("Found common ancestor", "number", number, "hash", hash)
   596  		return number, nil
   597  	}
   598  
   599  	start, end := uint64(0), head
   600  	if floor > 0 {
   601  		start = uint64(floor)
   602  	}
   603  	for start+1 < end {
   604  
   605  		check := (start + end) / 2
   606  
   607  		ttl := d.requestTTL()
   608  		timeout := time.After(ttl)
   609  
   610  		go p.peer.RequestHeadersByNumber(check, 1, 0, false)
   611  
   612  		for arrived := false; !arrived; {
   613  			select {
   614  			case <-d.cancelCh:
   615  				return 0, errCancelHeaderFetch
   616  
   617  			case packer := <-d.headerCh:
   618  
   619  				if packer.PeerId() != p.id {
   620  					d.logger.Debug("Received headers from incorrect peer", "peer", packer.PeerId())
   621  					break
   622  				}
   623  
   624  				headers := packer.(*headerPack).headers
   625  				if len(headers) != 1 {
   626  					p.log.Debug("Multiple headers for single request", "headers", len(headers))
   627  					return 0, errBadPeer
   628  				}
   629  				arrived = true
   630  
   631  				if (d.mode == FullSync && !d.blockchain.HasBlock(headers[0].Hash(), headers[0].Number.Uint64())) || (d.mode != FullSync && !d.lightchain.HasHeader(headers[0].Hash(), headers[0].Number.Uint64())) {
   632  					end = check
   633  					break
   634  				}
   635  				header := d.lightchain.GetHeaderByHash(headers[0].Hash())
   636  				if header.Number.Uint64() != check {
   637  					p.log.Debug("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check)
   638  					return 0, errBadPeer
   639  				}
   640  				start = check
   641  
   642  			case <-timeout:
   643  				p.log.Debug("Waiting for search header timed out", "elapsed", ttl)
   644  				return 0, errTimeout
   645  
   646  			case <-d.bodyCh:
   647  			case <-d.receiptCh:
   648  
   649  			}
   650  		}
   651  	}
   652  
   653  	if int64(start) <= floor {
   654  		p.log.Warn("Ancestor below allowance", "number", start, "hash", hash, "allowance", floor)
   655  		return 0, errInvalidAncestor
   656  	}
   657  	p.log.Debug("Found common ancestor", "number", start, "hash", hash)
   658  	return start, nil
   659  }
   660  
   661  func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) error {
   662  	p.log.Debug("Directing header downloads", "origin", from)
   663  	defer p.log.Debug("Header download terminated")
   664  
   665  	skeleton := true
   666  	request := time.Now()
   667  	timeout := time.NewTimer(0)
   668  	<-timeout.C
   669  	defer timeout.Stop()
   670  
   671  	var ttl time.Duration
   672  	getHeaders := func(from uint64) {
   673  		request = time.Now()
   674  
   675  		ttl = d.requestTTL()
   676  		timeout.Reset(ttl)
   677  
   678  		if skeleton {
   679  			p.log.Trace("Fetching skeleton headers", "count", MaxHeaderFetch, "from", from)
   680  			go p.peer.RequestHeadersByNumber(from+uint64(MaxHeaderFetch)-1, MaxSkeletonSize, MaxHeaderFetch-1, false)
   681  		} else {
   682  			p.log.Trace("Fetching full headers", "count", MaxHeaderFetch, "from", from)
   683  			go p.peer.RequestHeadersByNumber(from, MaxHeaderFetch, 0, false)
   684  		}
   685  	}
   686  
   687  	getHeaders(from)
   688  
   689  	for {
   690  		select {
   691  		case <-d.cancelCh:
   692  			return errCancelHeaderFetch
   693  
   694  		case packet := <-d.headerCh:
   695  
   696  			if packet.PeerId() != p.id {
   697  				d.logger.Debug("Received skeleton from incorrect peer", "peer", packet.PeerId())
   698  				break
   699  			}
   700  			headerReqTimer.UpdateSince(request)
   701  			timeout.Stop()
   702  
   703  			if packet.Items() == 0 && skeleton {
   704  				skeleton = false
   705  				getHeaders(from)
   706  				continue
   707  			}
   708  
   709  			if packet.Items() == 0 {
   710  
   711  				if atomic.LoadInt32(&d.committed) == 0 && pivot <= from {
   712  					p.log.Debug("No headers, waiting for pivot commit")
   713  					select {
   714  					case <-time.After(fsHeaderContCheck):
   715  						getHeaders(from)
   716  						continue
   717  					case <-d.cancelCh:
   718  						return errCancelHeaderFetch
   719  					}
   720  				}
   721  
   722  				p.log.Debug("No more headers available")
   723  				select {
   724  				case d.headerProcCh <- nil:
   725  					return nil
   726  				case <-d.cancelCh:
   727  					return errCancelHeaderFetch
   728  				}
   729  			}
   730  			headers := packet.(*headerPack).headers
   731  
   732  			if skeleton {
   733  				filled, proced, err := d.fillHeaderSkeleton(from, headers)
   734  				if err != nil {
   735  					p.log.Debug("Skeleton chain invalid", "err", err)
   736  					return errInvalidChain
   737  				}
   738  				headers = filled[proced:]
   739  				from += uint64(proced)
   740  			}
   741  
   742  			if len(headers) > 0 {
   743  				p.log.Trace("Scheduling new headers", "count", len(headers), "from", from)
   744  				select {
   745  				case d.headerProcCh <- headers:
   746  				case <-d.cancelCh:
   747  					return errCancelHeaderFetch
   748  				}
   749  				from += uint64(len(headers))
   750  			}
   751  			getHeaders(from)
   752  
   753  		case <-timeout.C:
   754  			if d.dropPeer == nil {
   755  
   756  				p.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", p.id)
   757  				break
   758  			}
   759  
   760  			p.log.Debug("Header request timed out", "elapsed", ttl)
   761  			headerTimeoutMeter.Mark(1)
   762  			d.dropPeer(p.id)
   763  
   764  			for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} {
   765  				select {
   766  				case ch <- false:
   767  				case <-d.cancelCh:
   768  				}
   769  			}
   770  			select {
   771  			case d.headerProcCh <- nil:
   772  			case <-d.cancelCh:
   773  			}
   774  			return errBadPeer
   775  		}
   776  	}
   777  }
   778  
   779  func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) ([]*types.Header, int, error) {
   780  	d.logger.Debug("Filling up skeleton", "from", from)
   781  	d.queue.ScheduleSkeleton(from, skeleton)
   782  
   783  	var (
   784  		deliver = func(packet dataPack) (int, error) {
   785  			pack := packet.(*headerPack)
   786  			return d.queue.DeliverHeaders(pack.peerId, pack.headers, d.headerProcCh)
   787  		}
   788  		expire   = func() map[string]int { return d.queue.ExpireHeaders(d.requestTTL()) }
   789  		throttle = func() bool { return false }
   790  		reserve  = func(p *peerConnection, count int) (*fetchRequest, bool, error) {
   791  			return d.queue.ReserveHeaders(p, count), false, nil
   792  		}
   793  		fetch    = func(p *peerConnection, req *fetchRequest) error { return p.FetchHeaders(req.From, MaxHeaderFetch) }
   794  		capacity = func(p *peerConnection) int { return p.HeaderCapacity(d.requestRTT()) }
   795  		setIdle  = func(p *peerConnection, accepted int) { p.SetHeadersIdle(accepted) }
   796  	)
   797  	err := d.fetchParts(errCancelHeaderFetch, d.headerCh, deliver, d.queue.headerContCh, expire,
   798  		d.queue.PendingHeaders, d.queue.InFlightHeaders, throttle, reserve,
   799  		nil, fetch, d.queue.CancelHeaders, capacity, d.peers.HeaderIdlePeers, setIdle, "headers")
   800  
   801  	d.logger.Debug("Skeleton fill terminated", "err", err)
   802  
   803  	filled, proced := d.queue.RetrieveHeaders()
   804  	return filled, proced, err
   805  }
   806  
   807  func (d *Downloader) fetchBodies(from uint64) error {
   808  	d.logger.Debug("Downloading block bodies", "origin", from)
   809  
   810  	var (
   811  		deliver = func(packet dataPack) (int, error) {
   812  			pack := packet.(*bodyPack)
   813  			return d.queue.DeliverBodies(pack.peerId, pack.transactions, pack.uncles)
   814  		}
   815  		expire   = func() map[string]int { return d.queue.ExpireBodies(d.requestTTL()) }
   816  		fetch    = func(p *peerConnection, req *fetchRequest) error { return p.FetchBodies(req) }
   817  		capacity = func(p *peerConnection) int { return p.BlockCapacity(d.requestRTT()) }
   818  		setIdle  = func(p *peerConnection, accepted int) { p.SetBodiesIdle(accepted) }
   819  	)
   820  	err := d.fetchParts(errCancelBodyFetch, d.bodyCh, deliver, d.bodyWakeCh, expire,
   821  		d.queue.PendingBlocks, d.queue.InFlightBlocks, d.queue.ShouldThrottleBlocks, d.queue.ReserveBodies,
   822  		d.bodyFetchHook, fetch, d.queue.CancelBodies, capacity, d.peers.BodyIdlePeers, setIdle, "bodies")
   823  
   824  	d.logger.Debug("Block body download terminated", "err", err)
   825  	return err
   826  }
   827  
   828  func (d *Downloader) fetchReceipts(from uint64) error {
   829  	d.logger.Debug("Downloading transaction receipts", "origin", from)
   830  
   831  	var (
   832  		deliver = func(packet dataPack) (int, error) {
   833  			pack := packet.(*receiptPack)
   834  			return d.queue.DeliverReceipts(pack.peerId, pack.receipts)
   835  		}
   836  		expire   = func() map[string]int { return d.queue.ExpireReceipts(d.requestTTL()) }
   837  		fetch    = func(p *peerConnection, req *fetchRequest) error { return p.FetchReceipts(req) }
   838  		capacity = func(p *peerConnection) int { return p.ReceiptCapacity(d.requestRTT()) }
   839  		setIdle  = func(p *peerConnection, accepted int) { p.SetReceiptsIdle(accepted) }
   840  	)
   841  	err := d.fetchParts(errCancelReceiptFetch, d.receiptCh, deliver, d.receiptWakeCh, expire,
   842  		d.queue.PendingReceipts, d.queue.InFlightReceipts, d.queue.ShouldThrottleReceipts, d.queue.ReserveReceipts,
   843  		d.receiptFetchHook, fetch, d.queue.CancelReceipts, capacity, d.peers.ReceiptIdlePeers, setIdle, "receipts")
   844  
   845  	d.logger.Debug("Transaction receipt download terminated", "err", err)
   846  	return err
   847  }
   848  
   849  func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliver func(dataPack) (int, error), wakeCh chan bool,
   850  	expire func() map[string]int, pending func() int, inFlight func() bool, throttle func() bool, reserve func(*peerConnection, int) (*fetchRequest, bool, error),
   851  	fetchHook func([]*types.Header), fetch func(*peerConnection, *fetchRequest) error, cancel func(*fetchRequest), capacity func(*peerConnection) int,
   852  	idle func() ([]*peerConnection, int), setIdle func(*peerConnection, int), kind string) error {
   853  
   854  	ticker := time.NewTicker(100 * time.Millisecond)
   855  	defer ticker.Stop()
   856  
   857  	update := make(chan struct{}, 1)
   858  
   859  	finished := false
   860  	for {
   861  		select {
   862  		case <-d.cancelCh:
   863  			return errCancel
   864  
   865  		case packet := <-deliveryCh:
   866  
   867  			if peer := d.peers.Peer(packet.PeerId()); peer != nil {
   868  
   869  				accepted, err := deliver(packet)
   870  				if err == errInvalidChain {
   871  					return err
   872  				}
   873  
   874  				if err != errStaleDelivery {
   875  					setIdle(peer, accepted)
   876  				}
   877  
   878  				switch {
   879  				case err == nil && packet.Items() == 0:
   880  					peer.log.Trace("Requested data not delivered", "type", kind)
   881  				case err == nil:
   882  					peer.log.Trace("Delivered new batch of data", "type", kind, "count", packet.Stats())
   883  				default:
   884  					peer.log.Trace("Failed to deliver retrieved data", "type", kind, "err", err)
   885  				}
   886  			}
   887  
   888  			select {
   889  			case update <- struct{}{}:
   890  			default:
   891  			}
   892  
   893  		case cont := <-wakeCh:
   894  
   895  			if !cont {
   896  				finished = true
   897  			}
   898  
   899  			select {
   900  			case update <- struct{}{}:
   901  			default:
   902  			}
   903  
   904  		case <-ticker.C:
   905  
   906  			select {
   907  			case update <- struct{}{}:
   908  			default:
   909  			}
   910  
   911  		case <-update:
   912  
   913  			if d.peers.Len() == 0 {
   914  				return errNoPeers
   915  			}
   916  
   917  			for pid, fails := range expire() {
   918  				if peer := d.peers.Peer(pid); peer != nil {
   919  
   920  					if fails > 2 {
   921  						peer.log.Trace("Data delivery timed out", "type", kind)
   922  						setIdle(peer, 0)
   923  					} else {
   924  						peer.log.Debug("Stalling delivery, dropping", "type", kind)
   925  						if d.dropPeer == nil {
   926  
   927  							peer.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", pid)
   928  						} else {
   929  							d.dropPeer(pid)
   930  						}
   931  					}
   932  				}
   933  			}
   934  
   935  			if pending() == 0 {
   936  				if !inFlight() && finished {
   937  					d.logger.Debug("Data fetching completed", "type", kind)
   938  					return nil
   939  				}
   940  				break
   941  			}
   942  
   943  			progressed, throttled, running := false, false, inFlight()
   944  			idles, total := idle()
   945  
   946  			for _, peer := range idles {
   947  
   948  				if throttle() {
   949  					throttled = true
   950  					break
   951  				}
   952  
   953  				if pending() == 0 {
   954  					break
   955  				}
   956  
   957  				request, progress, err := reserve(peer, capacity(peer))
   958  				if err != nil {
   959  					return err
   960  				}
   961  				if progress {
   962  					progressed = true
   963  				}
   964  				if request == nil {
   965  					continue
   966  				}
   967  				if request.From > 0 {
   968  					peer.log.Trace("Requesting new batch of data", "type", kind, "from", request.From)
   969  				} else {
   970  					peer.log.Trace("Requesting new batch of data", "type", kind, "count", len(request.Headers), "from", request.Headers[0].Number)
   971  				}
   972  
   973  				if fetchHook != nil {
   974  					fetchHook(request.Headers)
   975  				}
   976  				if err := fetch(peer, request); err != nil {
   977  
   978  					panic(fmt.Sprintf("%v: %s fetch assignment failed", peer, kind))
   979  				}
   980  				running = true
   981  			}
   982  
   983  			if !progressed && !throttled && !running && len(idles) == total && pending() > 0 {
   984  				return errPeersUnavailable
   985  			}
   986  		}
   987  	}
   988  }
   989  
   990  func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) error {
   991  
   992  	rollback := []*types.Header{}
   993  	defer func() {
   994  		if len(rollback) > 0 {
   995  
   996  			hashes := make([]common.Hash, len(rollback))
   997  			for i, header := range rollback {
   998  				hashes[i] = header.Hash()
   999  			}
  1000  			lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0
  1001  			lastFastBlock = d.blockchain.CurrentFastBlock().Number()
  1002  			lastBlock = d.blockchain.CurrentBlock().Number()
  1003  			d.lightchain.Rollback(hashes)
  1004  			curFastBlock, curBlock := common.Big0, common.Big0
  1005  			curFastBlock = d.blockchain.CurrentFastBlock().Number()
  1006  			curBlock = d.blockchain.CurrentBlock().Number()
  1007  			d.logger.Warn("Rolled back headers", "count", len(hashes),
  1008  				"header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number),
  1009  				"fast", fmt.Sprintf("%d->%d", lastFastBlock, curFastBlock),
  1010  				"block", fmt.Sprintf("%d->%d", lastBlock, curBlock))
  1011  		}
  1012  	}()
  1013  
  1014  	gotHeaders := false
  1015  
  1016  	for {
  1017  		select {
  1018  		case <-d.cancelCh:
  1019  			return errCancelHeaderProcessing
  1020  
  1021  		case headers := <-d.headerProcCh:
  1022  
  1023  			if len(headers) == 0 {
  1024  
  1025  				for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} {
  1026  					select {
  1027  					case ch <- false:
  1028  					case <-d.cancelCh:
  1029  					}
  1030  				}
  1031  
  1032  				head := d.blockchain.CurrentBlock()
  1033  				if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.NumberU64())) > 0 {
  1034  					return errStallingPeer
  1035  				}
  1036  
  1037  				if d.mode == FastSync {
  1038  					head := d.lightchain.CurrentHeader()
  1039  					if td.Cmp(d.lightchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 {
  1040  						return errStallingPeer
  1041  					}
  1042  				}
  1043  
  1044  				rollback = nil
  1045  				return nil
  1046  			}
  1047  
  1048  			gotHeaders = true
  1049  
  1050  			for len(headers) > 0 {
  1051  
  1052  				select {
  1053  				case <-d.cancelCh:
  1054  					return errCancelHeaderProcessing
  1055  				default:
  1056  				}
  1057  
  1058  				limit := maxHeadersProcess
  1059  				if limit > len(headers) {
  1060  					limit = len(headers)
  1061  				}
  1062  				chunk := headers[:limit]
  1063  
  1064  				if d.mode == FastSync {
  1065  
  1066  					unknown := make([]*types.Header, 0, len(headers))
  1067  					for _, header := range chunk {
  1068  						if !d.lightchain.HasHeader(header.Hash(), header.Number.Uint64()) {
  1069  							unknown = append(unknown, header)
  1070  						}
  1071  					}
  1072  
  1073  					frequency := fsHeaderCheckFrequency
  1074  					if chunk[len(chunk)-1].Number.Uint64()+uint64(fsHeaderForceVerify) > pivot {
  1075  						frequency = 1
  1076  					}
  1077  					if n, err := d.lightchain.InsertHeaderChain(chunk, frequency); err != nil {
  1078  
  1079  						if n > 0 {
  1080  							rollback = append(rollback, chunk[:n]...)
  1081  						}
  1082  						d.logger.Debug("Invalid header encountered", "number", chunk[n].Number, "hash", chunk[n].Hash(), "err", err)
  1083  						return errInvalidChain
  1084  					}
  1085  
  1086  					rollback = append(rollback, unknown...)
  1087  					if len(rollback) > fsHeaderSafetyNet {
  1088  						rollback = append(rollback[:0], rollback[len(rollback)-fsHeaderSafetyNet:]...)
  1089  					}
  1090  				}
  1091  
  1092  				if d.mode == FullSync || d.mode == FastSync {
  1093  
  1094  					for d.queue.PendingBlocks() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders {
  1095  						select {
  1096  						case <-d.cancelCh:
  1097  							return errCancelHeaderProcessing
  1098  						case <-time.After(time.Second):
  1099  						}
  1100  					}
  1101  
  1102  					inserts := d.queue.Schedule(chunk, origin)
  1103  					if len(inserts) != len(chunk) {
  1104  						d.logger.Debug("Stale headers")
  1105  						return errBadPeer
  1106  					}
  1107  				}
  1108  				headers = headers[limit:]
  1109  				origin += uint64(limit)
  1110  			}
  1111  
  1112  			d.syncStatsLock.Lock()
  1113  			if d.syncStatsChainHeight < origin {
  1114  				d.syncStatsChainHeight = origin - 1
  1115  			}
  1116  			d.syncStatsLock.Unlock()
  1117  
  1118  			for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} {
  1119  				select {
  1120  				case ch <- true:
  1121  				default:
  1122  				}
  1123  			}
  1124  		}
  1125  	}
  1126  }
  1127  
  1128  func (d *Downloader) processFullSyncContent() error {
  1129  	for {
  1130  		results := d.queue.Results(true)
  1131  		if len(results) == 0 {
  1132  			return nil
  1133  		}
  1134  		if d.chainInsertHook != nil {
  1135  			d.chainInsertHook(results)
  1136  		}
  1137  		if err := d.importBlockResults(results); err != nil {
  1138  			return err
  1139  		}
  1140  	}
  1141  }
  1142  
  1143  func (d *Downloader) importBlockResults(results []*fetchResult) error {
  1144  
  1145  	if len(results) == 0 {
  1146  		return nil
  1147  	}
  1148  	select {
  1149  	case <-d.quitCh:
  1150  		return errCancelContentProcessing
  1151  	default:
  1152  	}
  1153  
  1154  	first, last := results[0].Header, results[len(results)-1].Header
  1155  	d.logger.Debug("Inserting downloaded chain", "items", len(results),
  1156  		"firstnum", first.Number, "firsthash", first.Hash(),
  1157  		"lastnum", last.Number, "lasthash", last.Hash(),
  1158  	)
  1159  	blocks := make([]*types.Block, len(results))
  1160  	for i, result := range results {
  1161  		blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
  1162  	}
  1163  	if index, err := d.blockchain.InsertChain(blocks); err != nil {
  1164  		d.logger.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err)
  1165  		return errInvalidChain
  1166  	}
  1167  	return nil
  1168  }
  1169  
  1170  func (d *Downloader) processFastSyncContent(latest *types.Header) error {
  1171  
  1172  	stateSync := d.syncState(latest.Root)
  1173  	defer stateSync.Cancel()
  1174  	go func() {
  1175  		if err := stateSync.Wait(); err != nil && err != errCancelStateFetch {
  1176  			d.queue.Close()
  1177  		}
  1178  	}()
  1179  
  1180  	pivot := uint64(0)
  1181  	if height := latest.Number.Uint64(); height > uint64(fsMinFullBlocks) {
  1182  		pivot = height - uint64(fsMinFullBlocks)
  1183  	}
  1184  
  1185  	var (
  1186  		oldPivot *fetchResult
  1187  		oldTail  []*fetchResult
  1188  	)
  1189  	for {
  1190  
  1191  		results := d.queue.Results(oldPivot == nil)
  1192  		if len(results) == 0 {
  1193  
  1194  			if oldPivot == nil {
  1195  				return stateSync.Cancel()
  1196  			}
  1197  
  1198  			select {
  1199  			case <-d.cancelCh:
  1200  				return stateSync.Cancel()
  1201  			default:
  1202  			}
  1203  		}
  1204  		if d.chainInsertHook != nil {
  1205  			d.chainInsertHook(results)
  1206  		}
  1207  		if oldPivot != nil {
  1208  			results = append(append([]*fetchResult{oldPivot}, oldTail...), results...)
  1209  		}
  1210  
  1211  		if atomic.LoadInt32(&d.committed) == 0 {
  1212  			latest = results[len(results)-1].Header
  1213  			if height := latest.Number.Uint64(); height > pivot+2*uint64(fsMinFullBlocks) {
  1214  				d.logger.Warn("Pivot became stale, moving", "old", pivot, "new", height-uint64(fsMinFullBlocks))
  1215  				pivot = height - uint64(fsMinFullBlocks)
  1216  			}
  1217  		}
  1218  		P, beforeP, afterP := splitAroundPivot(pivot, results)
  1219  		if err := d.commitFastSyncData(beforeP, stateSync); err != nil {
  1220  			return err
  1221  		}
  1222  		if P != nil {
  1223  
  1224  			if oldPivot != P {
  1225  				stateSync.Cancel()
  1226  
  1227  				stateSync = d.syncState(P.Header.Root)
  1228  				defer stateSync.Cancel()
  1229  				go func() {
  1230  					if err := stateSync.Wait(); err != nil && err != errCancelStateFetch {
  1231  						d.queue.Close()
  1232  					}
  1233  				}()
  1234  				oldPivot = P
  1235  			}
  1236  
  1237  			select {
  1238  			case <-stateSync.done:
  1239  				if stateSync.err != nil {
  1240  					return stateSync.err
  1241  				}
  1242  				if err := d.commitPivotBlock(P); err != nil {
  1243  					return err
  1244  				}
  1245  				oldPivot = nil
  1246  
  1247  			case <-time.After(time.Second):
  1248  				oldTail = afterP
  1249  				continue
  1250  			}
  1251  		}
  1252  
  1253  		if err := d.importBlockResults(afterP); err != nil {
  1254  			return err
  1255  		}
  1256  	}
  1257  }
  1258  
  1259  func splitAroundPivot(pivot uint64, results []*fetchResult) (p *fetchResult, before, after []*fetchResult) {
  1260  	for _, result := range results {
  1261  		num := result.Header.Number.Uint64()
  1262  		switch {
  1263  		case num < pivot:
  1264  			before = append(before, result)
  1265  		case num == pivot:
  1266  			p = result
  1267  		default:
  1268  			after = append(after, result)
  1269  		}
  1270  	}
  1271  	return p, before, after
  1272  }
  1273  
  1274  func (d *Downloader) commitFastSyncData(results []*fetchResult, stateSync *stateSync) error {
  1275  
  1276  	if len(results) == 0 {
  1277  		return nil
  1278  	}
  1279  	select {
  1280  	case <-d.quitCh:
  1281  		return errCancelContentProcessing
  1282  	case <-stateSync.done:
  1283  		if err := stateSync.Wait(); err != nil {
  1284  			return err
  1285  		}
  1286  	default:
  1287  	}
  1288  
  1289  	first, last := results[0].Header, results[len(results)-1].Header
  1290  	d.logger.Debug("Inserting fast-sync blocks", "items", len(results),
  1291  		"firstnum", first.Number, "firsthash", first.Hash(),
  1292  		"lastnumn", last.Number, "lasthash", last.Hash(),
  1293  	)
  1294  	blocks := make([]*types.Block, len(results))
  1295  	receipts := make([]types.Receipts, len(results))
  1296  	for i, result := range results {
  1297  		blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
  1298  		receipts[i] = result.Receipts
  1299  	}
  1300  	if index, err := d.blockchain.InsertReceiptChain(blocks, receipts); err != nil {
  1301  		d.logger.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err)
  1302  		return errInvalidChain
  1303  	}
  1304  	return nil
  1305  }
  1306  
  1307  func (d *Downloader) commitPivotBlock(result *fetchResult) error {
  1308  	block := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
  1309  	d.logger.Debug("Committing fast sync pivot as new head", "number", block.Number(), "hash", block.Hash())
  1310  	if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{result.Receipts}); err != nil {
  1311  		return err
  1312  	}
  1313  	if err := d.blockchain.FastSyncCommitHead(block.Hash()); err != nil {
  1314  		return err
  1315  	}
  1316  	atomic.StoreInt32(&d.committed, 1)
  1317  	return nil
  1318  }
  1319  
  1320  func (d *Downloader) DeliverHeaders(id string, headers []*types.Header) (err error) {
  1321  	return d.deliver(id, d.headerCh, &headerPack{id, headers}, headerInMeter, headerDropMeter)
  1322  }
  1323  
  1324  func (d *Downloader) DeliverBodies(id string, transactions [][]*types.Transaction, uncles [][]*types.Header) (err error) {
  1325  	return d.deliver(id, d.bodyCh, &bodyPack{id, transactions, uncles}, bodyInMeter, bodyDropMeter)
  1326  }
  1327  
  1328  func (d *Downloader) DeliverReceipts(id string, receipts [][]*types.Receipt) (err error) {
  1329  	return d.deliver(id, d.receiptCh, &receiptPack{id, receipts}, receiptInMeter, receiptDropMeter)
  1330  }
  1331  
  1332  func (d *Downloader) DeliverNodeData(id string, data [][]byte) (err error) {
  1333  	return d.deliver(id, d.stateCh, &statePack{id, data}, stateInMeter, stateDropMeter)
  1334  }
  1335  
  1336  func (d *Downloader) deliver(id string, destCh chan dataPack, packet dataPack, inMeter, dropMeter metrics.Meter) (err error) {
  1337  
  1338  	inMeter.Mark(int64(packet.Items()))
  1339  	defer func() {
  1340  		if err != nil {
  1341  			dropMeter.Mark(int64(packet.Items()))
  1342  		}
  1343  	}()
  1344  
  1345  	d.cancelLock.RLock()
  1346  	cancel := d.cancelCh
  1347  	d.cancelLock.RUnlock()
  1348  	if cancel == nil {
  1349  		return errNoSyncActive
  1350  	}
  1351  	select {
  1352  	case destCh <- packet:
  1353  		return nil
  1354  	case <-cancel:
  1355  		return errNoSyncActive
  1356  	}
  1357  }
  1358  
  1359  func (d *Downloader) qosTuner() {
  1360  	for {
  1361  
  1362  		rtt := time.Duration((1-qosTuningImpact)*float64(atomic.LoadUint64(&d.rttEstimate)) + qosTuningImpact*float64(d.peers.medianRTT()))
  1363  		atomic.StoreUint64(&d.rttEstimate, uint64(rtt))
  1364  
  1365  		conf := atomic.LoadUint64(&d.rttConfidence)
  1366  		conf = conf + (1000000-conf)/2
  1367  		atomic.StoreUint64(&d.rttConfidence, conf)
  1368  
  1369  		d.logger.Debug("Recalculated downloader QoS values", "rtt", rtt, "confidence", float64(conf)/1000000.0, "ttl", d.requestTTL())
  1370  		select {
  1371  		case <-d.quitCh:
  1372  			return
  1373  		case <-time.After(rtt):
  1374  		}
  1375  	}
  1376  }
  1377  
  1378  func (d *Downloader) qosReduceConfidence() {
  1379  
  1380  	peers := uint64(d.peers.Len())
  1381  	if peers == 0 {
  1382  
  1383  		return
  1384  	}
  1385  	if peers == 1 {
  1386  		atomic.StoreUint64(&d.rttConfidence, 1000000)
  1387  		return
  1388  	}
  1389  
  1390  	if peers >= uint64(qosConfidenceCap) {
  1391  		return
  1392  	}
  1393  
  1394  	conf := atomic.LoadUint64(&d.rttConfidence) * (peers - 1) / peers
  1395  	if float64(conf)/1000000 < rttMinConfidence {
  1396  		conf = uint64(rttMinConfidence * 1000000)
  1397  	}
  1398  	atomic.StoreUint64(&d.rttConfidence, conf)
  1399  
  1400  	rtt := time.Duration(atomic.LoadUint64(&d.rttEstimate))
  1401  	d.logger.Debug("Relaxed downloader QoS values", "rtt", rtt, "confidence", float64(conf)/1000000.0, "ttl", d.requestTTL())
  1402  }
  1403  
  1404  func (d *Downloader) requestRTT() time.Duration {
  1405  	return time.Duration(atomic.LoadUint64(&d.rttEstimate)) * 9 / 10
  1406  }
  1407  
  1408  func (d *Downloader) requestTTL() time.Duration {
  1409  	var (
  1410  		rtt  = time.Duration(atomic.LoadUint64(&d.rttEstimate))
  1411  		conf = float64(atomic.LoadUint64(&d.rttConfidence)) / 1000000.0
  1412  	)
  1413  	ttl := time.Duration(ttlScaling) * time.Duration(float64(rtt)/conf)
  1414  	if ttl > ttlLimit {
  1415  		ttl = ttlLimit
  1416  	}
  1417  	return ttl
  1418  }