Skip to content

Commit f454abb

Browse files
sdaftuarpsgreco
authored andcommitted
p2p: Avoid prematurely clearing download state for other peers
Github-Pull: #27608 Rebased-From: 52e5207
1 parent 913a587 commit f454abb

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

src/net_processing.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)