From 2b67ea465c72461eca7d07897b6476f583bf9a19 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sun, 9 Jul 2023 01:05:30 +0000 Subject: [PATCH] Bugfix: net_processing: Restore "Already requested" error for FetchBlock --- src/net_processing.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 8da2c701d3..7e5b64d464 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -878,6 +878,9 @@ private: /** Have we requested this block from an outbound peer */ bool IsBlockRequestedFromOutbound(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + /** Have we requested this block from a specific peer */ + bool IsBlockRequestedFromPeer(const uint256& hash, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + /** Remove this block from our tracked requested blocks. Called if: * - the block has been received from a peer * - the request for the block has timed out @@ -1132,6 +1135,16 @@ bool PeerManagerImpl::IsBlockRequestedFromOutbound(const uint256& hash) return false; } +bool PeerManagerImpl::IsBlockRequestedFromPeer(const uint256& hash, NodeId peer) +{ + for (auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) { + auto [nodeid, block_it] = range.first->second; + if (nodeid == peer) return true; + } + + return false; +} + void PeerManagerImpl::RemoveBlockRequest(const uint256& hash, std::optional from_peer) { auto range = mapBlocksInFlight.equal_range(hash); @@ -1781,16 +1794,19 @@ std::optional PeerManagerImpl::FetchBlock(NodeId peer_id, const CBl // Ignore pre-segwit peers if (!CanServeWitnesses(*peer)) return "Pre-SegWit peer"; + const uint256& hash{block_index.GetBlockHash()}; + LOCK(cs_main); + if (IsBlockRequestedFromPeer(hash, peer_id)) return "Already requested from this peer"; + // Forget about all prior requests - RemoveBlockRequest(block_index.GetBlockHash(), std::nullopt); + RemoveBlockRequest(hash, std::nullopt); // Mark block as in-flight - if (!BlockRequested(peer_id, block_index)) return "Already requested from this peer"; + Assume(BlockRequested(peer_id, block_index)); // Construct message to request the block - const uint256& hash{block_index.GetBlockHash()}; std::vector invs{CInv(MSG_BLOCK | MSG_WITNESS_FLAG, hash)}; // Send block request message to the peer