Skip to content

Commit 29c4518

Browse files
committed
Move headers-direct-fetch logic into own function
1 parent bf8ea6d commit 29c4518

File tree

1 file changed

+72
-54
lines changed

1 file changed

+72
-54
lines changed

src/net_processing.cpp

Lines changed: 72 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,8 @@ class PeerManagerImpl final : public PeerManager
569569
bool CheckHeadersAreContinuous(const std::vector<CBlockHeader>& headers) const;
570570
/** Request further headers from this peer from a given block header */
571571
void FetchMoreHeaders(CNode& pfrom, const CBlockIndex *pindexLast, const Peer& peer);
572+
/** Potentially fetch blocks from this peer upon receipt of new headers tip */
573+
void HeadersDirectFetchBlocks(CNode& pfrom, const CBlockIndex* pindexLast);
572574

573575
void SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req);
574576

@@ -2276,6 +2278,73 @@ void PeerManagerImpl::FetchMoreHeaders(CNode& pfrom, const CBlockIndex *pindexLa
22762278
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexLast), uint256()));
22772279
}
22782280

2281+
/*
2282+
* Given a new headers tip ending in pindexLast, potentially request blocks towards that tip.
2283+
* We require that the given tip have at least as much work as our tip, and for
2284+
* our current tip to be "close to synced" (see CanDirectFetch()).
2285+
*/
2286+
void PeerManagerImpl::HeadersDirectFetchBlocks(CNode& pfrom, const CBlockIndex* pindexLast)
2287+
{
2288+
const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
2289+
2290+
LOCK(cs_main);
2291+
CNodeState *nodestate = State(pfrom.GetId());
2292+
2293+
if (CanDirectFetch() && pindexLast->IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= pindexLast->nChainWork) {
2294+
2295+
std::vector<const CBlockIndex*> vToFetch;
2296+
const CBlockIndex *pindexWalk = pindexLast;
2297+
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
2298+
while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
2299+
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
2300+
!IsBlockRequested(pindexWalk->GetBlockHash()) &&
2301+
(!DeploymentActiveAt(*pindexWalk, m_chainman, Consensus::DEPLOYMENT_SEGWIT) || State(pfrom.GetId())->fHaveWitness)) {
2302+
// We don't have this block, and it's not yet in flight.
2303+
vToFetch.push_back(pindexWalk);
2304+
}
2305+
pindexWalk = pindexWalk->pprev;
2306+
}
2307+
// If pindexWalk still isn't on our main chain, we're looking at a
2308+
// very large reorg at a time we think we're close to caught up to
2309+
// the main chain -- this shouldn't really happen. Bail out on the
2310+
// direct fetch and rely on parallel download instead.
2311+
if (!m_chainman.ActiveChain().Contains(pindexWalk)) {
2312+
LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
2313+
pindexLast->GetBlockHash().ToString(),
2314+
pindexLast->nHeight);
2315+
} else {
2316+
std::vector<CInv> vGetData;
2317+
// Download as much as possible, from earliest to latest.
2318+
for (const CBlockIndex *pindex : reverse_iterate(vToFetch)) {
2319+
if (nodestate->nBlocksInFlight >= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
2320+
// Can't download any more from this peer
2321+
break;
2322+
}
2323+
uint32_t nFetchFlags = GetFetchFlags(pfrom);
2324+
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
2325+
BlockRequested(pfrom.GetId(), *pindex);
2326+
LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
2327+
pindex->GetBlockHash().ToString(), pfrom.GetId());
2328+
}
2329+
if (vGetData.size() > 1) {
2330+
LogPrint(BCLog::NET, "Downloading blocks toward %s (%d) via headers direct fetch\n",
2331+
pindexLast->GetBlockHash().ToString(), pindexLast->nHeight);
2332+
}
2333+
if (vGetData.size() > 0) {
2334+
if (!m_ignore_incoming_txs &&
2335+
nodestate->m_provides_cmpctblocks &&
2336+
vGetData.size() == 1 &&
2337+
mapBlocksInFlight.size() == 1 &&
2338+
pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN)) {
2339+
// In any case, we want to download using a compact block, not a regular one
2340+
vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash);
2341+
}
2342+
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData));
2343+
}
2344+
}
2345+
}
2346+
}
2347+
22792348
void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
22802349
const std::vector<CBlockHeader>& headers,
22812350
bool via_compact_block)
@@ -2355,60 +2424,9 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
23552424
nodestate->m_last_block_announcement = GetTime();
23562425
}
23572426

2358-
// If this set of headers is valid and ends in a block with at least as
2359-
// much work as our tip, download as much as possible.
2360-
if (CanDirectFetch() && pindexLast->IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= pindexLast->nChainWork) {
2361-
std::vector<const CBlockIndex*> vToFetch;
2362-
const CBlockIndex *pindexWalk = pindexLast;
2363-
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
2364-
while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
2365-
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
2366-
!IsBlockRequested(pindexWalk->GetBlockHash()) &&
2367-
(!DeploymentActiveAt(*pindexWalk, m_chainman, Consensus::DEPLOYMENT_SEGWIT) || State(pfrom.GetId())->fHaveWitness)) {
2368-
// We don't have this block, and it's not yet in flight.
2369-
vToFetch.push_back(pindexWalk);
2370-
}
2371-
pindexWalk = pindexWalk->pprev;
2372-
}
2373-
// If pindexWalk still isn't on our main chain, we're looking at a
2374-
// very large reorg at a time we think we're close to caught up to
2375-
// the main chain -- this shouldn't really happen. Bail out on the
2376-
// direct fetch and rely on parallel download instead.
2377-
if (!m_chainman.ActiveChain().Contains(pindexWalk)) {
2378-
LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
2379-
pindexLast->GetBlockHash().ToString(),
2380-
pindexLast->nHeight);
2381-
} else {
2382-
std::vector<CInv> vGetData;
2383-
// Download as much as possible, from earliest to latest.
2384-
for (const CBlockIndex *pindex : reverse_iterate(vToFetch)) {
2385-
if (nodestate->nBlocksInFlight >= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
2386-
// Can't download any more from this peer
2387-
break;
2388-
}
2389-
uint32_t nFetchFlags = GetFetchFlags(pfrom);
2390-
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
2391-
BlockRequested(pfrom.GetId(), *pindex);
2392-
LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
2393-
pindex->GetBlockHash().ToString(), pfrom.GetId());
2394-
}
2395-
if (vGetData.size() > 1) {
2396-
LogPrint(BCLog::NET, "Downloading blocks toward %s (%d) via headers direct fetch\n",
2397-
pindexLast->GetBlockHash().ToString(), pindexLast->nHeight);
2398-
}
2399-
if (vGetData.size() > 0) {
2400-
if (!m_ignore_incoming_txs &&
2401-
nodestate->m_provides_cmpctblocks &&
2402-
vGetData.size() == 1 &&
2403-
mapBlocksInFlight.size() == 1 &&
2404-
pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN)) {
2405-
// In any case, we want to download using a compact block, not a regular one
2406-
vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash);
2407-
}
2408-
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData));
2409-
}
2410-
}
2411-
}
2427+
// Consider immediately downloading blocks.
2428+
HeadersDirectFetchBlocks(pfrom, pindexLast);
2429+
24122430
// If we're in IBD, we want outbound peers that will serve us a useful
24132431
// chain. Disconnect peers that are on chains with insufficient work.
24142432
if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && nCount != MAX_HEADERS_RESULTS) {

0 commit comments

Comments
 (0)