Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32# Copyright (c) 2017-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.5"""Test various command line arguments and configuration file parameters."""7import os8from pathlib import Path9import platform10import re11import tempfile12import time14from test_framework.netutil import UNREACHABLE_PROXY_ARG15from test_framework.test_framework import BitcoinTestFramework16from test_framework.test_node import ErrorMatch17from test_framework import util20class ConfArgsTest(BitcoinTestFramework):21def set_test_params(self):22self.setup_clean_chain = True23self.num_nodes = 124# Prune to prevent disk space warning on CI systems with limited space,25# when using networks other than regtest.26self.extra_args = [["-prune=550"]]27self.supports_cli = False28self.wallet_names = []29self.disable_autoconnect = False30self.uses_wallet = None32# Overridden to avoid attempt to sync not yet started nodes.33def setup_network(self):34self.setup_nodes()36# Overridden to not start nodes automatically - doing so is the37# responsibility of each test function.38def setup_nodes(self):39self.add_nodes(self.num_nodes, self.extra_args)40# Ensure a log file exists as TestNode.assert_debug_log() expects it.41self.nodes[0].debug_log_path.parent.mkdir()42self.nodes[0].debug_log_path.touch()44def test_dir_config(self):45self.log.info('Error should be emitted if config file is a directory')46conf_path = self.nodes[0].datadir_path / 'bitcoin.conf'47os.rename(conf_path, conf_path.with_suffix('.confbkp'))48conf_path.mkdir()49self.stop_node(0)50self.nodes[0].assert_start_raises_init_error(51extra_args=['-regtest'],52expected_msg=f'Error: Error reading configuration file: Config file "{conf_path}" is a directory.',53)54conf_path.rmdir()55os.rename(conf_path.with_suffix('.confbkp'), conf_path)57self.log.debug('Verifying includeconf directive pointing to directory is caught')58with open(conf_path, 'a') as conf:59conf.write(f'includeconf={self.nodes[0].datadir_path}\n')60self.nodes[0].assert_start_raises_init_error(61extra_args=['-regtest'],62expected_msg=f'Error: Error reading configuration file: Included config file "{self.nodes[0].datadir_path}" is a directory.',63)65self.nodes[0].replace_in_config([(f'includeconf={self.nodes[0].datadir_path}', '')])67def test_negated_config(self):68self.log.info('Disabling configuration via -noconf')70conf_path = self.nodes[0].datadir_path / 'bitcoin.conf'71with open(conf_path) as conf:72settings = [f'-{line.rstrip()}' for line in conf if len(line) > 1 and line[0] != '[']73os.rename(conf_path, conf_path.with_suffix('.confbkp'))75self.log.debug('Verifying garbage in config can be detected')76with open(conf_path, 'a') as conf:77conf.write('garbage\n')78self.nodes[0].assert_start_raises_init_error(79extra_args=['-regtest'],80expected_msg='Error: Error reading configuration file: parse error on line 1: garbage',81)83self.log.debug('Verifying that disabling of the config file means garbage inside of it does ' \84'not prevent the node from starting, and message about existing config file is logged')85ignored_file_message = [f'Data directory "{self.nodes[0].datadir_path}" contains a "bitcoin.conf" file which is explicitly ignored using -noconf.']86with self.nodes[0].assert_debug_log(expected_msgs=ignored_file_message):87self.start_node(0, extra_args=settings + ['-noconf'])88self.stop_node(0)90self.log.debug('Verifying no message appears when removing config file')91os.remove(conf_path)92with self.nodes[0].assert_debug_log(expected_msgs=[], unexpected_msgs=ignored_file_message):93self.start_node(0, extra_args=settings + ['-noconf'])94self.stop_node(0)96os.rename(conf_path.with_suffix('.confbkp'), conf_path)98def test_config_file_parser(self):99self.log.info('Test config file parser')101# Check that startup fails if conf= is set in bitcoin.conf or in an included conf file102bad_conf_file_path = self.nodes[0].datadir_path / "bitcoin_bad.conf"103util.write_config(bad_conf_file_path, n=0, chain='', extra_config='conf=some.conf\n')104conf_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'105self.nodes[0].assert_start_raises_init_error(106extra_args=[f'-conf={bad_conf_file_path}'],107expected_msg=conf_in_config_file_err,108)109inc_conf_file_path = self.nodes[0].datadir_path / 'include.conf'110with open(self.nodes[0].datadir_path / 'bitcoin.conf', 'a') as conf:111conf.write(f'includeconf={inc_conf_file_path}\n')112with open(inc_conf_file_path, 'w') as conf:113conf.write('conf=some.conf\n')114self.nodes[0].assert_start_raises_init_error(115expected_msg=conf_in_config_file_err,116)118self.nodes[0].assert_start_raises_init_error(119expected_msg='Error: Error parsing command line arguments: Invalid parameter -dash_cli=1',120extra_args=['-dash_cli=1'],121)122with open(inc_conf_file_path, 'w') as conf:123conf.write('dash_conf=1\n')125with self.nodes[0].assert_debug_log(expected_msgs=['Ignoring unknown configuration value dash_conf']):126self.start_node(0)127self.stop_node(0)129with open(inc_conf_file_path, 'w') as conf:130conf.write('reindex=1\n')132with 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"]):133self.start_node(0)134self.stop_node(0)136with open(inc_conf_file_path, 'w') as conf:137conf.write('-dash=1\n')138self.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 -')140if self.is_wallet_compiled():141with open(inc_conf_file_path, 'w') as conf:142conf.write("wallet=foo\n")143self.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.')145main_conf_file_path = self.nodes[0].datadir_path / "bitcoin_main.conf"146util.write_config(main_conf_file_path, n=0, chain='', extra_config=f'includeconf={inc_conf_file_path}\n')147with open(inc_conf_file_path, 'w') as conf:148conf.write('acceptnonstdtxn=1\n')149self.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')151with open(inc_conf_file_path, 'w') as conf:152conf.write('nono\n')153self.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')155with open(inc_conf_file_path, 'w') as conf:156conf.write('server=1\nrpcuser=someuser\nrpcpassword=some#pass')157self.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')159with open(inc_conf_file_path, 'w') as conf:160conf.write('server=1\nrpcuser=someuser\nmain.rpcpassword=some#pass')161self.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')163with open(inc_conf_file_path, 'w') as conf:164conf.write('server=1\nrpcuser=someuser\n[main]\nrpcpassword=some#pass')165self.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')167inc_conf_file2_path = self.nodes[0].datadir_path / 'include2.conf'168with open(self.nodes[0].datadir_path / 'bitcoin.conf', 'a') as conf:169conf.write(f'includeconf={inc_conf_file2_path}\n')171with open(inc_conf_file_path, 'w') as conf:172conf.write('testnot.datadir=1\n')173with open(inc_conf_file2_path, 'w') as conf:174conf.write('[testnet]\n')175self.restart_node(0)176self.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.')178with open(inc_conf_file_path, 'w') as conf:179conf.write('') # clear180with open(inc_conf_file2_path, 'w') as conf:181conf.write('') # clear183def test_config_file_log(self):184# Disable this test for windows currently because trying to override185# the default datadir through the environment does not seem to work.186if platform.system() == "Windows":187return189self.log.info('Test that correct configuration path is changed when configuration file changes the datadir')191# Create a temporary directory that will be treated as the default data192# directory by bitcoind.193env, default_datadir = util.get_temp_default_datadir(Path(self.options.tmpdir, "test_config_file_log"))194default_datadir.mkdir(parents=True)196# Write a bitcoin.conf file in the default data directory containing a197# datadir= line pointing at the node datadir.198node = self.nodes[0]199conf_text = node.bitcoinconf.read_text()200conf_path = default_datadir / "bitcoin.conf"201conf_path.write_text(f"datadir={node.datadir_path}\n{conf_text}")203# Drop the node -datadir= argument during this test, because if it is204# specified it would take precedence over the datadir setting in the205# config file.206node_args = node.args207node.args = [arg for arg in node.args if not arg.startswith("-datadir=")]209# Check that correct configuration file path is actually logged210# (conf_path, not node.bitcoinconf)211with self.nodes[0].assert_debug_log(expected_msgs=[f"Config file: {conf_path}"]):212self.start_node(0, ["-allowignoredconf"], env=env)213self.stop_node(0)215# Restore node arguments after the test216node.args = node_args218def test_invalid_command_line_options(self):219self.nodes[0].assert_start_raises_init_error(220expected_msg='Error: Error parsing command line arguments: Can not set -proxy with no value. Please specify value with -proxy=value.',221extra_args=['-proxy'],222)223# Provide a value different from 1 to the -wallet negated option224if self.is_wallet_compiled():225for value in [0, 'not_a_boolean']:226self.nodes[0].assert_start_raises_init_error(227expected_msg="Error: Invalid value detected for '-wallet' or '-nowallet'. '-wallet' requires a string value, while '-nowallet' accepts only '1' to disable all wallets",228extra_args=[f'-nowallet={value}'],229)231def test_log_buffer(self):232with self.nodes[0].assert_debug_log(expected_msgs=["[warning] Parsed potentially confusing double-negative -listen=0\n"]):233self.start_node(0, extra_args=['-nolisten=0'])234self.stop_node(0)236def test_args_log(self):237self.log.info('Test config args logging')238with self.nodes[0].assert_debug_log(239expected_msgs=[240'Command-line arg: addnode="some.node"',241'Command-line arg: rpcauth=****',242'Command-line arg: rpcpassword=****',243'Command-line arg: rpcuser=****',244'Command-line arg: torpassword=****',245f'Config file arg: {self.chain}="1"',246f'Config file arg: [{self.chain}] server="1"',247],248unexpected_msgs=[249'alice:f7efda5c189b999524f151318c0c86$d5b51b3beffbc0',250'secret-rpcuser',
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.