Skip to content

Commit 8140fb0

Browse files
committed
cli: modify -addrinfo to use getaddrmaninfo, getrawaddrman RPC endpoint
also display % of services the addresses support
1 parent 33adc75 commit 8140fb0

File tree

2 files changed

+89
-30
lines changed

2 files changed

+89
-30
lines changed
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Tools and Utilities
2+
--------
3+
4+
- CLI -addrinfo previously (v22 - v27) returned addresses known to the node after filtering for quality and recency.
5+
It now returns all the addresses known to the node. (#26988)

src/bitcoin-cli.cpp

+84-30
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,9 @@ static void SetupCliArgs(ArgsManager& argsman)
8888
"RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000",
8989
DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES),
9090
ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
91-
argsman.AddArg("-addrinfo", "Get the number of addresses known to the node, per network and total, after filtering for quality and recency. The total number of addresses known to the node may be higher.", ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
91+
argsman.AddArg("-addrinfo", "Get the number of addresses known to the node, per network and total.", ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
9292
argsman.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the output of -getinfo is the result of multiple non-atomic requests. Some entries in the output may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
9393
argsman.AddArg("-netinfo", "Get network peer connection information from the remote server. An optional integer argument from 0 to 4 can be passed for different peers listings (default: 0). Pass \"help\" for detailed help documentation.", ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
94-
9594
SetupChainParamsBaseOptions(argsman);
9695
argsman.AddArg("-color=<when>", strprintf("Color setting for CLI output (default: %s). Valid values: always, auto (add color codes when standard output is connected to a terminal and OS is not WIN32), never.", DEFAULT_COLOR_SETTING), ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
9796
argsman.AddArg("-named", strprintf("Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -259,50 +258,105 @@ class BaseRequestHandler
259258
/** Process addrinfo requests */
260259
class AddrinfoRequestHandler : public BaseRequestHandler
261260
{
262-
private:
263-
int8_t NetworkStringToId(const std::string& str) const
264-
{
265-
for (size_t i = 0; i < NETWORKS.size(); ++i) {
266-
if (str == NETWORKS[i]) return i;
267-
}
268-
return UNKNOWN_NETWORK;
269-
}
270-
271261
public:
262+
const int ID_ADDRINFO = 0;
263+
const int ID_SERVICEINFO = 1;
264+
272265
UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
273266
{
274267
if (!args.empty()) {
275268
throw std::runtime_error("-addrinfo takes no arguments");
276269
}
277-
UniValue params{RPCConvertValues("getnodeaddresses", std::vector<std::string>{{"0"}})};
278-
return JSONRPCRequestObj("getnodeaddresses", params, 1);
270+
UniValue result(UniValue::VARR);
271+
result.push_back(JSONRPCRequestObj("getaddrmaninfo", NullUniValue, ID_ADDRINFO));
272+
result.push_back(JSONRPCRequestObj("getrawaddrman", NullUniValue, ID_SERVICEINFO));
273+
return result;
279274
}
280275

281-
UniValue ProcessReply(const UniValue& reply) override
276+
UniValue ProcessReply(const UniValue& batch_in) override
282277
{
283-
if (!reply["error"].isNull()) return reply;
284-
const std::vector<UniValue>& nodes{reply["result"].getValues()};
285-
if (!nodes.empty() && nodes.at(0)["network"].isNull()) {
286-
throw std::runtime_error("-addrinfo requires bitcoind server to be running v22.0 and up");
287-
}
288-
// Count the number of peers known to our node, by network.
289-
std::array<uint64_t, NETWORKS.size()> counts{{}};
290-
for (const UniValue& node : nodes) {
291-
std::string network_name{node["network"].get_str()};
292-
const int8_t network_id{NetworkStringToId(network_name)};
293-
if (network_id == UNKNOWN_NETWORK) continue;
294-
++counts.at(network_id);
278+
const std::vector<UniValue> batch{JSONRPCProcessBatchReply(batch_in)};
279+
if (!batch[ID_ADDRINFO]["error"].isNull()) return batch[ID_ADDRINFO];
280+
if (!batch[ID_SERVICEINFO]["error"].isNull()) return batch[ID_SERVICEINFO];
281+
282+
const std::vector<std::string>& network_types{batch[ID_ADDRINFO]["result"].getKeys()};
283+
const std::vector<UniValue>& addrman_counts{batch[ID_ADDRINFO]["result"].getValues()};
284+
if (network_types.empty()) {
285+
throw std::runtime_error("-addrinfo requires bitcoind server to be running v28.0 and up. if using an earlier bitcoind server (v22.0 - v27.0), use the appropriate binary");
295286
}
287+
296288
// Prepare result to return to user.
297289
UniValue result{UniValue::VOBJ}, addresses{UniValue::VOBJ};
298290
uint64_t total{0}; // Total address count
299-
for (size_t i = 1; i < NETWORKS.size() - 1; ++i) {
300-
addresses.pushKV(NETWORKS[i], counts.at(i));
301-
total += counts.at(i);
291+
for (size_t i = 0; i < network_types.size() - 1; ++i) {
292+
uint64_t addr_count = addrman_counts[i]["total"].getInt<int>();
293+
addresses.pushKV(network_types[i], addr_count);
294+
total += addr_count;
302295
}
303296
addresses.pushKV("total", total);
304297
result.pushKV("addresses_known", std::move(addresses));
305-
return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V2);
298+
299+
const std::vector<std::string>& table_names{batch[ID_SERVICEINFO]["result"].getKeys()};
300+
const std::vector<UniValue>& table_entries{batch[ID_SERVICEINFO]["result"].getValues()};
301+
302+
UniValue services(UniValue::VOBJ);
303+
int t_count_network = 0, t_count_bloom = 0, t_count_witness = 0, t_count_compact_filter = 0, t_count_network_limited = 0, t_count_v2 = 0, t_total = 0;
304+
for (size_t i = 0; i < table_entries.size(); ++i) {
305+
const UniValue& entry = table_entries[i];
306+
int count_network = 0, count_bloom = 0, count_witness = 0, count_compact_filter = 0, count_network_limited = 0, count_v2 = 0;
307+
uint64_t total = entry.getValues().size();
308+
for (const UniValue& bucket_position : entry.getValues()) {
309+
uint64_t services = bucket_position["services"].getInt<uint64_t>();
310+
if (services & (1 << 0)){
311+
count_network++;
312+
}
313+
if (services & (1 << 2)){
314+
count_bloom++;
315+
}
316+
if (services & (1 << 3)){
317+
count_witness++;
318+
}
319+
if (services & (1 << 6)){
320+
count_compact_filter++;
321+
}
322+
if (services & (1 << 10)){
323+
count_network_limited++;
324+
}
325+
if (services & (1 << 11)){
326+
count_v2++;
327+
}
328+
}
329+
UniValue service_from_table(UniValue::VOBJ);
330+
double frac = 100/double(total);
331+
service_from_table.pushKV("% of NODE_NETWORK", count_network*frac);
332+
service_from_table.pushKV("% of NODE_BLOOM", count_bloom*frac);
333+
service_from_table.pushKV("% of NODE_WITNESS", count_witness*frac);
334+
service_from_table.pushKV("% of NODE_COMPACT_FILTERS", count_compact_filter*frac);
335+
service_from_table.pushKV("% of NODE_NETWORK_LIMITED", count_network_limited*frac);
336+
service_from_table.pushKV("% of NODE_P2P_V2", count_v2*frac);
337+
services.pushKV(table_names[i], service_from_table);
338+
339+
t_count_network += count_network;
340+
t_count_bloom += count_bloom;
341+
t_count_witness += count_witness;
342+
t_count_compact_filter += count_compact_filter;
343+
t_count_network_limited += count_network_limited;
344+
t_count_v2 += count_v2;
345+
t_total += total;
346+
}
347+
348+
UniValue service_from_table(UniValue::VOBJ);
349+
double frac = 100/double(t_total);
350+
service_from_table.pushKV("% of NODE_NETWORK", t_count_network*frac);
351+
service_from_table.pushKV("% of NODE_BLOOM", t_count_bloom*frac);
352+
service_from_table.pushKV("% of NODE_WITNESS", t_count_witness*frac);
353+
service_from_table.pushKV("% of NODE_COMPACT_FILTERS", t_count_compact_filter*frac);
354+
service_from_table.pushKV("% of NODE_NETWORK_LIMITED", t_count_network_limited*frac);
355+
service_from_table.pushKV("% of NODE_P2P_V2", t_count_v2*frac);
356+
services.pushKV("TOTAL", service_from_table);
357+
358+
result.pushKV("services", services);
359+
return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V2);
306360
}
307361
};
308362

0 commit comments

Comments
 (0)