@@ -365,9 +365,6 @@ struct Peer {
365
365
/* * Total number of addresses that were processed (excludes rate-limited ones). */
366
366
std::atomic<uint64_t > m_addr_processed{0 };
367
367
368
- /* * Set of txids to reconsider once their parent transactions have been accepted **/
369
- std::set<uint256> m_orphan_work_set GUARDED_BY (g_cs_orphans);
370
-
371
368
/* * Whether we've sent this peer a getheaders in response to an inv prior to initial-headers-sync completing */
372
369
bool m_inv_triggered_getheaders_before_sync GUARDED_BY (NetEventsInterface::g_msgproc_mutex){false };
373
370
@@ -584,8 +581,17 @@ class PeerManagerImpl final : public PeerManager
584
581
*/
585
582
bool MaybeDiscourageAndDisconnect (CNode& pnode, Peer& peer);
586
583
587
- void ProcessOrphanTx (std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
588
- EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
584
+ /* *
585
+ * Reconsider orphan transactions after a parent has been accepted to the mempool.
586
+ *
587
+ * @peer[in] peer The peer whose orphan transactions we will reconsider. Generally only one
588
+ * orphan will be reconsidered on each call of this function. This set
589
+ * may be added to if accepting an orphan causes its children to be
590
+ * reconsidered.
591
+ * @return True if there are still orphans in this peer's work set.
592
+ */
593
+ bool ProcessOrphanTx (Peer& peer)
594
+ EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, cs_main);
589
595
/* * Process a single headers message from a peer.
590
596
*
591
597
* @param[in] pfrom CNode of the peer
@@ -919,14 +925,14 @@ class PeerManagerImpl final : public PeerManager
919
925
/* * Storage for orphan information */
920
926
TxOrphanage m_orphanage;
921
927
922
- void AddToCompactExtraTransactions (const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans );
928
+ void AddToCompactExtraTransactions (const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex );
923
929
924
930
/* * Orphan/conflicted/etc transactions that are kept for compact block reconstruction.
925
931
* The last -blockreconstructionextratxn/DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN of
926
932
* these are kept in a ring buffer */
927
- std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY (g_cs_orphans );
933
+ std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY (g_msgproc_mutex );
928
934
/* * Offset into vExtraTxnForCompact to insert the next tx */
929
- size_t vExtraTxnForCompactIt GUARDED_BY (g_cs_orphans ) = 0;
935
+ size_t vExtraTxnForCompactIt GUARDED_BY (g_msgproc_mutex ) = 0;
930
936
931
937
/* * Check whether the last unknown block a peer advertised is not yet known. */
932
938
void ProcessBlockAvailability (NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -1490,7 +1496,7 @@ void PeerManagerImpl::FinalizeNode(const CNode& node)
1490
1496
for (const QueuedBlock& entry : state->vBlocksInFlight ) {
1491
1497
mapBlocksInFlight.erase (entry.pindex ->GetBlockHash ());
1492
1498
}
1493
- WITH_LOCK (g_cs_orphans, m_orphanage.EraseForPeer (nodeid) );
1499
+ m_orphanage.EraseForPeer (nodeid);
1494
1500
m_txrequest.DisconnectedPeer (nodeid);
1495
1501
if (m_txreconciliation) m_txreconciliation->ForgetPeer (nodeid);
1496
1502
m_num_preferred_download_peers -= state->fPreferredDownload ;
@@ -2880,33 +2886,24 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
2880
2886
return ;
2881
2887
}
2882
2888
2883
- /* *
2884
- * Reconsider orphan transactions after a parent has been accepted to the mempool.
2885
- *
2886
- * @param[in,out] orphan_work_set The set of orphan transactions to reconsider. Generally only one
2887
- * orphan will be reconsidered on each call of this function. This set
2888
- * may be added to if accepting an orphan causes its children to be
2889
- * reconsidered.
2890
- */
2891
- void PeerManagerImpl::ProcessOrphanTx (std::set<uint256>& orphan_work_set)
2889
+ bool PeerManagerImpl::ProcessOrphanTx (Peer& peer)
2892
2890
{
2891
+ AssertLockHeld (g_msgproc_mutex);
2893
2892
AssertLockHeld (cs_main);
2894
- AssertLockHeld (g_cs_orphans);
2895
-
2896
- while (!orphan_work_set.empty ()) {
2897
- const uint256 orphanHash = *orphan_work_set.begin ();
2898
- orphan_work_set.erase (orphan_work_set.begin ());
2899
2893
2900
- const auto [porphanTx, from_peer] = m_orphanage.GetTx (orphanHash);
2901
- if (porphanTx == nullptr ) continue ;
2894
+ CTransactionRef porphanTx = nullptr ;
2895
+ NodeId from_peer = -1 ;
2896
+ bool more = false ;
2902
2897
2898
+ while (CTransactionRef porphanTx = m_orphanage.GetTxToReconsider (peer.m_id , from_peer, more)) {
2903
2899
const MempoolAcceptResult result = m_chainman.ProcessTransaction (porphanTx);
2904
2900
const TxValidationState& state = result.m_state ;
2901
+ const uint256& orphanHash = porphanTx->GetHash ();
2905
2902
2906
2903
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
2907
2904
LogPrint (BCLog::MEMPOOL, " accepted orphan tx %s\n " , orphanHash.ToString ());
2908
2905
RelayTransaction (orphanHash, porphanTx->GetWitnessHash ());
2909
- m_orphanage.AddChildrenToWorkSet (*porphanTx, orphan_work_set );
2906
+ m_orphanage.AddChildrenToWorkSet (*porphanTx, peer. m_id );
2910
2907
m_orphanage.EraseTx (orphanHash);
2911
2908
for (const CTransactionRef& removedTx : result.m_replaced_transactions .value ()) {
2912
2909
AddToCompactExtraTransactions (removedTx);
@@ -2957,6 +2954,8 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
2957
2954
break ;
2958
2955
}
2959
2956
}
2957
+
2958
+ return more;
2960
2959
}
2961
2960
2962
2961
bool PeerManagerImpl::PrepareBlockFilterRequest (CNode& node, Peer& peer,
@@ -3990,7 +3989,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3990
3989
AddKnownTx (*peer, txid);
3991
3990
}
3992
3991
3993
- LOCK2 (cs_main, g_cs_orphans );
3992
+ LOCK (cs_main);
3994
3993
3995
3994
m_txrequest.ReceivedResponse (pfrom.GetId (), txid);
3996
3995
if (tx.HasWitness ()) m_txrequest.ReceivedResponse (pfrom.GetId (), wtxid);
@@ -4031,7 +4030,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4031
4030
m_txrequest.ForgetTxHash (tx.GetHash ());
4032
4031
m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
4033
4032
RelayTransaction (tx.GetHash (), tx.GetWitnessHash ());
4034
- m_orphanage.AddChildrenToWorkSet (tx, peer->m_orphan_work_set );
4033
+ m_orphanage.AddChildrenToWorkSet (tx, peer->m_id );
4035
4034
4036
4035
pfrom.m_last_tx_time = GetTime<std::chrono::seconds>();
4037
4036
@@ -4045,7 +4044,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4045
4044
}
4046
4045
4047
4046
// Recursively process any orphan transactions that depended on this one
4048
- ProcessOrphanTx (peer-> m_orphan_work_set );
4047
+ ProcessOrphanTx (* peer);
4049
4048
}
4050
4049
else if (state.GetResult () == TxValidationResult::TX_MISSING_INPUTS)
4051
4050
{
@@ -4226,7 +4225,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4226
4225
bool fBlockReconstructed = false ;
4227
4226
4228
4227
{
4229
- LOCK2 (cs_main, g_cs_orphans );
4228
+ LOCK (cs_main);
4230
4229
// If AcceptBlockHeader returned true, it set pindex
4231
4230
assert (pindex);
4232
4231
UpdateBlockAvailability (pfrom.GetId (), pindex->GetBlockHash ());
@@ -4854,28 +4853,24 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt
4854
4853
}
4855
4854
}
4856
4855
4856
+ bool has_more_orphans;
4857
4857
{
4858
- LOCK2 (cs_main, g_cs_orphans);
4859
- if (!peer->m_orphan_work_set .empty ()) {
4860
- ProcessOrphanTx (peer->m_orphan_work_set );
4861
- }
4858
+ LOCK (cs_main);
4859
+ has_more_orphans = ProcessOrphanTx (*peer);
4862
4860
}
4863
4861
4864
4862
if (pfrom->fDisconnect )
4865
4863
return false ;
4866
4864
4865
+ if (has_more_orphans) return true ;
4866
+
4867
4867
// this maintains the order of responses
4868
4868
// and prevents m_getdata_requests to grow unbounded
4869
4869
{
4870
4870
LOCK (peer->m_getdata_requests_mutex );
4871
4871
if (!peer->m_getdata_requests .empty ()) return true ;
4872
4872
}
4873
4873
4874
- {
4875
- LOCK (g_cs_orphans);
4876
- if (!peer->m_orphan_work_set .empty ()) return true ;
4877
- }
4878
-
4879
4874
// Don't bother if send buffer is too full to respond anyway
4880
4875
if (pfrom->fPauseSend ) return false ;
4881
4876
0 commit comments