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.
251}252}253return true;254}256std::optional<unsigned int> ArgsManager::GetArgFlags_(const std::string& name) const257{258AssertLockHeld(cs_args);259for (const auto& arg_map : m_available_args) {260const auto search = arg_map.second.find(name);261if (search != arg_map.second.end()) {262return search->second.m_flags;263}264}265return m_default_flags;266}268std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) const269{270LOCK(cs_args);271return GetArgFlags_(name);272}274void ArgsManager::SetDefaultFlags(std::optional<unsigned int> flags)275{276LOCK(cs_args);277m_default_flags = flags;278}280fs::path ArgsManager::GetPathArg_(std::string arg, const fs::path& default_value) const281{282AssertLockHeld(cs_args);283const auto value = GetSetting_(arg);284if (value.isFalse()) return {};285std::string path_str = SettingToString(value, "");286if (path_str.empty()) return default_value;287fs::path result = fs::PathFromString(path_str).lexically_normal();288// Remove trailing slash, if present.289return result.has_filename() ? result : result.parent_path();290}292fs::path ArgsManager::GetPathArg(std::string arg, const fs::path& default_value) const293{294LOCK(cs_args);295return GetPathArg_(std::move(arg), default_value);296}298fs::path ArgsManager::GetBlocksDirPath() const299{300LOCK(cs_args);301fs::path& path = m_cached_blocks_path;303// Cache the path to avoid calling fs::create_directories on every call of304// this function305if (!path.empty()) return path;307if (!GetSetting_("-blocksdir").isNull()) {308path = fs::absolute(GetPathArg_("-blocksdir"));309if (!fs::is_directory(path)) {310path = "";311return path;312}313} else {314path = GetDataDir(/*net_specific=*/false);315}317path /= fs::PathFromString(BaseParams().DataDir());318path /= "blocks";319fs::create_directories(path);320return path;321}323fs::path ArgsManager::GetDataDirBase() const {324LOCK(cs_args);325return GetDataDir(/*net_specific=*/false);326}328fs::path ArgsManager::GetDataDirNet() const {329LOCK(cs_args);330return GetDataDir(/*net_specific=*/true);331}333fs::path ArgsManager::GetDataDir(bool net_specific) const334{335AssertLockHeld(cs_args);336fs::path& path = net_specific ? m_cached_network_datadir_path : m_cached_datadir_path;338// Used cached path if available339if (!path.empty()) return path;341const fs::path datadir{GetPathArg_("-datadir")};342if (!datadir.empty()) {343path = fs::absolute(datadir);344if (!fs::is_directory(path)) {345path = "";346return path;347}348} else {349path = GetDefaultDataDir();350}352if (net_specific && !BaseParams().DataDir().empty()) {353path /= fs::PathFromString(BaseParams().DataDir());354}356return path;357}359void ArgsManager::ClearPathCache()360{361LOCK(cs_args);363m_cached_datadir_path = fs::path();364m_cached_network_datadir_path = fs::path();365m_cached_blocks_path = fs::path();366}368std::optional<const ArgsManager::Command> ArgsManager::GetCommand() const369{370Command ret;371LOCK(cs_args);372auto it = m_command.begin();373if (it == m_command.end()) {374// No command was passed375return std::nullopt;376}377if (!m_accept_any_command) {378// The registered command379ret.command = *(it++);380}381while (it != m_command.end()) {382// The unregistered command and args (if any)383ret.args.push_back(*(it++));384}385return ret;386}388bool ArgsManager::CheckCommandOptions(const std::string& command, std::vector<std::string>* errors) const389{390LOCK(cs_args);392auto command_options = m_available_args.find(OptionsCategory::COMMAND_OPTIONS);393if (command_options == m_available_args.end()) {394// There are no command-specific options at all, so everything is fine395return true;396}398const auto command_args = m_command_args.find(command);399auto is_valid_opt = [&](const auto& opt) EXCLUSIVE_LOCKS_REQUIRED(cs_args) -> bool {400if (command_args == m_command_args.end()) {401// Caller may not have checked that command actually exists402// before calling this function. In that case, treat it as403// having no valid command-specific options.404return false;405} else {406return command_args->second.contains(opt);407}408};410bool ok = true;411for (const auto& [arg, _] : command_options->second) {412if (!GetSetting_(arg).isNull() && !is_valid_opt(arg)) {413ok = false;414if (errors != nullptr) {415errors->emplace_back(strprintf("The %s option cannot be used with the '%s' command.", arg, command));416}417}418}419return ok;420}422std::vector<std::string> ArgsManager::GetArgs(const std::string& strArg) const423{424std::vector<std::string> result;425for (const common::SettingsValue& value : GetSettingsList(strArg)) {426result.push_back(value.isFalse() ? "0" : value.isTrue() ? "1" : value.get_str());427}428return result;429}431bool ArgsManager::IsArgSet(const std::string& strArg) const432{433return !GetSetting(strArg).isNull();434}436bool ArgsManager::GetSettingsPath(fs::path* filepath, bool temp, bool backup) const437{438fs::path settings = GetPathArg("-settings", BITCOIN_SETTINGS_FILENAME);439if (settings.empty()) {440return false;441}442if (backup) {443settings += ".bak";444}445if (filepath) {446*filepath = fsbridge::AbsPathJoin(GetDataDirNet(), temp ? settings + ".tmp" : settings);447}448return true;449}451static void SaveErrors(const std::vector<std::string> errors, std::vector<std::string>* error_out)452{453for (const auto& error : errors) {454if (error_out) {455error_out->emplace_back(error);456} else {457LogWarning("%s", error);458}459}460}462bool ArgsManager::ReadSettingsFile(std::vector<std::string>* errors)463{464fs::path path;465if (!GetSettingsPath(&path, /* temp= */ false)) {466return true; // Do nothing if settings file disabled.467}469LOCK(cs_args);470m_settings.rw_settings.clear();471std::vector<std::string> read_errors;472if (!common::ReadSettings(path, m_settings.rw_settings, read_errors)) {473SaveErrors(read_errors, errors);474return false;475}476for (const auto& setting : m_settings.rw_settings) {477KeyInfo key = InterpretKey(setting.first); // Split setting key into section and argname478if (!GetArgFlags_('-' + key.name)) {479LogWarning("Ignoring unknown rw_settings value %s", setting.first);480}481}482return true;483}485bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors, bool backup) const486{487fs::path path, path_tmp;488if (!GetSettingsPath(&path, /*temp=*/false, backup) || !GetSettingsPath(&path_tmp, /*temp=*/true, backup)) {489throw std::logic_error("Attempt to write settings file when dynamic settings are disabled.");490}492LOCK(cs_args);493std::vector<std::string> write_errors;494if (!common::WriteSettings(path_tmp, m_settings.rw_settings, write_errors)) {495SaveErrors(write_errors, errors);496return false;497}498if (!RenameOver(path_tmp, path)) {499SaveErrors({strprintf("Failed renaming settings file %s to %s\n", fs::PathToString(path_tmp), fs::PathToString(path))}, errors);500return false;
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.