diff --git a/doc/REST-interface.md b/doc/REST-interface.md
--- a/doc/REST-interface.md
+++ b/doc/REST-interface.md
@@ -97,10 +97,7 @@
Returns various information about the TX mempool.
Only supports JSON as output format.
-* loaded : (boolean) if the mempool is fully loaded
-* 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
+Refer to the `getmempoolinfo` RPC for documentation of the fields.
`GET /rest/mempool/contents.json`
diff --git a/doc/release-notes.md b/doc/release-notes.md
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -5,3 +5,5 @@
This release includes the following features and fixes:
+- A new `total_fee` field showing the total fees for all transactions in the
+ mempool has been added to the `getmempoolinfo` RPC.
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -2018,6 +2018,7 @@
ret.pushKV("size", (int64_t)pool.size());
ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
+ ret.pushKV("total_fee", pool.GetTotalFee());
size_t maxmempool =
gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
ret.pushKV("maxmempool", (int64_t)maxmempool);
@@ -2030,6 +2031,7 @@
}
static RPCHelpMan getmempoolinfo() {
+ const auto &ticker = Currency::get().ticker;
return RPCHelpMan{
"getmempoolinfo",
"Returns details on the active state of the TX memory pool.\n",
@@ -2047,8 +2049,11 @@
"Total memory usage for the mempool"},
{RPCResult::Type::NUM, "maxmempool",
"Maximum memory usage for the mempool"},
+ {RPCResult::Type::STR_AMOUNT, "total_fee",
+ "Total fees for the mempool in " + ticker +
+ ", ignoring modified fees through prioritizetransaction"},
{RPCResult::Type::STR_AMOUNT, "mempoolminfee",
- "Minimum fee rate in " + Currency::get().ticker +
+ "Minimum fee rate in " + ticker +
"/kB for tx to be accepted. Is the maximum of "
"minrelaytxfee and minimum mempool fee"},
{RPCResult::Type::STR_AMOUNT, "minrelaytxfee",
diff --git a/src/txmempool.h b/src/txmempool.h
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -502,10 +502,12 @@
std::atomic nTransactionsUpdated{0};
//! sum of all mempool tx's sizes.
- uint64_t totalTxSize;
+ uint64_t totalTxSize GUARDED_BY(cs);
+ //! sum of all mempool tx's fees (NOT modified fee)
+ Amount m_total_fee GUARDED_BY(cs);
//! sum of dynamic memory usage of all the map elements (NOT the maps
//! themselves)
- uint64_t cachedInnerUsage;
+ uint64_t cachedInnerUsage GUARDED_BY(cs);
mutable int64_t lastRollingFeeUpdate GUARDED_BY(cs);
mutable bool blockSinceLastRollingFeeBump GUARDED_BY(cs);
@@ -792,6 +794,11 @@
return totalTxSize;
}
+ Amount GetTotalFee() const EXCLUSIVE_LOCKS_REQUIRED(cs) {
+ AssertLockHeld(cs);
+ return m_total_fee;
+ }
+
bool exists(const TxId &txid) const {
LOCK(cs);
return mapTx.count(txid) != 0;
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -461,6 +461,7 @@
nTransactionsUpdated++;
totalTxSize += entry.GetTxSize();
+ m_total_fee += entry.GetFee();
vTxHashes.emplace_back(tx.GetHash(), newit);
newit->vTxHashesIdx = vTxHashes.size() - 1;
@@ -499,6 +500,7 @@
}
totalTxSize -= it->GetTxSize();
+ m_total_fee -= it->GetFee();
cachedInnerUsage -= it->DynamicMemoryUsage();
cachedInnerUsage -= memusage::DynamicUsage(it->GetMemPoolParentsConst()) +
memusage::DynamicUsage(it->GetMemPoolChildrenConst());
@@ -687,6 +689,7 @@
mapNextTx.clear();
vTxHashes.clear();
totalTxSize = 0;
+ m_total_fee = Amount::zero();
cachedInnerUsage = 0;
lastRollingFeeUpdate = GetTime();
blockSinceLastRollingFeeBump = false;
@@ -729,6 +732,7 @@
(unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
uint64_t checkTotal = 0;
+ Amount check_total_fee{Amount::zero()};
uint64_t innerUsage = 0;
CCoinsViewCache &active_coins_tip = active_chainstate.CoinsTip();
@@ -741,6 +745,7 @@
it != mapTx.end(); it++) {
unsigned int i = 0;
checkTotal += it->GetTxSize();
+ check_total_fee += it->GetFee();
innerUsage += it->DynamicMemoryUsage();
const CTransaction &tx = it->GetTx();
innerUsage += memusage::DynamicUsage(it->GetMemPoolParentsConst()) +
@@ -854,6 +859,7 @@
}
assert(totalTxSize == checkTotal);
+ assert(m_total_fee == check_total_fee);
assert(innerUsage == cachedInnerUsage);
}
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
--- a/test/functional/mempool_persist.py
+++ b/test/functional/mempool_persist.py
@@ -71,6 +71,8 @@
assert_equal(len(self.nodes[0].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")
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
assert_equal(fees['base'], fees['modified'])
@@ -78,6 +80,15 @@
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
assert_equal(fees['base'] + Decimal('10.0'), 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']
assert_greater_than_or_equal(tx_creation_time, tx_creation_time_lower)