diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -4,6 +4,7 @@ #include <bench/bench.h> #include <consensus/amount.h> +#include <kernel/mempool_entry.h> #include <policy/policy.h> #include <test/util/setup_common.h> #include <txmempool.h> diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp --- a/src/bench/mempool_stress.cpp +++ b/src/bench/mempool_stress.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bench/bench.h> +#include <kernel/mempool_entry.h> #include <policy/policy.h> #include <random.h> #include <test/util/setup_common.h> diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -5,6 +5,7 @@ #include <bench/bench.h> #include <chainparamsbase.h> #include <consensus/amount.h> +#include <kernel/mempool_entry.h> #include <rpc/mempool.h> #include <test/util/setup_common.h> #include <txmempool.h> diff --git a/src/kernel/mempool_entry.h b/src/kernel/mempool_entry.h new file mode 100644 --- /dev/null +++ b/src/kernel/mempool_entry.h @@ -0,0 +1,154 @@ +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_KERNEL_MEMPOOL_ENTRY_H +#define BITCOIN_KERNEL_MEMPOOL_ENTRY_H + +#include <consensus/amount.h> +#include <core_memusage.h> +#include <policy/policy.h> +#include <policy/settings.h> +#include <primitives/transaction.h> +#include <rcu.h> + +#include <chrono> +#include <cstddef> +#include <cstdint> +#include <functional> +#include <memory> +#include <set> + +struct LockPoints { + // Will be set to the blockchain height and median time past values that + // would be necessary to satisfy all relative locktime constraints (BIP68) + // of this tx given our view of block chain history + int height{0}; + int64_t time{0}; +}; + +struct CompareIteratorById { + // SFINAE for T where T is either a std::reference_wrapper<T> (e.g. a + // CTxMemPoolEntryRef) or an iterator to a pointer type (e.g., a txiter) + template <typename T> + bool operator()(const std::reference_wrapper<T> &a, + const std::reference_wrapper<T> &b) const { + return a.get()->GetTx().GetId() < b.get()->GetTx().GetId(); + } + template <typename T> bool operator()(const T &a, const T &b) const { + return (*a)->GetTx().GetId() < (*b)->GetTx().GetId(); + } +}; +/** Iterate txs in reverse-topological order */ +struct CompareIteratorByRevEntryId { + template <typename T> + bool operator()(const std::reference_wrapper<T> &a, + const std::reference_wrapper<T> &b) const { + return a.get()->GetEntryId() > b.get()->GetEntryId(); + } + + template <typename T> bool operator()(const T &a, const T &b) const { + return (*a)->GetEntryId() > (*b)->GetEntryId(); + } +}; + +class CTxMemPoolEntry; +using CTxMemPoolEntryRef = RCUPtr<CTxMemPoolEntry>; + +/** \class CTxMemPoolEntry + * + * CTxMemPoolEntry stores data about the corresponding transaction, as well as + * data about all in-mempool transactions that depend on the transaction + * ("descendant" transactions). + */ + +class CTxMemPoolEntry { +public: + // two aliases, should the types ever diverge + typedef std::set<std::reference_wrapper<const CTxMemPoolEntryRef>, + CompareIteratorById> + Parents; + typedef std::set<std::reference_wrapper<const CTxMemPoolEntryRef>, + CompareIteratorById> + Children; + +private: + //! Unique identifier -- used for topological sorting + uint64_t entryId = 0; + + const CTransactionRef tx; + mutable Parents m_parents; + mutable Children m_children; + //! Cached to avoid expensive parent-transaction lookups + const Amount nFee; + //! ... and avoid recomputing tx size + const size_t nTxSize; + //! ... and total memory usage + const size_t nUsageSize; + //! Local time when entering the mempool + const int64_t nTime; + //! Chain height when entering the mempool + const unsigned int entryHeight; + //! Total sigChecks + const int64_t sigChecks; + //! Used for determining the priority of the transaction for mining in a + //! block + Amount feeDelta{Amount::zero()}; + //! Track the height and time at which tx was final + LockPoints lockPoints; + + IMPLEMENT_RCU_REFCOUNT(uint64_t); + +public: + CTxMemPoolEntry(const CTransactionRef &_tx, const Amount fee, int64_t time, + unsigned int entry_height, int64_t sigchecks, LockPoints lp) + : tx{_tx}, nFee{fee}, + nTxSize(tx->GetTotalSize()), nUsageSize{RecursiveDynamicUsage(tx)}, + nTime(time), entryHeight{entry_height}, sigChecks(sigchecks), + lockPoints(lp) {} + + CTxMemPoolEntry(const CTxMemPoolEntry &other) = delete; + CTxMemPoolEntry(CTxMemPoolEntry &&other) + : entryId(other.entryId), tx(std::move(other.tx)), + m_parents(std::move(other.m_parents)), + m_children(std::move(other.m_children)), nFee(other.nFee), + nTxSize(other.nTxSize), nUsageSize(other.nUsageSize), + nTime(other.nTime), entryHeight(other.entryHeight), + sigChecks(other.sigChecks), feeDelta(other.feeDelta), + lockPoints(std::move(other.lockPoints)), + refcount(other.refcount.load()){}; + + uint64_t GetEntryId() const { return entryId; } + //! This should only be set by addUnchecked() before entry insertion into + //! mempool + void SetEntryId(uint64_t eid) { entryId = eid; } + + const CTransaction &GetTx() const { return *this->tx; } + CTransactionRef GetSharedTx() const { return this->tx; } + Amount GetFee() const { return nFee; } + size_t GetTxSize() const { return nTxSize; } + size_t GetTxVirtualSize() const { + return GetVirtualTransactionSize(nTxSize, sigChecks, + ::nBytesPerSigCheck); + } + + std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; } + unsigned int GetHeight() const { return entryHeight; } + int64_t GetSigChecks() const { return sigChecks; } + Amount GetModifiedFee() const { return nFee + feeDelta; } + CFeeRate GetModifiedFeeRate() const { + return CFeeRate(GetModifiedFee(), GetTxVirtualSize()); + } + size_t DynamicMemoryUsage() const { return nUsageSize; } + const LockPoints &GetLockPoints() const { return lockPoints; } + + // Updates the fee delta used for mining priority score + void UpdateFeeDelta(Amount newFeeDelta) { feeDelta = newFeeDelta; } + + const Parents &GetMemPoolParentsConst() const { return m_parents; } + const Children &GetMemPoolChildrenConst() const { return m_children; } + Parents &GetMemPoolParents() const { return m_parents; } + Children &GetMemPoolChildren() const { return m_children; } +}; + +#endif // BITCOIN_KERNEL_MEMPOOL_ENTRY_H diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -26,6 +26,7 @@ #include <headerssync.h> #include <index/blockfilterindex.h> #include <invrequest.h> +#include <kernel/mempool_entry.h> #include <merkleblock.h> #include <netbase.h> #include <netmessagemaker.h> diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -12,6 +12,7 @@ #include <interfaces/handler.h> #include <interfaces/node.h> #include <interfaces/wallet.h> +#include <kernel/mempool_entry.h> #include <mapport.h> #include <net.h> #include <net_processing.h> diff --git a/src/node/miner.h b/src/node/miner.h --- a/src/node/miner.h +++ b/src/node/miner.h @@ -7,6 +7,7 @@ #define BITCOIN_NODE_MINER_H #include <consensus/amount.h> +#include <kernel/mempool_entry.h> #include <primitives/block.h> #include <txmempool.h> diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <kernel/mempool_entry.h> #include <kernel/mempool_persist.h> #include <core_io.h> diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -5,6 +5,7 @@ #include <txmempool.h> #include <kernel/disconnected_transactions.h> +#include <kernel/mempool_entry.h> #include <policy/settings.h> #include <reverse_iterator.h> #include <util/system.h> diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -4,6 +4,7 @@ #include <test/util/setup_common.h> +#include <kernel/mempool_entry.h> #include <kernel/validation_cache_sizes.h> #include <addrman.h> diff --git a/src/txmempool.h b/src/txmempool.h --- a/src/txmempool.h +++ b/src/txmempool.h @@ -10,11 +10,11 @@ #include <consensus/amount.h> #include <core_memusage.h> #include <indirectmap.h> +#include <kernel/mempool_entry.h> #include <kernel/mempool_options.h> #include <policy/packages.h> #include <primitives/transaction.h> #include <radix.h> -#include <rcu.h> #include <sync.h> #include <uint256radixkey.h> #include <util/hasher.h> @@ -45,132 +45,6 @@ */ static const uint32_t MEMPOOL_HEIGHT = 0x7FFFFFFF; -struct LockPoints { - // Will be set to the blockchain height and median time past values that - // would be necessary to satisfy all relative locktime constraints (BIP68) - // of this tx given our view of block chain history - int height{0}; - int64_t time{0}; -}; - -struct CompareIteratorById { - // SFINAE for T where T is either a std::reference_wrapper<T> (e.g. a - // CTxMemPoolEntryRef) or an iterator to a pointer type (e.g., a txiter) - template <typename T> - bool operator()(const std::reference_wrapper<T> &a, - const std::reference_wrapper<T> &b) const { - return a.get()->GetTx().GetId() < b.get()->GetTx().GetId(); - } - template <typename T> bool operator()(const T &a, const T &b) const { - return (*a)->GetTx().GetId() < (*b)->GetTx().GetId(); - } -}; -/** Iterate txs in reverse-topological order */ -struct CompareIteratorByRevEntryId { - template <typename T> - bool operator()(const std::reference_wrapper<T> &a, - const std::reference_wrapper<T> &b) const { - return a.get()->GetEntryId() > b.get()->GetEntryId(); - } - - template <typename T> bool operator()(const T &a, const T &b) const { - return (*a)->GetEntryId() > (*b)->GetEntryId(); - } -}; - -class CTxMemPoolEntry; -using CTxMemPoolEntryRef = RCUPtr<CTxMemPoolEntry>; - -/** \class CTxMemPoolEntry - * - * CTxMemPoolEntry stores data about the corresponding transaction, as well as - * data about all in-mempool transactions that depend on the transaction - * ("descendant" transactions). - */ - -class CTxMemPoolEntry { -public: - // two aliases, should the types ever diverge - typedef std::set<std::reference_wrapper<const CTxMemPoolEntryRef>, - CompareIteratorById> - Parents; - typedef std::set<std::reference_wrapper<const CTxMemPoolEntryRef>, - CompareIteratorById> - Children; - -private: - //! Unique identifier -- used for topological sorting - uint64_t entryId = 0; - - const CTransactionRef tx; - mutable Parents m_parents; - mutable Children m_children; - //! Cached to avoid expensive parent-transaction lookups - const Amount nFee; - //! ... and avoid recomputing tx size - const size_t nTxSize; - //! ... and total memory usage - const size_t nUsageSize; - //! Local time when entering the mempool - const int64_t nTime; - //! Chain height when entering the mempool - const unsigned int entryHeight; - //! Total sigChecks - const int64_t sigChecks; - //! Used for determining the priority of the transaction for mining in a - //! block - Amount feeDelta{Amount::zero()}; - //! Track the height and time at which tx was final - LockPoints lockPoints; - - IMPLEMENT_RCU_REFCOUNT(uint64_t); - -public: - CTxMemPoolEntry(const CTransactionRef &_tx, const Amount fee, int64_t time, - unsigned int entry_height, int64_t sigchecks, - LockPoints lp); - - CTxMemPoolEntry(const CTxMemPoolEntry &other) = delete; - CTxMemPoolEntry(CTxMemPoolEntry &&other) - : entryId(other.entryId), tx(std::move(other.tx)), - m_parents(std::move(other.m_parents)), - m_children(std::move(other.m_children)), nFee(other.nFee), - nTxSize(other.nTxSize), nUsageSize(other.nUsageSize), - nTime(other.nTime), entryHeight(other.entryHeight), - sigChecks(other.sigChecks), feeDelta(other.feeDelta), - lockPoints(std::move(other.lockPoints)), - refcount(other.refcount.load()){}; - - uint64_t GetEntryId() const { return entryId; } - //! This should only be set by addUnchecked() before entry insertion into - //! mempool - void SetEntryId(uint64_t eid) { entryId = eid; } - - const CTransaction &GetTx() const { return *this->tx; } - CTransactionRef GetSharedTx() const { return this->tx; } - Amount GetFee() const { return nFee; } - size_t GetTxSize() const { return nTxSize; } - size_t GetTxVirtualSize() const; - - std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; } - unsigned int GetHeight() const { return entryHeight; } - int64_t GetSigChecks() const { return sigChecks; } - Amount GetModifiedFee() const { return nFee + feeDelta; } - CFeeRate GetModifiedFeeRate() const { - return CFeeRate(GetModifiedFee(), GetTxVirtualSize()); - } - size_t DynamicMemoryUsage() const { return nUsageSize; } - const LockPoints &GetLockPoints() const { return lockPoints; } - - // Updates the fee delta used for mining priority score - void UpdateFeeDelta(Amount feeDelta); - - const Parents &GetMemPoolParentsConst() const { return m_parents; } - const Children &GetMemPoolChildrenConst() const { return m_children; } - Parents &GetMemPoolParents() const { return m_parents; } - Children &GetMemPoolChildren() const { return m_children; } -}; - // extracts a transaction id from CTxMemPoolEntry or CTransactionRef struct mempoolentry_txid { typedef TxId result_type; diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -13,7 +13,6 @@ #include <consensus/validation.h> #include <policy/fees.h> #include <policy/policy.h> -#include <policy/settings.h> #include <reverse_iterator.h> #include <undo.h> #include <util/moneystr.h> @@ -26,22 +25,6 @@ #include <cmath> #include <limits> -CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef &_tx, const Amount fee, - int64_t time, unsigned int entry_height, - int64_t _sigChecks, LockPoints lp) - : tx{_tx}, nFee{fee}, - nTxSize(tx->GetTotalSize()), nUsageSize{RecursiveDynamicUsage(tx)}, - nTime(time), entryHeight{entry_height}, sigChecks(_sigChecks), - lockPoints(lp) {} - -size_t CTxMemPoolEntry::GetTxVirtualSize() const { - return GetVirtualTransactionSize(nTxSize, sigChecks, ::nBytesPerSigCheck); -} - -void CTxMemPoolEntry::UpdateFeeDelta(Amount newFeeDelta) { - feeDelta = newFeeDelta; -} - bool CTxMemPool::CalculateAncestors( setEntries &setAncestors, CTxMemPoolEntry::Parents &staged_ancestors) const { diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -7,6 +7,7 @@ #include <validation.h> #include <kernel/disconnected_transactions.h> +#include <kernel/mempool_entry.h> #include <kernel/mempool_persist.h> #include <arith_uint256.h>