Skip to content

Commit 4172102

Browse files
committed
merge bitcoin#26295: Replace global g_cs_orphans lock with local
This commit will not compile as-is as block based orphan reprocessing, a Dash-ism, has not been adapted to work with this refactor. That has been segmented out into a separate commit to aid in review.
1 parent 3665919 commit 4172102

File tree

8 files changed

+130
-103
lines changed

8 files changed

+130
-103
lines changed

src/init.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
#include <torcontrol.h>
6363
#include <txdb.h>
6464
#include <txmempool.h>
65-
#include <txorphanage.h>
6665
#include <util/asmap.h>
6766
#include <util/error.h>
6867
#include <util/moneystr.h>

src/net_processing.cpp

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
20072013
void 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

32483247
bool 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

src/test/fuzz/process_message.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include <test/util/net.h>
2020
#include <test/util/setup_common.h>
2121
#include <test/util/validation.h>
22-
#include <txorphanage.h>
2322
#include <validationinterface.h>
2423
#include <version.h>
2524

src/test/fuzz/process_messages.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include <test/util/net.h>
1414
#include <test/util/setup_common.h>
1515
#include <test/util/validation.h>
16-
#include <txorphanage.h>
1716
#include <validation.h>
1817
#include <validationinterface.h>
1918

src/test/fuzz/txorphan.cpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
4040
SetMockTime(ConsumeTime(fuzzed_data_provider));
4141

4242
TxOrphanage orphanage;
43-
std::set<uint256> orphan_work_set;
4443
std::vector<COutPoint> outpoints;
4544
// initial outpoints used to construct transactions later
4645
for (uint8_t i = 0; i < 4; i++) {
@@ -90,30 +89,32 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
9089
CallOneOf(
9190
fuzzed_data_provider,
9291
[&] {
93-
LOCK(g_cs_orphans);
94-
orphanage.AddChildrenToWorkSet(*tx, orphan_work_set);
92+
orphanage.AddChildrenToWorkSet(*tx, peer_id);
9593
},
9694
[&] {
97-
bool have_tx = orphanage.HaveTx(tx->GetHash());
9895
{
99-
LOCK(g_cs_orphans);
100-
bool get_tx = orphanage.GetTx(tx->GetHash()).first != nullptr;
101-
Assert(have_tx == get_tx);
96+
NodeId originator;
97+
bool more = true;
98+
CTransactionRef ref = orphanage.GetTxToReconsider(peer_id, originator, more);
99+
if (!ref) {
100+
Assert(!more);
101+
} else {
102+
bool have_tx = orphanage.HaveTx(ref->GetHash());
103+
Assert(have_tx);
104+
}
102105
}
103106
},
104107
[&] {
105108
bool have_tx = orphanage.HaveTx(tx->GetHash());
106109
// AddTx should return false if tx is too big or already have it
107110
// tx size is unknown, we only check when tx is already in orphanage
108111
{
109-
LOCK(g_cs_orphans);
110112
bool add_tx = orphanage.AddTx(tx, peer_id);
111113
// have_tx == true -> add_tx == false
112114
Assert(!have_tx || !add_tx);
113115
}
114116
have_tx = orphanage.HaveTx(tx->GetHash());
115117
{
116-
LOCK(g_cs_orphans);
117118
bool add_tx = orphanage.AddTx(tx, peer_id);
118119
// if have_tx is still false, it must be too big
119120
Assert(!have_tx == (::GetSerializeSize(*tx, PROTOCOL_VERSION) > MAX_STANDARD_TX_SIZE));
@@ -124,25 +125,22 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
124125
bool have_tx = orphanage.HaveTx(tx->GetHash());
125126
// EraseTx should return 0 if m_orphans doesn't have the tx
126127
{
127-
LOCK(g_cs_orphans);
128128
Assert(have_tx == orphanage.EraseTx(tx->GetHash()));
129129
}
130130
have_tx = orphanage.HaveTx(tx->GetHash());
131131
// have_tx should be false and EraseTx should fail
132132
{
133-
LOCK(g_cs_orphans);
134133
Assert(!have_tx && !orphanage.EraseTx(tx->GetHash()));
135134
}
136135
},
137136
[&] {
138-
LOCK(g_cs_orphans);
139137
orphanage.EraseForPeer(peer_id);
140138
},
141139
[&] {
142140
// test mocktime and expiry
143141
SetMockTime(ConsumeTime(fuzzed_data_provider));
144142
auto limit = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
145-
WITH_LOCK(g_cs_orphans, orphanage.LimitOrphans(limit));
143+
orphanage.LimitOrphans(limit);
146144
Assert(orphanage.Size() <= limit);
147145
});
148146
}

src/test/orphanage_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ BOOST_FIXTURE_TEST_SUITE(orphanage_tests, TestingSetup)
2020
class TxOrphanageTest : public TxOrphanage
2121
{
2222
public:
23-
inline size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
23+
inline size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
2424
{
25+
LOCK(m_mutex);
2526
return m_orphans.size();
2627
}
2728

28-
CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
29+
CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
2930
{
31+
LOCK(m_mutex);
3032
std::map<uint256, OrphanTx>::iterator it;
3133
it = m_orphans.lower_bound(InsecureRand256());
3234
if (it == m_orphans.end())
@@ -59,8 +61,6 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
5961
FillableSigningProvider keystore;
6062
BOOST_CHECK(keystore.AddKey(key));
6163

62-
LOCK(g_cs_orphans);
63-
6464
// 50 orphan transactions:
6565
for (int i = 0; i < 50; i++)
6666
{

0 commit comments

Comments
 (0)