Skip to content

Commit 4938a10

Browse files
committed
rpc, test: expose CNodeStats network in RPC getpeerinfo
1 parent 6df7882 commit 4938a10

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

src/rpc/net.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ static RPCHelpMan getpeerinfo()
9494
{RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"},
9595
{RPCResult::Type::STR, "addrbind", "(ip:port) Bind address of the connection to the peer"},
9696
{RPCResult::Type::STR, "addrlocal", "(ip:port) Local address as reported by the peer"},
97+
{RPCResult::Type::STR, "network", "Network (ipv4, ipv6, or onion) the peer connected through"},
9798
{RPCResult::Type::NUM, "mapped_as", "The AS in the BGP route to the peer used for diversifying\n"
9899
"peer selection (only available if the asmap config flag is set)"},
99100
{RPCResult::Type::STR_HEX, "services", "The services offered"},
@@ -165,10 +166,13 @@ static RPCHelpMan getpeerinfo()
165166
bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
166167
obj.pushKV("id", stats.nodeid);
167168
obj.pushKV("addr", stats.addrName);
168-
if (!(stats.addrLocal.empty()))
169-
obj.pushKV("addrlocal", stats.addrLocal);
170-
if (stats.addrBind.IsValid())
169+
if (stats.addrBind.IsValid()) {
171170
obj.pushKV("addrbind", stats.addrBind.ToString());
171+
}
172+
if (!(stats.addrLocal.empty())) {
173+
obj.pushKV("addrlocal", stats.addrLocal);
174+
}
175+
obj.pushKV("network", stats.m_network);
172176
if (stats.m_mapped_as != 0) {
173177
obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
174178
}

test/functional/feature_proxy.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
- proxy on IPv6
1919
2020
- Create various proxies (as threads)
21-
- Create bitcoinds that connect to them
22-
- Manipulate the bitcoinds using addnode (onetry) an observe effects
21+
- Create nodes that connect to them
22+
- Manipulate the peer connections using addnode (onetry) and observe effects
23+
- Test the getpeerinfo `network` field for the peer
2324
2425
addnode connect to IPv4
2526
addnode connect to IPv6
@@ -40,6 +41,12 @@
4041
from test_framework.netutil import test_ipv6_local
4142

4243
RANGE_BEGIN = PORT_MIN + 2 * PORT_RANGE # Start after p2p and rpc ports
44+
# From GetNetworkName() in netbase.cpp:
45+
NET_UNROUTABLE = ""
46+
NET_IPV4 = "ipv4"
47+
NET_IPV6 = "ipv6"
48+
NET_ONION = "onion"
49+
4350

4451
class ProxyTest(BitcoinTestFramework):
4552
def set_test_params(self):
@@ -90,10 +97,16 @@ def setup_nodes(self):
9097
self.add_nodes(self.num_nodes, extra_args=args)
9198
self.start_nodes()
9299

100+
def network_test(self, node, addr, network):
101+
for peer in node.getpeerinfo():
102+
if peer["addr"] == addr:
103+
assert_equal(peer["network"], network)
104+
93105
def node_test(self, node, proxies, auth, test_onion=True):
94106
rv = []
95-
# Test: outgoing IPv4 connection through node
96-
node.addnode("15.61.23.23:1234", "onetry")
107+
addr = "15.61.23.23:1234"
108+
self.log.debug("Test: outgoing IPv4 connection through node for address {}".format(addr))
109+
node.addnode(addr, "onetry")
97110
cmd = proxies[0].queue.get()
98111
assert isinstance(cmd, Socks5Command)
99112
# Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
@@ -104,10 +117,12 @@ def node_test(self, node, proxies, auth, test_onion=True):
104117
assert_equal(cmd.username, None)
105118
assert_equal(cmd.password, None)
106119
rv.append(cmd)
120+
self.network_test(node, addr, network=NET_IPV4)
107121

108122
if self.have_ipv6:
109-
# Test: outgoing IPv6 connection through node
110-
node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry")
123+
addr = "[1233:3432:2434:2343:3234:2345:6546:4534]:5443"
124+
self.log.debug("Test: outgoing IPv6 connection through node for address {}".format(addr))
125+
node.addnode(addr, "onetry")
111126
cmd = proxies[1].queue.get()
112127
assert isinstance(cmd, Socks5Command)
113128
# Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
@@ -118,10 +133,12 @@ def node_test(self, node, proxies, auth, test_onion=True):
118133
assert_equal(cmd.username, None)
119134
assert_equal(cmd.password, None)
120135
rv.append(cmd)
136+
self.network_test(node, addr, network=NET_IPV6)
121137

122138
if test_onion:
123-
# Test: outgoing onion connection through node
124-
node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
139+
addr = "bitcoinostk4e4re.onion:8333"
140+
self.log.debug("Test: outgoing onion connection through node for address {}".format(addr))
141+
node.addnode(addr, "onetry")
125142
cmd = proxies[2].queue.get()
126143
assert isinstance(cmd, Socks5Command)
127144
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
@@ -131,9 +148,11 @@ def node_test(self, node, proxies, auth, test_onion=True):
131148
assert_equal(cmd.username, None)
132149
assert_equal(cmd.password, None)
133150
rv.append(cmd)
151+
self.network_test(node, addr, network=NET_ONION)
134152

135-
# Test: outgoing DNS name connection through node
136-
node.addnode("node.noumenon:8333", "onetry")
153+
addr = "node.noumenon:8333"
154+
self.log.debug("Test: outgoing DNS name connection through node for address {}".format(addr))
155+
node.addnode(addr, "onetry")
137156
cmd = proxies[3].queue.get()
138157
assert isinstance(cmd, Socks5Command)
139158
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
@@ -143,6 +162,7 @@ def node_test(self, node, proxies, auth, test_onion=True):
143162
assert_equal(cmd.username, None)
144163
assert_equal(cmd.password, None)
145164
rv.append(cmd)
165+
self.network_test(node, addr, network=NET_UNROUTABLE)
146166

147167
return rv
148168

@@ -197,5 +217,6 @@ def networks_dict(d):
197217
assert_equal(n3[net]['proxy_randomize_credentials'], False)
198218
assert_equal(n3['onion']['reachable'], False)
199219

220+
200221
if __name__ == '__main__':
201222
ProxyTest().main()

0 commit comments

Comments
 (0)