mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-06-04 16:32:32 +02:00
Merge bitcoin/bitcoin#30062: net: add ASMap info in getrawaddrman
RPC
1e54d61c46
test: add coverage for `mapped_as` from `getrawaddrman` (brunoerg)8c2714907d
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 ACK1e54d61c46
virtu: ACK [1e54d61
](1e54d61c46
) 0xB10C: ACK1e54d61c46
glozow: ACK1e54d61c46
Tree-SHA512: af86bcc7a2e69bebd3fa9eaa2e527e0758c44c0a958de7292514d5f99f8f01f5df3bae11400451268e0255f738ff3acccc77f48fe129937512f1e9d9963c4c5e
This commit is contained in:
commit
83ae1bac9d
@ -1099,20 +1099,28 @@ static RPCHelpMan getaddrmaninfo()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue AddrmanEntryToJSON(const AddrInfo& info)
|
UniValue AddrmanEntryToJSON(const AddrInfo& info, CConnman& connman)
|
||||||
{
|
{
|
||||||
UniValue ret(UniValue::VOBJ);
|
UniValue ret(UniValue::VOBJ);
|
||||||
ret.pushKV("address", info.ToStringAddr());
|
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("port", info.GetPort());
|
||||||
ret.pushKV("services", (uint64_t)info.nServices);
|
ret.pushKV("services", (uint64_t)info.nServices);
|
||||||
ret.pushKV("time", int64_t{TicksSinceEpoch<std::chrono::seconds>(info.nTime)});
|
ret.pushKV("time", int64_t{TicksSinceEpoch<std::chrono::seconds>(info.nTime)});
|
||||||
ret.pushKV("network", GetNetworkName(info.GetNetClass()));
|
ret.pushKV("network", GetNetworkName(info.GetNetClass()));
|
||||||
ret.pushKV("source", info.source.ToStringAddr());
|
ret.pushKV("source", info.source.ToStringAddr());
|
||||||
ret.pushKV("source_network", GetNetworkName(info.source.GetNetClass()));
|
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;
|
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);
|
UniValue table(UniValue::VOBJ);
|
||||||
for (const auto& e : tableInfos) {
|
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
|
// Address manager tables have unique entries so there is no advantage
|
||||||
// in using UniValue::pushKV, which checks if the key already exists
|
// in using UniValue::pushKV, which checks if the key already exists
|
||||||
// in O(N). UniValue::pushKVEnd is used instead which currently is O(1).
|
// 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;
|
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_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::OBJ, "bucket/position", "the location in the address manager table (<bucket>/<position>)", {
|
||||||
{RPCResult::Type::STR, "address", "The address of the node"},
|
{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::NUM, "port", "The port number of the node"},
|
||||||
{RPCResult::Type::STR, "network", "The network (" + Join(GetNetworkNames(), ", ") + ") of the address"},
|
{RPCResult::Type::STR, "network", "The network (" + Join(GetNetworkNames(), ", ") + ") of the address"},
|
||||||
{RPCResult::Type::NUM, "services", "The services offered by the node"},
|
{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::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", "The address that relayed the address to us"},
|
||||||
{RPCResult::Type::STR, "source_network", "The network (" + Join(GetNetworkNames(), ", ") + ") of the source address"},
|
{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 {
|
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
|
||||||
AddrMan& addrman = EnsureAnyAddrman(request.context);
|
AddrMan& addrman = EnsureAnyAddrman(request.context);
|
||||||
|
NodeContext& node_context = EnsureAnyNodeContext(request.context);
|
||||||
|
CConnman& connman = EnsureConnman(node_context);
|
||||||
|
|
||||||
UniValue ret(UniValue::VOBJ);
|
UniValue ret(UniValue::VOBJ);
|
||||||
ret.pushKV("new", AddrmanTableToJSON(addrman.GetEntries(false)));
|
ret.pushKV("new", AddrmanTableToJSON(addrman.GetEntries(false), connman));
|
||||||
ret.pushKV("tried", AddrmanTableToJSON(addrman.GetEntries(true)));
|
ret.pushKV("tried", AddrmanTableToJSON(addrman.GetEntries(true), connman));
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -27,6 +27,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
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
|
DEFAULT_ASMAP_FILENAME = 'ip_asn.map' # defined in src/init.cpp
|
||||||
ASMAP = '../../src/test/data/asmap.raw' # path to unit test skeleton asmap
|
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"
|
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]):
|
with self.node.assert_debug_log(expected_msgs=[msg]):
|
||||||
self.start_node(0, extra_args=['-asmap'])
|
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)
|
os.remove(self.default_asmap)
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user