Skip to content

Commit 68f7f13

Browse files
committed
RPC/blockchain: getmempoolinfo: Return fee_histogram in older format (only)
1 parent 521f921 commit 68f7f13

File tree

2 files changed

+67
-72
lines changed

2 files changed

+67
-72
lines changed

src/rpc/mempool.cpp

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -719,26 +719,17 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool, const std::optional<MempoolHi
719719

720720
// Track total amount of available fees in fee rate groups
721721
CAmount total_fees = 0;
722-
UniValue groups(UniValue::VOBJ);
722+
UniValue info(UniValue::VOBJ);
723723
for (size_t i = 0; i < floors.size(); ++i) {
724724
UniValue info_sub(UniValue::VOBJ);
725-
info_sub.pushKV("size", sizes.at(i));
725+
info_sub.pushKV("sizes", sizes[i]);
726726
info_sub.pushKV("count", count.at(i));
727727
info_sub.pushKV("fees", fees.at(i));
728-
info_sub.pushKV("from", floors.at(i));
729-
730-
if (i == floors.size() - 1) {
731-
info_sub.pushKV("to", NullUniValue);
732-
} else {
733-
info_sub.pushKV("to", floors[i + 1] - 1);
734-
}
735-
728+
info_sub.pushKV("from_feerate", floors[i]);
729+
info_sub.pushKV("to_feerate", i == floors.size() - 1 ? std::numeric_limits<int64_t>::max() : floors[i + 1]);
736730
total_fees += fees.at(i);
737-
groups.pushKV(ToString(floors.at(i)), info_sub);
731+
info.pushKV(ToString(floors[i]), info_sub);
738732
}
739-
740-
UniValue info(UniValue::VOBJ);
741-
info.pushKV("fee_rate_groups", groups);
742733
info.pushKV("total_fees", total_fees);
743734
ret.pushKV("fee_histogram", info);
744735
}
@@ -773,18 +764,17 @@ static RPCHelpMan getmempoolinfo()
773764
{RPCResult::Type::BOOL, "fullrbf", "True if the mempool accepts RBF without replaceability signaling inspection"},
774765
{RPCResult::Type::OBJ, "fee_histogram", /*optional=*/true, "",
775766
{
776-
{RPCResult::Type::OBJ_DYN, "fee_rate_groups", "",
777-
{
778-
{RPCResult::Type::OBJ, "<fee_rate_group>", "Fee rate group named by its lower bound (in " + CURRENCY_ATOM + "/vB), identical to the \"from\" field below",
767+
{RPCResult::Type::OBJ, "<fee_rate_group>", "Fee rate group named by its lower bound (in " + CURRENCY_ATOM + "/vB), identical to the \"from_feerate\" field below",
779768
{
780-
{RPCResult::Type::NUM, "size", "Cumulative size of all transactions in the fee rate group (in vBytes)"},
769+
{RPCResult::Type::NUM, "sizes", "Cumulative size of all transactions in the fee rate group (in vBytes)"},
781770
{RPCResult::Type::NUM, "count", "Number of transactions in the fee rate group"},
782771
{RPCResult::Type::NUM, "fees", "Cumulative fees of all transactions in the fee rate group (in " + CURRENCY_ATOM + ")"},
783-
{RPCResult::Type::NUM, "from", "Group contains transactions with fee rates equal or greater than this value (in " + CURRENCY_ATOM + "/vB)"},
784-
{RPCResult::Type::ANY, "to", "Group contains transactions with fee rates equal or less than this value (in " + CURRENCY_ATOM + "/vB)"},
785-
}}}},
772+
{RPCResult::Type::NUM, "from_feerate", "Group contains transactions with fee rates equal or greater than this value (in " + CURRENCY_ATOM + "/vB)"},
773+
{RPCResult::Type::ANY, "to_feerate", "Group contains transactions with fee rates equal or less than this value (in " + CURRENCY_ATOM + "/vB)"},
774+
}},
775+
{RPCResult::Type::ELISION, "", ""},
786776
{RPCResult::Type::NUM, "total_fees", "Total available fees in mempool (in " + CURRENCY_ATOM + ")"},
787-
}},
777+
}, /*skip_type_check=*/ true},
788778
}},
789779
RPCExamples{
790780
HelpExampleCli("getmempoolinfo", "") +

test/functional/mempool_fee_histogram.py

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ def run_test(self):
6161
assert_equal(0, total_fees)
6262

6363
for i in ['1', '2', '3']:
64-
assert_equal(0, info['fee_histogram']['fee_rate_groups'][i]['size'])
65-
assert_equal(0, info['fee_histogram']['fee_rate_groups'][i]['count'])
66-
assert_equal(0, info['fee_histogram']['fee_rate_groups'][i]['fees'])
67-
assert_equal(int(i), info['fee_histogram']['fee_rate_groups'][i]['from'])
64+
assert_equal(0, info['fee_histogram'][i]['sizes'])
65+
assert_equal(0, info['fee_histogram'][i]['count'])
66+
assert_equal(0, info['fee_histogram'][i]['fees'])
67+
assert_equal(int(i), info['fee_histogram'][i]['from_feerate'])
6868

6969
self.log.info("Test that we have two spendable UTXOs and lock the second one")
7070
utxos = node.listunspent()
@@ -80,28 +80,28 @@ def run_test(self):
8080
(non_empty_groups, empty_groups, total_fees) = self.histogram_stats(info['fee_histogram'])
8181
assert_equal(1, non_empty_groups)
8282
assert_equal(3, empty_groups)
83-
assert_equal(1, info['fee_histogram']['fee_rate_groups'][tx1_info['feerate']]['count'])
83+
assert_equal(1, info['fee_histogram'][tx1_info['feerate']]['count'])
8484
assert_equal(total_fees, info['fee_histogram']['total_fees'])
8585

86-
assert_equal(0, info['fee_histogram']['fee_rate_groups']['1']['size'])
87-
assert_equal(0, info['fee_histogram']['fee_rate_groups']['1']['count'])
88-
assert_equal(0, info['fee_histogram']['fee_rate_groups']['1']['fees'])
89-
assert_equal(1, info['fee_histogram']['fee_rate_groups']['1']['from'])
86+
assert_equal(0, info['fee_histogram']['1']['sizes'])
87+
assert_equal(0, info['fee_histogram']['1']['count'])
88+
assert_equal(0, info['fee_histogram']['1']['fees'])
89+
assert_equal(1, info['fee_histogram']['1']['from_feerate'])
9090

91-
assert_equal(0, info['fee_histogram']['fee_rate_groups']['3']['size'])
92-
assert_equal(0, info['fee_histogram']['fee_rate_groups']['3']['count'])
93-
assert_equal(0, info['fee_histogram']['fee_rate_groups']['3']['fees'])
94-
assert_equal(3, info['fee_histogram']['fee_rate_groups']['3']['from'])
91+
assert_equal(0, info['fee_histogram']['3']['sizes'])
92+
assert_equal(0, info['fee_histogram']['3']['count'])
93+
assert_equal(0, info['fee_histogram']['3']['fees'])
94+
assert_equal(3, info['fee_histogram']['3']['from_feerate'])
9595

96-
assert_equal(188, info['fee_histogram']['fee_rate_groups']['5']['size'])
97-
assert_equal(1, info['fee_histogram']['fee_rate_groups']['5']['count'])
98-
assert_equal(940, info['fee_histogram']['fee_rate_groups']['5']['fees'])
99-
assert_equal(5, info['fee_histogram']['fee_rate_groups']['5']['from'])
96+
assert_equal(188, info['fee_histogram']['5']['sizes'])
97+
assert_equal(1, info['fee_histogram']['5']['count'])
98+
assert_equal(940, info['fee_histogram']['5']['fees'])
99+
assert_equal(5, info['fee_histogram']['5']['from_feerate'])
100100

101-
assert_equal(0, info['fee_histogram']['fee_rate_groups']['10']['size'])
102-
assert_equal(0, info['fee_histogram']['fee_rate_groups']['10']['count'])
103-
assert_equal(0, info['fee_histogram']['fee_rate_groups']['10']['fees'])
104-
assert_equal(10, info['fee_histogram']['fee_rate_groups']['10']['from'])
101+
assert_equal(0, info['fee_histogram']['10']['sizes'])
102+
assert_equal(0, info['fee_histogram']['10']['count'])
103+
assert_equal(0, info['fee_histogram']['10']['fees'])
104+
assert_equal(10, info['fee_histogram']['10']['from_feerate'])
105105

106106
self.log.info("Send tx2 transaction with 14 sat/vB fee rate (spends tx1 UTXO)")
107107
tx2_txid = node.sendtoaddress(address=node.getnewaddress(), amount=Decimal("25.0"), fee_rate=14, subtractfeefromamount=True)
@@ -115,7 +115,7 @@ def run_test(self):
115115
tx1p2_feerate = get_actual_fee_rate(tx1_info['fee'] + tx2_info['fee'], tx1_info['vsize'] + tx2_info['vsize'])
116116
assert_equal(1, non_empty_groups)
117117
assert_equal(14, empty_groups)
118-
assert_equal(2, info['fee_histogram']['fee_rate_groups'][tx1p2_feerate]['count'])
118+
assert_equal(2, info['fee_histogram'][tx1p2_feerate]['count'])
119119
assert_equal(total_fees, info['fee_histogram']['total_fees'])
120120

121121
# Unlock the second UTXO which we locked
@@ -132,26 +132,27 @@ def run_test(self):
132132
# tx1 should be grouped with tx2 + tx3 (descendants)
133133
# tx2 should be grouped with tx1 (ancestors only)
134134
# tx3 should be alone
135-
expected_histogram = {
136-
'fee_rate_groups': dict( (
135+
expected_histogram = dict(
136+
tuple(
137137
(str(n), {
138-
'from': n,
139-
'to': n,
138+
'from_feerate': n,
139+
'to_feerate': n + 1,
140140
'count': 0,
141141
'fees': 0,
142-
'size': 0,
142+
'sizes': 0,
143143
}) for n in range(1, 16)
144-
) ),
145-
'total_fees': tx1_info['fee'] + tx2_info['fee'] + tx3_info['fee'],
146-
}
147-
expected_frg = expected_histogram['fee_rate_groups']
148-
expected_frg['15']['to'] = None
144+
) + (
145+
('total_fees', tx1_info['fee'] + tx2_info['fee'] + tx3_info['fee']),
146+
)
147+
)
148+
expected_frg = expected_histogram
149+
expected_frg['15']['to_feerate'] = 9223372036854775807
149150
tx1p2p3_feerate = get_actual_fee_rate(expected_histogram['total_fees'], tx1_info['vsize'] + tx2_info['vsize'] + tx3_info['vsize'])
150151
def inc_expected(feerate, txinfo):
151152
this_frg = expected_frg[feerate]
152153
this_frg['count'] += 1
153154
this_frg['fees'] += txinfo['fee']
154-
this_frg['size'] += txinfo['vsize']
155+
this_frg['sizes'] += txinfo['vsize']
155156
inc_expected(tx1p2p3_feerate, tx1_info)
156157
inc_expected(tx1p2_feerate, tx2_info)
157158
inc_expected(tx3_info['feerate'], tx3_info)
@@ -163,26 +164,23 @@ def inc_expected(feerate, txinfo):
163164

164165
# Verify that the 6 sat/vB fee rate group has one transaction, and the 8-9 sat/vB fee rate group has two
165166
for collapse_n in (9, 11, 13, 15):
166-
for field in ('count', 'size', 'fees'):
167+
for field in ('count', 'sizes', 'fees'):
167168
expected_frg[str(collapse_n - 1)][field] += expected_frg[str(collapse_n)][field]
168-
expected_frg[str(collapse_n - 1)]['to'] += 1
169+
expected_frg[str(collapse_n - 1)]['to_feerate'] += 1
169170
del expected_frg[str(collapse_n)]
170-
expected_frg['14']['to'] += 1 # 16 is also skipped
171+
expected_frg['14']['to_feerate'] += 1 # 16 is also skipped
171172

172173
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,):
173-
frinfo = info['fee_histogram']['fee_rate_groups'][str(new_n)]
174-
if new_n == 10000:
175-
assert frinfo['to'] is None
176-
else:
177-
assert frinfo['to'] > frinfo['from']
178-
del frinfo['to']
174+
frinfo = info['fee_histogram'][str(new_n)]
175+
assert frinfo['to_feerate'] > frinfo['from_feerate']
176+
del frinfo['to_feerate']
179177
assert_equal(frinfo, {
180-
'from': new_n,
178+
'from_feerate': new_n,
181179
'count': 0,
182180
'fees': 0,
183-
'size': 0,
181+
'sizes': 0,
184182
})
185-
del info['fee_histogram']['fee_rate_groups'][str(new_n)]
183+
del info['fee_histogram'][str(new_n)]
186184
assert_equal(expected_histogram, info['fee_histogram'])
187185

