From 3931e6abc39b8aee1472028dbf76eeb10708d2b4 Mon Sep 17 00:00:00 2001 From: stratospher <44024636+stratospher@users.noreply.github.com> Date: Tue, 3 Oct 2023 09:04:40 +0530 Subject: [PATCH 1/3] rpc: `getaddrmaninfo` followups - make `getaddrmaninfo` RPC public since it's not for development purposes only and regular users might find it useful - add missing `all_networks` key to RPC help - use clang format spacing --- src/rpc/net.cpp | 81 +++++++++++++++++--------------------- test/functional/rpc_net.py | 5 --- 2 files changed, 37 insertions(+), 49 deletions(-) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 96d06b6b9f0..70d1cc715fc 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -1033,50 +1033,43 @@ static RPCHelpMan sendmsgtopeer() static RPCHelpMan getaddrmaninfo() { - return RPCHelpMan{"getaddrmaninfo", - "\nProvides information about the node's address manager by returning the number of " - "addresses in the `new` and `tried` tables and their sum for all networks.\n" - "This RPC is for testing only.\n", - {}, - RPCResult{ - RPCResult::Type::OBJ_DYN, "", "json object with network type as keys", - { - {RPCResult::Type::OBJ, "network", "the network (" + Join(GetNetworkNames(), ", ") + ")", - { - {RPCResult::Type::NUM, "new", "number of addresses in the new table, which represent potential peers the node has discovered but hasn't yet successfully connected to."}, - {RPCResult::Type::NUM, "tried", "number of addresses in the tried table, which represent peers the node has successfully connected to in the past."}, - {RPCResult::Type::NUM, "total", "total number of addresses in both new/tried tables"}, - }}, - } - }, - RPCExamples{ - HelpExampleCli("getaddrmaninfo", "") - + HelpExampleRpc("getaddrmaninfo", "") - }, - [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue - { - NodeContext& node = EnsureAnyNodeContext(request.context); - if (!node.addrman) { - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled"); - } + return RPCHelpMan{ + "getaddrmaninfo", + "\nProvides information about the node's address manager by returning the number of " + "addresses in the `new` and `tried` tables and their sum for all networks.\n", + {}, + RPCResult{ + RPCResult::Type::OBJ_DYN, "", "json object with network type as keys", { + {RPCResult::Type::OBJ, "network", "the network (" + Join(GetNetworkNames(), ", ") + ", all_networks)", { + {RPCResult::Type::NUM, "new", "number of addresses in the new table, which represent potential peers the node has discovered but hasn't yet successfully connected to."}, + {RPCResult::Type::NUM, "tried", "number of addresses in the tried table, which represent peers the node has successfully connected to in the past."}, + {RPCResult::Type::NUM, "total", "total number of addresses in both new/tried tables"}, + }}, + }}, + RPCExamples{HelpExampleCli("getaddrmaninfo", "") + HelpExampleRpc("getaddrmaninfo", "")}, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { + NodeContext& node = EnsureAnyNodeContext(request.context); + if (!node.addrman) { + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled"); + } - UniValue ret(UniValue::VOBJ); - for (int n = 0; n < NET_MAX; ++n) { - enum Network network = static_cast(n); - if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue; - UniValue obj(UniValue::VOBJ); - obj.pushKV("new", node.addrman->Size(network, true)); - obj.pushKV("tried", node.addrman->Size(network, false)); - obj.pushKV("total", node.addrman->Size(network)); - ret.pushKV(GetNetworkName(network), obj); - } - UniValue obj(UniValue::VOBJ); - obj.pushKV("new", node.addrman->Size(std::nullopt, true)); - obj.pushKV("tried", node.addrman->Size(std::nullopt, false)); - obj.pushKV("total", node.addrman->Size()); - ret.pushKV("all_networks", obj); - return ret; - }, + UniValue ret(UniValue::VOBJ); + for (int n = 0; n < NET_MAX; ++n) { + enum Network network = static_cast(n); + if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue; + UniValue obj(UniValue::VOBJ); + obj.pushKV("new", node.addrman->Size(network, true)); + obj.pushKV("tried", node.addrman->Size(network, false)); + obj.pushKV("total", node.addrman->Size(network)); + ret.pushKV(GetNetworkName(network), obj); + } + UniValue obj(UniValue::VOBJ); + obj.pushKV("new", node.addrman->Size(std::nullopt, true)); + obj.pushKV("tried", node.addrman->Size(std::nullopt, false)); + obj.pushKV("total", node.addrman->Size()); + ret.pushKV("all_networks", obj); + return ret; + }, }; } @@ -1164,10 +1157,10 @@ void RegisterNetRPCCommands(CRPCTable& t) {"network", &clearbanned}, {"network", &setnetworkactive}, {"network", &getnodeaddresses}, + {"network", &getaddrmaninfo}, {"hidden", &addconnection}, {"hidden", &addpeeraddress}, {"hidden", &sendmsgtopeer}, - {"hidden", &getaddrmaninfo}, {"hidden", &getrawaddrman}, }; for (const auto& c : commands) { diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py index 2c7f974d0bb..44b86662eac 100755 --- a/test/functional/rpc_net.py +++ b/test/functional/rpc_net.py @@ -371,11 +371,6 @@ class NetTest(BitcoinTestFramework): self.log.info("Test getaddrmaninfo") node = self.nodes[1] - self.log.debug("Test that getaddrmaninfo is a hidden RPC") - # It is hidden from general help, but its detailed help may be called directly. - assert "getaddrmaninfo" not in node.help() - assert "getaddrmaninfo" in node.help("getaddrmaninfo") - # current count of ipv4 addresses in addrman is {'new':1, 'tried':1} self.log.info("Test that count of addresses in addrman match expected values") res = node.getaddrmaninfo() From bf589a50a0d6a7b94f1ba1ddf24a1497fd35ad44 Mon Sep 17 00:00:00 2001 From: stratospher <44024636+stratospher@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:35:14 +0530 Subject: [PATCH 2/3] doc: add release notes for #27511 --- doc/release-notes/release-notes-27511.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 doc/release-notes/release-notes-27511.md diff --git a/doc/release-notes/release-notes-27511.md b/doc/release-notes/release-notes-27511.md new file mode 100644 index 00000000000..b5c0847e31b --- /dev/null +++ b/doc/release-notes/release-notes-27511.md @@ -0,0 +1,6 @@ +New RPCs +-------- + +- A new RPC `getaddrmaninfo` has been added to view the distribution of addresses in the new and tried table of the + node's address manager across different networks(ipv4, ipv6, onion, i2p, cjdns). The RPC returns count of addresses + in new and tried table as well as their sum for all networks. (#27511) From e6e444c06cbf09380f9924dff3d21c1be15d1753 Mon Sep 17 00:00:00 2001 From: stratospher <44024636+stratospher@users.noreply.github.com> Date: Tue, 3 Oct 2023 19:37:56 +0530 Subject: [PATCH 3/3] refactor: add and use EnsureAnyAddrman in rpc --- src/rpc/net.cpp | 35 +++++++++++++---------------------- src/rpc/server_util.cpp | 13 +++++++++++++ src/rpc/server_util.h | 3 +++ 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 70d1cc715fc..5a68bf9e1f5 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -949,10 +949,7 @@ static RPCHelpMan addpeeraddress() }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - NodeContext& node = EnsureAnyNodeContext(request.context); - if (!node.addrman) { - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled"); - } + AddrMan& addrman = EnsureAnyAddrman(request.context); const std::string& addr_string{request.params[0].get_str()}; const auto port{request.params[1].getInt()}; @@ -968,11 +965,11 @@ static RPCHelpMan addpeeraddress() address.nTime = Now(); // The source address is set equal to the address. This is equivalent to the peer // announcing itself. - if (node.addrman->Add({address}, address)) { + if (addrman.Add({address}, address)) { success = true; if (tried) { // Attempt to move the address to the tried addresses table. - node.addrman->Good(address); + addrman.Good(address); } } } @@ -1048,25 +1045,22 @@ static RPCHelpMan getaddrmaninfo() }}, RPCExamples{HelpExampleCli("getaddrmaninfo", "") + HelpExampleRpc("getaddrmaninfo", "")}, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - NodeContext& node = EnsureAnyNodeContext(request.context); - if (!node.addrman) { - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled"); - } + AddrMan& addrman = EnsureAnyAddrman(request.context); UniValue ret(UniValue::VOBJ); for (int n = 0; n < NET_MAX; ++n) { enum Network network = static_cast(n); if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue; UniValue obj(UniValue::VOBJ); - obj.pushKV("new", node.addrman->Size(network, true)); - obj.pushKV("tried", node.addrman->Size(network, false)); - obj.pushKV("total", node.addrman->Size(network)); + obj.pushKV("new", addrman.Size(network, true)); + obj.pushKV("tried", addrman.Size(network, false)); + obj.pushKV("total", addrman.Size(network)); ret.pushKV(GetNetworkName(network), obj); } UniValue obj(UniValue::VOBJ); - obj.pushKV("new", node.addrman->Size(std::nullopt, true)); - obj.pushKV("tried", node.addrman->Size(std::nullopt, false)); - obj.pushKV("total", node.addrman->Size()); + obj.pushKV("new", addrman.Size(std::nullopt, true)); + obj.pushKV("tried", addrman.Size(std::nullopt, false)); + obj.pushKV("total", addrman.Size()); ret.pushKV("all_networks", obj); return ret; }, @@ -1128,14 +1122,11 @@ static RPCHelpMan getrawaddrman() + HelpExampleRpc("getrawaddrman", "") }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - NodeContext& node = EnsureAnyNodeContext(request.context); - if (!node.addrman) { - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled"); - } + AddrMan& addrman = EnsureAnyAddrman(request.context); UniValue ret(UniValue::VOBJ); - ret.pushKV("new", AddrmanTableToJSON(node.addrman->GetEntries(false))); - ret.pushKV("tried", AddrmanTableToJSON(node.addrman->GetEntries(true))); + ret.pushKV("new", AddrmanTableToJSON(addrman.GetEntries(false))); + ret.pushKV("tried", AddrmanTableToJSON(addrman.GetEntries(true))); return ret; }, }; diff --git a/src/rpc/server_util.cpp b/src/rpc/server_util.cpp index 1d4afb3758c..efd4a43c288 100644 --- a/src/rpc/server_util.cpp +++ b/src/rpc/server_util.cpp @@ -108,3 +108,16 @@ PeerManager& EnsurePeerman(const NodeContext& node) } return *node.peerman; } + +AddrMan& EnsureAddrman(const NodeContext& node) +{ + if (!node.addrman) { + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled"); + } + return *node.addrman; +} + +AddrMan& EnsureAnyAddrman(const std::any& context) +{ + return EnsureAddrman(EnsureAnyNodeContext(context)); +} diff --git a/src/rpc/server_util.h b/src/rpc/server_util.h index 9af95724315..a4a53166b4b 100644 --- a/src/rpc/server_util.h +++ b/src/rpc/server_util.h @@ -7,6 +7,7 @@ #include +class AddrMan; class ArgsManager; class CBlockPolicyEstimator; class CConnman; @@ -31,5 +32,7 @@ CBlockPolicyEstimator& EnsureFeeEstimator(const node::NodeContext& node); CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context); CConnman& EnsureConnman(const node::NodeContext& node); PeerManager& EnsurePeerman(const node::NodeContext& node); +AddrMan& EnsureAddrman(const node::NodeContext& node); +AddrMan& EnsureAnyAddrman(const std::any& context); #endif // BITCOIN_RPC_SERVER_UTIL_H