aboutsummaryrefslogtreecommitdiff
path: root/src/net_processing.cpp
diff options
context:
space:
mode:
authorGreg Sanders <gsanders87@gmail.com>2023-05-09 12:56:49 -0400
committerGreg Sanders <gsanders87@gmail.com>2023-05-18 10:03:37 -0400
commitcce96182ba2457335868c65dc16b081c3dee32ee (patch)
treeff3cbb222e4379ab3b27a38405282ad5a681496d /src/net_processing.cpp
parenta90595478dcf4e443cd15bbb822d485dc42bdb18 (diff)
Convert mapBlocksInFlight to a multimap
Diffstat (limited to 'src/net_processing.cpp')
-rw-r--r--src/net_processing.cpp108
1 files changed, 71 insertions, 37 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 8138e8e985..8148014815 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -898,7 +898,8 @@ private:
*/
void FindNextBlocksToDownload(const Peer& peer, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- typedef std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator>> BlockDownloadMap;
+ /* Multimap used to preserve insertion order */
+ typedef std::multimap<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator>> BlockDownloadMap;
BlockDownloadMap mapBlocksInFlight GUARDED_BY(cs_main);
/** When our tip was last updated. */
@@ -1122,34 +1123,40 @@ bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
void PeerManagerImpl::RemoveBlockRequest(const uint256& hash, std::optional<NodeId> from_peer)
{
- auto it = mapBlocksInFlight.find(hash);
- if (it == mapBlocksInFlight.end()) {
- // Block was not requested
+ auto range = mapBlocksInFlight.equal_range(hash);
+ if (range.first == range.second) {
+ // Block was not requested from any peer
return;
}
- auto [node_id, list_it] = it->second;
+ // Currently we don't request more than one peer for same block
+ Assume(mapBlocksInFlight.count(hash) == 1);
- if (from_peer && node_id != *from_peer) {
- // Block was requested by another peer
- return;
- }
+ while (range.first != range.second) {
+ auto [node_id, list_it] = range.first->second;
- CNodeState *state = State(node_id);
- assert(state != nullptr);
+ if (from_peer && *from_peer != node_id) {
+ range.first++;
+ continue;
+ }
- if (state->vBlocksInFlight.begin() == list_it) {
- // First block on the queue was received, update the start download time for the next one
- state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
- }
- state->vBlocksInFlight.erase(list_it);
+ CNodeState *state = State(node_id);
+ assert(state != nullptr);
- if (state->vBlocksInFlight.empty()) {
- // Last validated block on the queue was received.
- m_peers_downloading_from--;
+ if (state->vBlocksInFlight.begin() == list_it) {
+ // First block on the queue was received, update the start download time for the next one
+ state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
+ }
+ state->vBlocksInFlight.erase(list_it);
+
+ if (state->vBlocksInFlight.empty()) {
+ // Last validated block on the queue for this peer was received.
+ m_peers_downloading_from--;
+ }
+ state->m_stalling_since = 0us;
+
+ range.first = mapBlocksInFlight.erase(range.first);
}
- state->m_stalling_since = 0us;
- mapBlocksInFlight.erase(it);
}
bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
@@ -1160,12 +1167,13 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
assert(state != nullptr);
// Short-circuit most stuff in case it is from the same node
- BlockDownloadMap::iterator itInFlight = mapBlocksInFlight.find(hash);
- if (itInFlight != mapBlocksInFlight.end() && itInFlight->second.first == nodeid) {
- if (pit) {
- *pit = &itInFlight->second.second;
+ for (auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
+ if (range.first->second.first == nodeid) {
+ if (pit) {
+ *pit = &range.first->second.second;
+ }
+ return false;
}
- return false;
}
// Make sure it's not listed somewhere already.
@@ -1178,7 +1186,7 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
state->m_downloading_since = GetTime<std::chrono::microseconds>();
m_peers_downloading_from++;
}
- itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it))).first;
+ auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
if (pit) {
*pit = &itInFlight->second.second;
}
@@ -1381,7 +1389,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(const Peer& peer, unsigned int co
}
} else if (waitingfor == -1) {
// This is the first already-in-flight block.
- waitingfor = mapBlocksInFlight[pindex->GetBlockHash()].first;
+ waitingfor = mapBlocksInFlight.lower_bound(pindex->GetBlockHash())->second.first;
}
}
}
@@ -1511,7 +1519,15 @@ void PeerManagerImpl::FinalizeNode(const CNode& node)
nSyncStarted--;
for (const QueuedBlock& entry : state->vBlocksInFlight) {
- mapBlocksInFlight.erase(entry.pindex->GetBlockHash());
+ auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
+ while (range.first != range.second) {
+ auto [node_id, list_it] = range.first->second;
+ if (node_id != nodeid) {
+ range.first++;
+ } else {
+ range.first = mapBlocksInFlight.erase(range.first);
+ }
+ }
}
m_orphanage.EraseForPeer(nodeid);
m_txrequest.DisconnectedPeer(nodeid);
@@ -4272,12 +4288,21 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
nodestate->m_last_block_announcement = GetTime();
}
- BlockDownloadMap::iterator blockInFlightIt = mapBlocksInFlight.find(pindex->GetBlockHash());
- bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end();
-
if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here
return;
+ auto range_flight = mapBlocksInFlight.equal_range(pindex->GetBlockHash());
+ bool fAlreadyInFlight = range_flight.first != range_flight.second;
+ bool in_flight_same_peer{false};
+
+ while (range_flight.first != range_flight.second) {
+ if (range_flight.first->second.first == pfrom.GetId()) {
+ in_flight_same_peer = true;
+ break;
+ }
+ range_flight.first++;
+ }
+
if (pindex->nChainWork <= m_chainman.ActiveChain().Tip()->nChainWork || // We know something better
pindex->nTx != 0) { // We had this block at some point, but pruned it
if (fAlreadyInFlight) {
@@ -4299,7 +4324,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// possibilities in compact block processing...
if (pindex->nHeight <= m_chainman.ActiveChain().Height() + 2) {
if ((!fAlreadyInFlight && nodestate->vBlocksInFlight.size() < MAX_BLOCKS_IN_TRANSIT_PER_PEER) ||
- (fAlreadyInFlight && blockInFlightIt->second.first == pfrom.GetId())) {
+ in_flight_same_peer) {
std::list<QueuedBlock>::iterator* queuedBlockIt = nullptr;
if (!BlockRequested(pfrom.GetId(), *pindex, &queuedBlockIt)) {
if (!(*queuedBlockIt)->partialBlock)
@@ -4431,14 +4456,23 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
{
LOCK(cs_main);
- BlockDownloadMap::iterator it = mapBlocksInFlight.find(resp.blockhash);
- if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock ||
- it->second.first != pfrom.GetId()) {
+ bool expected_blocktxn = false;
+ auto range_flight = mapBlocksInFlight.equal_range(resp.blockhash);
+ while (range_flight.first != range_flight.second) {
+ auto [node_id, block_it] = range_flight.first->second;
+ if (node_id == pfrom.GetId() && block_it->partialBlock) {
+ expected_blocktxn = true;
+ break;
+ }
+ range_flight.first++;
+ }
+
+ if (!expected_blocktxn) {
LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom.GetId());
return;
}
- PartiallyDownloadedBlock& partialBlock = *it->second.second->partialBlock;
+ PartiallyDownloadedBlock& partialBlock = *range_flight.first->second.second->partialBlock;
ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
if (status == READ_STATUS_INVALID) {
RemoveBlockRequest(resp.blockhash, pfrom.GetId()); // Reset in-flight state in case Misbehaving does not result in a disconnect