188186
self.log.info("Test getmempoolinfo(with_fee_histogram=False) does not return fee histogram")
@@ -193,16 +191,23 @@ def histogram_stats(self, histogram):
193191
empty_count = 0
194192
non_empty_count = 0
195193

196-
for key, bin in histogram['fee_rate_groups'].items():
197-
assert_equal(int(key), bin['from'])
194+
for key, bin in histogram.items():
195+
if key == 'total_fees':
196+
continue
197+
assert_equal(int(key), bin['from_feerate'])
198198
if bin['fees'] > 0:
199199
assert_greater_than(bin['count'], 0)
200200
else:
201201
assert_equal(bin['count'], 0)
202202
assert_greater_than_or_equal(bin['fees'], 0)
203-
assert_greater_than_or_equal(bin['size'], 0)
204-
if bin['to'] is not None:
205-
assert_greater_than_or_equal(bin['to'], bin['from'])
203+
assert_greater_than_or_equal(bin['sizes'], 0)
204+
if bin['to_feerate'] is not None:
205+
assert_greater_than_or_equal(bin['to_feerate'], bin['from_feerate'])
206+
for next_key in sorted((*(int(a) for a in histogram.keys() if a != 'total_fees'), 0x7fffffffffffffff)):
207+
if int(next_key) <= int(key):
208+
continue
209+
assert_equal(bin['to_feerate'], int(next_key))
210+
break
206211
total_fees += bin['fees']
207212

208213
if bin['count'] == 0:

0 commit comments

Comments
 (0)