@@ -154,39 +154,6 @@ namespace {
154
154
std::set<int > setDirtyFileInfo;
155
155
} // anon namespace
156
156
157
- /* Use this class to start tracking transactions that are removed from the
158
- * mempool and pass all those transactions through SyncTransaction when the
159
- * object goes out of scope. This is currently only used to call SyncTransaction
160
- * on conflicts removed from the mempool during block connection. Applied in
161
- * ActivateBestChain around ActivateBestStep which in turn calls:
162
- * ConnectTip->removeForBlock->removeConflicts
163
- */
164
- class MemPoolConflictRemovalTracker
165
- {
166
- private:
167
- std::vector<CTransactionRef> conflictedTxs;
168
- CTxMemPool &pool;
169
-
170
- public:
171
- MemPoolConflictRemovalTracker (CTxMemPool &_pool) : pool(_pool) {
172
- pool.NotifyEntryRemoved .connect (boost::bind (&MemPoolConflictRemovalTracker::NotifyEntryRemoved, this , _1, _2));
173
- }
174
-
175
- void NotifyEntryRemoved (CTransactionRef txRemoved, MemPoolRemovalReason reason) {
176
- if (reason == MemPoolRemovalReason::CONFLICT) {
177
- conflictedTxs.push_back (txRemoved);
178
- }
179
- }
180
-
181
- ~MemPoolConflictRemovalTracker () {
182
- pool.NotifyEntryRemoved .disconnect (boost::bind (&MemPoolConflictRemovalTracker::NotifyEntryRemoved, this , _1, _2));
183
- for (const auto & tx : conflictedTxs) {
184
- GetMainSignals ().SyncTransaction (*tx, NULL , CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
185
- }
186
- conflictedTxs.clear ();
187
- }
188
- };
189
-
190
157
CBlockIndex* FindForkInGlobalIndex (const CChain& chain, const CBlockLocator& locator)
191
158
{
192
159
// Find the first block the caller has in the main chain
@@ -2210,19 +2177,46 @@ static int64_t nTimePostConnect = 0;
2210
2177
/* *
2211
2178
* Used to track blocks whose transactions were applied to the UTXO state as a
2212
2179
* part of a single ActivateBestChainStep call.
2180
+ *
2181
+ * This class also tracks transactions that are removed from the mempool as
2182
+ * conflicts and can be used to pass all those transactions through
2183
+ * SyncTransaction.
2213
2184
*/
2214
- struct ConnectTrace {
2185
+ class ConnectTrace {
2215
2186
private:
2216
2187
std::vector<std::pair<CBlockIndex*, std::shared_ptr<const CBlock> > > blocksConnected;
2188
+ std::vector<CTransactionRef> conflictedTxs;
2189
+ CTxMemPool &pool;
2217
2190
2218
2191
public:
2192
+ ConnectTrace (CTxMemPool &_pool) : pool(_pool) {
2193
+ pool.NotifyEntryRemoved .connect (boost::bind (&ConnectTrace::NotifyEntryRemoved, this , _1, _2));
2194
+ }
2195
+
2196
+ ~ConnectTrace () {
2197
+ pool.NotifyEntryRemoved .disconnect (boost::bind (&ConnectTrace::NotifyEntryRemoved, this , _1, _2));
2198
+ }
2199
+
2219
2200
void BlockConnected (CBlockIndex* pindex, std::shared_ptr<const CBlock> pblock) {
2220
2201
blocksConnected.emplace_back (pindex, std::move (pblock));
2221
2202
}
2222
2203
2223
2204
std::vector<std::pair<CBlockIndex*, std::shared_ptr<const CBlock> > >& GetBlocksConnected () {
2224
2205
return blocksConnected;
2225
2206
}
2207
+
2208
+ void NotifyEntryRemoved (CTransactionRef txRemoved, MemPoolRemovalReason reason) {
2209
+ if (reason == MemPoolRemovalReason::CONFLICT) {
2210
+ conflictedTxs.push_back (txRemoved);
2211
+ }
2212
+ }
2213
+
2214
+ void CallSyncTransactionOnConflictedTransactions () {
2215
+ for (const auto & tx : conflictedTxs) {
2216
+ GetMainSignals ().SyncTransaction (*tx, NULL , CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
2217
+ }
2218
+ conflictedTxs.clear ();
2219
+ }
2226
2220
};
2227
2221
2228
2222
/* *
@@ -2470,18 +2464,11 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
2470
2464
break ;
2471
2465
2472
2466
const CBlockIndex *pindexFork;
2473
- ConnectTrace connectTrace;
2474
2467
bool fInitialDownload ;
2475
2468
{
2476
2469
LOCK (cs_main);
2477
- { // TODO: Temporarily ensure that mempool removals are notified before
2478
- // connected transactions. This shouldn't matter, but the abandoned
2479
- // state of transactions in our wallet is currently cleared when we
2480
- // receive another notification and there is a race condition where
2481
- // notification of a connected conflict might cause an outside process
2482
- // to abandon a transaction and then have it inadvertently cleared by
2483
- // the notification that the conflicted transaction was evicted.
2484
- MemPoolConflictRemovalTracker mrt (mempool);
2470
+ ConnectTrace connectTrace (mempool); // Destructed before cs_main is unlocked
2471
+
2485
2472
CBlockIndex *pindexOldTip = chainActive.Tip ();
2486
2473
if (pindexMostWork == NULL ) {
2487
2474
pindexMostWork = FindMostWorkChain ();
@@ -2505,8 +2492,15 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
2505
2492
fInitialDownload = IsInitialBlockDownload ();
2506
2493
2507
2494
// throw all transactions though the signal-interface
2508
-
2509
- } // MemPoolConflictRemovalTracker destroyed and conflict evictions are notified
2495
+ connectTrace.CallSyncTransactionOnConflictedTransactions ();
2496
+
2497
+ // TODO: Temporarily ensure that mempool removals are notified before
2498
+ // connected transactions. This shouldn't matter, but the abandoned
2499
+ // state of transactions in our wallet is currently cleared when we
2500
+ // receive another notification and there is a race condition where
2501
+ // notification of a connected conflict might cause an outside process
2502
+ // to abandon a transaction and then have it inadvertently cleared by
2503
+ // the notification that the conflicted transaction was evicted.
2510
2504
2511
2505
// Transactions in the connected block are notified
2512
2506
for (const auto & pair : connectTrace.GetBlocksConnected ()) {
0 commit comments