diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -885,6 +885,9 @@ /** Return true if the headers connect to each other, false otherwise */ bool CheckHeadersAreContinuous(const std::vector &headers) const; + /** Request further headers from this peer from a given block header */ + void FetchMoreHeaders(CNode &pfrom, const CBlockIndex *pindexLast, + const Peer &peer) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); void SendBlockTransactions(CNode &pfrom, Peer &peer, const CBlock &block, const BlockTransactionsRequest &req); @@ -3245,6 +3248,31 @@ return true; } +/** + * Continue fetching headers from a given point. + * pindexLast should be the last header we learned from a peer in their prior + * headers message. + * + * This is used for headers sync with a peer; even if pindexLast is an ancestor + * of a known chain (such as our tip) we don't yet know where the peer's chain + * might fork from what we know, so we continue exactly from where the peer + * left off. + */ +void PeerManagerImpl::FetchMoreHeaders(CNode &pfrom, + const CBlockIndex *pindexLast, + const Peer &peer) { + AssertLockHeld(::cs_main); + const CNetMsgMaker msgMaker(pfrom.GetCommonVersion()); + + LogPrint(BCLog::NET, + "more getheaders (%d) to end to peer=%d (startheight:%d)\n", + pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height); + m_connman.PushMessage( + &pfrom, msgMaker.Make(NetMsgType::GETHEADERS, + m_chainman.ActiveChain().GetLocator(pindexLast), + uint256())); +} + void PeerManagerImpl::ProcessHeadersMessage( const Config &config, CNode &pfrom, Peer &peer, const std::vector &headers, bool via_compact_block) { @@ -3304,6 +3332,14 @@ { LOCK(cs_main); + + // Consider fetching more headers. + if (nCount == MAX_HEADERS_RESULTS) { + // Headers message had its maximum size; the peer may have more + // headers. + FetchMoreHeaders(pfrom, pindexLast, peer); + } + CNodeState *nodestate = State(pfrom.GetId()); if (nodestate->nUnconnectingHeaders > 0) { LogPrint(BCLog::NET, @@ -3325,23 +3361,6 @@ nodestate->m_last_block_announcement = GetTime(); } - if (nCount == MAX_HEADERS_RESULTS) { - // Headers message had its maximum size; the peer may have more - // headers. - // TODO: optimize: if pindexLast is an ancestor of - // m_chainman.ActiveChain().Tip or m_chainman.m_best_header, - // continue from there instead. - LogPrint( - BCLog::NET, - "more getheaders (%d) to end to peer=%d (startheight:%d)\n", - pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height); - m_connman.PushMessage( - &pfrom, - msgMaker.Make(NetMsgType::GETHEADERS, - m_chainman.ActiveChain().GetLocator(pindexLast), - uint256())); - } - // If this set of headers is valid and ends in a block with at least as // much work as our tip, download as much as possible. if (CanDirectFetch() && pindexLast->IsValid(BlockValidity::TREE) &&