@@ -1039,8 +1039,11 @@ class PeerManagerImpl final : public PeerManager
10391039 /* * Remove this block from our tracked requested blocks. Called if:
10401040 * - the block has been recieved from a peer
10411041 * - the request for the block has timed out
1042+ * If "from_peer" is specified, then only remove the block if it is in
1043+ * flight from that peer (to avoid one peer's network traffic from
1044+ * affecting another's state).
10421045 */
1043- void RemoveBlockRequest (const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
1046+ void RemoveBlockRequest (const uint256& hash, std::optional<NodeId> from_peer ) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
10441047
10451048 /* Mark a block as in flight
10461049 * Returns false, still setting pit, if the block was already in flight from the same peer
@@ -1238,7 +1241,7 @@ bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
12381241 return mapBlocksInFlight.find (hash) != mapBlocksInFlight.end ();
12391242}
12401243
1241- void PeerManagerImpl::RemoveBlockRequest (const uint256& hash)
1244+ void PeerManagerImpl::RemoveBlockRequest (const uint256& hash, std::optional<NodeId> from_peer )
12421245{
12431246 auto it = mapBlocksInFlight.find (hash);
12441247 if (it == mapBlocksInFlight.end ()) {
@@ -1247,6 +1250,12 @@ void PeerManagerImpl::RemoveBlockRequest(const uint256& hash)
12471250 }
12481251
12491252 auto [node_id, list_it] = it->second ;
1253+
1254+ if (from_peer && node_id != *from_peer) {
1255+ // Block was requested by another peer
1256+ return ;
1257+ }
1258+
12501259 CNodeState *state = State (node_id);
12511260 assert (state != nullptr );
12521261
@@ -1282,7 +1291,7 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
12821291 }
12831292
12841293 // Make sure it's not listed somewhere already.
1285- RemoveBlockRequest (hash);
1294+ RemoveBlockRequest (hash, std:: nullopt );
12861295
12871296 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight .insert (state->vBlocksInFlight .end (),
12881297 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock (&m_mempool) : nullptr )});
@@ -3623,6 +3632,11 @@ void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr<const CBlo
36233632 m_chainman.ProcessNewBlock (block, force_processing, &new_block);
36243633 if (new_block) {
36253634 node.m_last_block_time = GetTime<std::chrono::seconds>();
3635+ // In case this block came from a different peer than we requested
3636+ // from, we can erase the block request now anyway (as we just stored
3637+ // this block to disk).
3638+ LOCK (cs_main);
3639+ RemoveBlockRequest (block->GetHash (), std::nullopt );
36263640 } else {
36273641 LOCK (cs_main);
36283642 mapBlockSource.erase (block->GetHash ());
@@ -4920,7 +4934,7 @@ void PeerManagerImpl::ProcessMessage(
49204934 PartiallyDownloadedBlock& partialBlock = *(*queuedBlockIt)->partialBlock ;
49214935 ReadStatus status = partialBlock.InitData (cmpctblock, vExtraTxnForCompact);
49224936 if (status == READ_STATUS_INVALID) {
4923- RemoveBlockRequest (pindex->GetBlockHash ()); // Reset in-flight state in case Misbehaving does not result in a disconnect
4937+ RemoveBlockRequest (pindex->GetBlockHash (), pfrom. GetId () ); // Reset in-flight state in case Misbehaving does not result in a disconnect
49244938 Misbehaving (pfrom.GetId (), 100 , " invalid compact block" );
49254939 return ;
49264940 } else if (status == READ_STATUS_FAILED) {
@@ -5014,7 +5028,7 @@ void PeerManagerImpl::ProcessMessage(
50145028 // process from some other peer. We do this after calling
50155029 // ProcessNewBlock so that a malleated cmpctblock announcement
50165030 // can't be used to interfere with block relay.
5017- RemoveBlockRequest (pblock->GetHash ());
5031+ RemoveBlockRequest (pblock->GetHash (), std:: nullopt );
50185032 }
50195033 }
50205034 return ;
@@ -5046,7 +5060,7 @@ void PeerManagerImpl::ProcessMessage(
50465060 PartiallyDownloadedBlock& partialBlock = *it->second .second ->partialBlock ;
50475061 ReadStatus status = partialBlock.FillBlock (*pblock, resp.txn );
50485062 if (status == READ_STATUS_INVALID) {
5049- RemoveBlockRequest (resp.blockhash ); // Reset in-flight state in case Misbehaving does not result in a disconnect
5063+ RemoveBlockRequest (resp.blockhash , pfrom. GetId () ); // Reset in-flight state in case Misbehaving does not result in a disconnect
50505064 Misbehaving (pfrom.GetId (), 100 , " invalid compact block/non-matching block transactions" );
50515065 return ;
50525066 } else if (status == READ_STATUS_FAILED) {
@@ -5072,7 +5086,7 @@ void PeerManagerImpl::ProcessMessage(
50725086 // though the block was successfully read, and rely on the
50735087 // handling in ProcessNewBlock to ensure the block index is
50745088 // updated, etc.
5075- RemoveBlockRequest (resp.blockhash ); // it is now an empty pointer
5089+ RemoveBlockRequest (resp.blockhash , pfrom. GetId () ); // it is now an empty pointer
50765090 fBlockRead = true ;
50775091 // mapBlockSource is used for potentially punishing peers and
50785092 // updating which peers send us compact blocks, so the race
@@ -5154,7 +5168,7 @@ void PeerManagerImpl::ProcessMessage(
51545168 // Always process the block if we requested it, since we may
51555169 // need it even when it's not a candidate for a new best tip.
51565170 forceProcessing = IsBlockRequested (hash);
5157- RemoveBlockRequest (hash);
5171+ RemoveBlockRequest (hash, pfrom. GetId () );
51585172 // mapBlockSource is only used for punishing peers and setting
51595173 // which peers send us compact blocks, so the race between here and
51605174 // cs_main in ProcessNewBlock is fine.
0 commit comments