0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-02 09:46:52 -05:00

Merge bitcoin/bitcoin#27511: rpc: Add test-only RPC getaddrmaninfo for new/tried table address count

28bac81a34 test: add functional test for getaddrmaninfo (stratospher)
c8eb8dae51 rpc: Introduce getaddrmaninfo for count of addresses stored in new/tried table (stratospher)

Pull request description:

  implements https://github.com/bitcoin/bitcoin/issues/26907. split off from #26988 to keep RPC, CLI discussions separate.

  This PR introduces a new RPC `getaddrmaninfo`which returns the count of addresses in the new/tried table of a node's addrman broken down by network type. This would be useful for users who want to see the distribution of addresses from different networks across new/tried table in the addrman.

  ```jsx
  $ getaddrmaninfo

  Result:
  {                   (json object) json object with network type as keys
    "network" : {     (json object) The network (ipv4, ipv6, onion, i2p, cjdns)
      "new" : n,      (numeric) number of addresses in new table
      "tried" : n,    (numeric) number of addresses in tried table
      "total" : n     (numeric) total number of addresses in both new/tried tables from a network
    },
    ...
  }
  ```

  ### additional context from [original PR](https://github.com/bitcoin/bitcoin/pull/26988)

  1. network coverage tests were skipped because there’s a small chance that addresses from different networks could hash to the same bucket and cause count of different network addresses in the tests to fail. see https://github.com/bitcoin/bitcoin/pull/26988#discussion_r1137596851.
  2. #26988 uses this RPC in -addrinfo CLI. Slight preference for keeping the RPC hidden since this info will mostly be useful to only super users. see https://github.com/bitcoin/bitcoin/pull/26988#discussion_r1173964808.

ACKs for top commit:
  0xB10C:
    ACK 28bac81a34
  willcl-ark:
    reACK 28bac81a34
  achow101:
    ACK 28bac81a34
  brunoerg:
    reACK 28bac81a34
  theStack:
    Code-review ACK 28bac81a34

Tree-SHA512: 346390167e1ebed7ca5c79328ea452633736aff8b7feefea77460e04d4489059334ae78a3f757f32f5fb7827b309d7186bebab3c3760b3dfb016d564a647371a
This commit is contained in:
Andrew Chow 2023-09-20 08:19:30 -04:00
commit ff564c75e7
No known key found for this signature in database
GPG key ID: 17565732E08E5E41
3 changed files with 74 additions and 0 deletions

View file

@ -1016,6 +1016,55 @@ 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");
}
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;
},
};
}
void RegisterNetRPCCommands(CRPCTable& t) void RegisterNetRPCCommands(CRPCTable& t)
{ {
static const CRPCCommand commands[]{ static const CRPCCommand commands[]{
@ -1035,6 +1084,7 @@ void RegisterNetRPCCommands(CRPCTable& t)
{"hidden", &addconnection}, {"hidden", &addconnection},
{"hidden", &addpeeraddress}, {"hidden", &addpeeraddress},
{"hidden", &sendmsgtopeer}, {"hidden", &sendmsgtopeer},
{"hidden", &getaddrmaninfo},
}; };
for (const auto& c : commands) { for (const auto& c : commands) {
t.appendCommand(c.name, &c); t.appendCommand(c.name, &c);

View file

@ -110,6 +110,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
"generate", "generate",
"generateblock", "generateblock",
"getaddednodeinfo", "getaddednodeinfo",
"getaddrmaninfo",
"getbestblockhash", "getbestblockhash",
"getblock", "getblock",
"getblockchaininfo", "getblockchaininfo",

View file

@ -66,6 +66,7 @@ class NetTest(BitcoinTestFramework):
self.test_getnodeaddresses() self.test_getnodeaddresses()
self.test_addpeeraddress() self.test_addpeeraddress()
self.test_sendmsgtopeer() self.test_sendmsgtopeer()
self.test_getaddrmaninfo()
def test_connection_count(self): def test_connection_count(self):
self.log.info("Test getconnectioncount") self.log.info("Test getconnectioncount")
@ -360,6 +361,28 @@ class NetTest(BitcoinTestFramework):
node.sendmsgtopeer(peer_id=0, msg_type="addr", msg=zero_byte_string.hex()) node.sendmsgtopeer(peer_id=0, msg_type="addr", msg=zero_byte_string.hex())
self.wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 0, timeout=10) self.wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 0, timeout=10)
def test_getaddrmaninfo(self):
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()
assert_equal(res["ipv4"]["new"], 1)
assert_equal(res["ipv4"]["tried"], 1)
assert_equal(res["ipv4"]["total"], 2)
assert_equal(res["all_networks"]["new"], 1)
assert_equal(res["all_networks"]["tried"], 1)
assert_equal(res["all_networks"]["total"], 2)
for net in ["ipv6", "onion", "i2p", "cjdns"]:
assert_equal(res[net]["new"], 0)
assert_equal(res[net]["tried"], 0)
assert_equal(res[net]["total"], 0)
if __name__ == '__main__': if __name__ == '__main__':
NetTest().main() NetTest().main()