@@ -2421,55 +2421,77 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
24212421 }
24222422 }
24232423
2424- LOCK (cs_main);
2425- const CBlockIndex* pindex = m_chainman.m_blockman .LookupBlockIndex (inv.hash );
2426- if (!pindex) {
2427- return ;
2428- }
2429- if (!BlockRequestAllowed (pindex)) {
2430- LogPrint (BCLog::NET, " %s: ignoring request from peer=%i for old block that isn't in the main chain\n " , __func__, pfrom.GetId ());
2431- return ;
2432- }
2433- // disconnect node in case we have reached the outbound limit for serving historical blocks
2434- if (m_connman.OutboundTargetReached (true ) &&
2435- (((m_chainman.m_best_header != nullptr ) && (m_chainman.m_best_header ->GetBlockTime () - pindex->GetBlockTime () > HISTORICAL_BLOCK_AGE)) || inv.IsMsgFilteredBlk ()) &&
2436- !pfrom.HasPermission (NetPermissionFlags::Download) // nodes with the download permission may exceed target
2437- ) {
2438- LogPrint (BCLog::NET, " historical block serving limit reached, disconnect peer=%d\n " , pfrom.GetId ());
2439- pfrom.fDisconnect = true ;
2440- return ;
2441- }
2442- // Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold
2443- if (!pfrom.HasPermission (NetPermissionFlags::NoBan) && (
2444- (((peer.m_our_services & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((peer.m_our_services & NODE_NETWORK) != NODE_NETWORK) && (m_chainman.ActiveChain ().Tip ()->nHeight - pindex->nHeight > (int )NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */ ) )
2445- )) {
2446- LogPrint (BCLog::NET, " Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n " , pfrom.GetId ());
2447- // disconnect node and prevent it from stalling (would otherwise wait for the missing block)
2448- pfrom.fDisconnect = true ;
2449- return ;
2450- }
2451- // Pruned nodes may have deleted the block, so check whether
2452- // it's available before trying to send.
2453- if (!(pindex->nStatus & BLOCK_HAVE_DATA)) {
2454- return ;
2424+ const CBlockIndex* pindex{nullptr };
2425+ const CBlockIndex* tip{nullptr };
2426+ bool can_direct_fetch{false };
2427+ FlatFilePos block_pos{};
2428+ {
2429+ LOCK (cs_main);
2430+ pindex = m_chainman.m_blockman .LookupBlockIndex (inv.hash );
2431+ if (!pindex) {
2432+ return ;
2433+ }
2434+ if (!BlockRequestAllowed (pindex)) {
2435+ LogPrint (BCLog::NET, " %s: ignoring request from peer=%i for old block that isn't in the main chain\n " , __func__, pfrom.GetId ());
2436+ return ;
2437+ }
2438+ // disconnect node in case we have reached the outbound limit for serving historical blocks
2439+ if (m_connman.OutboundTargetReached (true ) &&
2440+ (((m_chainman.m_best_header != nullptr ) && (m_chainman.m_best_header ->GetBlockTime () - pindex->GetBlockTime () > HISTORICAL_BLOCK_AGE)) || inv.IsMsgFilteredBlk ()) &&
2441+ !pfrom.HasPermission (NetPermissionFlags::Download) // nodes with the download permission may exceed target
2442+ ) {
2443+ LogPrint (BCLog::NET, " historical block serving limit reached, disconnect peer=%d\n " , pfrom.GetId ());
2444+ pfrom.fDisconnect = true ;
2445+ return ;
2446+ }
2447+ tip = m_chainman.ActiveChain ().Tip ();
2448+ // Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold
2449+ if (!pfrom.HasPermission (NetPermissionFlags::NoBan) && (
2450+ (((peer.m_our_services & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((peer.m_our_services & NODE_NETWORK) != NODE_NETWORK) && (tip->nHeight - pindex->nHeight > (int )NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */ ) )
2451+ )) {
2452+ LogPrint (BCLog::NET, " Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n " , pfrom.GetId ());
2453+ // disconnect node and prevent it from stalling (would otherwise wait for the missing block)
2454+ pfrom.fDisconnect = true ;
2455+ return ;
2456+ }
2457+ // Pruned nodes may have deleted the block, so check whether
2458+ // it's available before trying to send.
2459+ if (!(pindex->nStatus & BLOCK_HAVE_DATA)) {
2460+ return ;
2461+ }
2462+ can_direct_fetch = CanDirectFetch ();
2463+ block_pos = pindex->GetBlockPos ();
24552464 }
2465+
24562466 std::shared_ptr<const CBlock> pblock;
24572467 if (a_recent_block && a_recent_block->GetHash () == pindex->GetBlockHash ()) {
24582468 pblock = a_recent_block;
24592469 } else if (inv.IsMsgWitnessBlk ()) {
24602470 // Fast-path: in this case it is possible to serve the block directly from disk,
24612471 // as the network format matches the format on disk
24622472 std::vector<uint8_t > block_data;
2463- if (!m_chainman.m_blockman .ReadRawBlockFromDisk (block_data, pindex->GetBlockPos ())) {
2464- assert (!" cannot load block from disk" );
2473+ if (!m_chainman.m_blockman .ReadRawBlockFromDisk (block_data, block_pos)) {
2474+ if (WITH_LOCK (m_chainman.GetMutex (), return m_chainman.m_blockman .IsBlockPruned (*pindex))) {
2475+ LogPrint (BCLog::NET, " Block was pruned before it could be read, disconnect peer=%s\n " , pfrom.GetId ());
2476+ } else {
2477+ LogError (" Cannot load block from disk, disconnect peer=%d\n " , pfrom.GetId ());
2478+ }
2479+ pfrom.fDisconnect = true ;
2480+ return ;
24652481 }
24662482 MakeAndPushMessage (pfrom, NetMsgType::BLOCK, Span{block_data});
24672483 // Don't set pblock as we've sent the block
24682484 } else {
24692485 // Send block from disk
24702486 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2471- if (!m_chainman.m_blockman .ReadBlockFromDisk (*pblockRead, *pindex)) {
2472- assert (!" cannot load block from disk" );
2487+ if (!m_chainman.m_blockman .ReadBlockFromDisk (*pblockRead, block_pos)) {
2488+ if (WITH_LOCK (m_chainman.GetMutex (), return m_chainman.m_blockman .IsBlockPruned (*pindex))) {
2489+ LogPrint (BCLog::NET, " Block was pruned before it could be read, disconnect peer=%s\n " , pfrom.GetId ());
2490+ } else {
2491+ LogError (" Cannot load block from disk, disconnect peer=%d\n " , pfrom.GetId ());
2492+ }
2493+ pfrom.fDisconnect = true ;
2494+ return ;
24732495 }
24742496 pblock = pblockRead;
24752497 }
@@ -2507,7 +2529,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
25072529 // they won't have a useful mempool to match against a compact block,
25082530 // and we don't feel like constructing the object for them, so
25092531 // instead we respond with the full, non-compact block.
2510- if (CanDirectFetch () && pindex->nHeight >= m_chainman. ActiveChain (). Height () - MAX_CMPCTBLOCK_DEPTH) {
2532+ if (can_direct_fetch && pindex->nHeight >= tip-> nHeight - MAX_CMPCTBLOCK_DEPTH) {
25112533 if (a_recent_compact_block && a_recent_compact_block->header .GetHash () == pindex->GetBlockHash ()) {
25122534 MakeAndPushMessage (pfrom, NetMsgType::CMPCTBLOCK, *a_recent_compact_block);
25132535 } else {
@@ -2528,7 +2550,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
25282550 // and we want it right after the last block so they don't
25292551 // wait for other stuff first.
25302552 std::vector<CInv> vInv;
2531- vInv.emplace_back (MSG_BLOCK, m_chainman. ActiveChain (). Tip () ->GetBlockHash ());
2553+ vInv.emplace_back (MSG_BLOCK, tip ->GetBlockHash ());
25322554 MakeAndPushMessage (pfrom, NetMsgType::INV, vInv);
25332555 peer.m_continuation_block .SetNull ();
25342556 }
0 commit comments