@@ -157,6 +157,39 @@ namespace {
157
157
set<int > setDirtyFileInfo;
158
158
} // anon namespace
159
159
160
+ /* Use this class to start tracking transactions that are removed from the
161
+ * mempool and pass all those transactions through SyncTransaction when the
162
+ * object goes out of scope. This is currently only used to call SyncTransaction
163
+ * on conflicts removed from the mempool during block connection. Applied in
164
+ * ActivateBestChain around ActivateBestStep which in turn calls:
165
+ * ConnectTip->removeForBlock->removeConflicts
166
+ */
167
+ class MemPoolConflictRemovalTracker
168
+ {
169
+ private:
170
+ std::vector<CTransactionRef> conflictedTxs;
171
+ CTxMemPool &pool;
172
+
173
+ public:
174
+ MemPoolConflictRemovalTracker (CTxMemPool &_pool) : pool(_pool) {
175
+ pool.NotifyEntryRemoved .connect (boost::bind (&MemPoolConflictRemovalTracker::NotifyEntryRemoved, this , _1, _2));
176
+ }
177
+
178
+ void NotifyEntryRemoved (CTransactionRef txRemoved, MemPoolRemovalReason reason) {
179
+ if (reason == MemPoolRemovalReason::CONFLICT) {
180
+ conflictedTxs.push_back (txRemoved);
181
+ }
182
+ }
183
+
184
+ ~MemPoolConflictRemovalTracker () {
185
+ pool.NotifyEntryRemoved .disconnect (boost::bind (&MemPoolConflictRemovalTracker::NotifyEntryRemoved, this , _1, _2));
186
+ for (const auto & tx : conflictedTxs) {
187
+ GetMainSignals ().SyncTransaction (*tx, NULL , CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
188
+ }
189
+ conflictedTxs.clear ();
190
+ }
191
+ };
192
+
160
193
CBlockIndex* FindForkInGlobalIndex (const CChain& chain, const CBlockLocator& locator)
161
194
{
162
195
// Find the first block the caller has in the main chain
@@ -2453,6 +2486,14 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
2453
2486
bool fInitialDownload ;
2454
2487
{
2455
2488
LOCK (cs_main);
2489
+ { // TODO: Tempoarily ensure that mempool removals are notified before
2490
+ // connected transactions. This shouldn't matter, but the abandoned
2491
+ // state of transactions in our wallet is currently cleared when we
2492
+ // receive another notification and there is a race condition where
2493
+ // notification of a connected conflict might cause an outside process
2494
+ // to abandon a transaction and then have it inadvertantly cleared by
2495
+ // the notification that the conflicted transaction was evicted.
2496
+ MemPoolConflictRemovalTracker mrt (mempool);
2456
2497
CBlockIndex *pindexOldTip = chainActive.Tip ();
2457
2498
if (pindexMostWork == NULL ) {
2458
2499
pindexMostWork = FindMostWorkChain ();
@@ -2476,6 +2517,10 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
2476
2517
fInitialDownload = IsInitialBlockDownload ();
2477
2518
2478
2519
// throw all transactions though the signal-interface
2520
+
2521
+ } // MemPoolConflictRemovalTracker destroyed and conflict evictions are notified
2522
+
2523
+ // Transactions in the connnected block are notified
2479
2524
for (const auto & pair : connectTrace.blocksConnected ) {
2480
2525
assert (pair.second );
2481
2526
const CBlock& block = *(pair.second );
0 commit comments