Bitcoin ABC 0.32.4
P2P Digital Currency
init.cpp
Go to the documentation of this file.
1// Copyright (c) 2023 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <common/init.h>
6
7#include <chainparams.h>
8#include <common/args.h>
9#include <logging.h>
10#include <tinyformat.h>
11#include <util/fs.h>
12#include <util/translation.h>
13
14#include <algorithm>
15#include <exception>
16#include <optional>
17
18namespace common {
19std::optional<ConfigError> InitConfig(ArgsManager &args,
20 SettingsAbortFn settings_abort_fn) {
21 try {
22 if (!CheckDataDirOption(args)) {
23 return ConfigError{
25 strprintf(_("Specified data directory \"%s\" does not exist."),
26 args.GetArg("-datadir", ""))};
27 }
28
29 // Record original datadir and config paths before parsing the config
30 // file. It is possible for the config file to contain a datadir= line
31 // that changes the datadir path after it is parsed. This is useful for
32 // CLI tools to let them use a different data storage location without
33 // needing to pass it every time on the command line. (It is not
34 // possible for the config file to cause another configuration to be
35 // used, though. Specifying a conf= option in the config file causes a
36 // parse error, and specifying a datadir= location containing another
37 // bitcoin.conf file just ignores the other file.)
38 const fs::path orig_datadir_path{args.GetDataDirBase()};
39 const fs::path orig_config_path = args.GetConfigFilePath();
40
41 std::string error;
42 if (!args.ReadConfigFiles(error, true)) {
43 return ConfigError{
45 strprintf(_("Error reading configuration file: %s"), error)};
46 }
47
48 // Check for chain settings (Params() calls are only valid after this
49 // clause)
51
52 // Create datadir if it does not exist.
53 const auto base_path{args.GetDataDirBase()};
54 if (!fs::exists(base_path)) {
55 // When creating a *new* datadir, also create a "wallets"
56 // subdirectory, whether or not the wallet is enabled now, so if the
57 // wallet is enabled in the future, it will use the "wallets"
58 // subdirectory for creating and listing wallets, rather than the
59 // top-level directory where wallets could be mixed up with other
60 // files. For backwards compatibility, wallet code will use the
61 // "wallets" subdirectory only if it already exists, but never
62 // create it itself. There is discussion in
63 // https://github.com/bitcoin/bitcoin/issues/16220 about ways to
64 // change wallet code so it would no longer be necessary to create
65 // "wallets" subdirectories here.
66 fs::create_directories(base_path / "wallets");
67 }
68 const auto net_path{args.GetDataDirNet()};
69 if (!fs::exists(net_path)) {
70 fs::create_directories(net_path / "wallets");
71 }
72
73 // Show an error or warning if there is a bitcoin.conf file in the
74 // datadir that is being ignored.
75 const fs::path base_config_path = base_path / BITCOIN_CONF_FILENAME;
76 if (fs::exists(base_config_path) &&
77 !fs::equivalent(orig_config_path, base_config_path)) {
78 const std::string cli_config_path = args.GetArg("-conf", "");
79 const std::string config_source =
80 cli_config_path.empty()
81 ? strprintf("data directory %s",
82 fs::quoted(fs::PathToString(orig_datadir_path)))
83 : strprintf("command line argument %s",
84 fs::quoted("-conf=" + cli_config_path));
85 const std::string err = strprintf(
86 "Data directory %1$s contains a %2$s file which is ignored, "
87 "because a different configuration file "
88 "%3$s from %4$s is being used instead. Possible ways to "
89 "address this would be to:\n"
90 "- Delete or rename the %2$s file in data directory %1$s.\n"
91 "- Change datadir= or conf= options to specify one "
92 "configuration file, not two, and use "
93 "includeconf= to include any other configuration files.\n"
94 "- Set allowignoredconf=1 option to treat this condition as a "
95 "warning, not an error.",
96 fs::quoted(fs::PathToString(base_path)),
98 fs::quoted(fs::PathToString(orig_config_path)), config_source);
99 if (args.GetBoolArg("-allowignoredconf", false)) {
100 LogPrintf("Warning: %s\n", err);
101 } else {
103 }
104 }
105
106 // Create settings.json if -nosettings was not specified.
107 if (args.GetSettingsPath()) {
108 std::vector<std::string> details;
109 if (!args.ReadSettingsFile(&details)) {
110 const bilingual_str &message =
111 _("Settings file could not be read");
112 if (!settings_abort_fn) {
113 return ConfigError{ConfigStatus::FAILED, message, details};
114 } else if (settings_abort_fn(message, details)) {
115 return ConfigError{ConfigStatus::ABORTED, message, details};
116 } else {
117 details
118 .clear(); // User chose to ignore the error and proceed.
119 }
120 }
121 if (!args.WriteSettingsFile(&details)) {
122 const bilingual_str &message =
123 _("Settings file could not be written");
125 details};
126 }
127 }
128 } catch (const std::exception &e) {
130 }
131 return {};
132}
133} // namespace common
bool CheckDataDirOption(const ArgsManager &args)
Definition: args.cpp:753
const char *const BITCOIN_CONF_FILENAME
Definition: args.cpp:37
void SelectParams(const ChainType chain)
Sets the params returned by Params() to those for the given BIP70 chain name.
Definition: chainparams.cpp:50
bool ReadSettingsFile(std::vector< std::string > *errors=nullptr)
Read settings file.
Definition: args.cpp:403
ChainType GetChainType() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Definition: args.cpp:762
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: args.h:239
bool GetSettingsPath(fs::path *filepath=nullptr, bool temp=false, bool backup=false) const
Get settings file path, or return false if read-write settings were disabled with -nosettings.
Definition: args.cpp:376
bool WriteSettingsFile(std::vector< std::string > *errors=nullptr, bool backup=false) const
Write settings file or backup settings file.
Definition: args.cpp:426
fs::path GetDataDirBase() const
Get data directory path.
Definition: args.h:230
fs::path GetConfigFilePath() const
Return config file path (read-only)
Definition: args.cpp:758
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:463
bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
Definition: configfile.cpp:132
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:525
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
#define LogPrintf(...)
Definition: logging.h:424
Definition: args.cpp:865
std::optional< ConfigError > InitConfig(ArgsManager &args, SettingsAbortFn settings_abort_fn)
Read config files, and create datadir and settings.json if they don't exist.
Definition: init.cpp:19
@ ABORTED
Aborted by user.
@ FAILED_WRITE
Failed to write settings.json.
@ FAILED
Failed generically.
std::function< bool(const bilingual_str &message, const std::vector< std::string > &details)> SettingsAbortFn
Callback function to let the user decide whether to abort loading if settings.json file exists and ca...
Definition: init.h:37
static bool create_directories(const std::filesystem::path &p)
Create directory (and if necessary its parents), unless the leaf directory already exists or is a sym...
Definition: fs.h:184
static auto quoted(const std::string &s)
Definition: fs.h:112
static bool exists(const path &p)
Definition: fs.h:107
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:147
Bilingual messages:
Definition: translation.h:17
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:68
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:36