@@ -898,7 +898,8 @@ class PeerManagerImpl final : public PeerManager
898898 */
899899 void FindNextBlocksToDownload (const Peer& peer, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
900900
901- typedef std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator>> BlockDownloadMap;
901+ /* Multimap used to preserve insertion order */
902+ typedef std::multimap<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator>> BlockDownloadMap;
902903 BlockDownloadMap mapBlocksInFlight GUARDED_BY (cs_main);
903904
904905 /* * When our tip was last updated. */
@@ -1122,34 +1123,40 @@ bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
11221123
11231124void PeerManagerImpl::RemoveBlockRequest (const uint256& hash, std::optional<NodeId> from_peer)
11241125{
1125- auto it = mapBlocksInFlight.find (hash);
1126- if (it == mapBlocksInFlight. end () ) {
1127- // Block was not requested
1126+ auto range = mapBlocksInFlight.equal_range (hash);
1127+ if (range. first == range. second ) {
1128+ // Block was not requested from any peer
11281129 return ;
11291130 }
11301131
1131- auto [node_id, list_it] = it->second ;
1132+ // Currently we don't request more than one peer for same block
1133+ Assume (mapBlocksInFlight.count (hash) == 1 );
11321134
1133- if (from_peer && node_id != *from_peer) {
1134- // Block was requested by another peer
1135- return ;
1136- }
1135+ while (range.first != range.second ) {
1136+ auto [node_id, list_it] = range.first ->second ;
11371137
1138- CNodeState *state = State (node_id);
1139- assert (state != nullptr );
1138+ if (from_peer && *from_peer != node_id) {
1139+ range.first ++;
1140+ continue ;
1141+ }
11401142
1141- if (state->vBlocksInFlight .begin () == list_it) {
1142- // First block on the queue was received, update the start download time for the next one
1143- state->m_downloading_since = std::max (state->m_downloading_since , GetTime<std::chrono::microseconds>());
1144- }
1145- state->vBlocksInFlight .erase (list_it);
1143+ CNodeState *state = State (node_id);
1144+ assert (state != nullptr );
11461145
1147- if (state->vBlocksInFlight .empty ()) {
1148- // Last validated block on the queue was received.
1149- m_peers_downloading_from--;
1146+ if (state->vBlocksInFlight .begin () == list_it) {
1147+ // First block on the queue was received, update the start download time for the next one
1148+ state->m_downloading_since = std::max (state->m_downloading_since , GetTime<std::chrono::microseconds>());
1149+ }
1150+ state->vBlocksInFlight .erase (list_it);
1151+
1152+ if (state->vBlocksInFlight .empty ()) {
1153+ // Last validated block on the queue for this peer was received.
1154+ m_peers_downloading_from--;
1155+ }
1156+ state->m_stalling_since = 0us;
1157+
1158+ range.first = mapBlocksInFlight.erase (range.first );
11501159 }
1151- state->m_stalling_since = 0us;
1152- mapBlocksInFlight.erase (it);
11531160}
11541161
11551162bool 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
11601167 assert (state != nullptr );
11611168
11621169 // Short-circuit most stuff in case it is from the same node
1163- BlockDownloadMap::iterator itInFlight = mapBlocksInFlight.find (hash);
1164- if (itInFlight != mapBlocksInFlight.end () && itInFlight->second .first == nodeid) {
1165- if (pit) {
1166- *pit = &itInFlight->second .second ;
1170+ for (auto range = mapBlocksInFlight.equal_range (hash); range.first != range.second ; range.first ++) {
1171+ if (range.first ->second .first == nodeid) {
1172+ if (pit) {
1173+ *pit = &range.first ->second .second ;
1174+ }
1175+ return false ;
11671176 }
1168- return false ;
11691177 }
11701178
11711179 // Make sure it's not listed somewhere already.
@@ -1178,7 +1186,7 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
11781186 state->m_downloading_since = GetTime<std::chrono::microseconds>();
11791187 m_peers_downloading_from++;
11801188 }
1181- itInFlight = mapBlocksInFlight.insert (std::make_pair (hash, std::make_pair (nodeid, it))). first ;
1189+ auto itInFlight = mapBlocksInFlight.insert (std::make_pair (hash, std::make_pair (nodeid, it)));
11821190 if (pit) {
11831191 *pit = &itInFlight->second .second ;
11841192 }
@@ -1381,7 +1389,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(const Peer& peer, unsigned int co
13811389 }
13821390 } else if (waitingfor == -1 ) {
13831391 // This is the first already-in-flight block.
1384- waitingfor = mapBlocksInFlight[ pindex->GetBlockHash ()] .first ;
1392+ waitingfor = mapBlocksInFlight. lower_bound ( pindex->GetBlockHash ())-> second .first ;
13851393 }
13861394 }
13871395 }
@@ -1511,7 +1519,15 @@ void PeerManagerImpl::FinalizeNode(const CNode& node)
15111519 nSyncStarted--;
15121520
15131521 for (const QueuedBlock& entry : state->vBlocksInFlight ) {
1514- mapBlocksInFlight.erase (entry.pindex ->GetBlockHash ());
1522+ auto range = mapBlocksInFlight.equal_range (entry.pindex ->GetBlockHash ());
1523+ while (range.first != range.second ) {
1524+ auto [node_id, list_it] = range.first ->second ;
1525+ if (node_id != nodeid) {
1526+ range.first ++;
1527+ } else {
1528+ range.first = mapBlocksInFlight.erase (range.first );
1529+ }
1530+ }
15151531 }
15161532 m_orphanage.EraseForPeer (nodeid);
15171533 m_txrequest.DisconnectedPeer (nodeid);
@@ -4272,12 +4288,21 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
42724288 nodestate->m_last_block_announcement = GetTime ();
42734289 }
42744290
4275- BlockDownloadMap::iterator blockInFlightIt = mapBlocksInFlight.find (pindex->GetBlockHash ());
4276- bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end ();
4277-
42784291 if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here
42794292 return ;
42804293
4294+ auto range_flight = mapBlocksInFlight.equal_range (pindex->GetBlockHash ());
4295+ bool fAlreadyInFlight = range_flight.first != range_flight.second ;
4296+ bool in_flight_same_peer{false };
4297+
4298+ while (range_flight.first != range_flight.second ) {
4299+ if (range_flight.first ->second .first == pfrom.GetId ()) {
4300+ in_flight_same_peer = true ;
4301+ break ;
4302+ }
4303+ range_flight.first ++;
4304+ }
4305+
42814306 if (pindex->nChainWork <= m_chainman.ActiveChain ().Tip ()->nChainWork || // We know something better
42824307 pindex->nTx != 0 ) { // We had this block at some point, but pruned it
42834308 if (fAlreadyInFlight ) {
@@ -4299,7 +4324,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
42994324 // possibilities in compact block processing...
43004325 if (pindex->nHeight <= m_chainman.ActiveChain ().Height () + 2 ) {
43014326 if ((!fAlreadyInFlight && nodestate->vBlocksInFlight .size () < MAX_BLOCKS_IN_TRANSIT_PER_PEER) ||
4302- ( fAlreadyInFlight && blockInFlightIt-> second . first == pfrom. GetId ()) ) {
4327+ in_flight_same_peer ) {
43034328 std::list<QueuedBlock>::iterator* queuedBlockIt = nullptr ;
43044329 if (!BlockRequested (pfrom.GetId (), *pindex, &queuedBlockIt)) {
43054330 if (!(*queuedBlockIt)->partialBlock )
@@ -4431,14 +4456,23 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
44314456 {
44324457 LOCK (cs_main);
44334458
4434- BlockDownloadMap::iterator it = mapBlocksInFlight.find (resp.blockhash );
4435- if (it == mapBlocksInFlight.end () || !it->second .second ->partialBlock ||
4436- it->second .first != pfrom.GetId ()) {
4459+ bool expected_blocktxn = false ;
4460+ auto range_flight = mapBlocksInFlight.equal_range (resp.blockhash );
4461+ while (range_flight.first != range_flight.second ) {
4462+ auto [node_id, block_it] = range_flight.first ->second ;
4463+ if (node_id == pfrom.GetId () && block_it->partialBlock ) {
4464+ expected_blocktxn = true ;
4465+ break ;
4466+ }
4467+ range_flight.first ++;
4468+ }
4469+
4470+ if (!expected_blocktxn) {
44374471 LogPrint (BCLog::NET, " Peer %d sent us block transactions for block we weren't expecting\n " , pfrom.GetId ());
44384472 return ;
44394473 }
44404474
4441- PartiallyDownloadedBlock& partialBlock = *it ->second .second ->partialBlock ;
4475+ PartiallyDownloadedBlock& partialBlock = *range_flight. first ->second .second ->partialBlock ;
44424476 ReadStatus status = partialBlock.FillBlock (*pblock, resp.txn );
44434477 if (status == READ_STATUS_INVALID) {
44444478 RemoveBlockRequest (resp.blockhash , pfrom.GetId ()); // Reset in-flight state in case Misbehaving does not result in a disconnect
0 commit comments