Fetch runs in a loop, fetching blocks from the configured peer (e.g. the generator) and applying them to the local Chain. It returns when its context is canceled. After each attempt to fetch and apply a block, it calls health to report either an error or nil to indicate success.
(ctx context.Context, c *protocol.Chain, peer *rpc.Client, health func(error))
| 47 | // After each attempt to fetch and apply a block, it calls health |
| 48 | // to report either an error or nil to indicate success. |
| 49 | func Fetch(ctx context.Context, c *protocol.Chain, peer *rpc.Client, health func(error)) { |
| 50 | blockch, errch := DownloadBlocks(ctx, peer, c.Height()+1) |
| 51 | |
| 52 | var err error |
| 53 | var nfailures uint |
| 54 | for { |
| 55 | select { |
| 56 | case <-ctx.Done(): |
| 57 | log.Printf(ctx, "Deposed, Fetch exiting") |
| 58 | return |
| 59 | case err = <-errch: |
| 60 | health(err) |
| 61 | logNetworkError(ctx, err) |
| 62 | case b := <-blockch: |
| 63 | prevBlock, prevSnapshot := c.State() |
| 64 | for { |
| 65 | err = applyBlock(ctx, c, prevSnapshot, prevBlock, b) |
| 66 | if err == protocol.ErrBadBlock { |
| 67 | log.Fatalkv(ctx, log.KeyError, err) |
| 68 | } else if err != nil { |
| 69 | // This is a serious I/O error. |
| 70 | health(err) |
| 71 | log.Error(ctx, err) |
| 72 | nfailures++ |
| 73 | |
| 74 | time.Sleep(backoffDur(nfailures)) |
| 75 | continue |
| 76 | } |
| 77 | break |
| 78 | } |
| 79 | |
| 80 | health(nil) |
| 81 | nfailures = 0 |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | // DownloadBlocks starts a goroutine to download blocks from |
| 87 | // the given peer, starting at the given height and incrementing from there. |
nothing calls this directly
no test coverage detected