@@ -174,40 +174,6 @@ std::set<CBlockIndex*> setDirtyBlockIndex;
174174std::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-
211177CBlockIndex* 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 {
20632033private:
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
20662039public:
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