Skip to content

Commit 5d28013

Browse files
committed
Merge bitcoin/bitcoin#30507: m_tx_download_mutex followups
7c29e55 m_tx_download_mutex followups (glozow) e543c65 release m_tx_download_mutex before MakeAndPushMessage GETDATA (glozow) bce5f37 [refactor] change ActiveTipChange to use CBlockIndex ref instead of ptr (glozow) 7cc5ac5 [doc] TxOrphanage is no longer thread-safe (glozow) 6f49548 [refactor] combine block vtx loops in BlockConnected (glozow) Pull request description: Followup to #30111. Includes suggestions: - bitcoin/bitcoin#30111 (comment) - bitcoin/bitcoin#30111 (comment) - bitcoin/bitcoin#30111 (comment) - bitcoin/bitcoin#30111 (comment) - bitcoin/bitcoin#30111 (comment) ACKs for top commit: instagibbs: reACK bitcoin/bitcoin@7c29e55 theStack: re-ACK 7c29e55 dergoegge: reACK 7c29e55 Tree-SHA512: 79a9002d74739367789bbc64bb1d431f4d43a25a7934231e55814c2cb6981c15ef2d8465544ae2a4fbd734d9bed6cc41b37a923938a88cb8fea139523c1e98da
2 parents 119a0fa + 7c29e55 commit 5d28013

File tree

5 files changed

+39
-37
lines changed

5 files changed

+39
-37
lines changed

src/net_processing.cpp

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ class PeerManagerImpl final : public PeerManager
489489
CTxMemPool& pool, node::Warnings& warnings, Options opts);
490490

491491
/** Overridden from CValidationInterface. */
492-
void ActiveTipChange(const CBlockIndex* new_tip, bool) override
492+
void ActiveTipChange(const CBlockIndex& new_tip, bool) override
493493
EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);
494494
void BlockConnected(ChainstateRole role, const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override
495495
EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);
@@ -780,10 +780,8 @@ class PeerManagerImpl final : public PeerManager
780780
* - A txhash (txid or wtxid) in m_txrequest is not also in m_recent_rejects_reconsiderable.
781781
* - A txhash (txid or wtxid) in m_txrequest is not also in m_recent_confirmed_transactions.
782782
* - Each data structure's limits hold (m_orphanage max size, m_txrequest per-peer limits, etc).
783-
*
784-
* m_tx_download_mutex must be acquired before mempool.cs
785783
*/
786-
Mutex m_tx_download_mutex;
784+
Mutex m_tx_download_mutex ACQUIRED_BEFORE(m_mempool.cs);
787785
TxRequestTracker m_txrequest GUARDED_BY(m_tx_download_mutex);
788786
std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
789787

@@ -2070,8 +2068,10 @@ void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
20702068
scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
20712069
}
20722070

2073-
void PeerManagerImpl::ActiveTipChange(const CBlockIndex* new_tip, bool is_ibd)
2071+
void PeerManagerImpl::ActiveTipChange(const CBlockIndex& new_tip, bool is_ibd)
20742072
{
2073+
// Ensure mempool mutex was released, otherwise deadlock may occur if another thread holding
2074+
// m_tx_download_mutex waits on the mempool mutex.
20752075
AssertLockNotHeld(m_mempool.cs);
20762076
AssertLockNotHeld(m_tx_download_mutex);
20772077

@@ -2123,8 +2123,6 @@ void PeerManagerImpl::BlockConnected(
21232123
if (ptx->HasWitness()) {
21242124
m_recent_confirmed_transactions.insert(ptx->GetWitnessHash().ToUint256());
21252125
}
2126-
}
2127-
for (const auto& ptx : pblock->vtx) {
21282126
m_txrequest.ForgetTxHash(ptx->GetHash());
21292127
m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
21302128
}
@@ -5336,6 +5334,7 @@ bool PeerManagerImpl::MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer)
53365334

