CValidationInterface, mempool: add new callback to CValidationInterface

This commit adds a new callback `MempoolTransactionsRemovedForBlock` which notify
its listeners of the transactions that are removed from the mempool because a new
block is connected, along with the block height the transactions were removed.
The transactions are in `RemovedMempoolTransactionInfo` format.

`CTransactionRef`, base fee, virtual size, and height which the transaction was added
to the mempool are all members of the struct called `RemovedMempoolTransactionInfo`.

A struct `NewMempoolTransactionInfo`, which has fields similar to `RemovedMempoolTransactionInfo`,
will be added in a later commit, create a struct `TransactionInfo` with all similar fields.
They can both have a member with type `TransactionInfo`.
This commit is contained in:
ismaelsadeeq 2023-11-03 12:34:29 +01:00
parent 0889e07987
commit bfcd401368
4 changed files with 59 additions and 3 deletions

View File

@ -178,4 +178,34 @@ public:
using CTxMemPoolEntryRef = CTxMemPoolEntry::CTxMemPoolEntryRef; using CTxMemPoolEntryRef = CTxMemPoolEntry::CTxMemPoolEntryRef;
struct TransactionInfo {
const CTransactionRef m_tx;
/* The fee the transaction paid */
const CAmount m_fee;
/**
* The virtual transaction size.
*
* This is a policy field which considers the sigop cost of the
* transaction as well as its weight, and reinterprets it as bytes.
*
* It is the primary metric by which the mining algorithm selects
* transactions.
*/
const int64_t m_virtual_transaction_size;
/* The block height the transaction entered the mempool */
const unsigned int txHeight;
TransactionInfo(const CTransactionRef& tx, const CAmount& fee, const int64_t vsize, const unsigned int height)
: m_tx{tx},
m_fee{fee},
m_virtual_transaction_size{vsize},
txHeight{height} {}
};
struct RemovedMempoolTransactionInfo {
TransactionInfo info;
explicit RemovedMempoolTransactionInfo(const CTxMemPoolEntry& entry)
: info{entry.GetSharedTx(), entry.GetFee(), entry.GetTxSize(), entry.GetHeight()} {}
};
#endif // BITCOIN_KERNEL_MEMPOOL_ENTRY_H #endif // BITCOIN_KERNEL_MEMPOOL_ENTRY_H

View File

@ -654,17 +654,21 @@ void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigne
} }
// Before the txs in the new block have been removed from the mempool, update policy estimates // Before the txs in the new block have been removed from the mempool, update policy estimates
if (minerPolicyEstimator) {minerPolicyEstimator->processBlock(nBlockHeight, entries);} if (minerPolicyEstimator) {minerPolicyEstimator->processBlock(nBlockHeight, entries);}
std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
txs_removed_for_block.reserve(vtx.size());
for (const auto& tx : vtx) for (const auto& tx : vtx)
{ {
txiter it = mapTx.find(tx->GetHash()); txiter it = mapTx.find(tx->GetHash());
if (it != mapTx.end()) { if (it != mapTx.end()) {
setEntries stage; setEntries stage;
stage.insert(it); stage.insert(it);
txs_removed_for_block.emplace_back(*it);
RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK); RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK);
} }
removeConflicts(*tx); removeConflicts(*tx);
ClearPrioritisation(tx->GetHash()); ClearPrioritisation(tx->GetHash());
} }
GetMainSignals().MempoolTransactionsRemovedForBlock(txs_removed_for_block, nBlockHeight);
lastRollingFeeUpdate = GetTime(); lastRollingFeeUpdate = GetTime();
blockSinceLastRollingFeeBump = true; blockSinceLastRollingFeeBump = true;
} }

View File

