@@ -405,9 +405,6 @@ struct Peer {
405405 /* * Total number of addresses that were processed (excludes rate-limited ones). */
406406 std::atomic<uint64_t > m_addr_processed{0 };
407407
408- /* * Set of txids to reconsider once their parent transactions have been accepted **/
409- std::set<uint256> m_orphan_work_set GUARDED_BY (g_cs_orphans);
410-
411408 /* * Whether we've sent this peer a getheaders in response to an inv prior to initial-headers-sync completing */
412409 bool m_inv_triggered_getheaders_before_sync GUARDED_BY (NetEventsInterface::g_msgproc_mutex){false };
413410
@@ -711,8 +708,17 @@ class PeerManagerImpl final : public PeerManager
711708 */
712709 bool MaybeDiscourageAndDisconnect (CNode& pnode, Peer& peer);
713710
714- void ProcessOrphanTx (std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
715- EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
711+ /* *
712+ * Reconsider orphan transactions after a parent has been accepted to the mempool.
713+ *
714+ * @peer[in] peer The peer whose orphan transactions we will reconsider. Generally only one
715+ * orphan will be reconsidered on each call of this function. This set
716+ * may be added to if accepting an orphan causes its children to be
717+ * reconsidered.
718+ * @return True if there are still orphans in this peer's work set.
719+ */
720+ bool ProcessOrphanTx (Peer& peer)
721+ EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, cs_main);
716722 /* * Process a single headers message from a peer. */
717723 void ProcessHeadersMessage (CNode& pfrom, Peer& peer,
718724 const std::vector<CBlockHeader>& headers,
@@ -1040,14 +1046,14 @@ class PeerManagerImpl final : public PeerManager
10401046 /* * Storage for orphan information */
10411047 TxOrphanage m_orphanage;
10421048
1043- void AddToCompactExtraTransactions (const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans );
1049+ void AddToCompactExtraTransactions (const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex );
10441050
10451051 /* * Orphan/conflicted/etc transactions that are kept for compact block reconstruction.
10461052 * The last -blockreconstructionextratxn/DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN of
10471053 * these are kept in a ring buffer */
1048- std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY (g_cs_orphans );
1054+ std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY (g_msgproc_mutex );
10491055 /* * Offset into vExtraTxnForCompact to insert the next tx */
1050- size_t vExtraTxnForCompactIt GUARDED_BY (g_cs_orphans ) = 0;
1056+ size_t vExtraTxnForCompactIt GUARDED_BY (g_msgproc_mutex ) = 0;
10511057};
10521058
10531059// Keeps track of the time (in microseconds) when transactions were requested last time
@@ -1674,7 +1680,7 @@ void PeerManagerImpl::FinalizeNode(const CNode& node) {
16741680 for (const QueuedBlock& entry : state->vBlocksInFlight ) {
16751681 mapBlocksInFlight.erase (entry.pindex ->GetBlockHash ());
16761682 }
1677- WITH_LOCK (g_cs_orphans, m_orphanage.EraseForPeer (nodeid) );
1683+ m_orphanage.EraseForPeer (nodeid);
16781684 if (m_txreconciliation) m_txreconciliation->ForgetPeer (nodeid);
16791685 m_num_preferred_download_peers -= state->fPreferredDownload ;
16801686 m_peers_downloading_from -= (state->nBlocksInFlight != 0 );
@@ -1768,7 +1774,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c
17681774 return true ;
17691775}
17701776
1771- void PeerManagerImpl::AddToCompactExtraTransactions (const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans )
1777+ void PeerManagerImpl::AddToCompactExtraTransactions (const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(m_mutex )
17721778{
17731779 size_t max_extra_txn = gArgs .GetIntArg (" -blockreconstructionextratxn" , DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN);
17741780 if (max_extra_txn <= 0 )
@@ -2007,7 +2013,7 @@ void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
20072013void PeerManagerImpl::BlockConnected (const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex)
20082014{
20092015 {
2010- LOCK2 (::cs_main, g_cs_orphans );
2016+ LOCK2 (::cs_main, m_mutex );
20112017
20122018 auto orphanWorkSet = m_orphanage.GetCandidatesForBlock (*pblock);
20132019 while (!orphanWorkSet.empty ()) {
@@ -3197,33 +3203,24 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
31973203 return ;
31983204}
31993205
3200- /* *
3201- * Reconsider orphan transactions after a parent has been accepted to the mempool.
3202- *
3203- * @param[in,out] orphan_work_set The set of orphan transactions to reconsider. Generally only one
3204- * orphan will be reconsidered on each call of this function. This set
3205- * may be added to if accepting an orphan causes its children to be
3206- * reconsidered.
3207- */
3208- void PeerManagerImpl::ProcessOrphanTx (std::set<uint256>& orphan_work_set)
3206+ bool PeerManagerImpl::ProcessOrphanTx (Peer& peer)
32093207{
3208+ AssertLockHeld (g_msgproc_mutex);
32103209 AssertLockHeld (cs_main);
3211- AssertLockHeld (g_cs_orphans);
3212-
3213- while (!orphan_work_set.empty ()) {
3214- const uint256 orphanHash = *orphan_work_set.begin ();
3215- orphan_work_set.erase (orphan_work_set.begin ());
32163210
3217- const auto [porphanTx, from_peer] = m_orphanage.GetTx (orphanHash);
3218- if (porphanTx == nullptr ) continue ;
3211+ CTransactionRef porphanTx = nullptr ;
3212+ NodeId from_peer = -1 ;
3213+ bool more = false ;
32193214
3215+ while (CTransactionRef porphanTx = m_orphanage.GetTxToReconsider (peer.m_id , from_peer, more)) {
32203216 const MempoolAcceptResult result = m_chainman.ProcessTransaction (porphanTx);
32213217 const TxValidationState& state = result.m_state ;
3218+ const uint256& orphanHash = porphanTx->GetHash ();
32223219
32233220 if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
32243221 LogPrint (BCLog::MEMPOOL, " accepted orphan tx %s\n " , orphanHash.ToString ());
32253222 _RelayTransaction (porphanTx->GetHash ());
3226- m_orphanage.AddChildrenToWorkSet (*porphanTx, orphan_work_set );
3223+ m_orphanage.AddChildrenToWorkSet (*porphanTx, peer. m_id );
32273224 m_orphanage.EraseTx (orphanHash);
32283225 break ;
32293226 } else if (state.GetResult () != TxValidationResult::TX_MISSING_INPUTS) {
@@ -3243,6 +3240,8 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
32433240 break ;
32443241 }
32453242 }
3243+
3244+ return more;
32463245}
32473246
32483247bool PeerManagerImpl::PrepareBlockFilterRequest (CNode& node, Peer& peer,
@@ -4469,7 +4468,7 @@ void PeerManagerImpl::ProcessMessage(
44694468 }
44704469 }
44714470
4472- LOCK2 (cs_main, g_cs_orphans );
4471+ LOCK (cs_main);
44734472
44744473 if (AlreadyHave (inv)) {
44754474 if (pfrom.HasPermission (NetPermissionFlags::ForceRelay)) {
@@ -4499,7 +4498,7 @@ void PeerManagerImpl::ProcessMessage(
44994498 }
45004499
45014500 _RelayTransaction (tx.GetHash ());
4502- m_orphanage.AddChildrenToWorkSet (tx, peer->m_orphan_work_set );
4501+ m_orphanage.AddChildrenToWorkSet (tx, peer->m_id );
45034502
45044503 pfrom.m_last_tx_time = GetTime<std::chrono::seconds>();
45054504
@@ -4509,7 +4508,7 @@ void PeerManagerImpl::ProcessMessage(
45094508 m_mempool.size (), m_mempool.DynamicMemoryUsage () / 1000 );
45104509
45114510 // Recursively process any orphan transactions that depended on this one
4512- ProcessOrphanTx (peer-> m_orphan_work_set );
4511+ ProcessOrphanTx (* peer);
45134512 }
45144513 else if (state.GetResult () == TxValidationResult::TX_MISSING_INPUTS)
45154514 {
@@ -4648,7 +4647,7 @@ void PeerManagerImpl::ProcessMessage(
46484647 bool fBlockReconstructed = false ;
46494648
46504649 {
4651- LOCK2 (cs_main, g_cs_orphans );
4650+ LOCK (cs_main);
46524651 // If AcceptBlockHeader returned true, it set pindex
46534652 assert (pindex);
46544653 UpdateBlockAvailability (pfrom.GetId (), pindex->GetBlockHash ());
@@ -5351,28 +5350,24 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt
53515350 }
53525351 }
53535352
5353+ bool has_more_orphans;
53545354 {
5355- LOCK2 (cs_main, g_cs_orphans);
5356- if (!peer->m_orphan_work_set .empty ()) {
5357- ProcessOrphanTx (peer->m_orphan_work_set );
5358- }
5355+ LOCK (cs_main);
5356+ has_more_orphans = ProcessOrphanTx (*peer);
53595357 }
53605358
53615359 if (pfrom->fDisconnect )
53625360 return false ;
53635361
5362+ if (has_more_orphans) return true ;
5363+
53645364 // this maintains the order of responses
53655365 // and prevents m_getdata_requests to grow unbounded
53665366 {
53675367 LOCK (peer->m_getdata_requests_mutex );
53685368 if (!peer->m_getdata_requests .empty ()) return true ;
53695369 }
53705370
5371- {
5372- LOCK (g_cs_orphans);
5373- if (!peer->m_orphan_work_set .empty ()) return true ;
5374- }
5375-
53765371 // Don't bother if send buffer is too full to respond anyway
53775372 if (pfrom->fPauseSend ) return false ;
53785373
0 commit comments