@@ -883,8 +883,11 @@ class PeerManagerImpl final : public PeerManager
883883 /* * Remove this block from our tracked requested blocks. Called if:
884884 * - the block has been received from a peer
885885 * - the request for the block has timed out
886+ * If "from_peer" is specified, then only remove the block if it is in
887+ * flight from that peer (to avoid one peer's network traffic from
888+ * affecting another's state).
886889 */
887- void RemoveBlockRequest (const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
890+ void RemoveBlockRequest (const uint256& hash, std::optional<NodeId> from_peer ) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
888891
889892 /* Mark a block as in flight
890893 * Returns false, still setting pit, if the block was already in flight from the same peer
@@ -1120,7 +1123,7 @@ bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
11201123 return mapBlocksInFlight.find (hash) != mapBlocksInFlight.end ();
11211124}
11221125
1123- void PeerManagerImpl::RemoveBlockRequest (const uint256& hash)
1126+ void PeerManagerImpl::RemoveBlockRequest (const uint256& hash, std::optional<NodeId> from_peer )
11241127{
11251128 auto it = mapBlocksInFlight.find (hash);
11261129 if (it == mapBlocksInFlight.end ()) {
@@ -1129,6 +1132,12 @@ void PeerManagerImpl::RemoveBlockRequest(const uint256& hash)
11291132 }
11301133
11311134 auto [node_id, list_it] = it->second ;
1135+
1136+ if (from_peer && node_id != *from_peer) {
1137+ // Block was requested by another peer
1138+ return ;
1139+ }
1140+
11321141 CNodeState *state = State (node_id);
11331142 assert (state != nullptr );
11341143
@@ -1164,7 +1173,7 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
11641173 }
11651174
11661175 // Make sure it's not listed somewhere already.
1167- RemoveBlockRequest (hash);
1176+ RemoveBlockRequest (hash, std:: nullopt );
11681177
11691178 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight .insert (state->vBlocksInFlight .end (),
11701179 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock (&m_mempool) : nullptr )});
@@ -3155,6 +3164,11 @@ void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr<const CBlo
31553164 m_chainman.ProcessNewBlock (block, force_processing, min_pow_checked, &new_block);
31563165 if (new_block) {
31573166 node.m_last_block_time = GetTime<std::chrono::seconds>();
3167+ // In case this block came from a different peer than we requested
3168+ // from, we can erase the block request now anyway (as we just stored
3169+ // this block to disk).
3170+ LOCK (cs_main);
3171+ RemoveBlockRequest (block->GetHash (), std::nullopt );
31583172 } else {
31593173 LOCK (cs_main);
31603174 mapBlockSource.erase (block->GetHash ());
@@ -4305,7 +4319,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
43054319 PartiallyDownloadedBlock& partialBlock = *(*queuedBlockIt)->partialBlock ;
43064320 ReadStatus status = partialBlock.InitData (cmpctblock, vExtraTxnForCompact);
43074321 if (status == READ_STATUS_INVALID) {
4308- RemoveBlockRequest (pindex->GetBlockHash ()); // Reset in-flight state in case Misbehaving does not result in a disconnect
4322+ RemoveBlockRequest (pindex->GetBlockHash (), pfrom. GetId () ); // Reset in-flight state in case Misbehaving does not result in a disconnect
43094323 Misbehaving (*peer, 100 , " invalid compact block" );
43104324 return ;
43114325 } else if (status == READ_STATUS_FAILED) {
@@ -4400,7 +4414,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
44004414 // process from some other peer. We do this after calling
44014415 // ProcessNewBlock so that a malleated cmpctblock announcement
44024416 // can't be used to interfere with block relay.
4403- RemoveBlockRequest (pblock->GetHash ());
4417+ RemoveBlockRequest (pblock->GetHash (), std:: nullopt );
44044418 }
44054419 }
44064420 return ;
@@ -4432,7 +4446,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
44324446 PartiallyDownloadedBlock& partialBlock = *it->second .second ->partialBlock ;
44334447 ReadStatus status = partialBlock.FillBlock (*pblock, resp.txn );
44344448 if (status == READ_STATUS_INVALID) {
4435- RemoveBlockRequest (resp.blockhash ); // Reset in-flight state in case Misbehaving does not result in a disconnect
4449+ RemoveBlockRequest (resp.blockhash , pfrom. GetId () ); // Reset in-flight state in case Misbehaving does not result in a disconnect
44364450 Misbehaving (*peer, 100 , " invalid compact block/non-matching block transactions" );
44374451 return ;
44384452 } else if (status == READ_STATUS_FAILED) {
@@ -4458,7 +4472,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
44584472 // though the block was successfully read, and rely on the
44594473 // handling in ProcessNewBlock to ensure the block index is
44604474 // updated, etc.
4461- RemoveBlockRequest (resp.blockhash ); // it is now an empty pointer
4475+ RemoveBlockRequest (resp.blockhash , pfrom. GetId () ); // it is now an empty pointer
44624476 fBlockRead = true ;
44634477 // mapBlockSource is used for potentially punishing peers and
44644478 // updating which peers send us compact blocks, so the race
@@ -4547,7 +4561,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
45474561 // Always process the block if we requested it, since we may
45484562 // need it even when it's not a candidate for a new best tip.
45494563 forceProcessing = IsBlockRequested (hash);
4550- RemoveBlockRequest (hash);
4564+ RemoveBlockRequest (hash, pfrom. GetId () );
45514565 // mapBlockSource is only used for punishing peers and setting
45524566 // which peers send us compact blocks, so the race between here and
45534567 // cs_main in ProcessNewBlock is fine.
0 commit comments