diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index c9bf70cdb0..2e1305b77e 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -251,6 +251,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "pruneblockchain", 0, "height" }, { "keypoolrefill", 0, "newsize" }, { "getmempoolinfo", 0, "fee_histogram" }, + { "getmempoolinfo", 0, "with_fee_histogram" }, { "getrawmempool", 0, "verbose" }, { "getrawmempool", 1, "mempool_sequence" }, { "estimatesmartfee", 0, "conf_target" }, diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 3ad1ffbf21..7a98e7b826 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -745,7 +745,7 @@ static RPCHelpMan getmempoolinfo() return RPCHelpMan{"getmempoolinfo", "Returns details on the active state of the TX memory pool.\n", { - {"fee_histogram", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Fee statistics grouped by fee rate ranges", + {"fee_histogram|with_fee_histogram", {RPCArg::Type::ARR, RPCArg::Type::BOOL}, RPCArg::Optional::OMITTED, "Fee statistics grouped by fee rate ranges", { {"fee_rate", RPCArg::Type::NUM, RPCArg::Optional::NO, "Fee rate (in " + CURRENCY_ATOM + "/vB) to group the fees by"}, }, @@ -790,7 +790,11 @@ static RPCHelpMan getmempoolinfo() MempoolHistogramFeeRates histogram_floors; std::optional histogram_floors_opt = std::nullopt; - if (!request.params[0].isNull()) { + if (request.params[0].isBool()) { + if (request.params[0].isTrue()) { + histogram_floors_opt = MempoolInfoToJSON_const_histogram_floors; + } + } else if (!request.params[0].isNull()) { const UniValue histogram_floors_univalue = request.params[0].get_array(); if (histogram_floors_univalue.empty()) { diff --git a/src/rpc/mempool.h b/src/rpc/mempool.h index 5feb6089af..c775590b24 100644 --- a/src/rpc/mempool.h +++ b/src/rpc/mempool.h @@ -15,6 +15,15 @@ class UniValue; typedef std::vector MempoolHistogramFeeRates; +/* TODO: define log scale formular for dynamically creating the + * feelimits but with the property of not constantly changing + * (and thus screw up client implementations) */ +static const MempoolHistogramFeeRates MempoolInfoToJSON_const_histogram_floors{ + 1, 2, 3, 4, 5, 6, 7, 8, 10, + 12, 14, 17, 20, 25, 30, 40, 50, 60, 70, 80, 100, + 120, 140, 170, 200, 250, 300, 400, 500, 600, 700, 800, 1000, + 1200, 1400, 1700, 2000, 2500, 3000, 4000, 5000, 6000, 7000, 8000, 10000}; + /** Mempool information to JSON */ UniValue MempoolInfoToJSON(const CTxMemPool& pool, const std::optional& histogram_floors); diff --git a/test/functional/mempool_fee_histogram.py b/test/functional/mempool_fee_histogram.py index 71acbc6893..84f85f13c5 100755 --- a/test/functional/mempool_fee_histogram.py +++ b/test/functional/mempool_fee_histogram.py @@ -156,6 +156,28 @@ class MempoolFeeHistogramTest(BitcoinTestFramework): assert_equal(expected_histogram, info['fee_histogram']) + self.log.info("Test fee rate histogram with default groups") + info = node.getmempoolinfo(with_fee_histogram=True) + + # Verify that the 6 sat/vB fee rate group has one transaction, and the 8-9 sat/vB fee rate group has two + for collapse_n in (9, 11, 13, 15): + for field in ('count', 'size', 'fees'): + expected_frg[str(collapse_n - 1)][field] += expected_frg[str(collapse_n)][field] + del expected_frg[str(collapse_n)] + + for new_n in (17, 20, 25) + tuple(range(30, 90, 10)) + (100, 120, 140, 170, 200, 250) + tuple(range(300, 900, 100)) + (1000, 1200, 1400, 1700, 2000, 2500) + tuple(range(3000, 9000, 1000)) + (10000,): + assert(info['fee_histogram']['fee_rate_groups'][str(new_n)] == { + 'from': new_n, + 'count': 0, + 'fees': 0, + 'size': 0, + }) + del info['fee_histogram']['fee_rate_groups'][str(new_n)] + assert_equal(expected_histogram, info['fee_histogram']) + + self.log.info("Test getmempoolinfo(with_fee_histogram=False) does not return fee histogram") + assert('fee_histogram' not in node.getmempoolinfo(with_fee_histogram=False)) + def histogram_stats(self, histogram): total_fees = 0 empty_count = 0