mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
merge bitcoin#21843: enable GetAddr, GetAddresses, and getnodeaddresses by network
continuation of cf27db8574
from dash#5491
includes:
- 6c98c09
- 3f89c0e
- ce6bca8
This commit is contained in:
parent
51edeb082c
commit
ff3497c18b
@ -3,3 +3,6 @@ RPC changes
|
||||
|
||||
- The `getnodeaddresses` RPC now returns a "network" field indicating the
|
||||
network type (ipv4, ipv6, onion, or i2p) for each address.
|
||||
|
||||
- `getnodeaddresses` now also accepts a "network" argument (ipv4, ipv6, onion,
|
||||
or i2p) to return only addresses of the specified network.
|
||||
|
@ -904,6 +904,7 @@ static RPCHelpMan getnodeaddresses()
|
||||
"\nReturn known addresses, which can potentially be used to find new nodes in the network.\n",
|
||||
{
|
||||
{"count", RPCArg::Type::NUM, /* default */ "1", "The maximum number of addresses to return. Specify 0 to return all known addresses."},
|
||||
{"network", RPCArg::Type::STR, /* default */ "all networks", "Return only addresses of the specified network. Can be one of: " + Join(GetNetworkNames(), ", ") + "."},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::ARR, "", "",
|
||||
@ -920,7 +921,10 @@ static RPCHelpMan getnodeaddresses()
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("getnodeaddresses", "8")
|
||||
+ HelpExampleRpc("getnodeaddresses", "8")
|
||||
+ HelpExampleCli("getnodeaddresses", "4 \"i2p\"")
|
||||
+ HelpExampleCli("-named getnodeaddresses", "network=onion count=12")
|
||||
+ HelpExampleRpc("getnodeaddresses", "8")
|
||||
+ HelpExampleRpc("getnodeaddresses", "4, \"i2p\"")
|
||||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
@ -932,8 +936,13 @@ static RPCHelpMan getnodeaddresses()
|
||||
const int count{request.params[0].isNull() ? 1 : request.params[0].get_int()};
|
||||
if (count < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range");
|
||||
|
||||
const std::optional<Network> network{request.params[1].isNull() ? std::nullopt : std::optional<Network>{ParseNetwork(request.params[1].get_str())}};
|
||||
if (network == NET_UNROUTABLE) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Network not recognized: %s", request.params[1].get_str()));
|
||||
}
|
||||
|
||||
// returns a shuffled list of CAddress
|
||||
const std::vector<CAddress> vAddr{node.connman->GetAddresses(count, /* max_pct */ 0, /* network */ std::nullopt)};
|
||||
const std::vector<CAddress> vAddr{node.connman->GetAddresses(count, /* max_pct */ 0, network)};
|
||||
UniValue ret(UniValue::VARR);
|
||||
|
||||
for (const CAddress& addr : vAddr) {
|
||||
@ -1020,7 +1029,7 @@ static const CRPCCommand commands[] =
|
||||
{ "network", "clearbanned", &clearbanned, {} },
|
||||
{ "network", "cleardiscouraged", &cleardiscouraged, {} },
|
||||
{ "network", "setnetworkactive", &setnetworkactive, {"state"} },
|
||||
{ "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
|
||||
{ "network", "getnodeaddresses", &getnodeaddresses, {"count", "network"} },
|
||||
|
||||
{ "hidden", "addconnection", &addconnection, {"address", "connection_type"} },
|
||||
{ "hidden", "addpeeraddress", &addpeeraddress, {"address", "port"} },
|
||||
|
@ -204,43 +204,54 @@ class NetTest(DashTestFramework):
|
||||
def test_getnodeaddresses(self):
|
||||
self.log.info("Test getnodeaddresses")
|
||||
self.nodes[0].add_p2p_connection(P2PInterface())
|
||||
services = NODE_NETWORK
|
||||
|
||||
# Add some addresses to the Address Manager over RPC. Due to the way
|
||||
# bucket and bucket position are calculated, some of these addresses
|
||||
# will collide.
|
||||
# Add an IPv6 address to the address manager.
|
||||
ipv6_addr = "1233:3432:2434:2343:3234:2345:6546:4534"
|
||||
self.nodes[0].addpeeraddress(address=ipv6_addr, port=8333)
|
||||
|
||||
# Add 10,000 IPv4 addresses to the address manager. Due to the way bucket
|
||||
# and bucket positions are calculated, some of these addresses will collide.
|
||||
imported_addrs = []
|
||||
for i in range(10000):
|
||||
first_octet = i >> 8
|
||||
second_octet = i % 256
|
||||
a = "{}.{}.1.1".format(first_octet, second_octet) # IPV4
|
||||
a = f"{first_octet}.{second_octet}.1.1"
|
||||
imported_addrs.append(a)
|
||||
self.nodes[0].addpeeraddress(a, 8333)
|
||||
|
||||
# Obtain addresses via rpc call and check they were ones sent in before.
|
||||
#
|
||||
# Maximum possible addresses in addrman is 10000, although actual
|
||||
# number will usually be less due to bucket and bucket position
|
||||
# collisions.
|
||||
node_addresses = self.nodes[0].getnodeaddresses(0)
|
||||
# Fetch the addresses via the RPC and test the results.
|
||||
assert_equal(len(self.nodes[0].getnodeaddresses()), 1) # default count is 1
|
||||
assert_equal(len(self.nodes[0].getnodeaddresses(count=2)), 2)
|
||||
assert_equal(len(self.nodes[0].getnodeaddresses(network="ipv4", count=8)), 8)
|
||||
|
||||
# Maximum possible addresses in AddrMan is 10000. The actual number will
|
||||
# usually be less due to bucket and bucket position collisions.
|
||||
node_addresses = self.nodes[0].getnodeaddresses(0, "ipv4")
|
||||
assert_greater_than(len(node_addresses), 5000)
|
||||
assert_greater_than(10000, len(node_addresses))
|
||||
for a in node_addresses:
|
||||
assert_equal(a["time"], self.mocktime)
|
||||
assert_equal(a["services"], NODE_NETWORK)
|
||||
assert_equal(a["services"], services)
|
||||
assert a["address"] in imported_addrs
|
||||
assert_equal(a["port"], 8333)
|
||||
assert_equal(a["network"], "ipv4")
|
||||
|
||||
node_addresses = self.nodes[0].getnodeaddresses(1)
|
||||
assert_equal(len(node_addresses), 1)
|
||||
# Test the IPv6 address.
|
||||
res = self.nodes[0].getnodeaddresses(0, "ipv6")
|
||||
assert_equal(len(res), 1)
|
||||
assert_equal(res[0]["address"], ipv6_addr)
|
||||
assert_equal(res[0]["network"], "ipv6")
|
||||
assert_equal(res[0]["port"], 8333)
|
||||
assert_equal(res[0]["services"], services)
|
||||
|
||||
# Test for the absence of onion and I2P addresses.
|
||||
for network in ["onion", "i2p"]:
|
||||
assert_equal(self.nodes[0].getnodeaddresses(0, network), [])
|
||||
|
||||
# Test invalid arguments.
|
||||
assert_raises_rpc_error(-8, "Address count out of range", self.nodes[0].getnodeaddresses, -1)
|
||||
|
||||
# addrman's size cannot be known reliably after insertion, as hash collisions may occur
|
||||
# so only test that requesting a large number of addresses returns less than that
|
||||
LARGE_REQUEST_COUNT = 10000
|
||||
node_addresses = self.nodes[0].getnodeaddresses(LARGE_REQUEST_COUNT)
|
||||
assert_greater_than(LARGE_REQUEST_COUNT, len(node_addresses))
|
||||
assert_raises_rpc_error(-8, "Network not recognized: Foo", self.nodes[0].getnodeaddresses, 1, "Foo")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
Reference in New Issue
Block a user