Skip to content

Commit 50d3e0e

Browse files
committed
Handle conflicted transactions directly in ConnectTrace
Adapted version of btc@d3167ba9bbefc2e5b7062f81c481547f21c5e44b
1 parent 27fb897 commit 50d3e0e

File tree

1 file changed

+39
-45
lines changed

1 file changed

+39
-45
lines changed

src/validation.cpp

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -174,40 +174,6 @@ std::set<CBlockIndex*> setDirtyBlockIndex;
174174
std::set<int> setDirtyFileInfo;
175175
} // anon namespace
176176

177-
/* Use this class to start tracking transactions that are removed from the
178-
* mempool and pass all those transactions through SyncTransaction when the
179-
* object goes out of scope. This is currently only used to call SyncTransaction
180-
* on conflicts removed from the mempool during block connection. Applied in
181-
* ActivateBestChain around ActivateBestStep which in turn calls:
182-
* ConnectTip->removeForBlock->removeConflicts
183-
*/
184-
class MemPoolConflictRemovalTracker
185-
{
186-
private:
187-
std::vector<CTransactionRef> conflictedTxs;
188-
CTxMemPool &pool;
189-
std::unique_ptr<interfaces::Handler> m_handler_notify_entry_removed;
190-
191-
public:
192-
MemPoolConflictRemovalTracker(CTxMemPool &_pool) : pool(_pool) {
193-
m_handler_notify_entry_removed = interfaces::MakeHandler(pool.NotifyEntryRemoved.connect(std::bind(&MemPoolConflictRemovalTracker::NotifyEntryRemoved, this, std::placeholders::_1, std::placeholders::_2)));
194-
}
195-
196-
void NotifyEntryRemoved(CTransactionRef txRemoved, MemPoolRemovalReason reason) {
197-
if (reason == MemPoolRemovalReason::CONFLICT) {
198-
conflictedTxs.push_back(txRemoved);
199-
}
200-
}
201-
202-
~MemPoolConflictRemovalTracker() {
203-
m_handler_notify_entry_removed->disconnect();
204-
for (const auto& tx : conflictedTxs) {
205-
GetMainSignals().SyncTransaction(*tx, nullptr, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
206-
}
207-
conflictedTxs.clear();
208-
}
209-
};
210-
211177
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
212178
{
213179
// Find the first block the caller has in the main chain
@@ -2058,19 +2024,47 @@ static int64_t nTimePostConnect = 0;
20582024
/**
20592025
* Used to track blocks whose transactions were applied to the UTXO state as a
20602026
* part of a single ActivateBestChainStep call.
2027+
*
2028+
* This class also tracks transactions that are removed from the mempool as
2029+
* conflicts and can be used to pass all those transactions through
2030+
* SyncTransaction.
20612031
*/
2062-
struct ConnectTrace {
2032+
class ConnectTrace {
20632033
private:
20642034
std::vector<std::pair<CBlockIndex*, std::shared_ptr<const CBlock> > > blocksConnected;
2035+
std::vector<CTransactionRef> conflictedTxs;
2036+
CTxMemPool &pool;
2037+
std::unique_ptr<interfaces::Handler> m_handler_notify_entry_removed;
20652038

20662039
public:
2040+
ConnectTrace(CTxMemPool &_pool) : pool(_pool) {
2041+
m_handler_notify_entry_removed = interfaces::MakeHandler(pool.NotifyEntryRemoved.connect(std::bind(&ConnectTrace::NotifyEntryRemoved, this, std::placeholders::_1, std::placeholders::_2)));
2042+
}
2043+
2044+
~ConnectTrace() {
2045+
m_handler_notify_entry_removed->disconnect();
2046+
}
2047+
20672048
void BlockConnected(CBlockIndex* pindex, std::shared_ptr<const CBlock> pblock) {
20682049
blocksConnected.emplace_back(pindex, std::move(pblock));
20692050
}
20702051

20712052
std::vector<std::pair<CBlockIndex*, std::shared_ptr<const CBlock> > >& GetBlocksConnected() {
20722053
return blocksConnected;
20732054
}
2055+
2056+
void NotifyEntryRemoved(CTransactionRef txRemoved, MemPoolRemovalReason reason) {
2057+
if (reason == MemPoolRemovalReason::CONFLICT) {
2058+
conflictedTxs.emplace_back(txRemoved);
2059+
}
2060+
}
2061+
2062+
void CallSyncTransactionOnConflictedTransactions() {
2063+
for (const auto& tx : conflictedTxs) {
2064+
GetMainSignals().SyncTransaction(*tx, nullptr, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
2065+
}
2066+
conflictedTxs.clear();
2067+
}
20742068
};
20752069

20762070
/**
@@ -2321,22 +2315,15 @@ bool ActivateBestChain(CValidationState& state, std::shared_ptr<const CBlock> pb
23212315
boost::this_thread::interruption_point();
23222316

23232317
const CBlockIndex *pindexFork;
2324-
ConnectTrace connectTrace;
23252318
bool fInitialDownload;
23262319
while (true) {
23272320
TRY_LOCK(cs_main, lockMain);
23282321
if (!lockMain) {
23292322
MilliSleep(50);
23302323
continue;
23312324
}
2332-
{ // TODO: Temporarily ensure that mempool removals are notified before
2333-
// connected transactions. This shouldn't matter, but the abandoned
2334-
// state of transactions in our wallet is currently cleared when we
2335-
// receive another notification and there is a race condition where
2336-
// notification of a connected conflict might cause an outside process
2337-
// to abandon a transaction and then have it inadvertently cleared by
2338-
// the notification that the conflicted transaction was evicted.
2339-
MemPoolConflictRemovalTracker mrt(mempool);
2325+
ConnectTrace connectTrace(mempool); // Destructed before cs_main is unlocked
2326+
23402327
CBlockIndex *pindexOldTip = chainActive.Tip();
23412328
pindexMostWork = FindMostWorkChain();
23422329

@@ -2353,8 +2340,15 @@ bool ActivateBestChain(CValidationState& state, std::shared_ptr<const CBlock> pb
23532340
fInitialDownload = IsInitialBlockDownload();
23542341

23552342
// throw all transactions though the signal-interface
2343+
connectTrace.CallSyncTransactionOnConflictedTransactions();
23562344

2357-
} // MemPoolConflictRemovalTracker destroyed and conflict evictions are notified
2345+
// TODO: Temporarily ensure that mempool removals are notified before
2346+
// connected transactions. This shouldn't matter, but the abandoned
2347+
// state of transactions in our wallet is currently cleared when we
2348+
// receive another notification and there is a race condition where
2349+
// notification of a connected conflict might cause an outside process
2350+
// to abandon a transaction and then have it inadvertently cleared by
2351+
// the notification that the conflicted transaction was evicted.
23582352

23592353
// Transactions in the connnected block are notified
23602354
for (const auto& pair : connectTrace.GetBlocksConnected()) {

0 commit comments

Comments
 (0)