Inside Bitcoin
Opening the selected file…
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// Copyright (c) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-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.6#include <common/args.h>8#include <chainparamsbase.h>9#include <common/settings.h>10#include <sync.h>11#include <tinyformat.h>12#include <univalue.h>13#include <util/chaintype.h>14#include <util/check.h>15#include <util/fs.h>16#include <util/fs_helpers.h>17#include <util/log.h>18#include <util/strencodings.h>19#include <util/string.h>21#ifdef WIN3222#include <shlobj.h>23#endif25#include <algorithm>26#include <cstdlib>27#include <cstring>28#include <map>29#include <optional>30#include <stdexcept>31#include <string>32#include <utility>33#include <variant>35const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf";36const char * const BITCOIN_SETTINGS_FILENAME = "settings.json";38ArgsManager gArgs;40/**41* Interpret a string argument as a boolean.42*43* The definition of LocaleIndependentAtoi<int>() requires that non-numeric string values44* like "foo", return 0. This means that if a user unintentionally supplies a45* non-integer argument here, the return value is always false. This means that46* -foo=false does what the user probably expects, but -foo=true is well defined47* but does not do what they probably expected.48*49* The return value of LocaleIndependentAtoi<int>(...) is zero when given input not50* representable as an int.51*52* For a more extensive discussion of this topic (and a wide range of opinions53* on the Right Way to change this code), see PR12713.54*/55static bool InterpretBool(const std::string& strValue)56{57if (strValue.empty())58return true;59return (LocaleIndependentAtoi<int>(strValue) != 0);60}62static std::string SettingName(const std::string& arg)63{64return arg.size() > 0 && arg[0] == '-' ? arg.substr(1) : arg;65}67/**68* Parse "name", "section.name", "noname", "section.noname" settings keys.69*70* @note Where an option was negated can be later checked using the71* IsArgNegated() method. One use case for this is to have a way to disable72* options that are not normally boolean (e.g. using -nodebuglogfile to request73* that debug log output is not sent to any file at all).74*/75KeyInfo InterpretKey(std::string key)76{77KeyInfo result;78// Split section name from key name for keys like "testnet.foo" or "regtest.bar"79size_t option_index = key.find('.');80if (option_index != std::string::npos) {81result.section = key.substr(0, option_index);82key.erase(0, option_index + 1);83}84if (key.starts_with("no")) {85key.erase(0, 2);86result.negated = true;87}88result.name = key;89return result;90}92/**93* Interpret settings value based on registered flags.94*95* @param[in] key key information to know if key was negated96* @param[in] value string value of setting to be parsed97* @param[in] flags ArgsManager registered argument flags98* @param[out] error Error description if settings value is not valid99*100* @return parsed settings value if it is valid, otherwise nullopt accompanied101* by a descriptive error string102*/103std::optional<common::SettingsValue> InterpretValue(const KeyInfo& key, const std::string* value,104unsigned int flags, std::string& error)105{106// Return negated settings as false values.107if (key.negated) {108if (flags & ArgsManager::DISALLOW_NEGATION) {109error = strprintf("Negating of -%s is meaningless and therefore forbidden", key.name);110return std::nullopt;111}112// Double negatives like -nofoo=0 are supported (but discouraged)113if (value && !InterpretBool(*value)) {114LogWarning("Parsed potentially confusing double-negative -%s=%s", key.name, *value);115return true;116}117return false;118}119if (!value && (flags & ArgsManager::DISALLOW_ELISION)) {120error = strprintf("Can not set -%s with no value. Please specify value with -%s=value.", key.name, key.name);121return std::nullopt;122}123return value ? *value : "";124}126// Define default constructor and destructor that are not inline, so code instantiating this class doesn't need to127// #include class definitions for all members.128// For example, m_settings has an internal dependency on univalue.129ArgsManager::ArgsManager() = default;130ArgsManager::~ArgsManager() = default;132std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const133{134std::set<std::string> unsuitables;136LOCK(cs_args);138// if there's no section selected, don't worry139if (m_network.empty()) return std::set<std::string> {};141// if it's okay to use the default section for this network, don't worry142if (m_network == ChainTypeToString(ChainType::MAIN)) return std::set<std::string> {};144for (const auto& arg : m_network_only_args) {145if (OnlyHasDefaultSectionSetting(m_settings, m_network, SettingName(arg))) {146unsuitables.insert(arg);147}148}149return unsuitables;150}152std::list<SectionInfo> ArgsManager::GetUnrecognizedSections() const153{154// Section names to be recognized in the config file.155static const std::set<std::string> available_sections{156ChainTypeToString(ChainType::REGTEST),157ChainTypeToString(ChainType::SIGNET),158ChainTypeToString(ChainType::TESTNET),159ChainTypeToString(ChainType::TESTNET4),160ChainTypeToString(ChainType::MAIN),161};163LOCK(cs_args);164std::list<SectionInfo> unrecognized = m_config_sections;165unrecognized.remove_if([](const SectionInfo& appeared){ return available_sections.contains(appeared.m_name); });166return unrecognized;167}169void ArgsManager::SelectConfigNetwork(const std::string& network)170{171LOCK(cs_args);172m_network = network;173}175bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::string& error)176{177LOCK(cs_args);178m_settings.command_line_options.clear();180for (int i = 1; i < argc; i++) {181std::string key(argv[i]);183#ifdef __APPLE__184// At the first time when a user gets the "App downloaded from the185// internet" warning, and clicks the Open button, macOS passes186// a unique process serial number (PSN) as -psn_... command-line187// argument, which we filter out.188if (key.starts_with("-psn_")) continue;189#endif191if (key == "-") break; //bitcoin-tx using stdin192std::optional<std::string> val;193size_t is_index = key.find('=');194if (is_index != std::string::npos) {195val = key.substr(is_index + 1);196key.erase(is_index);197}198#ifdef WIN32199key = ToLower(key);200if (key[0] == '/')201key[0] = '-';202#endif204if (key[0] != '-') {205if (!m_accept_any_command && m_command.empty()) {206// The first non-dash arg is a registered command207std::optional<unsigned int> flags = GetArgFlags_(key);208if (!flags || !(*flags & ArgsManager::COMMAND)) {209error = strprintf("Invalid command '%s'", argv[i]);210return false;211}212}213m_command.push_back(key);214while (++i < argc) {215// The remaining args are command args216m_command.emplace_back(argv[i]);217}218break;219}221// Transform --foo to -foo222if (key.length() > 1 && key[1] == '-')223key.erase(0, 1);225// Transform -foo to foo226key.erase(0, 1);227KeyInfo keyinfo = InterpretKey(key);228std::optional<unsigned int> flags = GetArgFlags_('-' + keyinfo.name);230// Unknown command line options and command line options with dot231// characters (which are returned from InterpretKey with nonempty232// section strings) are not valid.233if (!flags || !keyinfo.section.empty()) {234error = strprintf("Invalid parameter %s", argv[i]);235return false;236}238std::optional<common::SettingsValue> value = InterpretValue(keyinfo, val ? &*val : nullptr, *flags, error);239if (!value) return false;241m_settings.command_line_options[keyinfo.name].push_back(*value);242}244// we do not allow -includeconf from command line, only -noincludeconf245if (auto* includes = common::FindKey(m_settings.command_line_options, "includeconf")) {246const common::SettingsSpan values{*includes};247// Range may be empty if -noincludeconf was passed248if (!values.empty()) {249error = "-includeconf cannot be used from commandline; -includeconf=" + values.begin()->write();250return false; // pick first value as example
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.