diff --git a/src/txmempool.cpp b/src/txmempool.cpp index e021cfb06e376..ec330b9a3aa57 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -649,17 +649,21 @@ void CTxMemPool::removeForBlock(const std::vector& vtx, unsigne } // Before the txs in the new block have been removed from the mempool, update policy estimates if (minerPolicyEstimator) {minerPolicyEstimator->processBlock(nBlockHeight, entries);} + std::vector txs_removed_for_block; + txs_removed_for_block.reserve(vtx.size()); for (const auto& tx : vtx) { txiter it = mapTx.find(tx->GetHash()); if (it != mapTx.end()) { setEntries stage; stage.insert(it); + txs_removed_for_block.push_back(tx); RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK); } removeConflicts(*tx); ClearPrioritisation(tx->GetHash()); } + GetMainSignals().MempoolTransactionsRemovedForConnectedBlock(txs_removed_for_block, nBlockHeight); lastRollingFeeUpdate = GetTime(); blockSinceLastRollingFeeBump = true; } diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 9241395ad54ed..6ceae6c761f56 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -214,6 +214,16 @@ void CMainSignals::TransactionAddedToMempool(const CTransactionRef& tx, uint64_t tx->GetWitnessHash().ToString()); } +void CMainSignals::MempoolTransactionsRemovedForConnectedBlock(const std::vector& txs_removed_for_block, unsigned int nBlockHeight) +{ + auto event = [txs_removed_for_block, nBlockHeight, this] { + m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.MempoolTransactionsRemovedForConnectedBlock(txs_removed_for_block, nBlockHeight); }); + }; + ENQUEUE_AND_LOG_EVENT(event, "%s: block height=%s txs=%s", __func__, + nBlockHeight, + txs_removed_for_block.size()); +} + void CMainSignals::TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) { auto event = [tx, reason, mempool_sequence, this] { m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.TransactionRemovedFromMempool(tx, reason, mempool_sequence); }); diff --git a/src/validationinterface.h b/src/validationinterface.h index eb15aa4d5f707..333475537815b 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -60,10 +60,10 @@ void CallFunctionInValidationInterfaceQueue(std::function func); void SyncWithValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main); /** - * Implement this to subscribe to events generated in validation + * Implement this to subscribe to events generated in validation and mempool * * Each CValidationInterface() subscriber will receive event callbacks - * in the order in which the events were generated by validation. + * in the order in which the events were generated by validation and mempool. * Furthermore, each ValidationInterface() subscriber may assume that * callbacks effectively run in a single thread with single-threaded * memory consistency. That is, for a given ValidationInterface() @@ -113,7 +113,7 @@ class CValidationInterface { * This does not fire for transactions that are removed from the mempool * because they have been included in a block. Any client that is interested * in transactions removed from the mempool for inclusion in a block can learn - * about those transactions from the BlockConnected notification. + * about those transactions from the MempoolTransactionsRemovedForConnectedBlock notification. * * Transactions that are removed from the mempool because they conflict * with a transaction in the new block will have @@ -131,9 +131,18 @@ class CValidationInterface { * Called on a background thread. */ virtual void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {} + /* Notifies listeners of transactions removed from the mempool as + * as a result of new block being connected. + * MempoolTransactionsRemovedForConnectedBlock will be fired before BlockConnected. + * + * Called on a background thread. + */ + virtual void MempoolTransactionsRemovedForConnectedBlock(const std::vector& txs_removed_for_block, unsigned int nBlockHeight) {} /** * Notifies listeners of a block being connected. - * Provides a vector of transactions evicted from the mempool as a result. + * Provides the block that was connected. + * The block contains a vector of transactions from the new block, + * some of the transactions in the vector may not be in our mempool. * * Called on a background thread. */ @@ -202,6 +211,7 @@ class CMainSignals { void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); void TransactionAddedToMempool(const CTransactionRef&, uint64_t mempool_sequence); void TransactionRemovedFromMempool(const CTransactionRef&, MemPoolRemovalReason, uint64_t mempool_sequence); + void MempoolTransactionsRemovedForConnectedBlock(const std::vector&, unsigned int nBlockHeight); void BlockConnected(ChainstateRole, const std::shared_ptr &, const CBlockIndex *pindex); void BlockDisconnected(const std::shared_ptr &, const CBlockIndex* pindex); void ChainStateFlushed(ChainstateRole, const CBlockLocator &);