53375335
bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgProc)
53385336
{
5337+
AssertLockNotHeld(m_tx_download_mutex);
53395338
AssertLockHeld(g_msgproc_mutex);
53405339

53415340
PeerRef peer = GetPeerRef(pfrom->GetId());
@@ -5827,6 +5826,7 @@ bool PeerManagerImpl::SetupAddressRelay(const CNode& node, Peer& peer)
58275826

58285827
bool PeerManagerImpl::SendMessages(CNode* pto)
58295828
{
5829+
AssertLockNotHeld(m_tx_download_mutex);
58305830
AssertLockHeld(g_msgproc_mutex);
58315831

58325832
PeerRef peer = GetPeerRef(pto->GetId());
@@ -6297,32 +6297,33 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
62976297
//
62986298
// Message: getdata (transactions)
62996299
//
6300-
LOCK(m_tx_download_mutex);
6301-
std::vector<std::pair<NodeId, GenTxid>> expired;
6302-
auto requestable = m_txrequest.GetRequestable(pto->GetId(), current_time, &expired);
6303-
for (const auto& entry : expired) {
6304-
LogPrint(BCLog::NET, "timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ? "wtx" : "tx",
6305-
entry.second.GetHash().ToString(), entry.first);
6306-
}
6307-
for (const GenTxid& gtxid : requestable) {
6308-
// Exclude m_recent_rejects_reconsiderable: we may be requesting a missing parent
6309-
// that was previously rejected for being too low feerate.
6310-
if (!AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false)) {
6311-
LogPrint(BCLog::NET, "Requesting %s %s peer=%d\n", gtxid.IsWtxid() ? "wtx" : "tx",
6312-
gtxid.GetHash().ToString(), pto->GetId());
6313-
vGetData.emplace_back(gtxid.IsWtxid() ? MSG_WTX : (MSG_TX | GetFetchFlags(*peer)), gtxid.GetHash());
6314-
if (vGetData.size() >= MAX_GETDATA_SZ) {
6315-
MakeAndPushMessage(*pto, NetMsgType::GETDATA, vGetData);
6316-
vGetData.clear();
6300+
{
6301+
LOCK(m_tx_download_mutex);
6302+
std::vector<std::pair<NodeId, GenTxid>> expired;
6303+
auto requestable = m_txrequest.GetRequestable(pto->GetId(), current_time, &expired);
6304+
for (const auto& entry : expired) {
6305+
LogPrint(BCLog::NET, "timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ? "wtx" : "tx",
6306+
entry.second.GetHash().ToString(), entry.first);
6307+
}
6308+
for (const GenTxid& gtxid : requestable) {
6309+
// Exclude m_recent_rejects_reconsiderable: we may be requesting a missing parent
6310+
// that was previously rejected for being too low feerate.
6311+
if (!AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false)) {
6312+
LogPrint(BCLog::NET, "Requesting %s %s peer=%d\n", gtxid.IsWtxid() ? "wtx" : "tx",
6313+
gtxid.GetHash().ToString(), pto->GetId());
6314+
vGetData.emplace_back(gtxid.IsWtxid() ? MSG_WTX : (MSG_TX | GetFetchFlags(*peer)), gtxid.GetHash());
6315+
if (vGetData.size() >= MAX_GETDATA_SZ) {
6316+
MakeAndPushMessage(*pto, NetMsgType::GETDATA, vGetData);
6317+
vGetData.clear();
6318+
}
6319+
m_txrequest.RequestedTx(pto->GetId(), gtxid.GetHash(), current_time + GETDATA_TX_INTERVAL);
6320+
} else {
6321+
// We have already seen this transaction, no need to download. This is just a belt-and-suspenders, as
6322+
// this should already be called whenever a transaction becomes AlreadyHaveTx().
6323+
m_txrequest.ForgetTxHash(gtxid.GetHash());
63176324
}
6318-
m_txrequest.RequestedTx(pto->GetId(), gtxid.GetHash(), current_time + GETDATA_TX_INTERVAL);
6319-
} else {
6320-
// We have already seen this transaction, no need to download. This is just a belt-and-suspenders, as
6321-
// this should already be called whenever a transaction becomes AlreadyHaveTx().
6322-
m_txrequest.ForgetTxHash(gtxid.GetHash());
63236325
}
6324-
}
6325-
6326+
} // release m_tx_download_mutex
63266327

63276328
if (!vGetData.empty())
63286329
MakeAndPushMessage(*pto, NetMsgType::GETDATA, vGetData);

src/txorphanage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* Since we cannot distinguish orphans from bad transactions with
1919
* non-existent inputs, we heavily limit the number of orphans
2020
* we keep and the duration we keep them for.
21+
* Not thread-safe. Requires external synchronization.
2122
*/
2223
class TxOrphanage {
2324
public:

src/validation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3553,7 +3553,7 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
35533553
} // release MempoolMutex
35543554
// Notify external listeners about the new tip, even if pindexFork == pindexNewTip.
35553555
if (m_chainman.m_options.signals && this == &m_chainman.ActiveChainstate()) {
3556-
m_chainman.m_options.signals->ActiveTipChange(pindexNewTip, m_chainman.IsInitialBlockDownload());
3556+
m_chainman.m_options.signals->ActiveTipChange(*Assert(pindexNewTip), m_chainman.IsInitialBlockDownload());
35573557
}
35583558
} // release cs_main
35593559
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
@@ -3778,7 +3778,7 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
37783778
// Fire ActiveTipChange now for the current chain tip to make sure clients are notified.
37793779
// ActivateBestChain may call this as well, but not necessarily.
37803780
if (m_chainman.m_options.signals) {
3781-
m_chainman.m_options.signals->ActiveTipChange(m_chain.Tip(), m_chainman.IsInitialBlockDownload());
3781+
m_chainman.m_options.signals->ActiveTipChange(*Assert(m_chain.Tip()), m_chainman.IsInitialBlockDownload());
37823782
}
37833783
}
37843784
return true;

