@@ -541,8 +541,11 @@ class PeerManagerImpl final : public PeerManager
541541 /* * Remove this block from our tracked requested blocks. Called if:
542542 * - the block has been received from a peer
543543 * - the request for the block has timed out
544+ * If "from_peer" is specified, then only remove the block if it is in
545+ * flight from that peer (to avoid one peer's network traffic from
546+ * affecting another's state).
544547 */
545- void RemoveBlockRequest (const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
548+ void RemoveBlockRequest (const uint256& hash, std::optional<NodeId> from_peer ) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
546549
547550 /* Mark a block as in flight
548551 * Returns false, still setting pit, if the block was already in flight from the same peer
@@ -853,7 +856,7 @@ bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
853856 return mapBlocksInFlight.find (hash) != mapBlocksInFlight.end ();
854857}
855858
856- void PeerManagerImpl::RemoveBlockRequest (const uint256& hash)
859+ void PeerManagerImpl::RemoveBlockRequest (const uint256& hash, std::optional<NodeId> from_peer )
857860{
858861 auto it = mapBlocksInFlight.find (hash);
859862 if (it == mapBlocksInFlight.end ()) {
@@ -862,6 +865,12 @@ void PeerManagerImpl::RemoveBlockRequest(const uint256& hash)
862865 }
863866
864867 auto [node_id, list_it] = it->second ;
868+
869+ if (from_peer && node_id != *from_peer) {
870+ // Block was requested by another peer
871+ return ;
872+ }
873+
865874 CNodeState *state = State (node_id);
866875 assert (state != nullptr );
867876
@@ -897,7 +906,7 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
897906 }
898907
899908 // Make sure it's not listed somewhere already.
900- RemoveBlockRequest (hash);
909+ RemoveBlockRequest (hash, std:: nullopt );
901910
902911 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight .insert (state->vBlocksInFlight .end (),
903912 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock (&m_mempool) : nullptr )});
@@ -2597,6 +2606,11 @@ void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr<const CBlo
25972606 m_chainman.ProcessNewBlock (m_chainparams, block, force_processing, &new_block);
25982607 if (new_block) {
25992608 node.m_last_block_time = GetTime<std::chrono::seconds>();
2609+ // In case this block came from a different peer than we requested
2610+ // from, we can erase the block request now anyway (as we just stored
2611+ // this block to disk).
2612+ LOCK (cs_main);
2613+ RemoveBlockRequest (block->GetHash (), std::nullopt );
26002614 } else {
26012615 LOCK (cs_main);
26022616 mapBlockSource.erase (block->GetHash ());
@@ -3670,7 +3684,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
36703684 PartiallyDownloadedBlock& partialBlock = *(*queuedBlockIt)->partialBlock ;
36713685 ReadStatus status = partialBlock.InitData (cmpctblock, vExtraTxnForCompact);
36723686 if (status == READ_STATUS_INVALID) {
3673- RemoveBlockRequest (pindex->GetBlockHash ()); // Reset in-flight state in case Misbehaving does not result in a disconnect
3687+ RemoveBlockRequest (pindex->GetBlockHash (), pfrom. GetId () ); // Reset in-flight state in case Misbehaving does not result in a disconnect
36743688 Misbehaving (pfrom.GetId (), 100 , " invalid compact block" );
36753689 return ;
36763690 } else if (status == READ_STATUS_FAILED) {
@@ -3765,7 +3779,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
37653779 // process from some other peer. We do this after calling
37663780 // ProcessNewBlock so that a malleated cmpctblock announcement
37673781 // can't be used to interfere with block relay.
3768- RemoveBlockRequest (pblock->GetHash ());
3782+ RemoveBlockRequest (pblock->GetHash (), std:: nullopt );
37693783 }
37703784 }
37713785 return ;
@@ -3797,7 +3811,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
37973811 PartiallyDownloadedBlock& partialBlock = *it->second .second ->partialBlock ;
37983812 ReadStatus status = partialBlock.FillBlock (*pblock, resp.txn );
37993813 if (status == READ_STATUS_INVALID) {
3800- RemoveBlockRequest (resp.blockhash ); // Reset in-flight state in case Misbehaving does not result in a disconnect
3814+ RemoveBlockRequest (resp.blockhash , pfrom. GetId () ); // Reset in-flight state in case Misbehaving does not result in a disconnect
38013815 Misbehaving (pfrom.GetId (), 100 , " invalid compact block/non-matching block transactions" );
38023816 return ;
38033817 } else if (status == READ_STATUS_FAILED) {
@@ -3823,7 +3837,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
38233837 // though the block was successfully read, and rely on the
38243838 // handling in ProcessNewBlock to ensure the block index is
38253839 // updated, etc.
3826- RemoveBlockRequest (resp.blockhash ); // it is now an empty pointer
3840+ RemoveBlockRequest (resp.blockhash , pfrom. GetId () ); // it is now an empty pointer
38273841 fBlockRead = true ;
38283842 // mapBlockSource is used for potentially punishing peers and
38293843 // updating which peers send us compact blocks, so the race
@@ -3891,7 +3905,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
38913905 // Always process the block if we requested it, since we may
38923906 // need it even when it's not a candidate for a new best tip.
38933907 forceProcessing = IsBlockRequested (hash);
3894- RemoveBlockRequest (hash);
3908+ RemoveBlockRequest (hash, pfrom. GetId () );
38953909 // mapBlockSource is only used for punishing peers and setting
38963910 // which peers send us compact blocks, so the race between here and
38973911 // cs_main in ProcessNewBlock is fine.
0 commit comments