diff options
author | glozow <gloriajzhao@gmail.com> | 2024-05-23 12:07:47 +0100 |
---|---|---|
committer | glozow <gloriajzhao@gmail.com> | 2024-05-23 12:08:36 +0100 |
commit | 83ae1bac9d3e01de994734b4bc7002deaf19bc67 (patch) | |
tree | 5cb51ed0494b5dfe8d6fcf896d9c501eb5924cd2 | |
parent | ef44726918c05e158246cb695ae358db603653e9 (diff) | |
parent | 1e54d61c4698debf3329d1960e06078ccbf8063c (diff) |
Merge bitcoin/bitcoin#30062: net: add ASMap info in `getrawaddrman` RPC
1e54d61c4698debf3329d1960e06078ccbf8063c test: add coverage for `mapped_as` from `getrawaddrman` (brunoerg)
8c2714907d1e1ffc58487b3b43e018c1ec10065b net: rpc: return peer's mapped AS in getrawaddrman (brunoerg)
Pull request description:
This PR adds two new fields in `getrawaddrman` RPC: "mapped_as" and "source_mapped_as". These fields are used to return the ASN (Autonomous System Number) mapped to the peer and its source. With these informations we can have a better view of the bucketing logic with ASMap specially in projects like [addrman-observer](https://github.com/0xb10c/addrman-observer).
ACKs for top commit:
fjahr:
Code review ACK 1e54d61c4698debf3329d1960e06078ccbf8063c
virtu:
ACK [1e54d61](https://github.com/bitcoin/bitcoin/commit/1e54d61c4698debf3329d1960e06078ccbf8063c)
0xB10C:
ACK 1e54d61c4698debf3329d1960e06078ccbf8063c
glozow:
ACK 1e54d61c4698debf3329d1960e06078ccbf8063c
Tree-SHA512: af86bcc7a2e69bebd3fa9eaa2e527e0758c44c0a958de7292514d5f99f8f01f5df3bae11400451268e0255f738ff3acccc77f48fe129937512f1e9d9963c4c5e
-rw-r--r-- | src/rpc/net.cpp | 22 | ||||
-rwxr-xr-x | test/functional/feature_asmap.py | 9 |
2 files changed, 26 insertions, 5 deletions
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 59397aa84d..53360f08fd 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -1099,20 +1099,28 @@ static RPCHelpMan getaddrmaninfo() }; } -UniValue AddrmanEntryToJSON(const AddrInfo& info) +UniValue AddrmanEntryToJSON(const AddrInfo& info, CConnman& connman) { UniValue ret(UniValue::VOBJ); ret.pushKV("address", info.ToStringAddr()); + const auto mapped_as{connman.GetMappedAS(info)}; + if (mapped_as != 0) { + ret.pushKV("mapped_as", mapped_as); + } ret.pushKV("port", info.GetPort()); ret.pushKV("services", (uint64_t)info.nServices); ret.pushKV("time", int64_t{TicksSinceEpoch<std::chrono::seconds>(info.nTime)}); ret.pushKV("network", GetNetworkName(info.GetNetClass())); ret.pushKV("source", info.source.ToStringAddr()); ret.pushKV("source_network", GetNetworkName(info.source.GetNetClass())); + const auto source_mapped_as{connman.GetMappedAS(info.source)}; + if (source_mapped_as != 0) { + ret.pushKV("source_mapped_as", source_mapped_as); + } return ret; } -UniValue AddrmanTableToJSON(const std::vector<std::pair<AddrInfo, AddressPosition>>& tableInfos) +UniValue AddrmanTableToJSON(const std::vector<std::pair<AddrInfo, AddressPosition>>& tableInfos, CConnman& connman) { UniValue table(UniValue::VOBJ); for (const auto& e : tableInfos) { @@ -1123,7 +1131,7 @@ UniValue AddrmanTableToJSON(const std::vector<std::pair<AddrInfo, AddressPositio // Address manager tables have unique entries so there is no advantage // in using UniValue::pushKV, which checks if the key already exists // in O(N). UniValue::pushKVEnd is used instead which currently is O(1). - table.pushKVEnd(key.str(), AddrmanEntryToJSON(info)); + table.pushKVEnd(key.str(), AddrmanEntryToJSON(info, connman)); } return table; } @@ -1139,12 +1147,14 @@ static RPCHelpMan getrawaddrman() {RPCResult::Type::OBJ_DYN, "table", "buckets with addresses in the address manager table ( new, tried )", { {RPCResult::Type::OBJ, "bucket/position", "the location in the address manager table (<bucket>/<position>)", { {RPCResult::Type::STR, "address", "The address of the node"}, + {RPCResult::Type::NUM, "mapped_as", /*optional=*/true, "The ASN mapped to the IP of this peer per our current ASMap"}, {RPCResult::Type::NUM, "port", "The port number of the node"}, {RPCResult::Type::STR, "network", "The network (" + Join(GetNetworkNames(), ", ") + ") of the address"}, {RPCResult::Type::NUM, "services", "The services offered by the node"}, {RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " when the node was last seen"}, {RPCResult::Type::STR, "source", "The address that relayed the address to us"}, {RPCResult::Type::STR, "source_network", "The network (" + Join(GetNetworkNames(), ", ") + ") of the source address"}, + {RPCResult::Type::NUM, "source_mapped_as", /*optional=*/true, "The ASN mapped to the IP of this peer's source per our current ASMap"} }} }} } @@ -1155,10 +1165,12 @@ static RPCHelpMan getrawaddrman() }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { AddrMan& addrman = EnsureAnyAddrman(request.context); + NodeContext& node_context = EnsureAnyNodeContext(request.context); + CConnman& connman = EnsureConnman(node_context); UniValue ret(UniValue::VOBJ); - ret.pushKV("new", AddrmanTableToJSON(addrman.GetEntries(false))); - ret.pushKV("tried", AddrmanTableToJSON(addrman.GetEntries(true))); + ret.pushKV("new", AddrmanTableToJSON(addrman.GetEntries(false), connman)); + ret.pushKV("tried", AddrmanTableToJSON(addrman.GetEntries(true), connman)); return ret; }, }; diff --git a/test/functional/feature_asmap.py b/test/functional/feature_asmap.py index 024a8fa18c..e469deef49 100755 --- a/test/functional/feature_asmap.py +++ b/test/functional/feature_asmap.py @@ -27,6 +27,7 @@ import os import shutil from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal DEFAULT_ASMAP_FILENAME = 'ip_asn.map' # defined in src/init.cpp ASMAP = '../../src/test/data/asmap.raw' # path to unit test skeleton asmap @@ -118,6 +119,14 @@ class AsmapTest(BitcoinTestFramework): msg = "ASMap Health Check: 4 clearnet peers are mapped to 3 ASNs with 0 peers being unmapped" with self.node.assert_debug_log(expected_msgs=[msg]): self.start_node(0, extra_args=['-asmap']) + raw_addrman = self.node.getrawaddrman() + asns = [] + for _, entries in raw_addrman.items(): + for _, entry in entries.items(): + asn = entry['mapped_as'] + if asn not in asns: + asns.append(asn) + assert_equal(len(asns), 3) os.remove(self.default_asmap) def run_test(self): |