github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/eth/downloader/downloader.go (about) 1 // Copyright 2015 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 downloader contains the manual full chain synchronisation. 18 package downloader 19 20 import ( 21 "errors" 22 "fmt" 23 "math/big" 24 "sync" 25 "sync/atomic" 26 "time" 27 28 ethereum "github.com/ethereum/go-ethereum" 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/core/rawdb" 31 "github.com/ethereum/go-ethereum/core/types" 32 "github.com/ethereum/go-ethereum/ethdb" 33 "github.com/ethereum/go-ethereum/event" 34 "github.com/ethereum/go-ethereum/log" 35 "github.com/ethereum/go-ethereum/metrics" 36 "github.com/ethereum/go-ethereum/params" 37 ) 38 39 var ( 40 MaxHashFetch = 512 // Amount of hashes to be fetched per retrieval request 41 MaxBlockFetch = 128 // Amount of blocks to be fetched per retrieval request 42 MaxHeaderFetch = 192 // Amount of block headers to be fetched per retrieval request 43 MaxSkeletonSize = 128 // Number of header fetches to need for a skeleton assembly 44 MaxBodyFetch = 128 // Amount of block bodies to be fetched per retrieval request 45 MaxReceiptFetch = 256 // Amount of transaction receipts to allow fetching per request 46 MaxStateFetch = 384 // Amount of node state values to allow fetching per request 47 48 MaxForkAncestry = 3 * params.EpochDuration // Maximum chain reorganisation 49 rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests 50 rttMaxEstimate = 20 * time.Second // Maximum round-trip time to target for download requests 51 rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value 52 ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion 53 ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts 54 55 qosTuningPeers = 5 // Number of peers to tune based on (best peers) 56 qosConfidenceCap = 10 // Number of peers above which not to modify RTT confidence 57 qosTuningImpact = 0.25 // Impact that a new tuning target has on the previous value 58 59 maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection) 60 maxHeadersProcess = 2048 // Number of header download results to import at once into the chain 61 maxResultsProcess = 2048 // Number of content download results to import at once into the chain 62 63 reorgProtThreshold = 48 // Threshold number of recent blocks to disable mini reorg protection 64 reorgProtHeaderDelay = 2 // Number of headers to delay delivering to cover mini reorgs 65 66 fsHeaderCheckFrequency = 100 // Verification frequency of the downloaded headers during fast sync 67 fsHeaderSafetyNet = 2048 // Number of headers to discard in case a chain violation is detected 68 fsHeaderForceVerify = 24 // Number of headers to verify before and after the pivot to accept it 69 fsHeaderContCheck = 3 * time.Second // Time interval to check for header continuations during state download 70 fsMinFullBlocks = 64 // Number of blocks to retrieve fully even in fast sync 71 ) 72 73 var ( 74 errBusy = errors.New("busy") 75 errUnknownPeer = errors.New("peer is unknown or unhealthy") 76 errBadPeer = errors.New("action from bad peer ignored") 77 errStallingPeer = errors.New("peer is stalling") 78 errUnsyncedPeer = errors.New("unsynced peer") 79 errNoPeers = errors.New("no peers to keep download active") 80 errTimeout = errors.New("timeout") 81 errEmptyHeaderSet = errors.New("empty header set by peer") 82 errPeersUnavailable = errors.New("no peers available or all tried for download") 83 errInvalidAncestor = errors.New("retrieved ancestor is invalid") 84 errInvalidChain = errors.New("retrieved hash chain is invalid") 85 errInvalidBlock = errors.New("retrieved block is invalid") 86 errInvalidBody = errors.New("retrieved block body is invalid") 87 errInvalidReceipt = errors.New("retrieved receipt is invalid") 88 errCancelBlockFetch = errors.New("block download canceled (requested)") 89 errCancelHeaderFetch = errors.New("block header download canceled (requested)") 90 errCancelBodyFetch = errors.New("block body download canceled (requested)") 91 errCancelReceiptFetch = errors.New("receipt download canceled (requested)") 92 errCancelStateFetch = errors.New("state data download canceled (requested)") 93 errCancelHeaderProcessing = errors.New("header processing canceled (requested)") 94 errCancelContentProcessing = errors.New("content processing canceled (requested)") 95 errNoSyncActive = errors.New("no sync active") 96 errTooOld = errors.New("peer doesn't speak recent enough protocol version (need version >= 62)") 97 ) 98 99 type Downloader struct { 100 mode SyncMode // Synchronisation mode defining the strategy used (per sync cycle) 101 mux *event.TypeMux // Event multiplexer to announce sync operation events 102 103 checkpoint uint64 // Checkpoint block number to enforce head against (e.g. fast sync) 104 genesis uint64 // Genesis block number to limit sync to (e.g. light client CHT) 105 queue *queue // Scheduler for selecting the hashes to download 106 peers *peerSet // Set of active peers from which download can proceed 107 stateDB ethdb.Database 108 109 rttEstimate uint64 // Round trip time to target for download requests 110 rttConfidence uint64 // Confidence in the estimated RTT (unit: millionths to allow atomic ops) 111 112 // Statistics 113 syncStatsChainOrigin uint64 // Origin block number where syncing started at 114 syncStatsChainHeight uint64 // Highest block number known when syncing started 115 syncStatsState stateSyncStats 116 syncStatsLock sync.RWMutex // Lock protecting the sync stats fields 117 118 lightchain LightChain 119 blockchain BlockChain 120 121 // Callbacks 122 dropPeer peerDropFn // Drops a peer for misbehaving 123 124 // Status 125 synchroniseMock func(id string, hash common.Hash) error // Replacement for synchronise during testing 126 synchronising int32 127 notified int32 128 committed int32 129 130 // Channels 131 headerCh chan dataPack // [eth/62] Channel receiving inbound block headers 132 bodyCh chan dataPack // [eth/62] Channel receiving inbound block bodies 133 receiptCh chan dataPack // [eth/63] Channel receiving inbound receipts 134 bodyWakeCh chan bool // [eth/62] Channel to signal the block body fetcher of new tasks 135 receiptWakeCh chan bool // [eth/63] Channel to signal the receipt fetcher of new tasks 136 headerProcCh chan []*types.Header // [eth/62] Channel to feed the header processor new tasks 137 138 // for stateFetcher 139 stateSyncStart chan *stateSync 140 trackStateReq chan *stateReq 141 stateCh chan dataPack // [eth/63] Channel receiving inbound node state data 142 143 // Cancellation and termination 144 cancelPeer string // Identifier of the peer currently being used as the master (cancel on drop) 145 cancelCh chan struct{} // Channel to cancel mid-flight syncs 146 cancelLock sync.RWMutex // Lock to protect the cancel channel and peer in delivers 147 cancelWg sync.WaitGroup // Make sure all fetcher goroutines have exited. 148 149 quitCh chan struct{} // Quit channel to signal termination 150 quitLock sync.RWMutex // Lock to prevent double closes 151 152 // Testing hooks 153 syncInitHook func(uint64, uint64) // Method to call upon initiating a new sync run 154 bodyFetchHook func([]*types.Header) // Method to call upon starting a block body fetch 155 receiptFetchHook func([]*types.Header) // Method to call upon starting a receipt fetch 156 chainInsertHook func([]*fetchResult) // Method to call upon inserting a chain of blocks (possibly in multiple invocations) 157 } 158 159 // LightChain encapsulates functions required to synchronise a light chain. 160 type LightChain interface { 161 // HasHeader verifies a header's presence in the local chain. 162 HasHeader(common.Hash, uint64) bool 163 164 // GetHeaderByHash retrieves a header from the local chain. 165 GetHeaderByHash(common.Hash) *types.Header 166 167 // CurrentHeader retrieves the head header from the local chain. 168 CurrentHeader() *types.Header 169 170 // GetTd returns the total difficulty of a local block. 171 GetTd(common.Hash, uint64) *big.Int 172 173 // InsertHeaderChain inserts a batch of headers into the local chain. 174 InsertHeaderChain([]*types.Header, int) (int, error) 175 176 // Rollback removes a few recently added elements from the local chain. 177 Rollback([]common.Hash) 178 } 179 180 // BlockChain encapsulates functions required to sync a (full or fast) blockchain. 181 type BlockChain interface { 182 LightChain 183 184 // HasBlock verifies a block's presence in the local chain. 185 HasBlock(common.Hash, uint64) bool 186 187 // HasFastBlock verifies a fast block's presence in the local chain. 188 HasFastBlock(common.Hash, uint64) bool 189 190 // GetBlockByHash retrieves a block from the local chain. 191 GetBlockByHash(common.Hash) *types.Block 192 193 // CurrentBlock retrieves the head block from the local chain. 194 CurrentBlock() *types.Block 195 196 // CurrentFastBlock retrieves the head fast block from the local chain. 197 CurrentFastBlock() *types.Block 198 199 // FastSyncCommitHead directly commits the head block to a certain entity. 200 FastSyncCommitHead(common.Hash) error 201 202 // InsertChain inserts a batch of blocks into the local chain. 203 InsertChain(types.Blocks) (int, error) 204 205 // InsertReceiptChain inserts a batch of receipts into the local chain. 206 InsertReceiptChain(types.Blocks, []types.Receipts) (int, error) 207 } 208 209 // New creates a new downloader to fetch hashes and blocks from remote peers. 210 func New(mode SyncMode, checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn) *Downloader { 211 if lightchain == nil { 212 lightchain = chain 213 } 214 dl := &Downloader{ 215 mode: mode, 216 stateDB: stateDb, 217 mux: mux, 218 checkpoint: checkpoint, 219 queue: newQueue(), 220 peers: newPeerSet(), 221 rttEstimate: uint64(rttMaxEstimate), 222 rttConfidence: uint64(1000000), 223 blockchain: chain, 224 lightchain: lightchain, 225 dropPeer: dropPeer, 226 headerCh: make(chan dataPack, 1), 227 bodyCh: make(chan dataPack, 1), 228 receiptCh: make(chan dataPack, 1), 229 bodyWakeCh: make(chan bool, 1), 230 receiptWakeCh: make(chan bool, 1), 231 headerProcCh: make(chan []*types.Header, 1), 232 quitCh: make(chan struct{}), 233 stateCh: make(chan dataPack), 234 stateSyncStart: make(chan *stateSync), 235 syncStatsState: stateSyncStats{ 236 processed: rawdb.ReadFastTrieProgress(stateDb), 237 }, 238 trackStateReq: make(chan *stateReq), 239 } 240 go dl.qosTuner() 241 go dl.stateFetcher() 242 return dl 243 } 244 245 // Progress retrieves the synchronisation boundaries, specifically the origin 246 // block where synchronisation started at (may have failed/suspended); the block 247 // or header sync is currently at; and the latest known block which the sync targets. 248 // 249 // In addition, during the state download phase of fast synchronisation the number 250 // of processed and the total number of known states are also returned. Otherwise 251 // these are zero. 252 func (d *Downloader) Progress() ethereum.SyncProgress { 253 // Lock the current stats and return the progress 254 d.syncStatsLock.RLock() 255 defer d.syncStatsLock.RUnlock() 256 257 current := uint64(0) 258 switch d.mode { 259 case FullSync: 260 current = d.blockchain.CurrentBlock().NumberU64() 261 case FastSync: 262 current = d.blockchain.CurrentFastBlock().NumberU64() 263 case LightSync: 264 current = d.lightchain.CurrentHeader().Number.Uint64() 265 } 266 return ethereum.SyncProgress{ 267 StartingBlock: d.syncStatsChainOrigin, 268 CurrentBlock: current, 269 HighestBlock: d.syncStatsChainHeight, 270 PulledStates: d.syncStatsState.processed, 271 KnownStates: d.syncStatsState.processed + d.syncStatsState.pending, 272 } 273 } 274 275 // Synchronising returns whether the downloader is currently retrieving blocks. 276 func (d *Downloader) Synchronising() bool { 277 return atomic.LoadInt32(&d.synchronising) > 0 278 } 279 280 // RegisterPeer injects a new download peer into the set of block source to be 281 // used for fetching hashes and blocks from. 282 func (d *Downloader) RegisterPeer(id string, version int, peer Peer) error { 283 logger := log.New("peer", id) 284 logger.Trace("Registering sync peer") 285 if err := d.peers.Register(newPeerConnection(id, version, peer, logger)); err != nil { 286 logger.Error("Failed to register sync peer", "err", err) 287 return err 288 } 289 d.qosReduceConfidence() 290 291 return nil 292 } 293 294 // RegisterLightPeer injects a light client peer, wrapping it so it appears as a regular peer. 295 func (d *Downloader) RegisterLightPeer(id string, version int, peer LightPeer) error { 296 return d.RegisterPeer(id, version, &lightPeerWrapper{peer}) 297 } 298 299 // UnregisterPeer remove a peer from the known list, preventing any action from 300 // the specified peer. An effort is also made to return any pending fetches into 301 // the queue. 302 func (d *Downloader) UnregisterPeer(id string) error { 303 // Unregister the peer from the active peer set and revoke any fetch tasks 304 logger := log.New("peer", id) 305 logger.Trace("Unregistering sync peer") 306 if err := d.peers.Unregister(id); err != nil { 307 logger.Error("Failed to unregister sync peer", "err", err) 308 return err 309 } 310 d.queue.Revoke(id) 311 312 // If this peer was the master peer, abort sync immediately 313 d.cancelLock.RLock() 314 master := id == d.cancelPeer 315 d.cancelLock.RUnlock() 316 317 if master { 318 d.cancel() 319 } 320 return nil 321 } 322 323 // Synchronise tries to sync up our local block chain with a remote peer, both 324 // adding various sanity checks as well as wrapping it with various log entries. 325 func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) error { 326 err := d.synchronise(id, head, td, mode) 327 switch err { 328 case nil: 329 case errBusy: 330 331 case errTimeout, errBadPeer, errStallingPeer, errUnsyncedPeer, 332 errEmptyHeaderSet, errPeersUnavailable, errTooOld, 333 errInvalidAncestor, errInvalidChain: 334 log.Warn("Synchronisation failed, dropping peer", "peer", id, "err", err) 335 if d.dropPeer == nil { 336 // The dropPeer method is nil when `--copydb` is used for a local copy. 337 // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored 338 log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", id) 339 } else { 340 d.dropPeer(id) 341 } 342 default: 343 log.Warn("Synchronisation failed, retrying", "err", err) 344 } 345 return err 346 } 347 348 // synchronise will select the peer and use it for synchronising. If an empty string is given 349 // it will use the best peer possible and synchronize if its TD is higher than our own. If any of the 350 // checks fail an error will be returned. This method is synchronous 351 func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode SyncMode) error { 352 // Mock out the synchronisation if testing 353 if d.synchroniseMock != nil { 354 return d.synchroniseMock(id, hash) 355 } 356 // Make sure only one goroutine is ever allowed past this point at once 357 if !atomic.CompareAndSwapInt32(&d.synchronising, 0, 1) { 358 return errBusy 359 } 360 defer atomic.StoreInt32(&d.synchronising, 0) 361 362 // Post a user notification of the sync (only once per session) 363 if atomic.CompareAndSwapInt32(&d.notified, 0, 1) { 364 log.Info("Block synchronisation started") 365 } 366 // Reset the queue, peer set and wake channels to clean any internal leftover state 367 d.queue.Reset() 368 d.peers.Reset() 369 370 for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} { 371 select { 372 case <-ch: 373 default: 374 } 375 } 376 for _, ch := range []chan dataPack{d.headerCh, d.bodyCh, d.receiptCh} { 377 for empty := false; !empty; { 378 select { 379 case <-ch: 380 default: 381 empty = true 382 } 383 } 384 } 385 for empty := false; !empty; { 386 select { 387 case <-d.headerProcCh: 388 default: 389 empty = true 390 } 391 } 392 // Create cancel channel for aborting mid-flight and mark the master peer 393 d.cancelLock.Lock() 394 d.cancelCh = make(chan struct{}) 395 d.cancelPeer = id 396 d.cancelLock.Unlock() 397 398 defer d.Cancel() // No matter what, we can't leave the cancel channel open 399 400 // Set the requested sync mode, unless it's forbidden 401 d.mode = mode 402 403 // Retrieve the origin peer and initiate the downloading process 404 p := d.peers.Peer(id) 405 if p == nil { 406 return errUnknownPeer 407 } 408 return d.syncWithPeer(p, hash, td) 409 } 410 411 // syncWithPeer starts a block synchronization based on the hash chain from the 412 // specified peer and head hash. 413 func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.Int) (err error) { 414 d.mux.Post(StartEvent{}) 415 defer func() { 416 // reset on error 417 if err != nil { 418 d.mux.Post(FailedEvent{err}) 419 } else { 420 latest := d.lightchain.CurrentHeader() 421 d.mux.Post(DoneEvent{latest}) 422 } 423 }() 424 if p.version < 62 { 425 return errTooOld 426 } 427 428 log.Debug("Synchronising with the network", "peer", p.id, "eth", p.version, "head", hash, "td", td, "mode", d.mode) 429 defer func(start time.Time) { 430 log.Debug("Synchronisation terminated", "elapsed", time.Since(start)) 431 }(time.Now()) 432 433 // Look up the sync boundaries: the common ancestor and the target block 434 latest, err := d.fetchHeight(p) 435 if err != nil { 436 return err 437 } 438 height := latest.Number.Uint64() 439 440 origin, err := d.findAncestor(p, latest) 441 if err != nil { 442 return err 443 } 444 d.syncStatsLock.Lock() 445 if d.syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin { 446 d.syncStatsChainOrigin = origin 447 } 448 d.syncStatsChainHeight = height 449 d.syncStatsLock.Unlock() 450 451 // Ensure our origin point is below any fast sync pivot point 452 pivot := uint64(0) 453 if d.mode == FastSync { 454 if height <= uint64(fsMinFullBlocks) { 455 origin = 0 456 } else { 457 pivot = height - uint64(fsMinFullBlocks) 458 if pivot <= origin { 459 origin = pivot - 1 460 } 461 } 462 } 463 d.committed = 1 464 if d.mode == FastSync && pivot != 0 { 465 d.committed = 0 466 } 467 // Initiate the sync using a concurrent header and content retrieval algorithm 468 d.queue.Prepare(origin+1, d.mode) 469 if d.syncInitHook != nil { 470 d.syncInitHook(origin, height) 471 } 472 473 fetchers := []func() error{ 474 func() error { return d.fetchHeaders(p, origin+1, pivot) }, // Headers are always retrieved 475 func() error { return d.fetchBodies(origin + 1) }, // Bodies are retrieved during normal and fast sync 476 func() error { return d.fetchReceipts(origin + 1) }, // Receipts are retrieved during fast sync 477 func() error { return d.processHeaders(origin+1, pivot, td) }, 478 } 479 if d.mode == FastSync { 480 fetchers = append(fetchers, func() error { return d.processFastSyncContent(latest) }) 481 } else if d.mode == FullSync { 482 fetchers = append(fetchers, d.processFullSyncContent) 483 } 484 return d.spawnSync(fetchers) 485 } 486 487 // spawnSync runs d.process and all given fetcher functions to completion in 488 // separate goroutines, returning the first error that appears. 489 func (d *Downloader) spawnSync(fetchers []func() error) error { 490 errc := make(chan error, len(fetchers)) 491 d.cancelWg.Add(len(fetchers)) 492 for _, fn := range fetchers { 493 fn := fn 494 go func() { defer d.cancelWg.Done(); errc <- fn() }() 495 } 496 // Wait for the first error, then terminate the others. 497 var err error 498 for i := 0; i < len(fetchers); i++ { 499 if i == len(fetchers)-1 { 500 // Close the queue when all fetchers have exited. 501 // This will cause the block processor to end when 502 // it has processed the queue. 503 d.queue.Close() 504 } 505 if err = <-errc; err != nil { 506 break 507 } 508 } 509 d.queue.Close() 510 d.Cancel() 511 return err 512 } 513 514 // cancel aborts all of the operations and resets the queue. However, cancel does 515 // not wait for the running download goroutines to finish. This method should be 516 // used when cancelling the downloads from inside the downloader. 517 func (d *Downloader) cancel() { 518 // Close the current cancel channel 519 d.cancelLock.Lock() 520 if d.cancelCh != nil { 521 select { 522 case <-d.cancelCh: 523 // Channel was already closed 524 default: 525 close(d.cancelCh) 526 } 527 } 528 d.cancelLock.Unlock() 529 } 530 531 // Cancel aborts all of the operations and waits for all download goroutines to 532 // finish before returning. 533 func (d *Downloader) Cancel() { 534 d.cancel() 535 d.cancelWg.Wait() 536 } 537 538 // Terminate interrupts the downloader, canceling all pending operations. 539 // The downloader cannot be reused after calling Terminate. 540 func (d *Downloader) Terminate() { 541 // Close the termination channel (make sure double close is allowed) 542 d.quitLock.Lock() 543 select { 544 case <-d.quitCh: 545 default: 546 close(d.quitCh) 547 } 548 d.quitLock.Unlock() 549 550 // Cancel any pending download requests 551 d.Cancel() 552 } 553 554 // fetchHeight retrieves the head header of the remote peer to aid in estimating 555 // the total time a pending synchronisation would take. 556 func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) { 557 p.log.Debug("Retrieving remote chain height") 558 559 // Request the advertised remote head block and wait for the response 560 head, _ := p.peer.Head() 561 go p.peer.RequestHeadersByHash(head, 1, 0, false) 562 563 ttl := d.requestTTL() 564 timeout := time.After(ttl) 565 for { 566 select { 567 case <-d.cancelCh: 568 return nil, errCancelBlockFetch 569 570 case packet := <-d.headerCh: 571 // Discard anything not from the origin peer 572 if packet.PeerId() != p.id { 573 log.Debug("Received headers from incorrect peer", "peer", packet.PeerId()) 574 break 575 } 576 // Make sure the peer actually gave something valid 577 headers := packet.(*headerPack).headers 578 if len(headers) != 1 { 579 p.log.Debug("Multiple headers for single request", "headers", len(headers)) 580 return nil, errBadPeer 581 } 582 head := headers[0] 583 if d.mode == FastSync && head.Number.Uint64() < d.checkpoint { 584 p.log.Warn("Remote head below checkpoint", "number", head.Number, "hash", head.Hash()) 585 return nil, errUnsyncedPeer 586 } 587 p.log.Debug("Remote head header identified", "number", head.Number, "hash", head.Hash()) 588 return head, nil 589 590 case <-timeout: 591 p.log.Debug("Waiting for head header timed out", "elapsed", ttl) 592 return nil, errTimeout 593 594 case <-d.bodyCh: 595 case <-d.receiptCh: 596 // Out of bounds delivery, ignore 597 } 598 } 599 } 600 601 // calculateRequestSpan calculates what headers to request from a peer when trying to determine the 602 // common ancestor. 603 // It returns parameters to be used for peer.RequestHeadersByNumber: 604 // from - starting block number 605 // count - number of headers to request 606 // skip - number of headers to skip 607 // and also returns 'max', the last block which is expected to be returned by the remote peers, 608 // given the (from,count,skip) 609 func calculateRequestSpan(remoteHeight, localHeight uint64) (int64, int, int, uint64) { 610 var ( 611 from int 612 count int 613 MaxCount = MaxHeaderFetch / 16 614 ) 615 // requestHead is the highest block that we will ask for. If requestHead is not offset, 616 // the highest block that we will get is 16 blocks back from head, which means we 617 // will fetch 14 or 15 blocks unnecessarily in the case the height difference 618 // between us and the peer is 1-2 blocks, which is most common 619 requestHead := int(remoteHeight) - 1 620 if requestHead < 0 { 621 requestHead = 0 622 } 623 // requestBottom is the lowest block we want included in the query 624 // Ideally, we want to include just below own head 625 requestBottom := int(localHeight - 1) 626 if requestBottom < 0 { 627 requestBottom = 0 628 } 629 totalSpan := requestHead - requestBottom 630 span := 1 + totalSpan/MaxCount 631 if span < 2 { 632 span = 2 633 } 634 if span > 16 { 635 span = 16 636 } 637 638 count = 1 + totalSpan/span 639 if count > MaxCount { 640 count = MaxCount 641 } 642 if count < 2 { 643 count = 2 644 } 645 from = requestHead - (count-1)*span 646 if from < 0 { 647 from = 0 648 } 649 max := from + (count-1)*span 650 return int64(from), count, span - 1, uint64(max) 651 } 652 653 // findAncestor tries to locate the common ancestor link of the local chain and 654 // a remote peers blockchain. In the general case when our node was in sync and 655 // on the correct chain, checking the top N links should already get us a match. 656 // In the rare scenario when we ended up on a long reorganisation (i.e. none of 657 // the head links match), we do a binary search to find the common ancestor. 658 func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) (uint64, error) { 659 // Figure out the valid ancestor range to prevent rewrite attacks 660 var ( 661 floor = int64(-1) 662 localHeight uint64 663 remoteHeight = remoteHeader.Number.Uint64() 664 ) 665 switch d.mode { 666 case FullSync: 667 localHeight = d.blockchain.CurrentBlock().NumberU64() 668 case FastSync: 669 localHeight = d.blockchain.CurrentFastBlock().NumberU64() 670 default: 671 localHeight = d.lightchain.CurrentHeader().Number.Uint64() 672 } 673 p.log.Debug("Looking for common ancestor", "local", localHeight, "remote", remoteHeight) 674 675 // Recap floor value for binary search 676 if localHeight >= MaxForkAncestry { 677 // We're above the max reorg threshold, find the earliest fork point 678 floor = int64(localHeight - MaxForkAncestry) 679 } 680 // If we're doing a light sync, ensure the floor doesn't go below the CHT, as 681 // all headers before that point will be missing. 682 if d.mode == LightSync { 683 // If we dont know the current CHT position, find it 684 if d.genesis == 0 { 685 header := d.lightchain.CurrentHeader() 686 for header != nil { 687 d.genesis = header.Number.Uint64() 688 if floor >= int64(d.genesis)-1 { 689 break 690 } 691 header = d.lightchain.GetHeaderByHash(header.ParentHash) 692 } 693 } 694 // We already know the "genesis" block number, cap floor to that 695 if floor < int64(d.genesis)-1 { 696 floor = int64(d.genesis) - 1 697 } 698 } 699 700 from, count, skip, max := calculateRequestSpan(remoteHeight, localHeight) 701 702 p.log.Trace("Span searching for common ancestor", "count", count, "from", from, "skip", skip) 703 go p.peer.RequestHeadersByNumber(uint64(from), count, skip, false) 704 705 // Wait for the remote response to the head fetch 706 number, hash := uint64(0), common.Hash{} 707 708 ttl := d.requestTTL() 709 timeout := time.After(ttl) 710 711 for finished := false; !finished; { 712 select { 713 case <-d.cancelCh: 714 return 0, errCancelHeaderFetch 715 716 case packet := <-d.headerCh: 717 // Discard anything not from the origin peer 718 if packet.PeerId() != p.id { 719 log.Debug("Received headers from incorrect peer", "peer", packet.PeerId()) 720 break 721 } 722 // Make sure the peer actually gave something valid 723 headers := packet.(*headerPack).headers 724 if len(headers) == 0 { 725 p.log.Warn("Empty head header set") 726 return 0, errEmptyHeaderSet 727 } 728 // Make sure the peer's reply conforms to the request 729 for i, header := range headers { 730 expectNumber := from + int64(i)*int64(skip+1) 731 if number := header.Number.Int64(); number != expectNumber { 732 p.log.Warn("Head headers broke chain ordering", "index", i, "requested", expectNumber, "received", number) 733 return 0, errInvalidChain 734 } 735 } 736 // Check if a common ancestor was found 737 finished = true 738 for i := len(headers) - 1; i >= 0; i-- { 739 // Skip any headers that underflow/overflow our requested set 740 if headers[i].Number.Int64() < from || headers[i].Number.Uint64() > max { 741 continue 742 } 743 // Otherwise check if we already know the header or not 744 h := headers[i].Hash() 745 n := headers[i].Number.Uint64() 746 747 var known bool 748 switch d.mode { 749 case FullSync: 750 known = d.blockchain.HasBlock(h, n) 751 case FastSync: 752 known = d.blockchain.HasFastBlock(h, n) 753 default: 754 known = d.lightchain.HasHeader(h, n) 755 } 756 if known { 757 number, hash = n, h 758 break 759 } 760 } 761 762 case <-timeout: 763 p.log.Debug("Waiting for head header timed out", "elapsed", ttl) 764 return 0, errTimeout 765 766 case <-d.bodyCh: 767 case <-d.receiptCh: 768 // Out of bounds delivery, ignore 769 } 770 } 771 // If the head fetch already found an ancestor, return 772 if hash != (common.Hash{}) { 773 if int64(number) <= floor { 774 p.log.Warn("Ancestor below allowance", "number", number, "hash", hash, "allowance", floor) 775 return 0, errInvalidAncestor 776 } 777 p.log.Debug("Found common ancestor", "number", number, "hash", hash) 778 return number, nil 779 } 780 // Ancestor not found, we need to binary search over our chain 781 start, end := uint64(0), remoteHeight 782 if floor > 0 { 783 start = uint64(floor) 784 } 785 p.log.Trace("Binary searching for common ancestor", "start", start, "end", end) 786 787 for start+1 < end { 788 // Split our chain interval in two, and request the hash to cross check 789 check := (start + end) / 2 790 791 ttl := d.requestTTL() 792 timeout := time.After(ttl) 793 794 go p.peer.RequestHeadersByNumber(check, 1, 0, false) 795 796 // Wait until a reply arrives to this request 797 for arrived := false; !arrived; { 798 select { 799 case <-d.cancelCh: 800 return 0, errCancelHeaderFetch 801 802 case packer := <-d.headerCh: 803 // Discard anything not from the origin peer 804 if packer.PeerId() != p.id { 805 log.Debug("Received headers from incorrect peer", "peer", packer.PeerId()) 806 break 807 } 808 // Make sure the peer actually gave something valid 809 headers := packer.(*headerPack).headers 810 if len(headers) != 1 { 811 p.log.Debug("Multiple headers for single request", "headers", len(headers)) 812 return 0, errBadPeer 813 } 814 arrived = true 815 816 // Modify the search interval based on the response 817 h := headers[0].Hash() 818 n := headers[0].Number.Uint64() 819 820 var known bool 821 switch d.mode { 822 case FullSync: 823 known = d.blockchain.HasBlock(h, n) 824 case FastSync: 825 known = d.blockchain.HasFastBlock(h, n) 826 default: 827 known = d.lightchain.HasHeader(h, n) 828 } 829 if !known { 830 end = check 831 break 832 } 833 header := d.lightchain.GetHeaderByHash(h) // Independent of sync mode, header surely exists 834 if header.Number.Uint64() != check { 835 p.log.Debug("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check) 836 return 0, errBadPeer 837 } 838 start = check 839 hash = h 840 841 case <-timeout: 842 p.log.Debug("Waiting for search header timed out", "elapsed", ttl) 843 return 0, errTimeout 844 845 case <-d.bodyCh: 846 case <-d.receiptCh: 847 // Out of bounds delivery, ignore 848 } 849 } 850 } 851 // Ensure valid ancestry and return 852 if int64(start) <= floor { 853 p.log.Warn("Ancestor below allowance", "number", start, "hash", hash, "allowance", floor) 854 return 0, errInvalidAncestor 855 } 856 p.log.Debug("Found common ancestor", "number", start, "hash", hash) 857 return start, nil 858 } 859 860 // fetchHeaders keeps retrieving headers concurrently from the number 861 // requested, until no more are returned, potentially throttling on the way. To 862 // facilitate concurrency but still protect against malicious nodes sending bad 863 // headers, we construct a header chain skeleton using the "origin" peer we are 864 // syncing with, and fill in the missing headers using anyone else. Headers from 865 // other peers are only accepted if they map cleanly to the skeleton. If no one 866 // can fill in the skeleton - not even the origin peer - it's assumed invalid and 867 // the origin is dropped. 868 func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) error { 869 p.log.Debug("Directing header downloads", "origin", from) 870 defer p.log.Debug("Header download terminated") 871 872 // Create a timeout timer, and the associated header fetcher 873 skeleton := true // Skeleton assembly phase or finishing up 874 request := time.Now() // time of the last skeleton fetch request 875 timeout := time.NewTimer(0) // timer to dump a non-responsive active peer 876 <-timeout.C // timeout channel should be initially empty 877 defer timeout.Stop() 878 879 var ttl time.Duration 880 getHeaders := func(from uint64) { 881 request = time.Now() 882 883 ttl = d.requestTTL() 884 timeout.Reset(ttl) 885 886 if skeleton { 887 p.log.Trace("Fetching skeleton headers", "count", MaxHeaderFetch, "from", from) 888 go p.peer.RequestHeadersByNumber(from+uint64(MaxHeaderFetch)-1, MaxSkeletonSize, MaxHeaderFetch-1, false) 889 } else { 890 p.log.Trace("Fetching full headers", "count", MaxHeaderFetch, "from", from) 891 go p.peer.RequestHeadersByNumber(from, MaxHeaderFetch, 0, false) 892 } 893 } 894 // Start pulling the header chain skeleton until all is done 895 getHeaders(from) 896 897 for { 898 select { 899 case <-d.cancelCh: 900 return errCancelHeaderFetch 901 902 case packet := <-d.headerCh: 903 // Make sure the active peer is giving us the skeleton headers 904 if packet.PeerId() != p.id { 905 log.Debug("Received skeleton from incorrect peer", "peer", packet.PeerId()) 906 break 907 } 908 headerReqTimer.UpdateSince(request) 909 timeout.Stop() 910 911 // If the skeleton's finished, pull any remaining head headers directly from the origin 912 if packet.Items() == 0 && skeleton { 913 skeleton = false 914 getHeaders(from) 915 continue 916 } 917 // If no more headers are inbound, notify the content fetchers and return 918 if packet.Items() == 0 { 919 // Don't abort header fetches while the pivot is downloading 920 if atomic.LoadInt32(&d.committed) == 0 && pivot <= from { 921 p.log.Debug("No headers, waiting for pivot commit") 922 select { 923 case <-time.After(fsHeaderContCheck): 924 getHeaders(from) 925 continue 926 case <-d.cancelCh: 927 return errCancelHeaderFetch 928 } 929 } 930 // Pivot done (or not in fast sync) and no more headers, terminate the process 931 p.log.Debug("No more headers available") 932 select { 933 case d.headerProcCh <- nil: 934 return nil 935 case <-d.cancelCh: 936 return errCancelHeaderFetch 937 } 938 } 939 headers := packet.(*headerPack).headers 940 941 // If we received a skeleton batch, resolve internals concurrently 942 if skeleton { 943 filled, proced, err := d.fillHeaderSkeleton(from, headers) 944 if err != nil { 945 p.log.Warn("Skeleton chain invalid", "err", err) 946 return errInvalidChain 947 } 948 headers = filled[proced:] 949 from += uint64(proced) 950 } else { 951 // If we're closing in on the chain head, but haven't yet reached it, delay 952 // the last few headers so mini reorgs on the head don't cause invalid hash 953 // chain errors. 954 if n := len(headers); n > 0 { 955 // Retrieve the current head we're at 956 head := uint64(0) 957 if d.mode == LightSync { 958 head = d.lightchain.CurrentHeader().Number.Uint64() 959 } else { 960 head = d.blockchain.CurrentFastBlock().NumberU64() 961 if full := d.blockchain.CurrentBlock().NumberU64(); head < full { 962 head = full 963 } 964 } 965 // If the head is way older than this batch, delay the last few headers 966 if head+uint64(reorgProtThreshold) < headers[n-1].Number.Uint64() { 967 delay := reorgProtHeaderDelay 968 if delay > n { 969 delay = n 970 } 971 headers = headers[:n-delay] 972 } 973 } 974 } 975 // Insert all the new headers and fetch the next batch 976 if len(headers) > 0 { 977 p.log.Trace("Scheduling new headers", "count", len(headers), "from", from) 978 select { 979 case d.headerProcCh <- headers: 980 case <-d.cancelCh: 981 return errCancelHeaderFetch 982 } 983 from += uint64(len(headers)) 984 getHeaders(from) 985 } else { 986 // No headers delivered, or all of them being delayed, sleep a bit and retry 987 p.log.Trace("All headers delayed, waiting") 988 select { 989 case <-time.After(fsHeaderContCheck): 990 getHeaders(from) 991 continue 992 case <-d.cancelCh: 993 return errCancelHeaderFetch 994 } 995 } 996 997 case <-timeout.C: 998 if d.dropPeer == nil { 999 // The dropPeer method is nil when `--copydb` is used for a local copy. 1000 // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored 1001 p.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", p.id) 1002 break 1003 } 1004 // Header retrieval timed out, consider the peer bad and drop 1005 p.log.Debug("Header request timed out", "elapsed", ttl) 1006 headerTimeoutMeter.Mark(1) 1007 d.dropPeer(p.id) 1008 1009 // Finish the sync gracefully instead of dumping the gathered data though 1010 for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} { 1011 select { 1012 case ch <- false: 1013 case <-d.cancelCh: 1014 } 1015 } 1016 select { 1017 case d.headerProcCh <- nil: 1018 case <-d.cancelCh: 1019 } 1020 return errBadPeer 1021 } 1022 } 1023 } 1024 1025 // fillHeaderSkeleton concurrently retrieves headers from all our available peers 1026 // and maps them to the provided skeleton header chain. 1027 // 1028 // Any partial results from the beginning of the skeleton is (if possible) forwarded 1029 // immediately to the header processor to keep the rest of the pipeline full even 1030 // in the case of header stalls. 1031 // 1032 // The method returns the entire filled skeleton and also the number of headers 1033 // already forwarded for processing. 1034 func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) ([]*types.Header, int, error) { 1035 log.Debug("Filling up skeleton", "from", from) 1036 d.queue.ScheduleSkeleton(from, skeleton) 1037 1038 var ( 1039 deliver = func(packet dataPack) (int, error) { 1040 pack := packet.(*headerPack) 1041 return d.queue.DeliverHeaders(pack.peerID, pack.headers, d.headerProcCh) 1042 } 1043 expire = func() map[string]int { return d.queue.ExpireHeaders(d.requestTTL()) } 1044 throttle = func() bool { return false } 1045 reserve = func(p *peerConnection, count int) (*fetchRequest, bool, error) { 1046 return d.queue.ReserveHeaders(p, count), false, nil 1047 } 1048 fetch = func(p *peerConnection, req *fetchRequest) error { return p.FetchHeaders(req.From, MaxHeaderFetch) } 1049 capacity = func(p *peerConnection) int { return p.HeaderCapacity(d.requestRTT()) } 1050 setIdle = func(p *peerConnection, accepted int) { p.SetHeadersIdle(accepted) } 1051 ) 1052 err := d.fetchParts(errCancelHeaderFetch, d.headerCh, deliver, d.queue.headerContCh, expire, 1053 d.queue.PendingHeaders, d.queue.InFlightHeaders, throttle, reserve, 1054 nil, fetch, d.queue.CancelHeaders, capacity, d.peers.HeaderIdlePeers, setIdle, "headers") 1055 1056 log.Debug("Skeleton fill terminated", "err", err) 1057 1058 filled, proced := d.queue.RetrieveHeaders() 1059 return filled, proced, err 1060 } 1061 1062 // fetchBodies iteratively downloads the scheduled block bodies, taking any 1063 // available peers, reserving a chunk of blocks for each, waiting for delivery 1064 // and also periodically checking for timeouts. 1065 func (d *Downloader) fetchBodies(from uint64) error { 1066 log.Debug("Downloading block bodies", "origin", from) 1067 1068 var ( 1069 deliver = func(packet dataPack) (int, error) { 1070 pack := packet.(*bodyPack) 1071 return d.queue.DeliverBodies(pack.peerID, pack.transactions, pack.uncles) 1072 } 1073 expire = func() map[string]int { return d.queue.ExpireBodies(d.requestTTL()) } 1074 fetch = func(p *peerConnection, req *fetchRequest) error { return p.FetchBodies(req) } 1075 capacity = func(p *peerConnection) int { return p.BlockCapacity(d.requestRTT()) } 1076 setIdle = func(p *peerConnection, accepted int) { p.SetBodiesIdle(accepted) } 1077 ) 1078 err := d.fetchParts(errCancelBodyFetch, d.bodyCh, deliver, d.bodyWakeCh, expire, 1079 d.queue.PendingBlocks, d.queue.InFlightBlocks, d.queue.ShouldThrottleBlocks, d.queue.ReserveBodies, 1080 d.bodyFetchHook, fetch, d.queue.CancelBodies, capacity, d.peers.BodyIdlePeers, setIdle, "bodies") 1081 1082 log.Debug("Block body download terminated", "err", err) 1083 return err 1084 } 1085 1086 // fetchReceipts iteratively downloads the scheduled block receipts, taking any 1087 // available peers, reserving a chunk of receipts for each, waiting for delivery 1088 // and also periodically checking for timeouts. 1089 func (d *Downloader) fetchReceipts(from uint64) error { 1090 log.Debug("Downloading transaction receipts", "origin", from) 1091 1092 var ( 1093 deliver = func(packet dataPack) (int, error) { 1094 pack := packet.(*receiptPack) 1095 return d.queue.DeliverReceipts(pack.peerID, pack.receipts) 1096 } 1097 expire = func() map[string]int { return d.queue.ExpireReceipts(d.requestTTL()) } 1098 fetch = func(p *peerConnection, req *fetchRequest) error { return p.FetchReceipts(req) } 1099 capacity = func(p *peerConnection) int { return p.ReceiptCapacity(d.requestRTT()) } 1100 setIdle = func(p *peerConnection, accepted int) { p.SetReceiptsIdle(accepted) } 1101 ) 1102 err := d.fetchParts(errCancelReceiptFetch, d.receiptCh, deliver, d.receiptWakeCh, expire, 1103 d.queue.PendingReceipts, d.queue.InFlightReceipts, d.queue.ShouldThrottleReceipts, d.queue.ReserveReceipts, 1104 d.receiptFetchHook, fetch, d.queue.CancelReceipts, capacity, d.peers.ReceiptIdlePeers, setIdle, "receipts") 1105 1106 log.Debug("Transaction receipt download terminated", "err", err) 1107 return err 1108 } 1109 1110 // fetchParts iteratively downloads scheduled block parts, taking any available 1111 // peers, reserving a chunk of fetch requests for each, waiting for delivery and 1112 // also periodically checking for timeouts. 1113 // 1114 // As the scheduling/timeout logic mostly is the same for all downloaded data 1115 // types, this method is used by each for data gathering and is instrumented with 1116 // various callbacks to handle the slight differences between processing them. 1117 // 1118 // The instrumentation parameters: 1119 // - errCancel: error type to return if the fetch operation is cancelled (mostly makes logging nicer) 1120 // - deliveryCh: channel from which to retrieve downloaded data packets (merged from all concurrent peers) 1121 // - deliver: processing callback to deliver data packets into type specific download queues (usually within `queue`) 1122 // - wakeCh: notification channel for waking the fetcher when new tasks are available (or sync completed) 1123 // - expire: task callback method to abort requests that took too long and return the faulty peers (traffic shaping) 1124 // - pending: task callback for the number of requests still needing download (detect completion/non-completability) 1125 // - inFlight: task callback for the number of in-progress requests (wait for all active downloads to finish) 1126 // - throttle: task callback to check if the processing queue is full and activate throttling (bound memory use) 1127 // - reserve: task callback to reserve new download tasks to a particular peer (also signals partial completions) 1128 // - fetchHook: tester callback to notify of new tasks being initiated (allows testing the scheduling logic) 1129 // - fetch: network callback to actually send a particular download request to a physical remote peer 1130 // - cancel: task callback to abort an in-flight download request and allow rescheduling it (in case of lost peer) 1131 // - capacity: network callback to retrieve the estimated type-specific bandwidth capacity of a peer (traffic shaping) 1132 // - idle: network callback to retrieve the currently (type specific) idle peers that can be assigned tasks 1133 // - setIdle: network callback to set a peer back to idle and update its estimated capacity (traffic shaping) 1134 // - kind: textual label of the type being downloaded to display in log mesages 1135 func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliver func(dataPack) (int, error), wakeCh chan bool, 1136 expire func() map[string]int, pending func() int, inFlight func() bool, throttle func() bool, reserve func(*peerConnection, int) (*fetchRequest, bool, error), 1137 fetchHook func([]*types.Header), fetch func(*peerConnection, *fetchRequest) error, cancel func(*fetchRequest), capacity func(*peerConnection) int, 1138 idle func() ([]*peerConnection, int), setIdle func(*peerConnection, int), kind string) error { 1139 1140 // Create a ticker to detect expired retrieval tasks 1141 ticker := time.NewTicker(100 * time.Millisecond) 1142 defer ticker.Stop() 1143 1144 update := make(chan struct{}, 1) 1145 1146 // Prepare the queue and fetch block parts until the block header fetcher's done 1147 finished := false 1148 for { 1149 select { 1150 case <-d.cancelCh: 1151 return errCancel 1152 1153 case packet := <-deliveryCh: 1154 // If the peer was previously banned and failed to deliver its pack 1155 // in a reasonable time frame, ignore its message. 1156 if peer := d.peers.Peer(packet.PeerId()); peer != nil { 1157 // Deliver the received chunk of data and check chain validity 1158 accepted, err := deliver(packet) 1159 if err == errInvalidChain { 1160 log.Warn("@Sourav, found ", "err", err) 1161 return err 1162 } 1163 // Unless a peer delivered something completely else than requested (usually 1164 // caused by a timed out request which came through in the end), set it to 1165 // idle. If the delivery's stale, the peer should have already been idled. 1166 if err != errStaleDelivery { 1167 setIdle(peer, accepted) 1168 } 1169 // Issue a log to the user to see what's going on 1170 switch { 1171 case err == nil && packet.Items() == 0: 1172 peer.log.Trace("Requested data not delivered", "type", kind) 1173 case err == nil: 1174 peer.log.Trace("Delivered new batch of data", "type", kind, "count", packet.Stats()) 1175 default: 1176 peer.log.Trace("Failed to deliver retrieved data", "type", kind, "err", err) 1177 } 1178 } 1179 // Blocks assembled, try to update the progress 1180 select { 1181 case update <- struct{}{}: 1182 default: 1183 } 1184 1185 case cont := <-wakeCh: 1186 // The header fetcher sent a continuation flag, check if it's done 1187 if !cont { 1188 finished = true 1189 } 1190 // Headers arrive, try to update the progress 1191 select { 1192 case update <- struct{}{}: 1193 default: 1194 } 1195 1196 case <-ticker.C: 1197 // Sanity check update the progress 1198 select { 1199 case update <- struct{}{}: 1200 default: 1201 } 1202 1203 case <-update: 1204 // Short circuit if we lost all our peers 1205 if d.peers.Len() == 0 { 1206 return errNoPeers 1207 } 1208 // Check for fetch request timeouts and demote the responsible peers 1209 for pid, fails := range expire() { 1210 if peer := d.peers.Peer(pid); peer != nil { 1211 // If a lot of retrieval elements expired, we might have overestimated the remote peer or perhaps 1212 // ourselves. Only reset to minimal throughput but don't drop just yet. If even the minimal times 1213 // out that sync wise we need to get rid of the peer. 1214 // 1215 // The reason the minimum threshold is 2 is because the downloader tries to estimate the bandwidth 1216 // and latency of a peer separately, which requires pushing the measures capacity a bit and seeing 1217 // how response times reacts, to it always requests one more than the minimum (i.e. min 2). 1218 if fails > 2 { 1219 peer.log.Trace("Data delivery timed out", "type", kind) 1220 setIdle(peer, 0) 1221 } else { 1222 peer.log.Debug("Stalling delivery, dropping", "type", kind) 1223 if d.dropPeer == nil { 1224 // The dropPeer method is nil when `--copydb` is used for a local copy. 1225 // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored 1226 peer.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", pid) 1227 } else { 1228 d.dropPeer(pid) 1229 } 1230 } 1231 } 1232 } 1233 // If there's nothing more to fetch, wait or terminate 1234 if pending() == 0 { 1235 if !inFlight() && finished { 1236 log.Debug("Data fetching completed", "type", kind) 1237 return nil 1238 } 1239 break 1240 } 1241 // Send a download request to all idle peers, until throttled 1242 progressed, throttled, running := false, false, inFlight() 1243 idles, total := idle() 1244 1245 for _, peer := range idles { 1246 // Short circuit if throttling activated 1247 if throttle() { 1248 throttled = true 1249 break 1250 } 1251 // Short circuit if there is no more available task. 1252 if pending() == 0 { 1253 break 1254 } 1255 // Reserve a chunk of fetches for a peer. A nil can mean either that 1256 // no more headers are available, or that the peer is known not to 1257 // have them. 1258 request, progress, err := reserve(peer, capacity(peer)) 1259 if err != nil { 1260 return err 1261 } 1262 if progress { 1263 progressed = true 1264 } 1265 if request == nil { 1266 continue 1267 } 1268 if request.From > 0 { 1269 peer.log.Trace("Requesting new batch of data", "type", kind, "from", request.From) 1270 } else { 1271 peer.log.Trace("Requesting new batch of data", "type", kind, "count", len(request.Headers), "from", request.Headers[0].Number) 1272 } 1273 // Fetch the chunk and make sure any errors return the hashes to the queue 1274 if fetchHook != nil { 1275 fetchHook(request.Headers) 1276 } 1277 if err := fetch(peer, request); err != nil { 1278 // Although we could try and make an attempt to fix this, this error really 1279 // means that we've double allocated a fetch task to a peer. If that is the 1280 // case, the internal state of the downloader and the queue is very wrong so 1281 // better hard crash and note the error instead of silently accumulating into 1282 // a much bigger issue. 1283 panic(fmt.Sprintf("%v: %s fetch assignment failed", peer, kind)) 1284 } 1285 running = true 1286 } 1287 // Make sure that we have peers available for fetching. If all peers have been tried 1288 // and all failed throw an error 1289 if !progressed && !throttled && !running && len(idles) == total && pending() > 0 { 1290 return errPeersUnavailable 1291 } 1292 } 1293 } 1294 } 1295 1296 // processHeaders takes batches of retrieved headers from an input channel and 1297 // keeps processing and scheduling them into the header chain and downloader's 1298 // queue until the stream ends or a failure occurs. 1299 func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) error { 1300 // Keep a count of uncertain headers to roll back 1301 rollback := []*types.Header{} 1302 defer func() { 1303 if len(rollback) > 0 { 1304 // Flatten the headers and roll them back 1305 hashes := make([]common.Hash, len(rollback)) 1306 for i, header := range rollback { 1307 hashes[i] = header.Hash() 1308 } 1309 lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0 1310 if d.mode != LightSync { 1311 lastFastBlock = d.blockchain.CurrentFastBlock().Number() 1312 lastBlock = d.blockchain.CurrentBlock().Number() 1313 } 1314 d.lightchain.Rollback(hashes) 1315 curFastBlock, curBlock := common.Big0, common.Big0 1316 if d.mode != LightSync { 1317 curFastBlock = d.blockchain.CurrentFastBlock().Number() 1318 curBlock = d.blockchain.CurrentBlock().Number() 1319 } 1320 log.Warn("Rolled back headers", "count", len(hashes), 1321 "header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number), 1322 "fast", fmt.Sprintf("%d->%d", lastFastBlock, curFastBlock), 1323 "block", fmt.Sprintf("%d->%d", lastBlock, curBlock)) 1324 } 1325 }() 1326 1327 // Wait for batches of headers to process 1328 gotHeaders := false 1329 1330 for { 1331 select { 1332 case <-d.cancelCh: 1333 return errCancelHeaderProcessing 1334 1335 case headers := <-d.headerProcCh: 1336 // Terminate header processing if we synced up 1337 if len(headers) == 0 { 1338 // Notify everyone that headers are fully processed 1339 for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} { 1340 select { 1341 case ch <- false: 1342 case <-d.cancelCh: 1343 } 1344 } 1345 // If no headers were retrieved at all, the peer violated its TD promise that it had a 1346 // better chain compared to ours. The only exception is if its promised blocks were 1347 // already imported by other means (e.g. fetcher): 1348 // 1349 // R <remote peer>, L <local node>: Both at block 10 1350 // R: Mine block 11, and propagate it to L 1351 // L: Queue block 11 for import 1352 // L: Notice that R's head and TD increased compared to ours, start sync 1353 // L: Import of block 11 finishes 1354 // L: Sync begins, and finds common ancestor at 11 1355 // L: Request new headers up from 11 (R's TD was higher, it must have something) 1356 // R: Nothing to give 1357 if d.mode != LightSync { 1358 head := d.blockchain.CurrentBlock() 1359 if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.NumberU64())) > 0 { 1360 return errStallingPeer 1361 } 1362 } 1363 // If fast or light syncing, ensure promised headers are indeed delivered. This is 1364 // needed to detect scenarios where an attacker feeds a bad pivot and then bails out 1365 // of delivering the post-pivot blocks that would flag the invalid content. 1366 // 1367 // This check cannot be executed "as is" for full imports, since blocks may still be 1368 // queued for processing when the header download completes. However, as long as the 1369 // peer gave us something useful, we're already happy/progressed (above check). 1370 if d.mode == FastSync || d.mode == LightSync { 1371 head := d.lightchain.CurrentHeader() 1372 if td.Cmp(d.lightchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 { 1373 return errStallingPeer 1374 } 1375 } 1376 // Disable any rollback and return 1377 rollback = nil 1378 return nil 1379 } 1380 // Otherwise split the chunk of headers into batches and process them 1381 gotHeaders = true 1382 for len(headers) > 0 { 1383 // Terminate if something failed in between processing chunks 1384 select { 1385 case <-d.cancelCh: 1386 return errCancelHeaderProcessing 1387 default: 1388 } 1389 // Select the next chunk of headers to import 1390 limit := maxHeadersProcess 1391 if limit > len(headers) { 1392 limit = len(headers) 1393 } 1394 chunk := headers[:limit] 1395 1396 // In case of header only syncing, validate the chunk immediately 1397 if d.mode == FastSync || d.mode == LightSync { 1398 // Collect the yet unknown headers to mark them as uncertain 1399 unknown := make([]*types.Header, 0, len(headers)) 1400 for _, header := range chunk { 1401 if !d.lightchain.HasHeader(header.Hash(), header.Number.Uint64()) { 1402 unknown = append(unknown, header) 1403 } 1404 } 1405 // If we're importing pure headers, verify based on their recentness 1406 frequency := fsHeaderCheckFrequency 1407 if chunk[len(chunk)-1].Number.Uint64()+uint64(fsHeaderForceVerify) > pivot { 1408 frequency = 1 1409 } 1410 if n, err := d.lightchain.InsertHeaderChain(chunk, frequency); err != nil { 1411 // If some headers were inserted, add them too to the rollback list 1412 if n > 0 { 1413 rollback = append(rollback, chunk[:n]...) 1414 } 1415 log.Debug("Invalid header encountered", "number", chunk[n].Number, "hash", chunk[n].Hash(), "err", err) 1416 return errInvalidChain 1417 } 1418 // All verifications passed, store newly found uncertain headers 1419 rollback = append(rollback, unknown...) 1420 if len(rollback) > fsHeaderSafetyNet { 1421 rollback = append(rollback[:0], rollback[len(rollback)-fsHeaderSafetyNet:]...) 1422 } 1423 } 1424 // Unless we're doing light chains, schedule the headers for associated content retrieval 1425 if d.mode == FullSync || d.mode == FastSync { 1426 // If we've reached the allowed number of pending headers, stall a bit 1427 for d.queue.PendingBlocks() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders { 1428 select { 1429 case <-d.cancelCh: 1430 return errCancelHeaderProcessing 1431 case <-time.After(time.Second): 1432 } 1433 } 1434 // Otherwise insert the headers for content retrieval 1435 inserts := d.queue.Schedule(chunk, origin) 1436 if len(inserts) != len(chunk) { 1437 log.Debug("Stale headers") 1438 return errBadPeer 1439 } 1440 } 1441 headers = headers[limit:] 1442 origin += uint64(limit) 1443 } 1444 // Update the highest block number we know if a higher one is found. 1445 d.syncStatsLock.Lock() 1446 if d.syncStatsChainHeight < origin { 1447 d.syncStatsChainHeight = origin - 1 1448 } 1449 d.syncStatsLock.Unlock() 1450 1451 // Signal the content downloaders of the availablility of new tasks 1452 for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} { 1453 select { 1454 case ch <- true: 1455 default: 1456 } 1457 } 1458 } 1459 } 1460 } 1461 1462 // processFullSyncContent takes fetch results from the queue and imports them into the chain. 1463 func (d *Downloader) processFullSyncContent() error { 1464 for { 1465 results := d.queue.Results(true) 1466 if len(results) == 0 { 1467 return nil 1468 } 1469 if d.chainInsertHook != nil { 1470 d.chainInsertHook(results) 1471 } 1472 if err := d.importBlockResults(results); err != nil { 1473 return err 1474 } 1475 } 1476 } 1477 1478 func (d *Downloader) importBlockResults(results []*fetchResult) error { 1479 // Check for any early termination requests 1480 if len(results) == 0 { 1481 return nil 1482 } 1483 select { 1484 case <-d.quitCh: 1485 return errCancelContentProcessing 1486 default: 1487 } 1488 // Retrieve the a batch of results to import 1489 first, last := results[0].Header, results[len(results)-1].Header 1490 log.Debug("Inserting downloaded chain", "items", len(results), 1491 "firstnum", first.Number, "firsthash", first.Hash(), 1492 "lastnum", last.Number, "lasthash", last.Hash(), 1493 ) 1494 blocks := make([]*types.Block, len(results)) 1495 for i, result := range results { 1496 blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles) 1497 } 1498 if index, err := d.blockchain.InsertChain(blocks); err != nil { 1499 if index < len(results) { 1500 log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err) 1501 } else { 1502 // The InsertChain method in blockchain.go will sometimes return an out-of-bounds index, 1503 // when it needs to preprocess blocks to import a sidechain. 1504 // The importer will put together a new list of blocks to import, which is a superset 1505 // of the blocks delivered from the downloader, and the indexing will be off. 1506 log.Debug("Downloaded item processing failed on sidechain import", "index", index, "err", err) 1507 } 1508 return errInvalidChain 1509 } 1510 return nil 1511 } 1512 1513 // processFastSyncContent takes fetch results from the queue and writes them to the 1514 // database. It also controls the synchronisation of state nodes of the pivot block. 1515 func (d *Downloader) processFastSyncContent(latest *types.Header) error { 1516 // Start syncing state of the reported head block. This should get us most of 1517 // the state of the pivot block. 1518 stateSync := d.syncState(latest.Root) 1519 defer stateSync.Cancel() 1520 go func() { 1521 if err := stateSync.Wait(); err != nil && err != errCancelStateFetch { 1522 d.queue.Close() // wake up Results 1523 } 1524 }() 1525 // Figure out the ideal pivot block. Note, that this goalpost may move if the 1526 // sync takes long enough for the chain head to move significantly. 1527 pivot := uint64(0) 1528 if height := latest.Number.Uint64(); height > uint64(fsMinFullBlocks) { 1529 pivot = height - uint64(fsMinFullBlocks) 1530 } 1531 // To cater for moving pivot points, track the pivot block and subsequently 1532 // accumulated download results separately. 1533 var ( 1534 oldPivot *fetchResult // Locked in pivot block, might change eventually 1535 oldTail []*fetchResult // Downloaded content after the pivot 1536 ) 1537 for { 1538 // Wait for the next batch of downloaded data to be available, and if the pivot 1539 // block became stale, move the goalpost 1540 results := d.queue.Results(oldPivot == nil) // Block if we're not monitoring pivot staleness 1541 if len(results) == 0 { 1542 // If pivot sync is done, stop 1543 if oldPivot == nil { 1544 return stateSync.Cancel() 1545 } 1546 // If sync failed, stop 1547 select { 1548 case <-d.cancelCh: 1549 return stateSync.Cancel() 1550 default: 1551 } 1552 } 1553 if d.chainInsertHook != nil { 1554 d.chainInsertHook(results) 1555 } 1556 if oldPivot != nil { 1557 results = append(append([]*fetchResult{oldPivot}, oldTail...), results...) 1558 } 1559 // Split around the pivot block and process the two sides via fast/full sync 1560 if atomic.LoadInt32(&d.committed) == 0 { 1561 latest = results[len(results)-1].Header 1562 if height := latest.Number.Uint64(); height > pivot+2*uint64(fsMinFullBlocks) { 1563 log.Warn("Pivot became stale, moving", "old", pivot, "new", height-uint64(fsMinFullBlocks)) 1564 pivot = height - uint64(fsMinFullBlocks) 1565 } 1566 } 1567 P, beforeP, afterP := splitAroundPivot(pivot, results) 1568 if err := d.commitFastSyncData(beforeP, stateSync); err != nil { 1569 return err 1570 } 1571 if P != nil { 1572 // If new pivot block found, cancel old state retrieval and restart 1573 if oldPivot != P { 1574 stateSync.Cancel() 1575 1576 stateSync = d.syncState(P.Header.Root) 1577 defer stateSync.Cancel() 1578 go func() { 1579 if err := stateSync.Wait(); err != nil && err != errCancelStateFetch { 1580 d.queue.Close() // wake up Results 1581 } 1582 }() 1583 oldPivot = P 1584 } 1585 // Wait for completion, occasionally checking for pivot staleness 1586 select { 1587 case <-stateSync.done: 1588 if stateSync.err != nil { 1589 return stateSync.err 1590 } 1591 if err := d.commitPivotBlock(P); err != nil { 1592 return err 1593 } 1594 oldPivot = nil 1595 1596 case <-time.After(time.Second): 1597 oldTail = afterP 1598 continue 1599 } 1600 } 1601 // Fast sync done, pivot commit done, full import 1602 if err := d.importBlockResults(afterP); err != nil { 1603 return err 1604 } 1605 } 1606 } 1607 1608 func splitAroundPivot(pivot uint64, results []*fetchResult) (p *fetchResult, before, after []*fetchResult) { 1609 for _, result := range results { 1610 num := result.Header.Number.Uint64() 1611 switch { 1612 case num < pivot: 1613 before = append(before, result) 1614 case num == pivot: 1615 p = result 1616 default: 1617 after = append(after, result) 1618 } 1619 } 1620 return p, before, after 1621 } 1622 1623 func (d *Downloader) commitFastSyncData(results []*fetchResult, stateSync *stateSync) error { 1624 // Check for any early termination requests 1625 if len(results) == 0 { 1626 return nil 1627 } 1628 select { 1629 case <-d.quitCh: 1630 return errCancelContentProcessing 1631 case <-stateSync.done: 1632 if err := stateSync.Wait(); err != nil { 1633 return err 1634 } 1635 default: 1636 } 1637 // Retrieve the a batch of results to import 1638 first, last := results[0].Header, results[len(results)-1].Header 1639 log.Debug("Inserting fast-sync blocks", "items", len(results), 1640 "firstnum", first.Number, "firsthash", first.Hash(), 1641 "lastnumn", last.Number, "lasthash", last.Hash(), 1642 ) 1643 blocks := make([]*types.Block, len(results)) 1644 receipts := make([]types.Receipts, len(results)) 1645 for i, result := range results { 1646 blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles) 1647 receipts[i] = result.Receipts 1648 } 1649 if index, err := d.blockchain.InsertReceiptChain(blocks, receipts); err != nil { 1650 log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err) 1651 return errInvalidChain 1652 } 1653 return nil 1654 } 1655 1656 func (d *Downloader) commitPivotBlock(result *fetchResult) error { 1657 block := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles) 1658 log.Debug("Committing fast sync pivot as new head", "number", block.Number(), "hash", block.Hash()) 1659 if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{result.Receipts}); err != nil { 1660 return err 1661 } 1662 if err := d.blockchain.FastSyncCommitHead(block.Hash()); err != nil { 1663 return err 1664 } 1665 atomic.StoreInt32(&d.committed, 1) 1666 return nil 1667 } 1668 1669 // DeliverHeaders injects a new batch of block headers received from a remote 1670 // node into the download schedule. 1671 func (d *Downloader) DeliverHeaders(id string, headers []*types.Header) (err error) { 1672 return d.deliver(id, d.headerCh, &headerPack{id, headers}, headerInMeter, headerDropMeter) 1673 } 1674 1675 // DeliverBodies injects a new batch of block bodies received from a remote node. 1676 func (d *Downloader) DeliverBodies(id string, transactions [][]*types.Transaction, uncles [][]*types.Header) (err error) { 1677 return d.deliver(id, d.bodyCh, &bodyPack{id, transactions, uncles}, bodyInMeter, bodyDropMeter) 1678 } 1679 1680 // DeliverReceipts injects a new batch of receipts received from a remote node. 1681 func (d *Downloader) DeliverReceipts(id string, receipts [][]*types.Receipt) (err error) { 1682 return d.deliver(id, d.receiptCh, &receiptPack{id, receipts}, receiptInMeter, receiptDropMeter) 1683 } 1684 1685 // DeliverNodeData injects a new batch of node state data received from a remote node. 1686 func (d *Downloader) DeliverNodeData(id string, data [][]byte) (err error) { 1687 return d.deliver(id, d.stateCh, &statePack{id, data}, stateInMeter, stateDropMeter) 1688 } 1689 1690 // deliver injects a new batch of data received from a remote node. 1691 func (d *Downloader) deliver(id string, destCh chan dataPack, packet dataPack, inMeter, dropMeter metrics.Meter) (err error) { 1692 // Update the delivery metrics for both good and failed deliveries 1693 inMeter.Mark(int64(packet.Items())) 1694 defer func() { 1695 if err != nil { 1696 dropMeter.Mark(int64(packet.Items())) 1697 } 1698 }() 1699 // Deliver or abort if the sync is canceled while queuing 1700 d.cancelLock.RLock() 1701 cancel := d.cancelCh 1702 d.cancelLock.RUnlock() 1703 if cancel == nil { 1704 return errNoSyncActive 1705 } 1706 select { 1707 case destCh <- packet: 1708 return nil 1709 case <-cancel: 1710 return errNoSyncActive 1711 } 1712 } 1713 1714 // qosTuner is the quality of service tuning loop that occasionally gathers the 1715 // peer latency statistics and updates the estimated request round trip time. 1716 func (d *Downloader) qosTuner() { 1717 for { 1718 // Retrieve the current median RTT and integrate into the previoust target RTT 1719 rtt := time.Duration((1-qosTuningImpact)*float64(atomic.LoadUint64(&d.rttEstimate)) + qosTuningImpact*float64(d.peers.medianRTT())) 1720 atomic.StoreUint64(&d.rttEstimate, uint64(rtt)) 1721 1722 // A new RTT cycle passed, increase our confidence in the estimated RTT 1723 conf := atomic.LoadUint64(&d.rttConfidence) 1724 conf = conf + (1000000-conf)/2 1725 atomic.StoreUint64(&d.rttConfidence, conf) 1726 1727 // Log the new QoS values and sleep until the next RTT 1728 log.Debug("Recalculated downloader QoS values", "rtt", rtt, "confidence", float64(conf)/1000000.0, "ttl", d.requestTTL()) 1729 select { 1730 case <-d.quitCh: 1731 return 1732 case <-time.After(rtt): 1733 } 1734 } 1735 } 1736 1737 // qosReduceConfidence is meant to be called when a new peer joins the downloader's 1738 // peer set, needing to reduce the confidence we have in out QoS estimates. 1739 func (d *Downloader) qosReduceConfidence() { 1740 // If we have a single peer, confidence is always 1 1741 peers := uint64(d.peers.Len()) 1742 if peers == 0 { 1743 // Ensure peer connectivity races don't catch us off guard 1744 return 1745 } 1746 if peers == 1 { 1747 atomic.StoreUint64(&d.rttConfidence, 1000000) 1748 return 1749 } 1750 // If we have a ton of peers, don't drop confidence) 1751 if peers >= uint64(qosConfidenceCap) { 1752 return 1753 } 1754 // Otherwise drop the confidence factor 1755 conf := atomic.LoadUint64(&d.rttConfidence) * (peers - 1) / peers 1756 if float64(conf)/1000000 < rttMinConfidence { 1757 conf = uint64(rttMinConfidence * 1000000) 1758 } 1759 atomic.StoreUint64(&d.rttConfidence, conf) 1760 1761 rtt := time.Duration(atomic.LoadUint64(&d.rttEstimate)) 1762 log.Debug("Relaxed downloader QoS values", "rtt", rtt, "confidence", float64(conf)/1000000.0, "ttl", d.requestTTL()) 1763 } 1764 1765 // requestRTT returns the current target round trip time for a download request 1766 // to complete in. 1767 // 1768 // Note, the returned RTT is .9 of the actually estimated RTT. The reason is that 1769 // the downloader tries to adapt queries to the RTT, so multiple RTT values can 1770 // be adapted to, but smaller ones are preferred (stabler download stream). 1771 func (d *Downloader) requestRTT() time.Duration { 1772 return time.Duration(atomic.LoadUint64(&d.rttEstimate)) * 9 / 10 1773 } 1774 1775 // requestTTL returns the current timeout allowance for a single download request 1776 // to finish under. 1777 func (d *Downloader) requestTTL() time.Duration { 1778 var ( 1779 rtt = time.Duration(atomic.LoadUint64(&d.rttEstimate)) 1780 conf = float64(atomic.LoadUint64(&d.rttConfidence)) / 1000000.0 1781 ) 1782 ttl := time.Duration(ttlScaling) * time.Duration(float64(rtt)/conf) 1783 if ttl > ttlLimit { 1784 ttl = ttlLimit 1785 } 1786 return ttl 1787 }