diff --git a/eth/handler.go b/eth/handler.go index eeb6a4f143..f3fe5dfe35 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -252,33 +252,31 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { } case GetBlocksMsg: - var blocks []*types.Block - + // Decode the retrieval message msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) if _, err := msgStream.List(); err != nil { return err } + // Gather blocks until the fetch or network limits is reached var ( - i int - totalsize common.StorageSize + hash common.Hash + bytes common.StorageSize + blocks []*types.Block ) for { - i++ - var hash common.Hash err := msgStream.Decode(&hash) if err == rlp.EOL { break } else if err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } - - block := pm.chainman.GetBlock(hash) - if block != nil { + // Retrieve the requested block, stopping if enough was found + if block := pm.chainman.GetBlock(hash); block != nil { blocks = append(blocks, block) - totalsize += block.Size() - } - if i == downloader.MaxBlockFetch || totalsize > maxBlockRespSize { - break + bytes += block.Size() + if len(blocks) >= downloader.MaxBlockFetch || bytes > maxBlockRespSize { + break + } } } return p.sendBlocks(blocks) @@ -360,8 +358,10 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { // BroadcastBlock will propagate the block to a subset of its connected peers, // only notifying the rest of the block's appearance. func (pm *ProtocolManager) BroadcastBlock(block *types.Block) { + hash := block.Hash() + // Retrieve all the target peers and split between full broadcast or only notification - peers := pm.peers.PeersWithoutBlock(block.Hash()) + peers := pm.peers.PeersWithoutBlock(hash) split := int(math.Sqrt(float64(len(peers)))) transfer := peers[:split] @@ -369,14 +369,14 @@ func (pm *ProtocolManager) BroadcastBlock(block *types.Block) { // Send out the data transfers and the notifications for _, peer := range notify { - peer.sendNewBlockHashes([]common.Hash{block.Hash()}) + peer.sendNewBlockHashes([]common.Hash{hash}) } - glog.V(logger.Detail).Infoln("broadcast hash to", len(notify), "peers.") + glog.V(logger.Detail).Infof("broadcast hash %x to %d peers.", hash[:4], len(notify)) for _, peer := range transfer { peer.sendNewBlock(block) } - glog.V(logger.Detail).Infoln("broadcast block to", len(transfer), "peers. Total processing time:", time.Since(block.ReceivedAt)) + glog.V(logger.Detail).Infof("broadcast block %x to %d peers. Total processing time: %v", hash[:4], len(transfer), time.Since(block.ReceivedAt)) } // BroadcastTx will propagate the block to its connected peers. It will sort