Loop is the main fetcher loop, checking and processing various notification events.
()
| 276 | // Loop is the main fetcher loop, checking and processing various notification |
| 277 | // events. |
| 278 | func (f *Fetcher) loop() { |
| 279 | // Iterate the block fetching until a quit is requested |
| 280 | fetchTimer := time.NewTimer(0) |
| 281 | completeTimer := time.NewTimer(0) |
| 282 | |
| 283 | for { |
| 284 | // if the fetching of a block takes too long, we stop it. |
| 285 | for hash, announce := range f.fetching { |
| 286 | if time.Since(announce.time) > fetchTimeout { |
| 287 | f.forgetHash(hash) |
| 288 | } |
| 289 | } |
| 290 | // import queued blocks (that are fetched) |
| 291 | height := f.chainHeight() |
| 292 | for !f.queue.Empty() { |
| 293 | op := f.queue.PopItem().(*inject) |
| 294 | hash := op.block.Hash() |
| 295 | if f.queueChangeHook != nil { |
| 296 | f.queueChangeHook(hash, false) |
| 297 | } |
| 298 | // If too high up the chain or phase, continue later |
| 299 | number := op.block.NumberU64() |
| 300 | if number > height+1 { |
| 301 | f.queue.Push(op, -float32(number)) |
| 302 | if f.queueChangeHook != nil { |
| 303 | f.queueChangeHook(hash, true) |
| 304 | } |
| 305 | break |
| 306 | } |
| 307 | // Otherwise if fresh and still unknown, try and import |
| 308 | if number+maxUncleDist < height || f.getBlock(hash) != nil { |
| 309 | f.forgetBlock(hash) |
| 310 | continue |
| 311 | } |
| 312 | // announced remote blocks are finally inserted |
| 313 | f.insert(op.origin, op.block) |
| 314 | } |
| 315 | |
| 316 | // Wait for an outside event to occur |
| 317 | select { |
| 318 | case <-f.quit: |
| 319 | // Fetcher terminating, abort all operations |
| 320 | return |
| 321 | |
| 322 | case notification := <-f.notify: |
| 323 | // A block was announced, make sure the peer isn't DOSing us |
| 324 | propAnnounceInMeter.Mark(1) |
| 325 | |
| 326 | count := f.announces[notification.origin] + 1 |
| 327 | if count > hashLimit { |
| 328 | log.Debug("Peer exceeded outstanding announces", "peer", notification.origin, "limit", hashLimit) |
| 329 | propAnnounceDOSMeter.Mark(1) |
| 330 | break |
| 331 | } |
| 332 | // If we have a valid block number, check that it's potentially useful |
| 333 | if notification.number > 0 { |
| 334 | if dist := int64(notification.number) - int64(f.chainHeight()); dist < -maxUncleDist || dist > maxQueueDist { |
| 335 | log.Debug("Peer discarded announcement", "peer", notification.origin, "number", notification.number, "hash", notification.hash.Hex(), "distance", dist) |
no test coverage detected