src/validationinterface.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ void ValidationSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlo
183183
fInitialDownload);
184184
}
185185

186-
void ValidationSignals::ActiveTipChange(const CBlockIndex *new_tip, bool is_ibd)
186+
void ValidationSignals::ActiveTipChange(const CBlockIndex& new_tip, bool is_ibd)
187187
{
188-
LOG_EVENT("%s: new block hash=%s block height=%d", __func__, new_tip->GetBlockHash().ToString(), new_tip->nHeight);
188+
LOG_EVENT("%s: new block hash=%s block height=%d", __func__, new_tip.GetBlockHash().ToString(), new_tip.nHeight);
189189
m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.ActiveTipChange(new_tip, is_ibd); });
190190
}
191191

src/validationinterface.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class CValidationInterface {
6464
/**
6565
* Notifies listeners any time the block chain tip changes, synchronously.
6666
*/
67-
virtual void ActiveTipChange(const CBlockIndex* new_tip, bool is_ibd) {};
67+
virtual void ActiveTipChange(const CBlockIndex& new_tip, bool is_ibd) {};
6868
/**
6969
* Notifies listeners of a transaction having been added to mempool.
7070
*
@@ -218,7 +218,7 @@ class ValidationSignals {
218218
void SyncWithValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main);
219219

220220
void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload);
221-
void ActiveTipChange(const CBlockIndex*, bool);
221+
void ActiveTipChange(const CBlockIndex&, bool);
222222
void TransactionAddedToMempool(const NewMempoolTransactionInfo&, uint64_t mempool_sequence);
223223
void TransactionRemovedFromMempool(const CTransactionRef&, MemPoolRemovalReason, uint64_t mempool_sequence);
224224
void MempoolTransactionsRemovedForBlock(const std::vector<RemovedMempoolTransactionInfo>&, unsigned int nBlockHeight);

0 commit comments

Comments
 (0)