@ -9,6 +9,7 @@
#include <chain.h> #include <chain.h>
#include <consensus/validation.h> #include <consensus/validation.h>
#include <kernel/chain.h> #include <kernel/chain.h>
#include <kernel/mempool_entry.h>
#include <logging.h> #include <logging.h>
#include <primitives/block.h> #include <primitives/block.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>
@ -233,6 +234,16 @@ void CMainSignals::BlockConnected(ChainstateRole role, const std::shared_ptr<con
pindex->nHeight); pindex->nHeight);
} }
void CMainSignals::MempoolTransactionsRemovedForBlock(const std::vector<RemovedMempoolTransactionInfo>& txs_removed_for_block, unsigned int nBlockHeight)
{
auto event = [txs_removed_for_block, nBlockHeight, this] {
m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.MempoolTransactionsRemovedForBlock(txs_removed_for_block, nBlockHeight); });
};
ENQUEUE_AND_LOG_EVENT(event, "%s: block height=%s txs removed=%s", __func__,
nBlockHeight,
txs_removed_for_block.size());
}
void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex) void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex)
{ {
auto event = [pblock, pindex, this] { auto event = [pblock, pindex, this] {

View File

@ -21,6 +21,7 @@ struct CBlockLocator;
class CValidationInterface; class CValidationInterface;
class CScheduler; class CScheduler;
enum class MemPoolRemovalReason; enum class MemPoolRemovalReason;
struct RemovedMempoolTransactionInfo;
/** Register subscriber */ /** Register subscriber */
void RegisterValidationInterface(CValidationInterface* callbacks); void RegisterValidationInterface(CValidationInterface* callbacks);
@ -60,10 +61,10 @@ void CallFunctionInValidationInterfaceQueue(std::function<void ()> func);
void SyncWithValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main); 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 * 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 * Furthermore, each ValidationInterface() subscriber may assume that
* callbacks effectively run in a single thread with single-threaded * callbacks effectively run in a single thread with single-threaded
* memory consistency. That is, for a given ValidationInterface() * memory consistency. That is, for a given ValidationInterface()
@ -113,7 +114,7 @@ protected:
* This does not fire for transactions that are removed from the mempool * 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 * 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 * 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 MempoolTransactionsRemovedForBlock notification.
* *
* Transactions that are removed from the mempool because they conflict * Transactions that are removed from the mempool because they conflict
* with a transaction in the new block will have * with a transaction in the new block will have
@ -131,6 +132,14 @@ protected:
* Called on a background thread. * Called on a background thread.
*/ */
virtual void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {} 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.
* MempoolTransactionsRemovedForBlock will be fired before BlockConnected.
*
* Called on a background thread.
*/
virtual void MempoolTransactionsRemovedForBlock(const std::vector<RemovedMempoolTransactionInfo>& txs_removed_for_block, unsigned int nBlockHeight) {}
/** /**
* Notifies listeners of a block being connected. * Notifies listeners of a block being connected.
* Provides a vector of transactions evicted from the mempool as a result. * Provides a vector of transactions evicted from the mempool as a result.
@ -140,6 +149,7 @@ protected:
virtual void BlockConnected(ChainstateRole role, const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex) {} virtual void BlockConnected(ChainstateRole role, const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex) {}
/** /**
* Notifies listeners of a block being disconnected * Notifies listeners of a block being disconnected
* Provides the block that was connected.
* *
* Called on a background thread. Only called for the active chainstate, since * Called on a background thread. Only called for the active chainstate, since
* background chainstates should never disconnect blocks. * background chainstates should never disconnect blocks.
@ -202,6 +212,7 @@ public:
void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload);
void TransactionAddedToMempool(const CTransactionRef&, uint64_t mempool_sequence); void TransactionAddedToMempool(const CTransactionRef&, uint64_t mempool_sequence);
void TransactionRemovedFromMempool(const CTransactionRef&, MemPoolRemovalReason, uint64_t mempool_sequence); void TransactionRemovedFromMempool(const CTransactionRef&, MemPoolRemovalReason, uint64_t mempool_sequence);
void MempoolTransactionsRemovedForBlock(const std::vector<RemovedMempoolTransactionInfo>&, unsigned int nBlockHeight);
void BlockConnected(ChainstateRole, const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex); void BlockConnected(ChainstateRole, const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex);
void BlockDisconnected(const std::shared_ptr<const CBlock> &, const CBlockIndex* pindex); void BlockDisconnected(const std::shared_ptr<const CBlock> &, const CBlockIndex* pindex);
void ChainStateFlushed(ChainstateRole, const CBlockLocator &); void ChainStateFlushed(ChainstateRole, const CBlockLocator &);