2017-12-07 16:38:26 -03:00
#!/usr/bin/env python3
2024-12-05 12:39:48 -03:00
# Copyright (c) 2017-present The Bitcoin Core developers
2017-12-07 16:38:26 -03: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
2023-09-02 01:09:43 -04:00
from pathlib import Path
2023-12-08 13:30:19 -03:00
import platform
2023-03-21 14:14:53 -03:00
import re
import tempfile
2020-09-05 12:51:33 -04:00
import time
2017-12-07 16:38:26 -03:00
from test_framework . test_framework import BitcoinTestFramework
2023-03-21 14:14:53 -03:00
from test_framework . test_node import ErrorMatch
2019-11-15 18:26:23 -03:00
from test_framework import util
2018-01-02 10:57:27 -03:00
2017-12-07 16:38:26 -03:00
class ConfArgsTest ( BitcoinTestFramework ) :
2022-11-09 08:53:13 -03:00
def add_options ( self , parser ) :
self . add_wallet_options ( parser )
2017-12-07 16:38:26 -03:00
def set_test_params ( self ) :
self . setup_clean_chain = True
self . num_nodes = 1
2019-12-06 11:37:49 -03:00
self . supports_cli = False
2020-09-28 21:24:06 -03:00
self . wallet_names = [ ]
2021-07-26 11:36:01 -04:00
self . disable_autoconnect = False
2017-12-07 16:38:26 -03:00
2024-12-03 06:32:20 -03:00
# Overridden to avoid attempt to sync not yet started nodes.
def setup_network ( self ) :
self . setup_nodes ( )
2024-12-05 12:39:48 -03:00
# Overridden to not start nodes automatically - doing so is the
2024-12-03 06:32:20 -03:00
# responsibility of each test function.
def setup_nodes ( self ) :
self . add_nodes ( self . num_nodes , self . extra_args )
# Ensure a log file exists as TestNode.assert_debug_log() expects it.
self . nodes [ 0 ] . debug_log_path . parent . mkdir ( )
self . nodes [ 0 ] . debug_log_path . touch ( )
2024-11-28 06:46:37 -03:00
def test_dir_config ( self ) :
self . log . info ( ' Error should be emitted if config file is a directory ' )
conf_path = self . nodes [ 0 ] . datadir_path / ' bitcoin.conf '
os . rename ( conf_path , conf_path . with_suffix ( ' .confbkp ' ) )
conf_path . mkdir ( )
self . stop_node ( 0 )
self . nodes [ 0 ] . assert_start_raises_init_error (
extra_args = [ ' -regtest ' ] ,
expected_msg = f ' Error: Error reading configuration file: Config file " { conf_path } " is a directory. ' ,
)
conf_path . rmdir ( )
os . rename ( conf_path . with_suffix ( ' .confbkp ' ) , conf_path )
self . log . debug ( ' Verifying includeconf directive pointing to directory is caught ' )
with open ( conf_path , ' a ' , encoding = ' utf-8 ' ) as conf :
conf . write ( f ' includeconf= { self . nodes [ 0 ] . datadir_path } \n ' )
self . nodes [ 0 ] . assert_start_raises_init_error (
extra_args = [ ' -regtest ' ] ,
expected_msg = f ' Error: Error reading configuration file: Included config file " { self . nodes [ 0 ] . datadir_path } " is a directory. ' ,
)
self . nodes [ 0 ] . replace_in_config ( [ ( f ' includeconf= { self . nodes [ 0 ] . datadir_path } ' , ' ' ) ] )
2024-12-03 06:55:13 -03:00
def test_negated_config ( self ) :
self . log . info ( ' Disabling configuration via -noconf ' )
conf_path = self . nodes [ 0 ] . datadir_path / ' bitcoin.conf '
with open ( conf_path , encoding = ' utf-8 ' ) as conf :
settings = [ f ' - { line . rstrip ( ) } ' for line in conf if len ( line ) > 1 and line [ 0 ] != ' [ ' ]
os . rename ( conf_path , conf_path . with_suffix ( ' .confbkp ' ) )
self . log . debug ( ' Verifying garbage in config can be detected ' )
with open ( conf_path , ' a ' , encoding = ' utf-8 ' ) as conf :
2024-12-04 10:42:27 -03:00
conf . write ( ' garbage \n ' )
2024-12-03 06:55:13 -03:00
self . nodes [ 0 ] . assert_start_raises_init_error (
extra_args = [ ' -regtest ' ] ,
expected_msg = ' Error: Error reading configuration file: parse error on line 1: garbage ' ,
)
self . log . debug ( ' Verifying that disabling of the config file means garbage inside of it does ' \
' not prevent the node from starting, and message about existing config file is logged ' )
ignored_file_message = [ f ' [InitConfig] Data directory " { self . nodes [ 0 ] . datadir_path } " contains a " bitcoin.conf " file which is explicitly ignored using -noconf. ' ]
with self . nodes [ 0 ] . assert_debug_log ( timeout = 60 , expected_msgs = ignored_file_message ) :
self . start_node ( 0 , extra_args = settings + [ ' -noconf ' ] )
self . stop_node ( 0 )
self . log . debug ( ' Verifying no message appears when removing config file ' )
os . remove ( conf_path )
with self . nodes [ 0 ] . assert_debug_log ( timeout = 60 , expected_msgs = [ ] , unexpected_msgs = ignored_file_message ) :
self . start_node ( 0 , extra_args = settings + [ ' -noconf ' ] )
self . stop_node ( 0 )
os . rename ( conf_path . with_suffix ( ' .confbkp ' ) , conf_path )
2018-09-06 06:29:40 -03:00
def test_config_file_parser ( self ) :
2022-07-31 10:13:06 -04:00
self . log . info ( ' Test config file parser ' )
2018-09-06 06:29:40 -03:00
2022-07-31 10:13:06 -04:00
# Check that startup fails if conf= is set in bitcoin.conf or in an included conf file
2023-06-14 07:00:11 -04:00
bad_conf_file_path = self . nodes [ 0 ] . datadir_path / " bitcoin_bad.conf "
2024-12-04 10:42:27 -03:00
util . write_config ( bad_conf_file_path , n = 0 , chain = ' ' , extra_config = ' conf=some.conf \n ' )
2022-07-31 10:13:06 -04:00
conf_in_config_file_err = ' Error: Error reading configuration file: conf cannot be set in the configuration file; use includeconf= if you want to include additional config files '
self . nodes [ 0 ] . assert_start_raises_init_error (
extra_args = [ f ' -conf= { bad_conf_file_path } ' ] ,
expected_msg = conf_in_config_file_err ,
)
2023-09-02 01:09:43 -04:00
inc_conf_file_path = self . nodes [ 0 ] . datadir_path / ' include.conf '
with open ( self . nodes [ 0 ] . datadir_path / ' bitcoin.conf ' , ' a ' , encoding = ' utf-8 ' ) as conf :
2021-06-11 01:52:58 -04:00
conf . write ( f ' includeconf= { inc_conf_file_path } \n ' )
2022-07-31 10:13:06 -04:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' conf=some.conf \n ' )
self . nodes [ 0 ] . assert_start_raises_init_error (
expected_msg = conf_in_config_file_err ,
)
2018-09-06 06:29:40 -03:00
2019-06-18 14:36:04 -04:00
self . nodes [ 0 ] . assert_start_raises_init_error (
2019-12-19 18:27:15 -03:00
expected_msg = ' Error: Error parsing command line arguments: Invalid parameter -dash_cli=1 ' ,
2019-06-18 14:36:04 -04:00
extra_args = [ ' -dash_cli=1 ' ] ,
)
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' dash_conf=1 \n ' )
2022-07-31 10:13:06 -04:00
2019-06-18 14:36:04 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' Ignoring unknown configuration value dash_conf ' ] ) :
self . start_node ( 0 )
self . stop_node ( 0 )
2022-07-31 10:13:06 -04:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' reindex=1 \n ' )
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' Warning: reindex=1 is set in the configuration file, which will significantly slow down startup. Consider removing or commenting out this option for better performance, unless there is currently a condition which makes rebuilding the indexes necessary ' ] ) :
self . start_node ( 0 )
self . stop_node ( 0 )
2018-09-06 06:29:40 -03:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' -dash=1 \n ' )
2019-07-10 08:06:57 -04: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 06:29:40 -03:00
2019-07-27 05:37:09 -04: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 01:52:58 -04: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 17:04:35 -03:00
2023-06-14 07:00:11 -04:00
main_conf_file_path = self . nodes [ 0 ] . datadir_path / " bitcoin_main.conf "
2021-06-11 01:52:58 -04:00
util . write_config ( main_conf_file_path , n = 0 , chain = ' ' , extra_config = f ' includeconf= { inc_conf_file_path } \n ' )
2019-04-25 09:32:35 -04:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' acceptnonstdtxn=1 \n ' )
2023-03-21 14:14:53 -03:00
self . nodes [ 0 ] . assert_start_raises_init_error ( extra_args = [ f " -conf= { main_conf_file_path } " , " -allowignoredconf " ] , expected_msg = ' Error: acceptnonstdtxn is not currently supported for main chain ' )
2019-04-25 09:32:35 -04:00
2018-09-06 06:29:40 -03:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' nono \n ' )
2019-07-10 08:06:57 -04: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 06:29:40 -03:00
2018-10-16 02:19:53 -03: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 08:06:57 -04: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 02:19:53 -03:00
2019-01-03 07:54:19 -03: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 08:06:57 -04: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 07:54:19 -03: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 08:06:57 -04: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 07:54:19 -03:00
2023-09-02 01:09:43 -04:00
inc_conf_file2_path = self . nodes [ 0 ] . datadir_path / ' include2.conf '
with open ( self . nodes [ 0 ] . datadir_path / ' bitcoin.conf ' , ' a ' , encoding = ' utf-8 ' ) as conf :
2021-06-11 01:52:58 -04:00
conf . write ( f ' includeconf= { inc_conf_file2_path } \n ' )
2019-02-04 00:53:19 -03:00
2018-11-11 23:06:36 -03:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
2019-02-04 00:53:19 -03: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-11 23:06:36 -03:00
self . restart_node ( 0 )
2021-06-11 01:52:58 -04: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-11 23:06:36 -03:00
2018-09-06 06:29:40 -03:00
with open ( inc_conf_file_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' ' ) # clear
2019-02-04 00:53:19 -03:00
with open ( inc_conf_file2_path , ' w ' , encoding = ' utf-8 ' ) as conf :
conf . write ( ' ' ) # clear
2018-09-06 06:29:40 -03:00
2023-03-27 11:17:57 -03:00
def test_config_file_log ( self ) :
# Disable this test for windows currently because trying to override
# the default datadir through the environment does not seem to work.
2023-12-08 13:30:19 -03:00
if platform . system ( ) == " Windows " :
2023-03-27 11:17:57 -03:00
return
self . log . info ( ' Test that correct configuration path is changed when configuration file changes the datadir ' )
# Create a temporary directory that will be treated as the default data
# directory by bitcoind.
2023-09-02 01:09:43 -04:00
env , default_datadir = util . get_temp_default_datadir ( Path ( self . options . tmpdir , " test_config_file_log " ) )
2023-03-27 11:17:57 -03:00
default_datadir . mkdir ( parents = True )
# Write a bitcoin.conf file in the default data directory containing a
# datadir= line pointing at the node datadir.
node = self . nodes [ 0 ]
2023-09-02 01:09:43 -04:00
conf_text = node . bitcoinconf . read_text ( )
2023-03-27 11:17:57 -03:00
conf_path = default_datadir / " bitcoin.conf "
2023-09-02 01:09:43 -04:00
conf_path . write_text ( f " datadir= { node . datadir_path } \n { conf_text } " )
2023-03-27 11:17:57 -03:00
# Drop the node -datadir= argument during this test, because if it is
# specified it would take precedence over the datadir setting in the
# config file.
node_args = node . args
node . args = [ arg for arg in node . args if not arg . startswith ( " -datadir= " ) ]
# Check that correct configuration file path is actually logged
# (conf_path, not node.bitcoinconf)
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ f " Config file: { conf_path } " ] ) :
self . start_node ( 0 , [ " -allowignoredconf " ] , env = env )
self . stop_node ( 0 )
# Restore node arguments after the test
node . args = node_args
2020-09-23 09:30:02 -03:00
def test_invalid_command_line_options ( self ) :
self . nodes [ 0 ] . assert_start_raises_init_error (
2022-04-12 03:00:28 -04:00
expected_msg = ' Error: Error parsing command line arguments: Can not set -proxy with no value. Please specify value with -proxy=value. ' ,
2020-09-23 09:30:02 -03:00
extra_args = [ ' -proxy ' ] ,
)
2024-08-22 18:41:54 -04:00
# Provide a value different from 1 to the -wallet negated option
if self . is_wallet_compiled ( ) :
for value in [ 0 , ' not_a_boolean ' ] :
self . nodes [ 0 ] . assert_start_raises_init_error (
expected_msg = " Error: Invalid value detected for ' -wallet ' or ' -nowallet ' . ' -wallet ' requires a string value, while ' -nowallet ' accepts only ' 1 ' to disable all wallets " ,
extra_args = [ f ' -nowallet= { value } ' ] ,
)
2020-09-23 09:30:02 -03:00
2018-05-02 22:09:28 -03:00
def test_log_buffer ( self ) :
2020-01-07 19:53:40 -03:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' Warning: parsed potentially confusing double-negative -connect=0 \n ' ] ) :
2018-05-02 22:09:28 -03:00
self . start_node ( 0 , extra_args = [ ' -noconnect=0 ' ] )
2024-12-03 06:32:20 -03:00
self . stop_node ( 0 )
2018-05-02 22:09:28 -03:00
2020-01-20 12:32:42 -03:00
def test_args_log ( self ) :
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: rpcpassword=**** ' ,
' Command-line arg: rpcuser=**** ' ,
' Command-line arg: torpassword=**** ' ,
2021-06-11 01:52:58 -04:00
f ' Config file arg: { self . chain } = " 1 " ' ,
f ' Config file arg: [ { self . chain } ] server= " 1 " ' ,
2020-01-20 12:32:42 -03:00
] ,
unexpected_msgs = [
' alice:f7efda5c189b999524f151318c0c86$d5b51b3beffbc0 ' ,
' secret-rpcuser ' ,
' secret-torpassword ' ,
2023-01-06 00:35:17 -03:00
' Command-line arg: rpcbind=**** ' ,
' Command-line arg: rpcallowip=**** ' ,
2020-01-20 12:32:42 -03:00
] ) :
self . start_node ( 0 , extra_args = [
' -addnode=some.node ' ,
' -rpcauth=alice:f7efda5c189b999524f151318c0c86$d5b51b3beffbc0 ' ,
' -rpcbind=127.1.1.1 ' ,
2023-01-06 00:35:17 -03:00
' -rpcbind=127.0.0.1 ' ,
" -rpcallowip=127.0.0.1 " ,
2020-01-20 12:32:42 -03:00
' -rpcpassword= ' ,
' -rpcuser=secret-rpcuser ' ,
' -torpassword=secret-torpassword ' ,
] )
2024-12-03 06:32:20 -03:00
self . stop_node ( 0 )
2020-01-20 12:32:42 -03:00
2020-07-18 04:00:30 -04:00
def test_networkactive ( self ) :
self . log . info ( ' Test -networkactive option ' )
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: true \n ' ] ) :
self . start_node ( 0 )
2021-02-21 07:01:20 -03:00
self . stop_node ( 0 )
2020-07-18 04:00:30 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: true \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -networkactive ' ] )
2021-02-21 07:01:20 -03:00
self . stop_node ( 0 )
2020-07-18 04:00:30 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: true \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -networkactive=1 ' ] )
2021-02-21 07:01:20 -03:00
self . stop_node ( 0 )
2020-07-18 04:00:30 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: false \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -networkactive=0 ' ] )
2021-02-21 07:01:20 -03:00
self . stop_node ( 0 )
2020-07-18 04:00:30 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: false \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -nonetworkactive ' ] )
2021-02-21 07:01:20 -03:00
self . stop_node ( 0 )
2020-07-18 04:00:30 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' SetNetworkActive: false \n ' ] ) :
self . start_node ( 0 , extra_args = [ ' -nonetworkactive=1 ' ] )
2024-12-03 06:32:20 -03:00
self . stop_node ( 0 )
2020-07-18 04:00:30 -04:00
2020-09-05 12:51:33 -04:00
def test_seed_peers ( self ) :
2021-02-12 14:35:18 -03:00
self . log . info ( ' Test seed peers ' )
2023-09-02 01:09:43 -04:00
default_data_dir = self . nodes [ 0 ] . datadir_path
peer_dat = default_data_dir / ' peers.dat '
2020-09-05 12:51:33 -04:00
# No peers.dat exists and -dnsseed=1
2021-05-28 16:45:15 -04: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
2023-09-02 01:09:43 -04:00
assert not peer_dat . exists ( )
2021-02-12 14:35:18 -03:00
start = int ( time . time ( ) )
2021-09-08 05:39:06 -03: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 06:53:58 -03:00
self . start_node ( 0 , extra_args = [ ' -dnsseed=1 ' , ' -fixedseeds=1 ' , f ' -mocktime= { start } ' ] )
2024-12-03 06:32:20 -03: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-12 14:35:18 -03:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [
2021-02-21 06:53:58 -03:00
" Adding fixed seeds as 60 seconds have passed and addrman is empty " ,
] ) :
2021-02-12 14:35:18 -03:00
self . nodes [ 0 ] . setmocktime ( start + 65 )
2020-09-05 12:51:33 -04:00
self . stop_node ( 0 )
# No peers.dat exists and -dnsseed=0
# We expect the node will fallback immediately to fixed seeds
2023-09-02 01:09:43 -04:00
assert not peer_dat . exists ( )
2020-09-05 12:51:33 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [
" Loaded 0 addresses from peers.dat " ,
" DNS seeding disabled " ,
2023-05-04 14:59:29 -04:00
" Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet) and neither -addnode nor -seednode are provided \n " ,
2021-02-21 06:53:58 -03:00
] ) :
self . start_node ( 0 , extra_args = [ ' -dnsseed=0 ' , ' -fixedseeds=1 ' ] )
2020-09-05 12:51:33 -04:00
self . stop_node ( 0 )
2022-07-22 14:51:44 -04:00
self . nodes [ 0 ] . assert_start_raises_init_error ( [ ' -dnsseed=1 ' , ' -onlynet=i2p ' , ' -i2psam=127.0.0.1:7656 ' ] , " Error: Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6 " )
2020-09-05 12:51:33 -04:00
# No peers.dat exists and dns seeds are disabled.
# We expect the node will not add fixed seeds when explicitly disabled.
2023-09-02 01:09:43 -04:00
assert not peer_dat . exists ( )
2020-09-05 12:51:33 -04:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [
" Loaded 0 addresses from peers.dat " ,
" DNS seeding disabled " ,
2021-02-21 06:53:58 -03:00
" Fixed seeds are disabled " ,
] ) :
2020-09-05 12:51:33 -04:00
self . start_node ( 0 , extra_args = [ ' -dnsseed=0 ' , ' -fixedseeds=0 ' ] )
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
2023-09-02 01:09:43 -04:00
assert not peer_dat . exists ( )
2021-02-12 14:35:18 -03:00
start = int ( time . time ( ) )
2021-09-08 05:39:06 -03: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 06:53:58 -03:00
self . start_node ( 0 , extra_args = [ ' -dnsseed=0 ' , ' -fixedseeds=1 ' , ' -addnode=fakenodeaddr ' , f ' -mocktime= { start } ' ] )
2021-02-12 14:35:18 -03:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [
2021-02-21 06:53:58 -03:00
" Adding fixed seeds as 60 seconds have passed and addrman is empty " ,
] ) :
2021-02-12 14:35:18 -03:00
self . nodes [ 0 ] . setmocktime ( start + 65 )
2024-12-03 06:32:20 -03:00
self . stop_node ( 0 )
2020-09-05 12:51:33 -04:00
2020-09-25 16:33:47 -03:00
def test_connect_with_seednode ( self ) :
self . log . info ( ' Test -connect with -seednode ' )
seednode_ignored = [ ' -seednode is ignored when -connect is used \n ' ]
dnsseed_ignored = [ ' -dnsseed is ignored when -connect is used and -proxy is specified \n ' ]
addcon_thread_started = [ ' addcon thread start \n ' ]
# When -connect is supplied, expanding addrman via getaddr calls to ADDR_FETCH(-seednode)
# nodes is irrelevant and -seednode is ignored.
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = seednode_ignored ) :
self . start_node ( 0 , extra_args = [ ' -connect=fakeaddress1 ' , ' -seednode=fakeaddress2 ' ] )
# With -proxy, an ADDR_FETCH connection is made to a peer that the dns seed resolves to.
# ADDR_FETCH connections are not used when -connect is used.
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = dnsseed_ignored ) :
self . restart_node ( 0 , extra_args = [ ' -connect=fakeaddress1 ' , ' -dnsseed=1 ' , ' -proxy=1.2.3.4 ' ] )
# If the user did not disable -dnsseed, but it was soft-disabled because they provided -connect,
# they shouldn't see a warning about -dnsseed being ignored.
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = addcon_thread_started ,
unexpected_msgs = dnsseed_ignored ) :
self . restart_node ( 0 , extra_args = [ ' -connect=fakeaddress1 ' , ' -proxy=1.2.3.4 ' ] )
# We have to supply expected_msgs as it's a required argument
# The expected_msg must be something we are confident will be logged after the unexpected_msg
# These cases test for -connect being supplied but only to disable it
for connect_arg in [ ' -connect=0 ' , ' -noconnect ' ] :
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = addcon_thread_started ,
unexpected_msgs = seednode_ignored ) :
self . restart_node ( 0 , extra_args = [ connect_arg , ' -seednode=fakeaddress2 ' ] )
2024-12-03 06:32:20 -03:00
self . stop_node ( 0 )
2020-09-25 16:33:47 -03:00
2023-03-21 14:14:53 -03:00
def test_ignored_conf ( self ) :
self . log . info ( ' Test error is triggered when the datadir in use contains a bitcoin.conf file that would be ignored '
' because a conflicting -conf file argument is passed. ' )
node = self . nodes [ 0 ]
with tempfile . NamedTemporaryFile ( dir = self . options . tmpdir , mode = " wt " , delete = False ) as temp_conf :
2023-09-02 01:09:43 -04:00
temp_conf . write ( f " datadir= { node . datadir_path } \n " )
2023-03-21 14:14:53 -03:00
node . assert_start_raises_init_error ( [ f " -conf= { temp_conf . name } " ] , re . escape (
2023-09-02 01:09:43 -04:00
f ' Error: Data directory " { node . datadir_path } " contains a " bitcoin.conf " file which is ignored, because a '
2023-03-21 14:14:53 -03:00
f ' different configuration file " { temp_conf . name } " from command line argument " -conf= { temp_conf . name } " '
f ' is being used instead. ' ) + r " [ \ s \ S]* " , match = ErrorMatch . FULL_REGEX )
# Test that passing a redundant -conf command line argument pointing to
# the same bitcoin.conf that would be loaded anyway does not trigger an
# error.
2023-09-02 01:09:43 -04:00
self . start_node ( 0 , [ f ' -conf= { node . datadir_path } /bitcoin.conf ' ] )
2023-03-21 14:14:53 -03:00
self . stop_node ( 0 )
def test_ignored_default_conf ( self ) :
# Disable this test for windows currently because trying to override
# the default datadir through the environment does not seem to work.
2023-12-08 13:30:19 -03:00
if platform . system ( ) == " Windows " :
2023-03-21 14:14:53 -03:00
return
self . log . info ( ' Test error is triggered when bitcoin.conf in the default data directory sets another datadir '
' and it contains a different bitcoin.conf file that would be ignored ' )
# Create a temporary directory that will be treated as the default data
# directory by bitcoind.
2023-09-02 01:09:43 -04:00
env , default_datadir = util . get_temp_default_datadir ( Path ( self . options . tmpdir , " home " ) )
2023-03-21 14:14:53 -03:00
default_datadir . mkdir ( parents = True )
# Write a bitcoin.conf file in the default data directory containing a
# datadir= line pointing at the node datadir. This will trigger a
# startup error because the node datadir contains a different
# bitcoin.conf that would be ignored.
node = self . nodes [ 0 ]
2023-09-02 01:09:43 -04:00
( default_datadir / " bitcoin.conf " ) . write_text ( f " datadir= { node . datadir_path } \n " )
2023-03-21 14:14:53 -03:00
# Drop the node -datadir= argument during this test, because if it is
# specified it would take precedence over the datadir setting in the
# config file.
node_args = node . args
node . args = [ arg for arg in node . args if not arg . startswith ( " -datadir= " ) ]
node . assert_start_raises_init_error ( [ ] , re . escape (
2023-09-02 01:09:43 -04:00
f ' Error: Data directory " { node . datadir_path } " contains a " bitcoin.conf " file which is ignored, because a '
2023-03-21 14:14:53 -03:00
f ' different configuration file " { default_datadir } /bitcoin.conf " from data directory " { default_datadir } " '
f ' is being used instead. ' ) + r " [ \ s \ S]* " , env = env , match = ErrorMatch . FULL_REGEX )
node . args = node_args
2023-08-21 02:21:34 -04:00
def test_acceptstalefeeestimates_arg_support ( self ) :
self . log . info ( " Test -acceptstalefeeestimates option support " )
conf_file = self . nodes [ 0 ] . datadir_path / " bitcoin.conf "
2024-03-31 18:50:42 -03:00
for chain , chain_name in { ( " main " , " " ) , ( " test " , " testnet3 " ) , ( " signet " , " signet " ) , ( " testnet4 " , " testnet4 " ) } :
2023-08-21 02:21:34 -04:00
util . write_config ( conf_file , n = 0 , chain = chain_name , extra_config = ' acceptstalefeeestimates=1 \n ' )
self . nodes [ 0 ] . assert_start_raises_init_error ( expected_msg = f ' Error: acceptstalefeeestimates is not supported on { chain } chain. ' )
util . write_config ( conf_file , n = 0 , chain = " regtest " ) # Reset to regtest
2024-03-31 18:50:42 -03:00
def test_testnet3_deprecation_msg ( self ) :
self . log . info ( " Test testnet3 deprecation warning " )
t3_warning_log = " Warning: Support for testnet3 is deprecated and will be removed in an upcoming release. Consider switching to testnet4. "
def warning_msg ( node , approx_size ) :
return f ' Warning: Disk space for " { node . datadir_path / node . chain / " blocks " } " may not accommodate the block files. Approximately { approx_size } GB of data will be stored in this directory. '
# Testnet3 node will log the warning
self . nodes [ 0 ] . chain = ' testnet3 '
self . nodes [ 0 ] . replace_in_config ( [ ( ' regtest= ' , ' testnet= ' ) , ( ' [regtest] ' , ' [test] ' ) ] )
with self . nodes [ 0 ] . assert_debug_log ( [ t3_warning_log ] ) :
self . start_node ( 0 )
# Some CI environments will have limited space and some others won't
# so we need to handle both cases as a valid result.
self . nodes [ 0 ] . stderr . seek ( 0 )
err = self . nodes [ 0 ] . stdout . read ( )
self . nodes [ 0 ] . stderr . seek ( 0 )
self . nodes [ 0 ] . stderr . truncate ( )
if err != b ' ' and err != warning_msg ( self . nodes [ 0 ] , 42 ) :
raise AssertionError ( " Unexpected stderr after shutdown of Testnet3 node " )
self . stop_node ( 0 )
# Testnet4 node will not log the warning
self . nodes [ 0 ] . chain = ' testnet4 '
self . nodes [ 0 ] . replace_in_config ( [ ( ' testnet= ' , ' testnet4= ' ) , ( ' [test] ' , ' [testnet4] ' ) ] )
with self . nodes [ 0 ] . assert_debug_log ( [ ] , unexpected_msgs = [ t3_warning_log ] ) :
self . start_node ( 0 )
self . stop_node ( 0 )
# Reset to regtest
self . nodes [ 0 ] . chain = ' regtest '
self . nodes [ 0 ] . replace_in_config ( [ ( ' testnet4= ' , ' regtest= ' ) , ( ' [testnet4] ' , ' [regtest] ' ) ] )
2017-12-07 16:38:26 -03:00
def run_test ( self ) :
2018-05-02 22:09:28 -03:00
self . test_log_buffer ( )
2020-01-20 12:32:42 -03:00
self . test_args_log ( )
2020-09-05 12:51:33 -04:00
self . test_seed_peers ( )
2020-07-18 04:00:30 -04:00
self . test_networkactive ( )
2020-09-25 16:33:47 -03:00
self . test_connect_with_seednode ( )
2018-05-02 22:09:28 -03:00
2024-11-28 06:46:37 -03:00
self . test_dir_config ( )
2024-12-03 06:55:13 -03:00
self . test_negated_config ( )
2018-09-06 06:29:40 -03:00
self . test_config_file_parser ( )
2023-03-27 11:17:57 -03:00
self . test_config_file_log ( )
2020-09-23 09:30:02 -03:00
self . test_invalid_command_line_options ( )
2023-03-21 14:14:53 -03:00
self . test_ignored_conf ( )
self . test_ignored_default_conf ( )
2023-08-21 02:21:34 -04:00
self . test_acceptstalefeeestimates_arg_support ( )
2024-03-31 18:50:42 -03:00
self . test_testnet3_deprecation_msg ( )
2018-09-06 06:29:40 -03:00
2017-12-07 16:38:26 -03: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 " ) ]
2023-09-02 01:09:43 -04:00
default_data_dir = self . nodes [ 0 ] . datadir_path
new_data_dir = default_data_dir / ' newdatadir '
new_data_dir_2 = default_data_dir / ' newdatadir2 '
2017-12-07 16:38:26 -03:00
# Check that using -datadir argument on non-existent directory fails
2023-09-02 01:09:43 -04:00
self . nodes [ 0 ] . datadir_path = new_data_dir
2021-06-11 01:52:58 -04: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 16:38:26 -03:00
# Check that using non-existent datadir in conf file fails
2023-09-02 01:09:43 -04:00
conf_file = default_data_dir / " bitcoin.conf "
2018-04-04 05:05:00 -03:00
2019-08-22 12:17:31 -04:00
# datadir needs to be set before [chain] section
2022-04-26 13:39:07 -04:00
with open ( conf_file , encoding = ' utf8 ' ) as f :
conf_file_contents = f . read ( )
2018-04-04 05:05:00 -03:00
with open ( conf_file , ' w ' , encoding = ' utf8 ' ) as f :
2021-06-11 01:52:58 -04:00
f . write ( f " datadir= { new_data_dir } \n " )
2018-04-04 05:05:00 -03:00
f . write ( conf_file_contents )
2021-06-11 01:52:58 -04: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 16:38:26 -03:00
2021-08-04 06:24:40 -04:00
# Check that an explicitly specified config file that cannot be opened fails
2023-09-02 01:09:43 -04:00
none_existent_conf_file = default_data_dir / " none_existent_bitcoin.conf "
self . nodes [ 0 ] . assert_start_raises_init_error ( [ ' -conf= ' + f ' { none_existent_conf_file } ' ] , ' Error: Error reading configuration file: specified config file " ' + f ' { none_existent_conf_file } ' + ' " could not be opened. ' )
2021-08-04 06:24:40 -04:00
2017-12-07 16:38:26 -03:00
# Create the directory and ensure the config file now works
2023-09-02 01:09:43 -04:00
new_data_dir . mkdir ( )
2021-06-11 01:52:58 -04:00
self . start_node ( 0 , [ f ' -conf= { conf_file } ' ] )
2019-07-24 12:15:10 -04:00
self . stop_node ( 0 )
2023-09-02 01:09:43 -04:00
assert ( new_data_dir / self . chain / ' blocks ' ) . exists ( )
2017-12-07 16:38:26 -03:00
# Ensure command line argument overrides datadir in conf
2023-09-02 01:09:43 -04:00
new_data_dir_2 . mkdir ( )
self . nodes [ 0 ] . datadir_path = new_data_dir_2
2021-06-11 01:52:58 -04:00
self . start_node ( 0 , [ f ' -datadir= { new_data_dir_2 } ' , f ' -conf= { conf_file } ' ] )
2023-09-02 01:09:43 -04:00
assert ( new_data_dir_2 / self . chain / ' blocks ' ) . exists ( )
2018-09-23 12:34:51 -03:00
2017-12-07 16:38:26 -03:00
if __name__ == ' __main__ ' :
2024-07-16 17:05:14 -04:00
ConfArgsTest ( __file__ ) . main ( )