Merge bitcoin/bitcoin#28565: rpc: getaddrmaninfo followups

e6e444c06c refactor: add and use EnsureAnyAddrman in rpc (stratospher)
bf589a50a0 doc: add release notes for #27511 (stratospher)
3931e6abc3 rpc: `getaddrmaninfo` followups (stratospher)

Pull request description:

  - make `getaddrmaninfo` RPC public since it's not for development purposes only and regular users might find it useful. [#26988 (comment)](https://github.com/bitcoin/bitcoin/pull/26988#issuecomment-1738371584)
  - add missing `all_networks` key to RPC help. [#27511 (comment)](https://github.com/bitcoin/bitcoin/pull/27511#discussion_r1335084087)
  - fix clang format spacing
  - add and use `EnsureAddrman` in RPC code. [#27511 (comment)](https://github.com/bitcoin/bitcoin/pull/27511#discussion_r1331501491)

ACKs for top commit:
  0xB10C:
    Code Review re-ACK e6e444c06c
  theStack:
    Code-review ACK e6e444c06c
  pablomartin4btc:
    tested ACK e6e444c06c

Tree-SHA512: c14090d5c64ff15e92d252578de2437bb2ce2e1e431d6698580241a29190f0a3528ae5b013c0ddb76a9ae538507191295c37cab7fd93469941cadbde44587072
This commit is contained in:
fanquake 2023-10-16 11:07:26 +02:00
commit 22fa1f4702
No known key found for this signature in database
GPG Key ID: 2EEB9F5CC09526C1
5 changed files with 62 additions and 61 deletions

View File

@ -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)

View File

@ -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<uint16_t>()};
@ -968,11 +965,11 @@ static RPCHelpMan addpeeraddress()
address.nTime = Now<NodeSeconds>();
// 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);
}
}
}
@ -1033,50 +1030,40 @@ 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 {
AddrMan& addrman = EnsureAnyAddrman(request.context);
UniValue ret(UniValue::VOBJ);
for (int n = 0; n < NET_MAX; ++n) {
enum Network network = static_cast<enum Network>(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<enum Network>(n);
if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
UniValue obj(UniValue::VOBJ);
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", 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;
},
};
}
@ -1135,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;
},
};
@ -1164,10 +1148,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) {

View File

@ -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));
}

View File

@ -7,6 +7,7 @@
#include <any>
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

View File

@ -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()