Skip to content

Commit 0042783

Browse files
fanquakevijaydasmp
authored andcommitted
Merge bitcoin#27608: p2p: Avoid prematurely clearing download state for other peers
52e5207 p2p: Avoid prematurely clearing download state for other peers (Suhas Daftuar) Pull request description: Avoid letting one peer send us data that clears out the download request (and related timers etc) from another peer. The exception is if a block is definitely stored to disk, in which case we'll clear the download state (just as we do for compact blocks). ACKs for top commit: jamesob: ACK 52e5207 ([`jamesob/ackr/27608.1.sdaftuar.p2p_avoid_prematurely_cl`](https://github.com/jamesob/bitcoin/tree/ackr/27608.1.sdaftuar.p2p_avoid_prematurely_cl)) instagibbs: ACK 52e5207 fjahr: Code review ACK 52e5207 mzumsande: Code Review ACK 52e5207 Tree-SHA512: 3ee92507edc3303c16c70ca44ba6c28c104afe95196e4b9167032590ed23d4f569f654f8eb8758940bd6536bc9ca810d2a77d2739db386b927e8b3f3cf55cb16
1 parent 30eb354 commit 0042783

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
@@ -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

Comments
 (0)