| 2354 | } |
| 2355 | |
| 2356 | void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& inv) |
| 2357 | { |
| 2358 | std::shared_ptr<const CBlock> a_recent_block; |
| 2359 | std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block; |
| 2360 | { |
| 2361 | LOCK(m_most_recent_block_mutex); |
| 2362 | a_recent_block = m_most_recent_block; |
| 2363 | a_recent_compact_block = m_most_recent_compact_block; |
| 2364 | } |
| 2365 | |
| 2366 | bool need_activate_chain = false; |
| 2367 | { |
| 2368 | LOCK(cs_main); |
| 2369 | const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.hash); |
| 2370 | if (pindex) { |
| 2371 | if (pindex->HaveNumChainTxs() && !pindex->IsValid(BLOCK_VALID_SCRIPTS) && |
| 2372 | pindex->IsValid(BLOCK_VALID_TREE)) { |
| 2373 | // If we have the block and all of its parents, but have not yet validated it, |
| 2374 | // we might be in the middle of connecting it (ie in the unlock of cs_main |
| 2375 | // before ActivateBestChain but after AcceptBlock). |
| 2376 | // In this case, we need to run ActivateBestChain prior to checking the relay |
| 2377 | // conditions below. |
| 2378 | need_activate_chain = true; |
| 2379 | } |
| 2380 | } |
| 2381 | } // release cs_main before calling ActivateBestChain |
| 2382 | if (need_activate_chain) { |
| 2383 | BlockValidationState state; |
| 2384 | if (!m_chainman.ActiveChainstate().ActivateBestChain(state, a_recent_block)) { |
| 2385 | LogDebug(BCLog::NET, "failed to activate chain (%s)\n", state.ToString()); |
| 2386 | } |
| 2387 | } |
| 2388 | |
| 2389 | const CBlockIndex* pindex{nullptr}; |
| 2390 | const CBlockIndex* tip{nullptr}; |
| 2391 | bool can_direct_fetch{false}; |
| 2392 | FlatFilePos block_pos{}; |
| 2393 | { |
| 2394 | LOCK(cs_main); |
| 2395 | pindex = m_chainman.m_blockman.LookupBlockIndex(inv.hash); |
| 2396 | if (!pindex) { |
| 2397 | return; |
| 2398 | } |
| 2399 | if (!BlockRequestAllowed(*pindex)) { |
| 2400 | LogDebug(BCLog::NET, "%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.GetId()); |
| 2401 | return; |
| 2402 | } |
| 2403 | // disconnect node in case we have reached the outbound limit for serving historical blocks |
| 2404 | if (m_connman.OutboundTargetReached(true) && |
| 2405 | (((m_chainman.m_best_header != nullptr) && (m_chainman.m_best_header->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.IsMsgFilteredBlk()) && |
| 2406 | !pfrom.HasPermission(NetPermissionFlags::Download) // nodes with the download permission may exceed target |
| 2407 | ) { |
| 2408 | LogDebug(BCLog::NET, "historical block serving limit reached, %s", pfrom.DisconnectMsg()); |
| 2409 | pfrom.fDisconnect = true; |
| 2410 | return; |
| 2411 | } |
| 2412 | tip = m_chainman.ActiveChain().Tip(); |
| 2413 | // Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold |
nothing calls this directly
no test coverage detected