2017-03-25 11:29:56 -03:00
#!/usr/bin/env python3
2023-10-18 05:41:20 -03:00
# Copyright (c) 2017-present The Bitcoin Core developers
2017-03-25 11:29:56 -03:00
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
""" Test RPC calls related to net.
Tests correspond to code in rpc / net . cpp .
"""
2018-06-22 04:53:39 -04:00
from decimal import Decimal
2020-08-15 03:01:21 -04:00
from itertools import product
2023-12-08 14:23:01 -03:00
import platform
2020-08-15 03:01:21 -04:00
import time
2018-06-22 04:53:39 -04:00
2020-08-17 05:45:44 -04:00
import test_framework . messages
2023-09-23 11:54:37 -03:00
from test_framework . netutil import ADDRMAN_NEW_BUCKET_COUNT , ADDRMAN_TRIED_BUCKET_COUNT , ADDRMAN_BUCKET_SIZE
2021-09-19 09:11:09 -03:00
from test_framework . p2p import (
P2PInterface ,
P2P_SERVICES ,
2020-08-17 05:45:44 -04:00
)
2017-03-25 11:29:56 -03:00
from test_framework . test_framework import BitcoinTestFramework
from test_framework . util import (
2020-08-15 03:01:21 -04:00
assert_approx ,
2017-03-25 11:29:56 -03:00
assert_equal ,
2018-05-02 09:19:40 -03:00
assert_greater_than ,
2017-07-12 10:33:46 -04:00
assert_raises_rpc_error ,
2017-04-17 22:42:10 -03:00
p2p_port ,
2017-03-25 11:29:56 -03:00
)
2020-10-29 19:00:44 -03:00
from test_framework . wallet import MiniWallet
2019-09-10 17:07:36 -03:00
2020-05-29 18:05:40 -04:00
2019-09-10 17:07:36 -03:00
def assert_net_servicesnames ( servicesflag , servicenames ) :
""" Utility that checks if all flags are correctly decoded in
` getpeerinfo ` and ` getnetworkinfo ` .
: param servicesflag : The services as an integer .
2019-09-29 23:15:18 -03:00
: param servicenames : The list of decoded services names , as strings .
2019-09-10 17:07:36 -03:00
"""
2019-09-22 01:20:38 -03:00
servicesflag_generated = 0
for servicename in servicenames :
servicesflag_generated | = getattr ( test_framework . messages , ' NODE_ ' + servicename )
assert servicesflag_generated == servicesflag
2017-03-25 11:29:56 -03:00
2020-05-29 18:05:40 -04:00
2017-03-25 11:29:56 -03:00
class NetTest ( BitcoinTestFramework ) :
2017-06-09 18:21:21 -04:00
def set_test_params ( self ) :
2017-03-25 11:29:56 -03:00
self . num_nodes = 2
2020-06-07 12:41:10 -04:00
self . extra_args = [ [ " -minrelaytxfee=0.00001000 " ] , [ " -minrelaytxfee=0.00000500 " ] ]
2019-12-06 11:37:49 -03:00
self . supports_cli = False
2017-03-25 11:29:56 -03:00
def run_test ( self ) :
2020-10-29 19:00:44 -03:00
# We need miniwallet to make a transaction
self . wallet = MiniWallet ( self . nodes [ 0 ] )
2020-09-04 16:37:24 -04:00
# By default, the test framework sets up an addnode connection from
# node 1 --> node0. By connecting node0 --> node 1, we're left with
# the two nodes being connected both ways.
# Topology will look like: node0 <--> node1
2020-09-17 04:46:07 -03:00
self . connect_nodes ( 0 , 1 )
2020-10-21 16:12:09 -03:00
self . sync_all ( )
2019-09-16 10:22:49 -03:00
2020-08-15 03:15:19 -04:00
self . test_connection_count ( )
self . test_getpeerinfo ( )
self . test_getnettotals ( )
self . test_getnetworkinfo ( )
2022-10-21 15:41:35 -03:00
self . test_addnode_getaddednodeinfo ( )
2020-05-29 18:05:40 -04:00
self . test_service_flags ( )
2020-08-15 03:15:19 -04:00
self . test_getnodeaddresses ( )
2021-05-22 16:09:28 -04:00
self . test_addpeeraddress ( )
2023-08-22 13:15:14 -04:00
self . test_sendmsgtopeer ( )
2023-01-29 15:24:43 -03:00
self . test_getaddrmaninfo ( )
2023-09-23 11:54:37 -03:00
self . test_getrawaddrman ( )
2017-04-21 18:41:57 -03:00
2020-08-15 03:15:19 -04:00
def test_connection_count ( self ) :
self . log . info ( " Test getconnectioncount " )
# After using `connect_nodes` to connect nodes 0 and 1 to each other.
2017-04-21 18:41:57 -03:00
assert_equal ( self . nodes [ 0 ] . getconnectioncount ( ) , 2 )
2020-09-04 16:32:14 -04:00
def test_getpeerinfo ( self ) :
self . log . info ( " Test getpeerinfo " )
# Create a few getpeerinfo last_block/last_transaction values.
2020-10-29 19:00:44 -03:00
self . wallet . send_self_transfer ( from_node = self . nodes [ 0 ] ) # Make a transaction so we can see it in the getpeerinfo results
2021-08-19 11:10:24 -04:00
self . generate ( self . nodes [ 1 ] , 1 )
2020-09-04 16:32:14 -04:00
time_now = int ( time . time ( ) )
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
# the address bound to on one side will be the source address for the other node
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 [ 0 ] [ 0 ] [ ' minfeefilter ' ] , Decimal ( " 0.00000500 " ) )
assert_equal ( peer_info [ 1 ] [ 0 ] [ ' minfeefilter ' ] , Decimal ( " 0.00001000 " ) )
# check the `servicesnames` field
for info in peer_info :
assert_net_servicesnames ( int ( info [ 0 ] [ " services " ] , 0x10 ) , info [ 0 ] [ " servicesnames " ] )
assert_equal ( peer_info [ 0 ] [ 0 ] [ ' connection_type ' ] , ' inbound ' )
assert_equal ( peer_info [ 0 ] [ 1 ] [ ' connection_type ' ] , ' manual ' )
assert_equal ( peer_info [ 1 ] [ 0 ] [ ' connection_type ' ] , ' manual ' )
assert_equal ( peer_info [ 1 ] [ 1 ] [ ' connection_type ' ] , ' inbound ' )
2021-02-01 19:56:20 -03:00
# Check dynamically generated networks list in getpeerinfo help output.
2021-09-09 10:55:45 -03:00
assert " (ipv4, ipv6, onion, i2p, cjdns, not_publicly_routable) " in self . nodes [ 0 ] . help ( " getpeerinfo " )
2021-02-01 19:56:20 -03:00
2022-11-17 07:23:08 -03:00
self . log . info ( " Check getpeerinfo output before a version message was sent " )
no_version_peer_id = 2
no_version_peer_conntime = int ( time . time ( ) )
self . nodes [ 0 ] . setmocktime ( no_version_peer_conntime )
2023-12-09 09:26:18 -03:00
with self . nodes [ 0 ] . wait_for_new_peer ( ) :
2022-11-21 20:10:20 -03:00
no_version_peer = self . nodes [ 0 ] . add_p2p_connection ( P2PInterface ( ) , send_version = False , wait_for_verack = False )
2022-11-17 07:23:08 -03:00
self . nodes [ 0 ] . setmocktime ( 0 )
peer_info = self . nodes [ 0 ] . getpeerinfo ( ) [ no_version_peer_id ]
peer_info . pop ( " addr " )
peer_info . pop ( " addrbind " )
assert_equal (
peer_info ,
{
" addr_processed " : 0 ,
" addr_rate_limited " : 0 ,
" addr_relay_enabled " : False ,
" bip152_hb_from " : False ,
" bip152_hb_to " : False ,
" bytesrecv " : 0 ,
" bytesrecv_per_msg " : { } ,
" bytessent " : 0 ,
" bytessent_per_msg " : { } ,
" connection_type " : " inbound " ,
" conntime " : no_version_peer_conntime ,
" id " : no_version_peer_id ,
" inbound " : True ,
" inflight " : [ ] ,
" last_block " : 0 ,
" last_transaction " : 0 ,
" lastrecv " : 0 ,
" lastsend " : 0 ,
" minfeefilter " : Decimal ( " 0E-8 " ) ,
" network " : " not_publicly_routable " ,
" permissions " : [ ] ,
" presynced_headers " : - 1 ,
" relaytxes " : False ,
" services " : " 0000000000000000 " ,
" servicesnames " : [ ] ,
2023-07-30 23:26:04 -04:00
" session_id " : " " ,
2022-11-17 07:23:08 -03:00
" startingheight " : - 1 ,
" subver " : " " ,
" synced_blocks " : - 1 ,
" synced_headers " : - 1 ,
" timeoffset " : 0 ,
2023-09-14 22:20:07 -03:00
" transport_protocol_type " : " v1 " if not self . options . v2transport else " detecting " ,
2022-11-17 07:23:08 -03:00
" version " : 0 ,
} ,
)
2022-11-21 20:10:20 -03:00
no_version_peer . peer_disconnect ( )
self . wait_until ( lambda : len ( self . nodes [ 0 ] . getpeerinfo ( ) ) == 2 )
2022-11-17 07:23:08 -03:00
2020-08-15 03:15:19 -04:00
def test_getnettotals ( self ) :
self . log . info ( " Test getnettotals " )
2020-10-28 07:14:55 -03:00
# Test getnettotals and getpeerinfo by doing a ping. The bytes
2023-09-14 22:20:07 -03:00
# sent/received should increase by at least the size of one ping
# and one pong. Both have a payload size of 8 bytes, but the total
# size depends on the used p2p version:
# - p2p v1: 24 bytes (header) + 8 bytes (payload) = 32 bytes
# - p2p v2: 21 bytes (header/tag with short-id) + 8 bytes (payload) = 29 bytes
ping_size = 32 if not self . options . v2transport else 29
2018-03-27 18:18:01 -03:00
net_totals_before = self . nodes [ 0 ] . getnettotals ( )
2020-10-28 07:14:55 -03:00
peer_info_before = self . nodes [ 0 ] . getpeerinfo ( )
2017-04-21 18:41:57 -03:00
self . nodes [ 0 ] . ping ( )
2023-09-14 22:20:07 -03:00
self . wait_until ( lambda : ( self . nodes [ 0 ] . getnettotals ( ) [ ' totalbytessent ' ] > = net_totals_before [ ' totalbytessent ' ] + ping_size * 2 ) , timeout = 1 )
self . wait_until ( lambda : ( self . nodes [ 0 ] . getnettotals ( ) [ ' totalbytesrecv ' ] > = net_totals_before [ ' totalbytesrecv ' ] + ping_size * 2 ) , timeout = 1 )
2018-02-21 02:25:02 -03:00
2020-11-04 07:06:59 -03:00
for peer_before in peer_info_before :
peer_after = lambda : next ( p for p in self . nodes [ 0 ] . getpeerinfo ( ) if p [ ' id ' ] == peer_before [ ' id ' ] )
2023-09-14 22:20:07 -03:00
self . wait_until ( lambda : peer_after ( ) [ ' bytesrecv_per_msg ' ] . get ( ' pong ' , 0 ) > = peer_before [ ' bytesrecv_per_msg ' ] . get ( ' pong ' , 0 ) + ping_size , timeout = 1 )
self . wait_until ( lambda : peer_after ( ) [ ' bytessent_per_msg ' ] . get ( ' ping ' , 0 ) > = peer_before [ ' bytessent_per_msg ' ] . get ( ' ping ' , 0 ) + ping_size , timeout = 1 )
2017-04-21 18:41:57 -03:00
2020-08-15 03:15:19 -04:00
def test_getnetworkinfo ( self ) :
self . log . info ( " Test getnetworkinfo " )
2020-06-29 04:04:08 -04:00
info = self . nodes [ 0 ] . getnetworkinfo ( )
assert_equal ( info [ ' networkactive ' ] , True )
assert_equal ( info [ ' connections ' ] , 2 )
assert_equal ( info [ ' connections_in ' ] , 1 )
assert_equal ( info [ ' connections_out ' ] , 1 )
2017-03-25 11:29:56 -03:00
2020-07-18 04:00:30 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: false \n ' ] ) :
self . nodes [ 0 ] . setnetworkactive ( state = False )
2017-03-25 11:29:56 -03:00
assert_equal ( self . nodes [ 0 ] . getnetworkinfo ( ) [ ' networkactive ' ] , False )
2018-02-26 19:04:41 -03:00
# Wait a bit for all sockets to close
2022-12-03 13:43:14 -03:00
for n in self . nodes :
self . wait_until ( lambda : n . getnetworkinfo ( ) [ ' connections ' ] == 0 , timeout = 3 )
2017-03-25 11:29:56 -03:00
2020-07-18 04:00:30 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: true \n ' ] ) :
self . nodes [ 0 ] . setnetworkactive ( state = True )
2020-08-15 03:15:19 -04:00
# Connect nodes both ways.
2020-09-17 04:46:07 -03:00
self . connect_nodes ( 0 , 1 )
self . connect_nodes ( 1 , 0 )
2019-09-16 10:22:49 -03:00
2020-06-29 04:04:08 -04:00
info = self . nodes [ 0 ] . getnetworkinfo ( )
assert_equal ( info [ ' networkactive ' ] , True )
assert_equal ( info [ ' connections ' ] , 2 )
assert_equal ( info [ ' connections_in ' ] , 1 )
assert_equal ( info [ ' connections_out ' ] , 1 )
2017-03-25 11:29:56 -03:00
2019-09-10 17:07:36 -03:00
# check the `servicesnames` field
network_info = [ node . getnetworkinfo ( ) for node in self . nodes ]
for info in network_info :
2019-09-22 01:20:38 -03:00
assert_net_servicesnames ( int ( info [ " localservices " ] , 0x10 ) , info [ " localservicesnames " ] )
2019-09-10 17:07:36 -03:00
2021-02-01 19:56:20 -03:00
# Check dynamically generated networks list in getnetworkinfo help output.
2021-09-09 10:55:45 -03:00
assert " (ipv4, ipv6, onion, i2p, cjdns) " in self . nodes [ 0 ] . help ( " getnetworkinfo " )
2021-02-01 19:56:20 -03:00
2022-10-21 15:41:35 -03:00
def test_addnode_getaddednodeinfo ( self ) :
self . log . info ( " Test addnode and getaddednodeinfo " )
2017-04-17 22:42:10 -03:00
assert_equal ( self . nodes [ 0 ] . getaddednodeinfo ( ) , [ ] )
# add a node (node2) to node0
ip_port = " 127.0.0.1: {} " . format ( p2p_port ( 2 ) )
2018-11-13 15:42:36 -03:00
self . nodes [ 0 ] . addnode ( node = ip_port , command = ' add ' )
2023-07-25 15:29:00 -04:00
# try to add an equivalent ip
2023-12-08 14:23:01 -03:00
# (note that OpenBSD doesn't support the IPv4 shorthand notation with omitted zero-bytes)
if platform . system ( ) != " OpenBSD " :
ip_port2 = " 127.1: {} " . format ( p2p_port ( 2 ) )
assert_raises_rpc_error ( - 23 , " Node already added " , self . nodes [ 0 ] . addnode , node = ip_port2 , command = ' add ' )
2017-04-17 22:42:10 -03:00
# check that the node has indeed been added
2023-07-25 15:29:00 -04:00
added_nodes = self . nodes [ 0 ] . getaddednodeinfo ( )
2017-04-17 22:42:10 -03:00
assert_equal ( len ( added_nodes ) , 1 )
assert_equal ( added_nodes [ 0 ] [ ' addednode ' ] , ip_port )
2020-08-10 18:01:53 -04:00
# check that node cannot be added again
assert_raises_rpc_error ( - 23 , " Node already added " , self . nodes [ 0 ] . addnode , node = ip_port , command = ' add ' )
# check that node can be removed
self . nodes [ 0 ] . addnode ( node = ip_port , command = ' remove ' )
assert_equal ( self . nodes [ 0 ] . getaddednodeinfo ( ) , [ ] )
2022-10-21 15:41:35 -03:00
# check that an invalid command returns an error
assert_raises_rpc_error ( - 1 , ' addnode " node " " command " ' , self . nodes [ 0 ] . addnode , node = ip_port , command = ' abc ' )
2020-08-10 18:01:53 -04:00
# check that trying to remove the node again returns an error
assert_raises_rpc_error ( - 24 , " Node could not be removed " , self . nodes [ 0 ] . addnode , node = ip_port , command = ' remove ' )
2017-08-15 19:24:39 -03:00
# check that a non-existent node returns an error
2018-03-27 18:18:01 -03:00
assert_raises_rpc_error ( - 24 , " Node has not been added " , self . nodes [ 0 ] . getaddednodeinfo , ' 1.1.1.1 ' )
2017-04-17 22:42:10 -03:00
2020-05-29 18:05:40 -04:00
def test_service_flags ( self ) :
2020-08-15 03:15:19 -04:00
self . log . info ( " Test service flags " )
2020-05-29 18:05:40 -04:00
self . nodes [ 0 ] . add_p2p_connection ( P2PInterface ( ) , services = ( 1 << 4 ) | ( 1 << 63 ) )
2022-02-05 15:19:47 -03:00
if self . options . v2transport :
assert_equal ( [ ' UNKNOWN[2^4] ' , ' P2P_V2 ' , ' UNKNOWN[2^63] ' ] , self . nodes [ 0 ] . getpeerinfo ( ) [ - 1 ] [ ' servicesnames ' ] )
else :
assert_equal ( [ ' UNKNOWN[2^4] ' , ' UNKNOWN[2^63] ' ] , self . nodes [ 0 ] . getpeerinfo ( ) [ - 1 ] [ ' servicesnames ' ] )
2020-05-29 18:05:40 -04:00
self . nodes [ 0 ] . disconnect_p2ps ( )
2020-08-15 03:15:19 -04:00
def test_getnodeaddresses ( self ) :
self . log . info ( " Test getnodeaddresses " )
2018-05-02 09:19:40 -03:00
self . nodes [ 0 ] . add_p2p_connection ( P2PInterface ( ) )
2021-05-02 13:42:29 -04:00
# 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.
2018-05-02 09:19:40 -03:00
imported_addrs = [ ]
2020-07-23 13:10:35 -04:00
for i in range ( 10000 ) :
first_octet = i >> 8
second_octet = i % 256
2021-05-02 13:42:29 -04:00
a = f " { first_octet } . { second_octet } .1.1 "
2018-05-02 09:19:40 -03:00
imported_addrs . append ( a )
2020-07-23 13:10:35 -04:00
self . nodes [ 0 ] . addpeeraddress ( a , 8333 )
2018-05-02 09:19:40 -03:00
2021-05-02 13:42:29 -04:00
# 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 " )
2020-07-23 13:10:35 -04:00
assert_greater_than ( len ( node_addresses ) , 5000 )
assert_greater_than ( 10000 , len ( node_addresses ) )
2018-05-02 09:19:40 -03:00
for a in node_addresses :
2020-07-23 11:21:14 -04:00
assert_greater_than ( a [ " time " ] , 1527811200 ) # 1st June 2018
2021-09-19 09:11:09 -03:00
assert_equal ( a [ " services " ] , P2P_SERVICES )
2018-05-02 09:19:40 -03:00
assert a [ " address " ] in imported_addrs
assert_equal ( a [ " port " ] , 8333 )
2021-04-03 15:21:28 -03:00
assert_equal ( a [ " network " ] , " ipv4 " )
2018-05-02 09:19:40 -03:00
2021-05-02 13:42:29 -04:00
# 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 )
2021-09-19 09:11:09 -03:00
assert_equal ( res [ 0 ] [ " services " ] , P2P_SERVICES )
2020-07-23 11:21:14 -04:00
2021-09-22 12:06:31 -03:00
# Test for the absence of onion, I2P and CJDNS addresses.
for network in [ " onion " , " i2p " , " cjdns " ] :
2021-05-02 13:42:29 -04:00
assert_equal ( self . nodes [ 0 ] . getnodeaddresses ( 0 , network ) , [ ] )
2018-05-02 09:19:40 -03:00
2021-05-02 13:42:29 -04:00
# Test invalid arguments.
assert_raises_rpc_error ( - 8 , " Address count out of range " , self . nodes [ 0 ] . getnodeaddresses , - 1 )
assert_raises_rpc_error ( - 8 , " Network not recognized: Foo " , self . nodes [ 0 ] . getnodeaddresses , 1 , " Foo " )
2018-05-02 09:19:40 -03:00
2021-05-22 16:09:28 -04:00
def test_addpeeraddress ( self ) :
2021-09-14 08:06:38 -03:00
""" RPC addpeeraddress sets the source address equal to the destination address.
If an address with the same / 16 as an existing new entry is passed , it will be
placed in the same new bucket and have a 1 / 64 chance of the bucket positions
colliding ( depending on the value of nKey in the addrman ) , in which case the
new address won ' t be added. The probability of collision can be reduced to
1 / 2 ^ 16 = 1 / 65536 by using an address from a different / 16. We avoid this here
by first testing adding a tried table entry before testing adding a new table one .
"""
2021-05-22 16:09:28 -04:00
self . log . info ( " Test addpeeraddress " )
2021-09-14 08:06:38 -03:00
self . restart_node ( 1 , [ " -checkaddrman=1 " ] )
2021-05-22 16:09:28 -04:00
node = self . nodes [ 1 ]
self . log . debug ( " Test that addpeerinfo is a hidden RPC " )
# It is hidden from general help, but its detailed help may be called directly.
assert " addpeerinfo " not in node . help ( )
assert " addpeerinfo " in node . help ( " addpeerinfo " )
self . log . debug ( " Test that adding an empty address fails " )
assert_equal ( node . addpeeraddress ( address = " " , port = 8333 ) , { " success " : False } )
assert_equal ( node . getnodeaddresses ( count = 0 ) , [ ] )
2022-12-05 11:15:36 -03:00
self . log . debug ( " Test that non-bool tried fails " )
assert_raises_rpc_error ( - 3 , " JSON value of type string is not of expected type bool " , self . nodes [ 0 ] . addpeeraddress , address = " 1.2.3.4 " , tried = " True " , port = 1234 )
2022-05-13 16:29:09 -04:00
self . log . debug ( " Test that adding an address with invalid port fails " )
assert_raises_rpc_error ( - 1 , " JSON integer out of range " , self . nodes [ 0 ] . addpeeraddress , address = " 1.2.3.4 " , port = - 1 )
2023-10-18 05:41:20 -03:00
assert_raises_rpc_error ( - 1 , " JSON integer out of range " , self . nodes [ 0 ] . addpeeraddress , address = " 1.2.3.4 " , port = 65536 )
2022-05-13 16:29:09 -04:00
2021-09-14 08:06:38 -03:00
self . log . debug ( " Test that adding a valid address to the tried table succeeds " )
2023-10-18 05:41:20 -03:00
self . addr_time = int ( time . time ( ) )
node . setmocktime ( self . addr_time )
2021-09-14 08:06:38 -03:00
assert_equal ( node . addpeeraddress ( address = " 1.2.3.4 " , tried = True , port = 8333 ) , { " success " : True } )
2021-09-02 20:01:31 -04:00
with node . assert_debug_log ( expected_msgs = [ " CheckAddrman: new 0, tried 1, total 1 started " ] ) :
2021-09-14 08:06:38 -03:00
addrs = node . getnodeaddresses ( count = 0 ) # getnodeaddresses re-runs the addrman checks
assert_equal ( len ( addrs ) , 1 )
assert_equal ( addrs [ 0 ] [ " address " ] , " 1.2.3.4 " )
assert_equal ( addrs [ 0 ] [ " port " ] , 8333 )
self . log . debug ( " Test that adding an already-present tried address to the new and tried tables fails " )
for value in [ True , False ] :
assert_equal ( node . addpeeraddress ( address = " 1.2.3.4 " , tried = value , port = 8333 ) , { " success " : False } )
2021-05-22 16:09:28 -04:00
assert_equal ( len ( node . getnodeaddresses ( count = 0 ) ) , 1 )
2021-09-14 08:06:38 -03:00
self . log . debug ( " Test that adding a second address, this time to the new table, succeeds " )
assert_equal ( node . addpeeraddress ( address = " 2.0.0.0 " , port = 8333 ) , { " success " : True } )
2021-09-02 20:01:31 -04:00
with node . assert_debug_log ( expected_msgs = [ " CheckAddrman: new 1, tried 1, total 2 started " ] ) :
2021-09-14 08:06:38 -03:00
addrs = node . getnodeaddresses ( count = 0 ) # getnodeaddresses re-runs the addrman checks
assert_equal ( len ( addrs ) , 2 )
2023-08-22 13:15:14 -04:00
def test_sendmsgtopeer ( self ) :
node = self . nodes [ 0 ]
self . restart_node ( 0 )
2023-09-14 22:20:07 -03:00
# we want to use a p2p v1 connection here in order to ensure
# a peer id of zero (a downgrade from v2 to v1 would lead
# to an increase of the peer id)
self . connect_nodes ( 0 , 1 , peer_advertises_v2 = False )
2023-08-22 13:15:14 -04:00
self . log . info ( " Test sendmsgtopeer " )
self . log . debug ( " Send a valid message " )
with self . nodes [ 1 ] . assert_debug_log ( expected_msgs = [ " received: addr " ] ) :
node . sendmsgtopeer ( peer_id = 0 , msg_type = " addr " , msg = " FFFFFF " )
self . log . debug ( " Test error for sending to non-existing peer " )
assert_raises_rpc_error ( - 1 , " Error: Could not send message to peer " , node . sendmsgtopeer , peer_id = 100 , msg_type = " addr " , msg = " FF " )
self . log . debug ( " Test that zero-length msg_type is allowed " )
node . sendmsgtopeer ( peer_id = 0 , msg_type = " addr " , msg = " " )
self . log . debug ( " Test error for msg_type that is too long " )
assert_raises_rpc_error ( - 8 , " Error: msg_type too long, max length is 12 " , node . sendmsgtopeer , peer_id = 0 , msg_type = " long_msg_type " , msg = " FF " )
self . log . debug ( " Test that unknown msg_type is allowed " )
node . sendmsgtopeer ( peer_id = 0 , msg_type = " unknown " , msg = " FF " )
self . log . debug ( " Test that empty msg is allowed " )
node . sendmsgtopeer ( peer_id = 0 , msg_type = " addr " , msg = " FF " )
self . log . debug ( " Test that oversized messages are allowed, but get us disconnected " )
zero_byte_string = b ' \x00 ' * 4000001
node . sendmsgtopeer ( peer_id = 0 , msg_type = " addr " , msg = zero_byte_string . hex ( ) )
self . wait_until ( lambda : len ( self . nodes [ 0 ] . getpeerinfo ( ) ) == 0 , timeout = 10 )
2023-01-29 15:24:43 -03:00
def test_getaddrmaninfo ( self ) :
self . log . info ( " Test getaddrmaninfo " )
node = self . nodes [ 1 ]
# current count of ipv4 addresses in addrman is {'new':1, 'tried':1}
self . log . info ( " Test that count of addresses in addrman match expected values " )
res = node . getaddrmaninfo ( )
assert_equal ( res [ " ipv4 " ] [ " new " ] , 1 )
assert_equal ( res [ " ipv4 " ] [ " tried " ] , 1 )
assert_equal ( res [ " ipv4 " ] [ " total " ] , 2 )
assert_equal ( res [ " all_networks " ] [ " new " ] , 1 )
assert_equal ( res [ " all_networks " ] [ " tried " ] , 1 )
assert_equal ( res [ " all_networks " ] [ " total " ] , 2 )
for net in [ " ipv6 " , " onion " , " i2p " , " cjdns " ] :
assert_equal ( res [ net ] [ " new " ] , 0 )
assert_equal ( res [ net ] [ " tried " ] , 0 )
assert_equal ( res [ net ] [ " total " ] , 0 )
2020-05-29 18:05:40 -04:00
2023-09-23 11:54:37 -03:00
def test_getrawaddrman ( self ) :
self . log . info ( " Test getrawaddrman " )
node = self . nodes [ 1 ]
self . log . debug ( " Test that getrawaddrman is a hidden RPC " )
# It is hidden from general help, but its detailed help may be called directly.
assert " getrawaddrman " not in node . help ( )
assert " getrawaddrman " in node . help ( " getrawaddrman " )
def check_addr_information ( result , expected ) :
""" Utility to compare a getrawaddrman result entry with an expected entry """
assert_equal ( result [ " address " ] , expected [ " address " ] )
assert_equal ( result [ " port " ] , expected [ " port " ] )
assert_equal ( result [ " services " ] , expected [ " services " ] )
assert_equal ( result [ " network " ] , expected [ " network " ] )
assert_equal ( result [ " source " ] , expected [ " source " ] )
assert_equal ( result [ " source_network " ] , expected [ " source_network " ] )
2023-10-18 05:41:20 -03:00
assert_equal ( result [ " time " ] , self . addr_time )
2023-09-23 11:54:37 -03:00
def check_getrawaddrman_entries ( expected ) :
""" Utility to compare a getrawaddrman result with expected addrman contents """
getrawaddrman = node . getrawaddrman ( )
getaddrmaninfo = node . getaddrmaninfo ( )
for ( table_name , table_info ) in expected . items ( ) :
assert_equal ( len ( getrawaddrman [ table_name ] ) , len ( table_info [ " entries " ] ) )
assert_equal ( len ( getrawaddrman [ table_name ] ) , getaddrmaninfo [ " all_networks " ] [ table_name ] )
for bucket_position in getrawaddrman [ table_name ] . keys ( ) :
bucket = int ( bucket_position . split ( " / " ) [ 0 ] )
position = int ( bucket_position . split ( " / " ) [ 1 ] )
# bucket and position only be sanity checked here as the
# test-addrman isn't deterministic
assert 0 < = int ( bucket ) < table_info [ " bucket_count " ]
assert 0 < = int ( position ) < ADDRMAN_BUCKET_SIZE
entry = getrawaddrman [ table_name ] [ bucket_position ]
expected_entry = list ( filter ( lambda e : e [ " address " ] == entry [ " address " ] , table_info [ " entries " ] ) ) [ 0 ]
check_addr_information ( entry , expected_entry )
# we expect one addrman new and tried table entry, which were added in a previous test
expected = {
" new " : {
" bucket_count " : ADDRMAN_NEW_BUCKET_COUNT ,
" entries " : [
{
" address " : " 2.0.0.0 " ,
" port " : 8333 ,
" services " : 9 ,
" network " : " ipv4 " ,
" source " : " 2.0.0.0 " ,
" source_network " : " ipv4 " ,
}
]
} ,
" tried " : {
" bucket_count " : ADDRMAN_TRIED_BUCKET_COUNT ,
" entries " : [
{
" address " : " 1.2.3.4 " ,
" port " : 8333 ,
" services " : 9 ,
" network " : " ipv4 " ,
" source " : " 1.2.3.4 " ,
" source_network " : " ipv4 " ,
}
]
}
}
self . log . debug ( " Test that the getrawaddrman contains information about the addresses added in a previous test " )
check_getrawaddrman_entries ( expected )
self . log . debug ( " Add one new address to each addrman table " )
expected [ " new " ] [ " entries " ] . append ( {
" address " : " 2803:0:1234:abcd::1 " ,
" services " : 9 ,
" network " : " ipv6 " ,
" source " : " 2803:0:1234:abcd::1 " ,
" source_network " : " ipv6 " ,
" port " : - 1 , # set once addpeeraddress is successful
} )
expected [ " tried " ] [ " entries " ] . append ( {
" address " : " nrfj6inpyf73gpkyool35hcmne5zwfmse3jl3aw23vk7chdemalyaqad.onion " ,
" services " : 9 ,
" network " : " onion " ,
" source " : " nrfj6inpyf73gpkyool35hcmne5zwfmse3jl3aw23vk7chdemalyaqad.onion " ,
" source_network " : " onion " ,
" port " : - 1 , # set once addpeeraddress is successful
} )
port = 0
for ( table_name , table_info ) in expected . items ( ) :
# There's a slight chance that the to-be-added address collides with an already
# present table entry. To avoid this, we increment the port until an address has been
# added. Incrementing the port changes the position in the new table bucket (bucket
# stays the same) and changes both the bucket and the position in the tried table.
while True :
if node . addpeeraddress ( address = table_info [ " entries " ] [ 1 ] [ " address " ] , port = port , tried = table_name == " tried " ) [ " success " ] :
table_info [ " entries " ] [ 1 ] [ " port " ] = port
self . log . debug ( f " Added { table_info [ ' entries ' ] [ 1 ] [ ' address ' ] } to { table_name } table " )
break
else :
port + = 1
self . log . debug ( " Test that the newly added addresses appear in getrawaddrman " )
check_getrawaddrman_entries ( expected )
2017-03-25 11:29:56 -03:00
if __name__ == ' __main__ ' :
NetTest ( ) . main ( )