mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-02 09:46:52 -05:00
rpc: Return total fee in mempool
Also, add missing lock annotations
This commit is contained in:
parent
4bd586607d
commit
fa362064e3
5 changed files with 32 additions and 14 deletions
|
@ -111,12 +111,7 @@ $ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff76
|
||||||
|
|
||||||
Returns various information about the TX mempool.
|
Returns various information about the TX mempool.
|
||||||
Only supports JSON as output format.
|
Only supports JSON as output format.
|
||||||
* loaded : (boolean) if the mempool is fully loaded
|
Refer to the `getmempoolinfo` RPC for documentation of the fields.
|
||||||
* size : (numeric) the number of transactions in the TX mempool
|
|
||||||
* bytes : (numeric) size of the TX mempool in bytes
|
|
||||||
* usage : (numeric) total TX mempool memory usage
|
|
||||||
* maxmempool : (numeric) maximum memory usage for the mempool in bytes
|
|
||||||
* mempoolminfee : (numeric) minimum feerate (BTC per KB) for tx to be accepted
|
|
||||||
|
|
||||||
`GET /rest/mempool/contents.json`
|
`GET /rest/mempool/contents.json`
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
#include <node/coinstats.h>
|
#include <node/coinstats.h>
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
#include <node/utxo_snapshot.h>
|
#include <node/utxo_snapshot.h>
|
||||||
#include <policy/fees.h>
|
|
||||||
#include <policy/feerate.h>
|
#include <policy/feerate.h>
|
||||||
|
#include <policy/fees.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <policy/rbf.h>
|
#include <policy/rbf.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
|
@ -1500,6 +1500,7 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool)
|
||||||
ret.pushKV("size", (int64_t)pool.size());
|
ret.pushKV("size", (int64_t)pool.size());
|
||||||
ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
|
ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
|
||||||
ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
|
ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
|
||||||
|
ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));
|
||||||
size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
|
size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
|
||||||
ret.pushKV("maxmempool", (int64_t) maxmempool);
|
ret.pushKV("maxmempool", (int64_t) maxmempool);
|
||||||
ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK()));
|
ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK()));
|
||||||
|
@ -1520,6 +1521,7 @@ static RPCHelpMan getmempoolinfo()
|
||||||
{RPCResult::Type::NUM, "size", "Current tx count"},
|
{RPCResult::Type::NUM, "size", "Current tx count"},
|
||||||
{RPCResult::Type::NUM, "bytes", "Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted"},
|
{RPCResult::Type::NUM, "bytes", "Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted"},
|
||||||
{RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"},
|
{RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"},
|
||||||
|
{RPCResult::Type::STR_AMOUNT, "total_fee", "Total fees for the mempool in " + CURRENCY_UNIT + ", ignoring modified fees through prioritizetransaction"},
|
||||||
{RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"},
|
{RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"},
|
||||||
{RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"},
|
{RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"},
|
||||||
{RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"},
|
{RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"},
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
#include <consensus/tx_verify.h>
|
#include <consensus/tx_verify.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <optional.h>
|
#include <optional.h>
|
||||||
#include <validation.h>
|
|
||||||
#include <policy/policy.h>
|
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
|
#include <policy/policy.h>
|
||||||
#include <policy/settings.h>
|
#include <policy/settings.h>
|
||||||
#include <reverse_iterator.h>
|
#include <reverse_iterator.h>
|
||||||
#include <util/system.h>
|
|
||||||
#include <util/moneystr.h>
|
#include <util/moneystr.h>
|
||||||
|
#include <util/system.h>
|
||||||
#include <util/time.h>
|
#include <util/time.h>
|
||||||
|
#include <validation.h>
|
||||||
#include <validationinterface.h>
|
#include <validationinterface.h>
|
||||||
|
|
||||||
CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
|
CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
|
||||||
|
@ -396,7 +396,10 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
|
||||||
|
|
||||||
nTransactionsUpdated++;
|
nTransactionsUpdated++;
|
||||||
totalTxSize += entry.GetTxSize();
|
totalTxSize += entry.GetTxSize();
|
||||||
if (minerPolicyEstimator) {minerPolicyEstimator->processTransaction(entry, validFeeEstimate);}
|
m_total_fee += entry.GetFee();
|
||||||
|
if (minerPolicyEstimator) {
|
||||||
|
minerPolicyEstimator->processTransaction(entry, validFeeEstimate);
|
||||||
|
}
|
||||||
|
|
||||||
vTxHashes.emplace_back(tx.GetWitnessHash(), newit);
|
vTxHashes.emplace_back(tx.GetWitnessHash(), newit);
|
||||||
newit->vTxHashesIdx = vTxHashes.size() - 1;
|
newit->vTxHashesIdx = vTxHashes.size() - 1;
|
||||||
|
@ -432,6 +435,7 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
|
||||||
vTxHashes.clear();
|
vTxHashes.clear();
|
||||||
|
|
||||||
totalTxSize -= it->GetTxSize();
|
totalTxSize -= it->GetTxSize();
|
||||||
|
m_total_fee -= it->GetFee();
|
||||||
cachedInnerUsage -= it->DynamicMemoryUsage();
|
cachedInnerUsage -= it->DynamicMemoryUsage();
|
||||||
cachedInnerUsage -= memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst());
|
cachedInnerUsage -= memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst());
|
||||||
mapTx.erase(it);
|
mapTx.erase(it);
|
||||||
|
@ -590,6 +594,7 @@ void CTxMemPool::_clear()
|
||||||
mapTx.clear();
|
mapTx.clear();
|
||||||
mapNextTx.clear();
|
mapNextTx.clear();
|
||||||
totalTxSize = 0;
|
totalTxSize = 0;
|
||||||
|
m_total_fee = 0;
|
||||||
cachedInnerUsage = 0;
|
cachedInnerUsage = 0;
|
||||||
lastRollingFeeUpdate = GetTime();
|
lastRollingFeeUpdate = GetTime();
|
||||||
blockSinceLastRollingFeeBump = false;
|
blockSinceLastRollingFeeBump = false;
|
||||||
|
@ -623,6 +628,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||||
LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
|
LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
|
||||||
|
|
||||||
uint64_t checkTotal = 0;
|
uint64_t checkTotal = 0;
|
||||||
|
CAmount check_total_fee{0};
|
||||||
uint64_t innerUsage = 0;
|
uint64_t innerUsage = 0;
|
||||||
|
|
||||||
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
|
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
|
||||||
|
@ -632,6 +638,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||||
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
checkTotal += it->GetTxSize();
|
checkTotal += it->GetTxSize();
|
||||||
|
check_total_fee += it->GetFee();
|
||||||
innerUsage += it->DynamicMemoryUsage();
|
innerUsage += it->DynamicMemoryUsage();
|
||||||
const CTransaction& tx = it->GetTx();
|
const CTransaction& tx = it->GetTx();
|
||||||
innerUsage += memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst());
|
innerUsage += memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst());
|
||||||
|
@ -726,6 +733,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(totalTxSize == checkTotal);
|
assert(totalTxSize == checkTotal);
|
||||||
|
assert(m_total_fee == check_total_fee);
|
||||||
assert(innerUsage == cachedInnerUsage);
|
assert(innerUsage == cachedInnerUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
#include <optional.h>
|
#include <optional.h>
|
||||||
#include <policy/feerate.h>
|
#include <policy/feerate.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
#include <sync.h>
|
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
|
#include <sync.h>
|
||||||
#include <util/hasher.h>
|
#include <util/hasher.h>
|
||||||
|
|
||||||
#include <boost/multi_index_container.hpp>
|
#include <boost/multi_index_container.hpp>
|
||||||
|
@ -478,8 +478,9 @@ private:
|
||||||
std::atomic<unsigned int> nTransactionsUpdated{0}; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
|
std::atomic<unsigned int> nTransactionsUpdated{0}; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
|
||||||
CBlockPolicyEstimator* minerPolicyEstimator;
|
CBlockPolicyEstimator* minerPolicyEstimator;
|
||||||
|
|
||||||
uint64_t totalTxSize; //!< sum of all mempool tx's virtual sizes. Differs from serialized tx size since witness data is discounted. Defined in BIP 141.
|
uint64_t totalTxSize GUARDED_BY(cs); //!< sum of all mempool tx's virtual sizes. Differs from serialized tx size since witness data is discounted. Defined in BIP 141.
|
||||||
uint64_t cachedInnerUsage; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves)
|
CAmount m_total_fee GUARDED_BY(cs); //!< sum of all mempool tx's fees (NOT modified fee)
|
||||||
|
uint64_t cachedInnerUsage GUARDED_BY(cs); //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves)
|
||||||
|
|
||||||
mutable int64_t lastRollingFeeUpdate;
|
mutable int64_t lastRollingFeeUpdate;
|
||||||
mutable bool blockSinceLastRollingFeeBump;
|
mutable bool blockSinceLastRollingFeeBump;
|
||||||
|
@ -724,6 +725,12 @@ public:
|
||||||
return totalTxSize;
|
return totalTxSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CAmount GetTotalFee() const EXCLUSIVE_LOCKS_REQUIRED(cs)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs);
|
||||||
|
return m_total_fee;
|
||||||
|
}
|
||||||
|
|
||||||
bool exists(const GenTxid& gtxid) const
|
bool exists(const GenTxid& gtxid) const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
|
|
@ -69,6 +69,8 @@ class MempoolPersistTest(BitcoinTestFramework):
|
||||||
assert_equal(len(self.nodes[0].getrawmempool()), 5)
|
assert_equal(len(self.nodes[0].getrawmempool()), 5)
|
||||||
assert_equal(len(self.nodes[1].getrawmempool()), 5)
|
assert_equal(len(self.nodes[1].getrawmempool()), 5)
|
||||||
|
|
||||||
|
total_fee_old = self.nodes[0].getmempoolinfo()['total_fee']
|
||||||
|
|
||||||
self.log.debug("Prioritize a transaction on node0")
|
self.log.debug("Prioritize a transaction on node0")
|
||||||
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
|
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
|
||||||
assert_equal(fees['base'], fees['modified'])
|
assert_equal(fees['base'], fees['modified'])
|
||||||
|
@ -76,6 +78,10 @@ class MempoolPersistTest(BitcoinTestFramework):
|
||||||
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
|
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
|
||||||
assert_equal(fees['base'] + Decimal('0.00001000'), fees['modified'])
|
assert_equal(fees['base'] + Decimal('0.00001000'), fees['modified'])
|
||||||
|
|
||||||
|
self.log.info('Check the total base fee is unchanged after prioritisetransaction')
|
||||||
|
assert_equal(total_fee_old, self.nodes[0].getmempoolinfo()['total_fee'])
|
||||||
|
assert_equal(total_fee_old, sum(v['fees']['base'] for k, v in self.nodes[0].getrawmempool(verbose=True).items()))
|
||||||
|
|
||||||
tx_creation_time = self.nodes[0].getmempoolentry(txid=last_txid)['time']
|
tx_creation_time = self.nodes[0].getmempoolentry(txid=last_txid)['time']
|
||||||
assert_greater_than_or_equal(tx_creation_time, tx_creation_time_lower)
|
assert_greater_than_or_equal(tx_creation_time, tx_creation_time_lower)
|
||||||
assert_greater_than_or_equal(tx_creation_time_higher, tx_creation_time)
|
assert_greater_than_or_equal(tx_creation_time_higher, tx_creation_time)
|
||||||
|
|
Loading…
Add table
Reference in a new issue