Changeset View
Changeset View
Standalone View
Standalone View
test/functional/rpc_net.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2017 The Bitcoin Core developers | # Copyright (c) 2017 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Test RPC calls related to net. | """Test RPC calls related to net. | ||||
Tests correspond to code in rpc/net.cpp. | Tests correspond to code in rpc/net.cpp. | ||||
""" | """ | ||||
from decimal import Decimal | from decimal import Decimal | ||||
from itertools import product | |||||
import time | |||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import ( | from test_framework.util import ( | ||||
assert_approx, | |||||
assert_equal, | assert_equal, | ||||
assert_greater_than_or_equal, | assert_greater_than_or_equal, | ||||
assert_greater_than, | assert_greater_than, | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
connect_nodes, | connect_nodes, | ||||
p2p_port, | p2p_port, | ||||
wait_until, | wait_until, | ||||
) | ) | ||||
Show All 24 Lines | class NetTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.num_nodes = 2 | self.num_nodes = 2 | ||||
self.extra_args = [["-minrelaytxfee=0.00001000"], | self.extra_args = [["-minrelaytxfee=0.00001000"], | ||||
["-minrelaytxfee=0.00000500"]] | ["-minrelaytxfee=0.00000500"]] | ||||
self.supports_cli = False | self.supports_cli = False | ||||
def run_test(self): | def run_test(self): | ||||
self.log.info('Get out of IBD for the minfeefilter test') | # Get out of IBD for the minfeefilter and getpeerinfo tests. | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(101) | ||||
self.log.info('Connect nodes both way') | # Connect nodes both ways. | ||||
connect_nodes(self.nodes[0], self.nodes[1]) | connect_nodes(self.nodes[0], self.nodes[1]) | ||||
connect_nodes(self.nodes[1], self.nodes[0]) | connect_nodes(self.nodes[1], self.nodes[0]) | ||||
self._test_connection_count() | self.test_connection_count() | ||||
self._test_getnettotals() | self.test_getpeerinfo() | ||||
self._test_getnetworkinfo() | self.test_getnettotals() | ||||
self._test_getaddednodeinfo() | self.test_getnetworkinfo() | ||||
self._test_getpeerinfo() | self.test_getaddednodeinfo() | ||||
self.test_service_flags() | self.test_service_flags() | ||||
self._test_getnodeaddresses() | self.test_getnodeaddresses() | ||||
def _test_connection_count(self): | def test_connection_count(self): | ||||
# connect_nodes connects each node to the other | self.log.info("Test getconnectioncount") | ||||
# After using `connect_nodes` to connect nodes 0 and 1 to each other. | |||||
assert_equal(self.nodes[0].getconnectioncount(), 2) | assert_equal(self.nodes[0].getconnectioncount(), 2) | ||||
def _test_getnettotals(self): | def test_getnettotals(self): | ||||
self.log.info("Test getnettotals") | |||||
# getnettotals totalbytesrecv and totalbytessent should be | # getnettotals totalbytesrecv and totalbytessent should be | ||||
# consistent with getpeerinfo. Since the RPC calls are not atomic, | # consistent with getpeerinfo. Since the RPC calls are not atomic, | ||||
# and messages might have been recvd or sent between RPC calls, call | # and messages might have been recvd or sent between RPC calls, call | ||||
# getnettotals before and after and verify that the returned values | # getnettotals before and after and verify that the returned values | ||||
# from getpeerinfo are bounded by those values. | # from getpeerinfo are bounded by those values. | ||||
net_totals_before = self.nodes[0].getnettotals() | net_totals_before = self.nodes[0].getnettotals() | ||||
peer_info = self.nodes[0].getpeerinfo() | peer_info = self.nodes[0].getpeerinfo() | ||||
net_totals_after = self.nodes[0].getnettotals() | net_totals_after = self.nodes[0].getnettotals() | ||||
Show All 25 Lines | def test_getnettotals(self): | ||||
after['bytesrecv_per_msg'].get( | after['bytesrecv_per_msg'].get( | ||||
'pong', 0), before['bytesrecv_per_msg'].get( | 'pong', 0), before['bytesrecv_per_msg'].get( | ||||
'pong', 0) + 32) | 'pong', 0) + 32) | ||||
assert_greater_than_or_equal( | assert_greater_than_or_equal( | ||||
after['bytessent_per_msg'].get( | after['bytessent_per_msg'].get( | ||||
'ping', 0), before['bytessent_per_msg'].get( | 'ping', 0), before['bytessent_per_msg'].get( | ||||
'ping', 0) + 32) | 'ping', 0) + 32) | ||||
def _test_getnetworkinfo(self): | def test_getnetworkinfo(self): | ||||
self.log.info("Test getnetworkinfo") | |||||
assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) | assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) | ||||
assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) | assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) | ||||
self.nodes[0].setnetworkactive(state=False) | self.nodes[0].setnetworkactive(state=False) | ||||
assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], False) | assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], False) | ||||
# Wait a bit for all sockets to close | # Wait a bit for all sockets to close | ||||
wait_until(lambda: self.nodes[0].getnetworkinfo()[ | wait_until(lambda: self.nodes[0].getnetworkinfo()[ | ||||
'connections'] == 0, timeout=3) | 'connections'] == 0, timeout=3) | ||||
self.nodes[0].setnetworkactive(state=True) | self.nodes[0].setnetworkactive(state=True) | ||||
self.log.info('Connect nodes both way') | # Connect nodes both ways. | ||||
connect_nodes(self.nodes[0], self.nodes[1]) | connect_nodes(self.nodes[0], self.nodes[1]) | ||||
connect_nodes(self.nodes[1], self.nodes[0]) | connect_nodes(self.nodes[1], self.nodes[0]) | ||||
assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) | assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) | ||||
assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) | assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) | ||||
# check the `servicesnames` field | # check the `servicesnames` field | ||||
network_info = [node.getnetworkinfo() for node in self.nodes] | network_info = [node.getnetworkinfo() for node in self.nodes] | ||||
for info in network_info: | for info in network_info: | ||||
assert_net_servicesnames(int(info["localservices"], 0x10), | assert_net_servicesnames(int(info["localservices"], 0x10), | ||||
info["localservicesnames"]) | info["localservicesnames"]) | ||||
def _test_getaddednodeinfo(self): | def test_getaddednodeinfo(self): | ||||
self.log.info("Test getaddednodeinfo") | |||||
assert_equal(self.nodes[0].getaddednodeinfo(), []) | assert_equal(self.nodes[0].getaddednodeinfo(), []) | ||||
# add a node (node2) to node0 | # add a node (node2) to node0 | ||||
ip_port = "127.0.0.1:{}".format(p2p_port(2)) | ip_port = "127.0.0.1:{}".format(p2p_port(2)) | ||||
self.nodes[0].addnode(node=ip_port, command='add') | self.nodes[0].addnode(node=ip_port, command='add') | ||||
# check that the node has indeed been added | # check that the node has indeed been added | ||||
added_nodes = self.nodes[0].getaddednodeinfo(ip_port) | added_nodes = self.nodes[0].getaddednodeinfo(ip_port) | ||||
assert_equal(len(added_nodes), 1) | assert_equal(len(added_nodes), 1) | ||||
assert_equal(added_nodes[0]['addednode'], ip_port) | assert_equal(added_nodes[0]['addednode'], ip_port) | ||||
# check that a non-existent node returns an error | # check that a non-existent node returns an error | ||||
assert_raises_rpc_error(-24, "Node has not been added", | assert_raises_rpc_error(-24, "Node has not been added", | ||||
self.nodes[0].getaddednodeinfo, '1.1.1.1') | self.nodes[0].getaddednodeinfo, '1.1.1.1') | ||||
def _test_getpeerinfo(self): | def test_getpeerinfo(self): | ||||
self.log.info("Test getpeerinfo") | |||||
# Create a few getpeerinfo last_block/last_transaction values. | |||||
if self.is_wallet_compiled(): | |||||
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1) | |||||
self.nodes[1].generate(1) | |||||
self.sync_all() | |||||
time_now = int(time.time()) | |||||
peer_info = [x.getpeerinfo() for x in self.nodes] | peer_info = [x.getpeerinfo() for x in self.nodes] | ||||
# Verify last_block and last_transaction keys/values. | |||||
for node, peer, field in product(range(self.num_nodes), range(2), [ | |||||
'last_block', 'last_transaction']): | |||||
assert field in peer_info[node][peer].keys() | |||||
if peer_info[node][peer][field] != 0: | |||||
assert_approx(peer_info[node][peer][field], time_now, vspan=60) | |||||
# check both sides of bidirectional connection between nodes | # check both sides of bidirectional connection between nodes | ||||
# the address bound to on one side will be the source address for the | # the address bound to on one side will be the source address for the | ||||
# other node | # other node | ||||
assert_equal(peer_info[0][0]['addrbind'], peer_info[1][0]['addr']) | assert_equal(peer_info[0][0]['addrbind'], peer_info[1][0]['addr']) | ||||
assert_equal(peer_info[1][0]['addrbind'], peer_info[0][0]['addr']) | assert_equal(peer_info[1][0]['addrbind'], peer_info[0][0]['addr']) | ||||
assert_equal(peer_info[0][0]['minfeefilter'], Decimal("0.00000500")) | assert_equal(peer_info[0][0]['minfeefilter'], Decimal("0.00000500")) | ||||
assert_equal(peer_info[1][0]['minfeefilter'], Decimal("0.00001000")) | assert_equal(peer_info[1][0]['minfeefilter'], Decimal("0.00001000")) | ||||
# check the `servicesnames` field | # check the `servicesnames` field | ||||
for info in peer_info: | for info in peer_info: | ||||
assert_net_servicesnames(int(info[0]["services"], 0x10), | assert_net_servicesnames(int(info[0]["services"], 0x10), | ||||
info[0]["servicesnames"]) | info[0]["servicesnames"]) | ||||
def test_service_flags(self): | def test_service_flags(self): | ||||
self.log.info("Test service flags") | |||||
self.nodes[0].add_p2p_connection( | self.nodes[0].add_p2p_connection( | ||||
P2PInterface(), services=( | P2PInterface(), services=( | ||||
1 << 5) | ( | 1 << 5) | ( | ||||
1 << 63)) | 1 << 63)) | ||||
assert_equal(['UNKNOWN[2^5]', 'UNKNOWN[2^63]'], | assert_equal(['UNKNOWN[2^5]', 'UNKNOWN[2^63]'], | ||||
self.nodes[0].getpeerinfo()[-1]['servicesnames']) | self.nodes[0].getpeerinfo()[-1]['servicesnames']) | ||||
self.nodes[0].disconnect_p2ps() | self.nodes[0].disconnect_p2ps() | ||||
def _test_getnodeaddresses(self): | def test_getnodeaddresses(self): | ||||
self.log.info("Test getnodeaddresses") | |||||
self.nodes[0].add_p2p_connection(P2PInterface()) | self.nodes[0].add_p2p_connection(P2PInterface()) | ||||
# send some addresses to the node via the p2p message addr | # send some addresses to the node via the p2p message addr | ||||
msg = msg_addr() | msg = msg_addr() | ||||
imported_addrs = [] | imported_addrs = [] | ||||
for i in range(256): | for i in range(256): | ||||
a = "123.123.123.{}".format(i) | a = "123.123.123.{}".format(i) | ||||
imported_addrs.append(a) | imported_addrs.append(a) | ||||
Show All 31 Lines |