2017-12-07 20:38:26 +01:00
#!/usr/bin/env python3
2021-07-28 13:57:16 +02:00
# Copyright (c) 2017-2021 The Bitcoin Core developers
2017-12-07 20:38:26 +01:00
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
""" Test various command line arguments and configuration file parameters. """
import os
2020-09-05 18:51:33 +02:00
import time
2017-12-07 20:38:26 +01:00
from test_framework . test_framework import BitcoinTestFramework
2019-11-15 22:26:23 +01:00
from test_framework import util
2018-01-02 14:57:27 +01:00
2017-12-07 20:38:26 +01:00
class ConfArgsTest ( BitcoinTestFramework ) :
def set_test_params ( self ) :
self . setup_clean_chain = True
self . num_nodes = 1
2019-12-06 15:37:49 +01:00
self . supports_cli = False
2020-09-29 02:24:06 +02:00
self . wallet_names = [ ]
2021-07-26 17:36:01 +02:00
self . disable_autoconnect = False
2017-12-07 20:38:26 +01:00
2018-09-06 11:29:40 +02:00
def test_config_file_parser ( self ) :
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2018-09-06 11:29:40 +02:00
inc_conf_file_path = os . path . join ( self . nodes [ 0 ] . datadir , ' include.conf ' )
with open ( os . path . join ( self . nodes [ 0 ] . datadir , ' bitcoin.conf ' ) , ' a ' , encoding = ' utf-8 ' ) as conf :
2021-06-11 07:52:58 +02:00
conf . write ( f ' includeconf= { inc_conf_file_path } \n ' )
2018-09-06 11:29:40 +02:00
2019-06-18 20:36:04 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error (
2019-12-19 22:27:15 +01:00
expected_msg = ' Error: Error parsing command line arguments: Invalid parameter -dash_cli=1 ' ,
2019-06-18 20:36:04 +02:00
extra_args = [ ' -dash_cli=1 ' ] ,
)
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' dash_conf=1 \n ' )
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' Ignoring unknown configuration value dash_conf ' ] ) :
self . start_node ( 0 )
self . stop_node ( 0 )
2018-09-06 11:29:40 +02:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' -dash=1 \n ' )
2019-07-10 14:06:57 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error ( expected_msg = ' Error: Error reading configuration file: parse error on line 1: -dash=1, options in configuration file must be specified without leading - ' )
2018-09-06 11:29:40 +02:00
2019-07-27 11:37:09 +02:00
if self . is_wallet_compiled ( ) :
with open ( inc_conf_file_path , ' w ' , encoding = ' utf8 ' ) as conf :
conf . write ( " wallet=foo \n " )
2021-06-11 07:52:58 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error ( expected_msg = f ' Error: Config setting for -wallet only applied on { self . chain } network when in [ { self . chain } ] section. ' )
2019-03-21 21:04:35 +01:00
2019-11-15 22:26:23 +01:00
main_conf_file_path = os . path . join ( self . options . tmpdir , ' node0 ' , ' bitcoin_main.conf ' )
2021-06-11 07:52:58 +02:00
util . write_config ( main_conf_file_path , n = 0 , chain = ' ' , extra_config = f ' includeconf= { inc_conf_file_path } \n ' )
2019-04-25 15:32:35 +02:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' acceptnonstdtxn=1 \n ' )
2021-06-11 07:52:58 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error ( extra_args = [ f " -conf= { main_conf_file_path } " ] , expected_msg = ' Error: acceptnonstdtxn is not currently supported for main chain ' )
2019-04-25 15:32:35 +02:00
2018-09-06 11:29:40 +02:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' nono \n ' )
2019-07-10 14:06:57 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error ( expected_msg = ' Error: Error reading configuration file: parse error on line 1: nono, if you intended to specify a negated option, use nono=1 instead ' )
2018-09-06 11:29:40 +02:00
2018-10-16 07:19:53 +02:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' server=1 \n rpcuser=someuser \n rpcpassword=some#pass ' )
2019-07-10 14:06:57 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error ( expected_msg = ' Error: Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided ' )
2018-10-16 07:19:53 +02:00
2019-01-03 11:54:19 +01:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' server=1 \n rpcuser=someuser \n main.rpcpassword=some#pass ' )
2019-07-10 14:06:57 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error ( expected_msg = ' Error: Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided ' )
2019-01-03 11:54:19 +01:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' server=1 \n rpcuser=someuser \n [main] \n rpcpassword=some#pass ' )
2019-07-10 14:06:57 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error ( expected_msg = ' Error: Error reading configuration file: parse error on line 4, using # in rpcpassword can be ambiguous and should be avoided ' )
2019-01-03 11:54:19 +01:00
2019-02-04 04:53:19 +01:00
inc_conf_file2_path = os . path . join ( self . nodes [ 0 ] . datadir , ' include2.conf ' )
with open ( os . path . join ( self . nodes [ 0 ] . datadir , ' bitcoin.conf ' ) , ' a ' , encoding = ' utf-8 ' ) as conf :
2021-06-11 07:52:58 +02:00
conf . write ( f ' includeconf= { inc_conf_file2_path } \n ' )
2019-02-04 04:53:19 +01:00
2018-11-12 03:06:36 +01:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
2019-02-04 04:53:19 +01:00
conf . write ( ' testnot.datadir=1 \n ' )
with open ( inc_conf_file2_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' [testnet] \n ' )
2018-11-12 03:06:36 +01:00
self . restart_node ( 0 )
2021-06-11 07:52:58 +02:00
self . nodes [ 0 ] . stop_node ( expected_stderr = f ' Warning: { inc_conf_file_path } :1 Section [testnot] is not recognized. { os . linesep } { inc_conf_file2_path } :1 Section [testnet] is not recognized. ' )
2018-11-12 03:06:36 +01:00
2018-09-06 11:29:40 +02:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' ' ) # clear
2019-02-04 04:53:19 +01:00
with open ( inc_conf_file2_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' ' ) # clear
2018-09-06 11:29:40 +02:00
2020-09-23 14:30:02 +02:00
def test_invalid_command_line_options ( self ) :
self . nodes [ 0 ] . assert_start_raises_init_error (
expected_msg = ' Error: No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>. ' ,
extra_args = [ ' -proxy ' ] ,
)
2018-05-03 03:09:28 +02:00
def test_log_buffer ( self ) :
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2020-01-07 23:53:40 +01:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' Warning: parsed potentially confusing double-negative -connect=0 \n ' ] ) :
2018-05-03 03:09:28 +02:00
self . start_node ( 0 , extra_args = [ ' -noconnect=0 ' ] )
2020-01-20 16:32:42 +01:00
def test_args_log ( self ) :
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2020-01-20 16:32:42 +01:00
self . log . info ( ' Test config args logging ' )
with self . nodes [ 0 ] . assert_debug_log (
expected_msgs = [
' Command-line arg: addnode= " some.node " ' ,
' Command-line arg: rpcauth=**** ' ,
' Command-line arg: rpcbind=**** ' ,
' Command-line arg: rpcpassword=**** ' ,
' Command-line arg: rpcuser=**** ' ,
' Command-line arg: torpassword=**** ' ,
2021-06-11 07:52:58 +02:00
f ' Config file arg: { self . chain } = " 1 " ' ,
f ' Config file arg: [ { self . chain } ] server= " 1 " ' ,
2020-01-20 16:32:42 +01:00
] ,
unexpected_msgs = [
' alice:f7efda5c189b999524f151318c0c86$d5b51b3beffbc0 ' ,
' 127.1.1.1 ' ,
' secret-rpcuser ' ,
' secret-torpassword ' ,
] ) :
self . start_node ( 0 , extra_args = [
' -addnode=some.node ' ,
' -rpcauth=alice:f7efda5c189b999524f151318c0c86$d5b51b3beffbc0 ' ,
' -rpcbind=127.1.1.1 ' ,
' -rpcpassword= ' ,
' -rpcuser=secret-rpcuser ' ,
' -torpassword=secret-torpassword ' ,
] )
2020-07-18 10:00:30 +02:00
def test_networkactive ( self ) :
self . log . info ( ' Test -networkactive option ' )
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2020-07-18 10:00:30 +02:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: true \n ' ] ) :
self . start_node ( 0 )
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2020-07-18 10:00:30 +02:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: true \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -networkactive ' ] )
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2020-07-18 10:00:30 +02:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: true \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -networkactive=1 ' ] )
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2020-07-18 10:00:30 +02:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: false \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -networkactive=0 ' ] )
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2020-07-18 10:00:30 +02:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: false \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -nonetworkactive ' ] )
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2020-07-18 10:00:30 +02:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: false \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -nonetworkactive=1 ' ] )
2020-09-05 18:51:33 +02:00
def test_seed_peers ( self ) :
2021-02-12 18:35:18 +01:00
self . log . info ( ' Test seed peers ' )
2020-09-05 18:51:33 +02:00
default_data_dir = self . nodes [ 0 ] . datadir
2021-02-21 10:53:58 +01:00
# Only regtest has no fixed seeds. To avoid connections to random
# nodes, regtest is the only network where it is safe to enable
# -fixedseeds in tests
util . assert_equal ( self . nodes [ 0 ] . getblockchaininfo ( ) [ ' chain ' ] , ' regtest ' )
2021-02-21 11:01:20 +01:00
self . stop_node ( 0 )
2020-09-05 18:51:33 +02:00
# No peers.dat exists and -dnsseed=1
2021-05-28 22:45:15 +02:00
# We expect the node will use DNS Seeds, but Regtest mode does not have
# any valid DNS seeds. So after 60 seconds, the node should fallback to
# fixed seeds
2020-09-05 18:51:33 +02:00
assert not os . path . exists ( os . path . join ( default_data_dir , " peers.dat " ) )
2021-02-12 18:35:18 +01:00
start = int ( time . time ( ) )
2021-09-08 10:39:06 +02:00
with self . nodes [ 0 ] . assert_debug_log (
expected_msgs = [
" Loaded 0 addresses from peers.dat " ,
" 0 addresses found from DNS seeds " ,
" opencon thread start " , # Ensure ThreadOpenConnections::start time is properly set
] ,
timeout = 10 ,
) :
2021-02-21 10:53:58 +01:00
self . start_node ( 0 , extra_args = [ ' -dnsseed=1 ' , ' -fixedseeds=1 ' , f ' -mocktime= { start } ' ] )
2021-02-12 18:35:18 +01:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [
2021-02-21 10:53:58 +01:00
" Adding fixed seeds as 60 seconds have passed and addrman is empty " ,
] ) :
2021-02-12 18:35:18 +01:00
self . nodes [ 0 ] . setmocktime ( start + 65 )
2020-09-05 18:51:33 +02:00
self . stop_node ( 0 )
# No peers.dat exists and -dnsseed=0
# We expect the node will fallback immediately to fixed seeds
assert not os . path . exists ( os . path . join ( default_data_dir , " peers.dat " ) )
start = time . time ( )
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [
" Loaded 0 addresses from peers.dat " ,
" DNS seeding disabled " ,
2021-02-21 10:53:58 +01:00
" Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted \n " ,
] ) :
self . start_node ( 0 , extra_args = [ ' -dnsseed=0 ' , ' -fixedseeds=1 ' ] )
2020-09-05 18:51:33 +02:00
assert time . time ( ) - start < 60
self . stop_node ( 0 )
# No peers.dat exists and dns seeds are disabled.
# We expect the node will not add fixed seeds when explicitly disabled.
assert not os . path . exists ( os . path . join ( default_data_dir , " peers.dat " ) )
start = time . time ( )
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [
" Loaded 0 addresses from peers.dat " ,
" DNS seeding disabled " ,
2021-02-21 10:53:58 +01:00
" Fixed seeds are disabled " ,
] ) :
2020-09-05 18:51:33 +02:00
self . start_node ( 0 , extra_args = [ ' -dnsseed=0 ' , ' -fixedseeds=0 ' ] )
assert time . time ( ) - start < 60
self . stop_node ( 0 )
# No peers.dat exists and -dnsseed=0, but a -addnode is provided
# We expect the node will allow 60 seconds prior to using fixed seeds
assert not os . path . exists ( os . path . join ( default_data_dir , " peers.dat " ) )
2021-02-12 18:35:18 +01:00
start = int ( time . time ( ) )
2021-09-08 10:39:06 +02:00
with self . nodes [ 0 ] . assert_debug_log (
expected_msgs = [
" Loaded 0 addresses from peers.dat " ,
" DNS seeding disabled " ,
" opencon thread start " , # Ensure ThreadOpenConnections::start time is properly set
] ,
timeout = 10 ,
) :
2021-02-21 10:53:58 +01:00
self . start_node ( 0 , extra_args = [ ' -dnsseed=0 ' , ' -fixedseeds=1 ' , ' -addnode=fakenodeaddr ' , f ' -mocktime= { start } ' ] )
2021-02-12 18:35:18 +01:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [
2021-02-21 10:53:58 +01:00
" Adding fixed seeds as 60 seconds have passed and addrman is empty " ,
] ) :
2021-02-12 18:35:18 +01:00
self . nodes [ 0 ] . setmocktime ( start + 65 )
2020-09-05 18:51:33 +02:00
2017-12-07 20:38:26 +01:00
def run_test ( self ) :
2018-05-03 03:09:28 +02:00
self . test_log_buffer ( )
2020-01-20 16:32:42 +01:00
self . test_args_log ( )
2020-09-05 18:51:33 +02:00
self . test_seed_peers ( )
2020-07-18 10:00:30 +02:00
self . test_networkactive ( )
2018-05-03 03:09:28 +02:00
2018-09-06 11:29:40 +02:00
self . test_config_file_parser ( )
2020-09-23 14:30:02 +02:00
self . test_invalid_command_line_options ( )
2018-09-06 11:29:40 +02:00
2017-12-07 20:38:26 +01:00
# Remove the -datadir argument so it doesn't override the config file
self . nodes [ 0 ] . args = [ arg for arg in self . nodes [ 0 ] . args if not arg . startswith ( " -datadir " ) ]
2018-01-02 14:57:27 +01:00
default_data_dir = self . nodes [ 0 ] . datadir
2017-12-07 20:38:26 +01:00
new_data_dir = os . path . join ( default_data_dir , ' newdatadir ' )
new_data_dir_2 = os . path . join ( default_data_dir , ' newdatadir2 ' )
# Check that using -datadir argument on non-existent directory fails
self . nodes [ 0 ] . datadir = new_data_dir
2021-06-11 07:52:58 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error ( [ f ' -datadir= { new_data_dir } ' ] , f ' Error: Specified data directory " { new_data_dir } " does not exist. ' )
2017-12-07 20:38:26 +01:00
# Check that using non-existent datadir in conf file fails
conf_file = os . path . join ( default_data_dir , " bitcoin.conf " )
2018-04-04 10:05:00 +02:00
2019-08-22 18:17:31 +02:00
# datadir needs to be set before [chain] section
2018-04-04 10:05:00 +02:00
conf_file_contents = open ( conf_file , encoding = ' utf8 ' ) . read ( )
with open ( conf_file , ' w ' , encoding = ' utf8 ' ) as f :
2021-06-11 07:52:58 +02:00
f . write ( f " datadir= { new_data_dir } \n " )
2018-04-04 10:05:00 +02:00
f . write ( conf_file_contents )
2021-06-11 07:52:58 +02:00
self . nodes [ 0 ] . assert_start_raises_init_error ( [ f ' -conf= { conf_file } ' ] , f ' Error: Error reading configuration file: specified data directory " { new_data_dir } " does not exist. ' )
2017-12-07 20:38:26 +01:00
2021-08-04 12:24:40 +02:00
# Check that an explicitly specified config file that cannot be opened fails
none_existent_conf_file = os . path . join ( default_data_dir , " none_existent_bitcoin.conf " )
self . nodes [ 0 ] . assert_start_raises_init_error ( [ ' -conf= ' + none_existent_conf_file ] , ' Error: Error reading configuration file: specified config file " ' + none_existent_conf_file + ' " could not be opened. ' )
2017-12-07 20:38:26 +01:00
# Create the directory and ensure the config file now works
os . mkdir ( new_data_dir )
2021-06-11 07:52:58 +02:00
self . start_node ( 0 , [ f ' -conf= { conf_file } ' ] )
2019-07-24 18:15:10 +02:00
self . stop_node ( 0 )
2019-08-22 18:17:31 +02:00
assert os . path . exists ( os . path . join ( new_data_dir , self . chain , ' blocks ' ) )
2017-12-07 20:38:26 +01:00
# Ensure command line argument overrides datadir in conf
os . mkdir ( new_data_dir_2 )
self . nodes [ 0 ] . datadir = new_data_dir_2
2021-06-11 07:52:58 +02:00
self . start_node ( 0 , [ f ' -datadir= { new_data_dir_2 } ' , f ' -conf= { conf_file } ' ] )
2019-08-22 18:17:31 +02:00
assert os . path . exists ( os . path . join ( new_data_dir_2 , self . chain , ' blocks ' ) )
2018-09-23 17:34:51 +02:00
2017-12-07 20:38:26 +01:00
if __name__ == ' __main__ ' :
ConfArgsTest ( ) . main ( )