eth/downloader: avoid node data with zero length

1.sending nodedata with zero length may cause the requesting peer retrieve
this GetNodeDataMsg again and again, and can block block synchronise.
Warn this case in log for attention
2.to handle this case at client peer just avoid deliver such node data

Depends-On: N/A
This commit is contained in:
pip.zhang 2020-01-13 16:38:14 +08:00
parent c2d65d34d5
commit 87a2c3600b
2 changed files with 16 additions and 0 deletions

View file

@ -150,6 +150,7 @@ func (d *Downloader) runStateSync(s *stateSync) *stateSync {
req.timer.Stop()
req.response = pack.(*statePack).states
log.Debug("Received node data", "len", len(req.response))
finished = append(finished, req)
delete(active, pack.PeerId())

View file

@ -601,6 +601,12 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
bytes += len(entry)
}
}
log.Debug("Sending node data", "len", len(data))
if len(data) == 0 {
// in this case, sending node data with len=0 may cause the requesting peer retrieve this GetNodeDataMsg
// again and again, and can block block synchronise.
log.Warn("Sending node data is invalid", "len", len(data))
}
return p.SendNodeData(data)
case p.version >= eth63 && msg.Code == NodeDataMsg:
@ -609,6 +615,15 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
if err := msg.Decode(&data); err != nil {
return errResp(ErrDecode, "msg %v: %v", msg, err)
}
// to make peer compatible with old peer sending zero node data, just avoid deliver this node data.
// Why:
// deliver zero node data will cause statesync failing before other fetchers which interrupts all other
// fetchers, then all fetchers including statesync fetcher will run again and again until blocks from other
// peers were inserted
if len(data) == 0 {
log.Warn("No need to deliver zero len data")
return nil
}
// Deliver all to the downloader
if err := pm.downloader.DeliverNodeData(p.id, data); err != nil {
log.Debug("Failed to deliver node state data", "err", err)