diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3022,6 +3022,7 @@ LOCK(cs_main); const auto current_time = GetTime(); + std::optional best_block; for (CInv &inv : vInv) { if (interruptMsgProc) { @@ -3033,25 +3034,16 @@ fAlreadyHave ? "have" : "new", pfrom.GetId()); if (inv.type == MSG_BLOCK) { - const BlockHash hash(inv.hash); + const BlockHash hash{inv.hash}; UpdateBlockAvailability(pfrom.GetId(), hash); if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(hash)) { - // We used to request the full block here, but since - // headers-announcements are now the primary method of - // announcement on the network, and since, in the case that - // a node fell back to inv we probably have a reorg which we - // should get the headers for first, we now only provide a - // getheaders response here. When we receive the headers, we - // will then ask for the blocks we need. - m_connman.PushMessage( - &pfrom, msgMaker.Make(NetMsgType::GETHEADERS, - ::ChainActive().GetLocator( - pindexBestHeader), - hash)); - LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", - pindexBestHeader->nHeight, hash.ToString(), - pfrom.GetId()); + // Headers-first is the primary method of announcement on + // the network. If a node fell back to sending blocks by + // inv, it's probably for a re-org. The final block hash + // provided should be the highest, so send a getheaders and + // then fetch the blocks we need to catch up. + best_block = std::move(hash); } } else { const TxId txid(inv.hash); @@ -3069,6 +3061,18 @@ } } } + + if (best_block) { + m_connman.PushMessage( + &pfrom, + msgMaker.Make(NetMsgType::GETHEADERS, + ::ChainActive().GetLocator(pindexBestHeader), + *best_block)); + LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", + pindexBestHeader->nHeight, best_block->ToString(), + pfrom.GetId()); + } + return; }