(ctx context.Context, h uint32)
| 82 | } |
| 83 | |
| 84 | func (c *Chain) blockingFetchBlock(ctx context.Context, h uint32) (unreachable uint32) { |
| 85 | var ( |
| 86 | cld, ccl = context.WithTimeout(ctx, c.tick) |
| 87 | wg = &sync.WaitGroup{} |
| 88 | ) |
| 89 | defer func() { |
| 90 | wg.Wait() |
| 91 | ccl() |
| 92 | }() |
| 93 | for _, info := range c.getRemoteBPInfos() { |
| 94 | wg.Add(1) |
| 95 | go func(remote *blockProducerInfo) { |
| 96 | defer wg.Done() |
| 97 | var ( |
| 98 | err error |
| 99 | req = &types.FetchBlockReq{ |
| 100 | Envelope: proto.Envelope{ |
| 101 | // TODO(lambda): Add fields. |
| 102 | }, |
| 103 | Height: h, |
| 104 | } |
| 105 | resp = &types.FetchBlockResp{} |
| 106 | ) |
| 107 | var le = log.WithFields(log.Fields{ |
| 108 | "local": c.getLocalBPInfo(), |
| 109 | "remote": remote, |
| 110 | "height": h, |
| 111 | }) |
| 112 | if err = c.caller.CallNodeWithContext( |
| 113 | cld, remote.nodeID, route.MCCFetchBlock.String(), req, resp, |
| 114 | ); err != nil { |
| 115 | le.WithError(err).Warn("failed to fetch block") |
| 116 | atomic.AddUint32(&unreachable, 1) |
| 117 | return |
| 118 | } |
| 119 | if resp.Block == nil { |
| 120 | le.Debug("fetch block request reply: no such block") |
| 121 | return |
| 122 | } |
| 123 | // Push new block from other peers |
| 124 | le.WithFields(log.Fields{ |
| 125 | "parent": resp.Block.ParentHash().Short(4), |
| 126 | "hash": resp.Block.BlockHash().Short(4), |
| 127 | }).Debug("fetch block request reply: found block") |
| 128 | select { |
| 129 | case c.pendingBlocks <- resp.Block: |
| 130 | case <-cld.Done(): |
| 131 | log.WithError(cld.Err()).Warn("add pending block aborted") |
| 132 | } |
| 133 | }(info) |
| 134 | } |
| 135 | return |
| 136 | } |
no test coverage detected