@@ -883,8 +883,11 @@ class PeerManagerImpl final : public PeerManager
883
883
/* * Remove this block from our tracked requested blocks. Called if:
884
884
* - the block has been received from a peer
885
885
* - 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).
886
889
*/
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);
888
891
889
892
/* Mark a block as in flight
890
893
* 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)
1120
1123
return mapBlocksInFlight.find (hash) != mapBlocksInFlight.end ();
1121
1124
}
1122
1125
1123
- void PeerManagerImpl::RemoveBlockRequest (const uint256& hash)
1126
+ void PeerManagerImpl::RemoveBlockRequest (const uint256& hash, std::optional<NodeId> from_peer )
1124
1127
{
1125
1128
auto it = mapBlocksInFlight.find (hash);
1126
1129
if (it == mapBlocksInFlight.end ()) {
@@ -1129,6 +1132,12 @@ void PeerManagerImpl::RemoveBlockRequest(const uint256& hash)
1129
1132
}
1130
1133
1131
1134
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
+
1132
1141
CNodeState *state = State (node_id);
1133
1142
assert (state != nullptr );
1134
1143
@@ -1164,7 +1173,7 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
1164
1173
}
1165
1174
1166
1175
// Make sure it's not listed somewhere already.
1167
- RemoveBlockRequest (hash);
1176
+ RemoveBlockRequest (hash, std::nullopt );
1168
1177
1169
1178
std::list<QueuedBlock>::iterator it = state->vBlocksInFlight .insert (state->vBlocksInFlight .end (),
1170
1179
{&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
3155
3164
m_chainman.ProcessNewBlock (block, force_processing, min_pow_checked, &new_block);
3156
3165
if (new_block) {
3157
3166
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);
3158
3172
} else {
3159
3173
LOCK (cs_main);
3160
3174
mapBlockSource.erase (block->GetHash ());
@@ -4305,7 +4319,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4305
4319
PartiallyDownloadedBlock& partialBlock = *(*queuedBlockIt)->partialBlock ;
4306
4320
ReadStatus status = partialBlock.InitData (cmpctblock, vExtraTxnForCompact);
4307
4321
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
4309
4323
Misbehaving (*peer, 100 , " invalid compact block" );
4310
4324
return ;
4311
4325
} else if (status == READ_STATUS_FAILED) {
@@ -4400,7 +4414,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4400
4414
// process from some other peer. We do this after calling
4401
4415
// ProcessNewBlock so that a malleated cmpctblock announcement
4402
4416
// can't be used to interfere with block relay.
4403
- RemoveBlockRequest (pblock->GetHash ());
4417
+ RemoveBlockRequest (pblock->GetHash (), std::nullopt );
4404
4418
}
4405
4419
}
4406
4420
return ;
@@ -4432,7 +4446,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4432
4446
PartiallyDownloadedBlock& partialBlock = *it->second .second ->partialBlock ;
4433
4447
ReadStatus status = partialBlock.FillBlock (*pblock, resp.txn );
4434
4448
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
4436
4450
Misbehaving (*peer, 100 , " invalid compact block/non-matching block transactions" );
4437
4451
return ;
4438
4452
} else if (status == READ_STATUS_FAILED) {
@@ -4458,7 +4472,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4458
4472
// though the block was successfully read, and rely on the
4459
4473
// handling in ProcessNewBlock to ensure the block index is
4460
4474
// updated, etc.
4461
- RemoveBlockRequest (resp.blockhash ); // it is now an empty pointer
4475
+ RemoveBlockRequest (resp.blockhash , pfrom. GetId () ); // it is now an empty pointer
4462
4476
fBlockRead = true ;
4463
4477
// mapBlockSource is used for potentially punishing peers and
4464
4478
// updating which peers send us compact blocks, so the race
@@ -4547,7 +4561,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4547
4561
// Always process the block if we requested it, since we may
4548
4562
// need it even when it's not a candidate for a new best tip.
4549
4563
forceProcessing = IsBlockRequested (hash);
4550
- RemoveBlockRequest (hash);
4564
+ RemoveBlockRequest (hash, pfrom. GetId () );
4551
4565
// mapBlockSource is only used for punishing peers and setting
4552
4566
// which peers send us compact blocks, so the race between here and
4553
4567
// cs_main in ProcessNewBlock is fine.
0 commit comments