From 5fb1ef702694597eb049ee242e135751d36b7733 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 26 Jul 2017 17:05:59 +0800 Subject: [PATCH] Problem: headers is changed in FilterHeaders, so the if statement is not necessarily always true See https://github.com/ethereum/go-ethereum/pull/14848 for an explanation of why the line `len(headers) > 0 || !filter` is added back. I still don't think we should check total difficulty of the peer with the fork header like ETH does. It might break light clients that only keep the last 256 blocks and does not prevent network attacks. See #313 for an explanation. --- eth/handler.go | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/eth/handler.go b/eth/handler.go index 8a5887be4..14462922f 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -404,15 +404,24 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { if err := msg.Decode(&headers); err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } + // Good will assumption. Even if the peer is ahead of the fork check header but returns + // empty header response, it might be that the peer is a light client which only keeps + // the last 256 block headers. Besides it does not prevent network attacks. See #313 for + // an explaination. + if len(headers) == 0 && p.timeout != nil { + // Disable the fork drop timeout + p.timeout.Stop() + p.timeout = nil + return nil + } // Filter out any explicitly requested headers, deliver the rest to the downloader - if len(headers) == 0 || len(headers) == 1 { + filter := len(headers) == 1 + if filter { if p.timeout != nil { // Disable the fork drop timeout p.timeout.Stop() p.timeout = nil } - } - if len(headers) == 1 { if err := pm.chainConfig.HeaderCheck(headers[0]); err != nil { pm.removePeer(p.id) return err @@ -420,9 +429,11 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { // Irrelevant of the fork checks, send the header to the fetcher just in case headers = pm.fetcher.FilterHeaders(headers, time.Now()) } - err := pm.downloader.DeliverHeaders(p.id, headers) - if err != nil { - glog.V(logger.Debug).Infoln(err) + if len(headers) > 0 || !filter { + err := pm.downloader.DeliverHeaders(p.id, headers) + if err != nil { + glog.V(logger.Debug).Infoln(err) + } } case p.version >= eth62 && msg.Code == GetBlockBodiesMsg: