Bitcoin ABC  0.26.3
P2P Digital Currency
args.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <common/args.h>
7 
8 #include <chainparamsbase.h>
9 #include <logging.h>
10 #include <sync.h>
11 #include <tinyformat.h>
12 #include <univalue.h>
13 #include <util/fs.h>
14 #include <util/fs_helpers.h>
15 #include <util/settings.h>
16 #include <util/strencodings.h>
17 
18 #ifdef WIN32
19 #include <codecvt> /* for codecvt_utf8_utf16 */
20 #include <shellapi.h> /* for CommandLineToArgvW */
21 #include <shlobj.h> /* for CSIDL_APPDATA */
22 #endif
23 
24 #include <algorithm>
25 #include <cassert>
26 #include <cstdint>
27 #include <cstdlib>
28 #include <cstring>
29 #include <filesystem>
30 #include <map>
31 #include <optional>
32 #include <stdexcept>
33 #include <string>
34 
35 const char *const BITCOIN_CONF_FILENAME = "bitcoin.conf";
36 const char *const BITCOIN_SETTINGS_FILENAME = "settings.json";
37 
39 
57 static bool InterpretBool(const std::string &strValue) {
58  if (strValue.empty()) {
59  return true;
60  }
61  return (atoi(strValue) != 0);
62 }
63 
64 static std::string SettingName(const std::string &arg) {
65  return arg.size() > 0 && arg[0] == '-' ? arg.substr(1) : arg;
66 }
67 
87 util::SettingsValue InterpretOption(std::string &section, std::string &key,
88  const std::string &value) {
89  // Split section name from key name for keys like "testnet.foo" or
90  // "regtest.bar"
91  size_t option_index = key.find('.');
92  if (option_index != std::string::npos) {
93  section = key.substr(0, option_index);
94  key.erase(0, option_index + 1);
95  }
96  if (key.substr(0, 2) == "no") {
97  key.erase(0, 2);
98  // Double negatives like -nofoo=0 are supported (but discouraged)
99  if (!InterpretBool(value)) {
100  LogPrintf("Warning: parsed potentially confusing double-negative "
101  "-%s=%s\n",
102  key, value);
103  return true;
104  }
105  return false;
106  }
107  return value;
108 }
109 
117 bool CheckValid(const std::string &key, const util::SettingsValue &val,
118  unsigned int flags, std::string &error) {
119  if (val.isBool() && !(flags & ArgsManager::ALLOW_BOOL)) {
120  error = strprintf(
121  "Negating of -%s is meaningless and therefore forbidden", key);
122  return false;
123  }
124  return true;
125 }
126 
127 // Define default constructor and destructor that are not inline, so code
128 // instantiating this class doesn't need to #include class definitions for all
129 // members. For example, m_settings has an internal dependency on univalue.
132 
133 const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const {
134  std::set<std::string> unsuitables;
135 
136  LOCK(cs_args);
137 
138  // if there's no section selected, don't worry
139  if (m_network.empty()) {
140  return std::set<std::string>{};
141  }
142 
143  // if it's okay to use the default section for this network, don't worry
144  if (m_network == CBaseChainParams::MAIN) {
145  return std::set<std::string>{};
146  }
147 
148  for (const auto &arg : m_network_only_args) {
149  if (OnlyHasDefaultSectionSetting(m_settings, m_network,
150  SettingName(arg))) {
151  unsuitables.insert(arg);
152  }
153  }
154  return unsuitables;
155 }
156 
157 const std::list<SectionInfo> ArgsManager::GetUnrecognizedSections() const {
158  // Section names to be recognized in the config file.
159  static const std::set<std::string> available_sections{
162 
163  LOCK(cs_args);
164  std::list<SectionInfo> unrecognized = m_config_sections;
165  unrecognized.remove_if([](const SectionInfo &appeared) {
166  return available_sections.find(appeared.m_name) !=
167  available_sections.end();
168  });
169  return unrecognized;
170 }
171 
172 void ArgsManager::SelectConfigNetwork(const std::string &network) {
173  LOCK(cs_args);
174  m_network = network;
175 }
176 
177 bool ParseKeyValue(std::string &key, std::string &val) {
178  size_t is_index = key.find('=');
179  if (is_index != std::string::npos) {
180  val = key.substr(is_index + 1);
181  key.erase(is_index);
182  }
183 #ifdef WIN32
184  key = ToLower(key);
185  if (key[0] == '/') {
186  key[0] = '-';
187  }
188 #endif
189 
190  if (key[0] != '-') {
191  return false;
192  }
193 
194  // Transform --foo to -foo
195  if (key.length() > 1 && key[1] == '-') {
196  key.erase(0, 1);
197  }
198  return true;
199 }
200 
201 bool ArgsManager::ParseParameters(int argc, const char *const argv[],
202  std::string &error) {
203  LOCK(cs_args);
204  m_settings.command_line_options.clear();
205 
206  for (int i = 1; i < argc; i++) {
207  std::string key(argv[i]);
208 
209 #ifdef MAC_OSX
210  // At the first time when a user gets the "App downloaded from the
211  // internet" warning, and clicks the Open button, macOS passes
212  // a unique process serial number (PSN) as -psn_... command-line
213  // argument, which we filter out.
214  if (key.substr(0, 5) == "-psn_") {
215  continue;
216  }
217 #endif
218 
219  if (key == "-") {
220  // bitcoin-tx using stdin
221  break;
222  }
223  std::string val;
224  if (!ParseKeyValue(key, val)) {
225  break;
226  }
227 
228  // Transform -foo to foo
229  key.erase(0, 1);
230  std::string section;
231  util::SettingsValue value = InterpretOption(section, key, val);
232  std::optional<unsigned int> flags = GetArgFlags('-' + key);
233 
234  // Unknown command line options and command line options with dot
235  // characters (which are returned from InterpretOption with nonempty
236  // section strings) are not valid.
237  if (!flags || !section.empty()) {
238  error = strprintf("Invalid parameter %s", argv[i]);
239  return false;
240  }
241 
242  if (!CheckValid(key, value, *flags, error)) {
243  return false;
244  }
245 
246  m_settings.command_line_options[key].push_back(value);
247  }
248 
249  // we do not allow -includeconf from command line
250  bool success = true;
251  if (auto *includes =
252  util::FindKey(m_settings.command_line_options, "includeconf")) {
253  for (const auto &include : util::SettingsSpan(*includes)) {
254  error +=
255  "-includeconf cannot be used from commandline; -includeconf=" +
256  include.get_str() + "\n";
257  success = false;
258  }
259  }
260  return success;
261 }
262 
263 std::optional<unsigned int>
264 ArgsManager::GetArgFlags(const std::string &name) const {
265  LOCK(cs_args);
266  for (const auto &arg_map : m_available_args) {
267  const auto search = arg_map.second.find(name);
268  if (search != arg_map.second.end()) {
269  return search->second.m_flags;
270  }
271  }
272  return std::nullopt;
273 }
274 
276  const fs::path &default_value) const {
277  if (IsArgNegated(arg)) {
278  return fs::path{};
279  }
280  std::string path_str = GetArg(arg, "");
281  if (path_str.empty()) {
282  return default_value;
283  }
284  fs::path result = fs::PathFromString(path_str).lexically_normal();
285  // Remove trailing slash, if present.
286  return result.has_filename() ? result : result.parent_path();
287 }
288 
290  LOCK(cs_args);
291  fs::path &path = m_cached_blocks_path;
292 
293  // Cache the path to avoid calling fs::create_directories on every call of
294  // this function
295  if (!path.empty()) {
296  return path;
297  }
298 
299  if (IsArgSet("-blocksdir")) {
300  path = fs::absolute(GetPathArg("-blocksdir"));
301  if (!fs::is_directory(path)) {
302  path = "";
303  return path;
304  }
305  } else {
306  path = GetDataDirBase();
307  }
308 
309  path /= fs::PathFromString(BaseParams().DataDir());
310  path /= "blocks";
312  return path;
313 }
314 
315 const fs::path &ArgsManager::GetDataDir(bool net_specific) const {
316  LOCK(cs_args);
317  fs::path &path =
318  net_specific ? m_cached_network_datadir_path : m_cached_datadir_path;
319 
320  // Used cached path if available
321  if (!path.empty()) {
322  return path;
323  }
324 
325  const fs::path datadir{GetPathArg("-datadir")};
326  if (!datadir.empty()) {
327  path = fs::absolute(datadir);
328  if (!fs::is_directory(path)) {
329  path = "";
330  return path;
331  }
332  } else {
333  path = GetDefaultDataDir();
334  }
335 
336  if (net_specific && !BaseParams().DataDir().empty()) {
337  path /= fs::PathFromString(BaseParams().DataDir());
338  }
339 
340  return path;
341 }
342 
353  auto path{GetDataDir(/*net_specific=*/false)};
354  if (!fs::exists(path)) {
355  fs::create_directories(path / "wallets");
356  }
357  path = GetDataDir(/*net_specific=*/true);
358  if (!fs::exists(path)) {
359  fs::create_directories(path / "wallets");
360  }
361 }
362 
364  LOCK(cs_args);
365 
366  m_cached_datadir_path = fs::path();
367  m_cached_network_datadir_path = fs::path();
368  m_cached_blocks_path = fs::path();
369 }
370 
371 std::vector<std::string> ArgsManager::GetArgs(const std::string &strArg) const {
372  std::vector<std::string> result;
373  for (const util::SettingsValue &value : GetSettingsList(strArg)) {
374  result.push_back(value.isFalse() ? "0"
375  : value.isTrue() ? "1"
376  : value.get_str());
377  }
378  return result;
379 }
380 
381 bool ArgsManager::IsArgSet(const std::string &strArg) const {
382  return !GetSetting(strArg).isNull();
383 }
384 
385 bool ArgsManager::InitSettings(std::string &error) {
386  EnsureDataDir();
387  if (!GetSettingsPath()) {
388  return true; // Do nothing if settings file disabled.
389  }
390 
391  std::vector<std::string> errors;
392  if (!ReadSettingsFile(&errors)) {
393  error = strprintf("Failed loading settings file:\n- %s\n",
394  Join(errors, "\n- "));
395  return false;
396  }
397  if (!WriteSettingsFile(&errors)) {
398  error = strprintf("Failed saving settings file:\n- %s\n",
399  Join(errors, "\n- "));
400  return false;
401  }
402  return true;
403 }
404 
405 bool ArgsManager::GetSettingsPath(fs::path *filepath, bool temp,
406  bool backup) const {
407  fs::path settings = GetPathArg("-settings", BITCOIN_SETTINGS_FILENAME);
408  if (settings.empty()) {
409  return false;
410  }
411  if (backup) {
412  settings += ".bak";
413  }
414  if (filepath) {
415  *filepath = fsbridge::AbsPathJoin(GetDataDirNet(),
416  temp ? settings + ".tmp" : settings);
417  }
418  return true;
419 }
420 
421 static void SaveErrors(const std::vector<std::string> errors,
422  std::vector<std::string> *error_out) {
423  for (const auto &error : errors) {
424  if (error_out) {
425  error_out->emplace_back(error);
426  } else {
427  LogPrintf("%s\n", error);
428  }
429  }
430 }
431 
432 bool ArgsManager::ReadSettingsFile(std::vector<std::string> *errors) {
433  fs::path path;
434  if (!GetSettingsPath(&path, /* temp= */ false)) {
435  return true; // Do nothing if settings file disabled.
436  }
437 
438  LOCK(cs_args);
439  m_settings.rw_settings.clear();
440  std::vector<std::string> read_errors;
441  if (!util::ReadSettings(path, m_settings.rw_settings, read_errors)) {
442  SaveErrors(read_errors, errors);
443  return false;
444  }
445  for (const auto &setting : m_settings.rw_settings) {
446  std::string section;
447  std::string key = setting.first;
448  // Split setting key into section and argname
449  (void)InterpretOption(section, key, /* value */ {});
450  if (!GetArgFlags('-' + key)) {
451  LogPrintf("Ignoring unknown rw_settings value %s\n", setting.first);
452  }
453  }
454  return true;
455 }
456 
457 bool ArgsManager::WriteSettingsFile(std::vector<std::string> *errors,
458  bool backup) const {
459  fs::path path, path_tmp;
460  if (!GetSettingsPath(&path, /*temp=*/false, backup) ||
461  !GetSettingsPath(&path_tmp, /*temp=*/true, backup)) {
462  throw std::logic_error("Attempt to write settings file when dynamic "
463  "settings are disabled.");
464  }
465 
466  LOCK(cs_args);
467  std::vector<std::string> write_errors;
468  if (!util::WriteSettings(path_tmp, m_settings.rw_settings, write_errors)) {
469  SaveErrors(write_errors, errors);
470  return false;
471  }
472  if (!RenameOver(path_tmp, path)) {
473  SaveErrors(
474  {strprintf("Failed renaming settings file %s to %s\n",
475  fs::PathToString(path_tmp), fs::PathToString(path))},
476  errors);
477  return false;
478  }
479  return true;
480 }
481 
483 ArgsManager::GetPersistentSetting(const std::string &name) const {
484  LOCK(cs_args);
485  return util::GetSetting(
486  m_settings, m_network, name, !UseDefaultSection("-" + name),
487  /*ignore_nonpersistent=*/true, /*get_chain_name=*/false);
488 }
489 
490 bool ArgsManager::IsArgNegated(const std::string &strArg) const {
491  return GetSetting(strArg).isFalse();
492 }
493 
494 std::string ArgsManager::GetArg(const std::string &strArg,
495  const std::string &strDefault) const {
496  return GetArg(strArg).value_or(strDefault);
497 }
498 
499 std::optional<std::string>
500 ArgsManager::GetArg(const std::string &strArg) const {
501  const util::SettingsValue value = GetSetting(strArg);
502  return SettingToString(value);
503 }
504 
505 std::optional<std::string> SettingToString(const util::SettingsValue &value) {
506  if (value.isNull()) {
507  return std::nullopt;
508  }
509  if (value.isFalse()) {
510  return "0";
511  }
512  if (value.isTrue()) {
513  return "1";
514  }
515  if (value.isNum()) {
516  return value.getValStr();
517  }
518  return value.get_str();
519 }
520 
521 std::string SettingToString(const util::SettingsValue &value,
522  const std::string &strDefault) {
523  return SettingToString(value).value_or(strDefault);
524 }
525 
526 int64_t ArgsManager::GetIntArg(const std::string &strArg,
527  int64_t nDefault) const {
528  return GetIntArg(strArg).value_or(nDefault);
529 }
530 
531 std::optional<int64_t> ArgsManager::GetIntArg(const std::string &strArg) const {
532  const util::SettingsValue value = GetSetting(strArg);
533  return SettingToInt(value);
534 }
535 
536 std::optional<int64_t> SettingToInt(const util::SettingsValue &value) {
537  if (value.isNull()) {
538  return std::nullopt;
539  }
540  if (value.isFalse()) {
541  return 0;
542  }
543  if (value.isTrue()) {
544  return 1;
545  }
546  if (value.isNum()) {
547  return value.getInt<int64_t>();
548  }
549  return atoi64(value.get_str());
550 }
551 
552 int64_t SettingToInt(const util::SettingsValue &value, int64_t nDefault) {
553  return SettingToInt(value).value_or(nDefault);
554 }
555 
556 bool ArgsManager::GetBoolArg(const std::string &strArg, bool fDefault) const {
557  return GetBoolArg(strArg).value_or(fDefault);
558 }
559 
560 std::optional<bool> ArgsManager::GetBoolArg(const std::string &strArg) const {
561  const util::SettingsValue value = GetSetting(strArg);
562  return SettingToBool(value);
563 }
564 
565 std::optional<bool> SettingToBool(const util::SettingsValue &value) {
566  if (value.isNull()) {
567  return std::nullopt;
568  }
569  if (value.isBool()) {
570  return value.get_bool();
571  }
572  return InterpretBool(value.get_str());
573 }
574 
575 bool SettingToBool(const util::SettingsValue &value, bool fDefault) {
576  return SettingToBool(value).value_or(fDefault);
577 }
578 
579 bool ArgsManager::SoftSetArg(const std::string &strArg,
580  const std::string &strValue) {
581  LOCK(cs_args);
582  if (IsArgSet(strArg)) {
583  return false;
584  }
585  ForceSetArg(strArg, strValue);
586  return true;
587 }
588 
589 bool ArgsManager::SoftSetBoolArg(const std::string &strArg, bool fValue) {
590  if (fValue) {
591  return SoftSetArg(strArg, std::string("1"));
592  } else {
593  return SoftSetArg(strArg, std::string("0"));
594  }
595 }
596 
597 void ArgsManager::ForceSetArg(const std::string &strArg,
598  const std::string &strValue) {
599  LOCK(cs_args);
600  m_settings.forced_settings[SettingName(strArg)] = strValue;
601 }
602 
608 void ArgsManager::ForceSetMultiArg(const std::string &strArg,
609  const std::vector<std::string> &values) {
610  LOCK(cs_args);
611  util::SettingsValue value;
612  value.setArray();
613  for (const std::string &s : values) {
614  value.push_back(s);
615  }
616 
617  m_settings.forced_settings[SettingName(strArg)] = value;
618 }
619 
620 void ArgsManager::AddArg(const std::string &name, const std::string &help,
621  unsigned int flags, const OptionsCategory &cat) {
622  // Split arg name from its help param
623  size_t eq_index = name.find('=');
624  if (eq_index == std::string::npos) {
625  eq_index = name.size();
626  }
627  std::string arg_name = name.substr(0, eq_index);
628 
629  LOCK(cs_args);
630  std::map<std::string, Arg> &arg_map = m_available_args[cat];
631  auto ret = arg_map.emplace(
632  arg_name,
633  Arg{name.substr(eq_index, name.size() - eq_index), help, flags});
634  // Make sure an insertion actually happened.
635  assert(ret.second);
636 
638  m_network_only_args.emplace(arg_name);
639  }
640 }
641 
642 void ArgsManager::AddHiddenArgs(const std::vector<std::string> &names) {
643  for (const std::string &name : names) {
645  }
646 }
647 
648 void ArgsManager::ClearForcedArg(const std::string &strArg) {
649  LOCK(cs_args);
650  m_settings.forced_settings.erase(SettingName(strArg));
651 }
652 
653 std::string ArgsManager::GetHelpMessage() const {
654  const bool show_debug = GetBoolArg("-help-debug", false);
655 
656  std::string usage = "";
657  LOCK(cs_args);
658  for (const auto &arg_map : m_available_args) {
659  switch (arg_map.first) {
661  usage += HelpMessageGroup("Options:");
662  break;
664  usage += HelpMessageGroup("Connection options:");
665  break;
667  usage += HelpMessageGroup("ZeroMQ notification options:");
668  break;
670  usage += HelpMessageGroup("Debugging/Testing options:");
671  break;
673  usage += HelpMessageGroup("Node relay options:");
674  break;
676  usage += HelpMessageGroup("Block creation options:");
677  break;
679  usage += HelpMessageGroup("RPC server options:");
680  break;
682  usage += HelpMessageGroup("Wallet options:");
683  break;
685  if (show_debug) {
686  usage +=
687  HelpMessageGroup("Wallet debugging/testing options:");
688  }
689  break;
691  usage += HelpMessageGroup("Chain selection options:");
692  break;
694  usage += HelpMessageGroup("UI Options:");
695  break;
697  usage += HelpMessageGroup("Commands:");
698  break;
700  usage += HelpMessageGroup("Register Commands:");
701  break;
703  usage += HelpMessageGroup("Avalanche options:");
704  break;
706  usage += HelpMessageGroup("Chronik options:");
707  break;
708  default:
709  break;
710  }
711 
712  // When we get to the hidden options, stop
713  if (arg_map.first == OptionsCategory::HIDDEN) {
714  break;
715  }
716 
717  for (const auto &arg : arg_map.second) {
718  if (show_debug || !(arg.second.m_flags & ArgsManager::DEBUG_ONLY)) {
719  std::string name;
720  if (arg.second.m_help_param.empty()) {
721  name = arg.first;
722  } else {
723  name = arg.first + arg.second.m_help_param;
724  }
725  usage += HelpMessageOpt(name, arg.second.m_help_text);
726  }
727  }
728  }
729  return usage;
730 }
731 
732 bool HelpRequested(const ArgsManager &args) {
733  return args.IsArgSet("-?") || args.IsArgSet("-h") ||
734  args.IsArgSet("-help") || args.IsArgSet("-help-debug");
735 }
736 
738  args.AddArg("-?", "Print this help message and exit", false,
740  args.AddHiddenArgs({"-h", "-help"});
741 }
742 
743 static const int screenWidth = 79;
744 static const int optIndent = 2;
745 static const int msgIndent = 7;
746 
747 std::string HelpMessageGroup(const std::string &message) {
748  return std::string(message) + std::string("\n\n");
749 }
750 
751 std::string HelpMessageOpt(const std::string &option,
752  const std::string &message) {
753  return std::string(optIndent, ' ') + std::string(option) +
754  std::string("\n") + std::string(msgIndent, ' ') +
756  std::string("\n\n");
757 }
758 
760  // Windows: C:\Users\Username\AppData\Roaming\Bitcoin
761  // macOS: ~/Library/Application Support/Bitcoin
762  // Unix-like: ~/.bitcoin
763 #ifdef WIN32
764  // Windows
765  return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
766 #else
767  fs::path pathRet;
768  char *pszHome = getenv("HOME");
769  if (pszHome == nullptr || strlen(pszHome) == 0) {
770  pathRet = fs::path("/");
771  } else {
772  pathRet = fs::path(pszHome);
773  }
774 #ifdef MAC_OSX
775  // macOS
776  return pathRet / "Library/Application Support/Bitcoin";
777 #else
778  // Unix-like
779  return pathRet / ".bitcoin";
780 #endif
781 #endif
782 }
783 
784 bool CheckDataDirOption(const ArgsManager &args) {
785  const fs::path datadir{args.GetPathArg("-datadir")};
786  return datadir.empty() || fs::is_directory(fs::absolute(datadir));
787 }
788 
790  return GetConfigFile(*this, GetPathArg("-conf", BITCOIN_CONF_FILENAME));
791 }
792 
793 std::string ArgsManager::GetChainName() const {
794  auto get_net = [&](const std::string &arg) {
795  LOCK(cs_args);
796  util::SettingsValue value =
797  util::GetSetting(m_settings, /*section=*/"", SettingName(arg),
798  /*ignore_default_section_config=*/false,
799  /*ignore_nonpersistent=*/false,
800  /*get_chain_name=*/true);
801  return value.isNull() ? false
802  : value.isBool() ? value.get_bool()
803  : InterpretBool(value.get_str());
804  };
805 
806  const bool fRegTest = get_net("-regtest");
807  const bool fTestNet = get_net("-testnet");
808  const bool is_chain_arg_set = IsArgSet("-chain");
809 
810  if (int(is_chain_arg_set) + int(fRegTest) + int(fTestNet) > 1) {
811  throw std::runtime_error("Invalid combination of -regtest, -testnet "
812  "and -chain. Can use at most one.");
813  }
814  if (fRegTest) {
816  }
817  if (fTestNet) {
819  }
820  return GetArg("-chain", CBaseChainParams::MAIN);
821 }
822 
823 bool ArgsManager::UseDefaultSection(const std::string &arg) const {
824  return m_network == CBaseChainParams::MAIN ||
825  m_network_only_args.count(arg) == 0;
826 }
827 
828 util::SettingsValue ArgsManager::GetSetting(const std::string &arg) const {
829  LOCK(cs_args);
830  return util::GetSetting(m_settings, m_network, SettingName(arg),
831  !UseDefaultSection(arg),
832  /*ignore_nonpersistent=*/false,
833  /*get_chain_name=*/false);
834 }
835 
836 std::vector<util::SettingsValue>
837 ArgsManager::GetSettingsList(const std::string &arg) const {
838  LOCK(cs_args);
839  return util::GetSettingsList(m_settings, m_network, SettingName(arg),
840  !UseDefaultSection(arg));
841 }
842 
844  const std::string &prefix, const std::string &section,
845  const std::map<std::string, std::vector<util::SettingsValue>> &args) const {
846  std::string section_str = section.empty() ? "" : "[" + section + "] ";
847  for (const auto &arg : args) {
848  for (const auto &value : arg.second) {
849  std::optional<unsigned int> flags = GetArgFlags('-' + arg.first);
850  if (flags) {
851  std::string value_str =
852  (*flags & SENSITIVE) ? "****" : value.write();
853  LogPrintf("%s %s%s=%s\n", prefix, section_str, arg.first,
854  value_str);
855  }
856  }
857  }
858 }
859 
860 void ArgsManager::LogArgs() const {
861  LOCK(cs_args);
862  for (const auto &section : m_settings.ro_config) {
863  logArgsPrefix("Config file arg:", section.first, section.second);
864  }
865  for (const auto &setting : m_settings.rw_settings) {
866  LogPrintf("Setting file arg: %s = %s\n", setting.first,
867  setting.second.write());
868  }
869  logArgsPrefix("Command-line arg:", "", m_settings.command_line_options);
870 }
871 
872 namespace common {
873 #ifdef WIN32
874 WinCmdLineArgs::WinCmdLineArgs() {
875  wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
876  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf8_cvt;
877  argv = new char *[argc];
878  args.resize(argc);
879  for (int i = 0; i < argc; i++) {
880  args[i] = utf8_cvt.to_bytes(wargv[i]);
881  argv[i] = &*args[i].begin();
882  }
883  LocalFree(wargv);
884 }
885 
886 WinCmdLineArgs::~WinCmdLineArgs() {
887  delete[] argv;
888 }
889 
890 std::pair<int, char **> WinCmdLineArgs::get() {
891  return std::make_pair(argc, argv);
892 }
893 #endif
894 } // namespace common
bool HelpRequested(const ArgsManager &args)
Definition: args.cpp:732
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
Definition: args.cpp:737
fs::path GetDefaultDataDir()
Definition: args.cpp:759
static const int msgIndent
Definition: args.cpp:745
bool CheckValid(const std::string &key, const util::SettingsValue &val, unsigned int flags, std::string &error)
Check settings value validity according to flags.
Definition: args.cpp:117
static void SaveErrors(const std::vector< std::string > errors, std::vector< std::string > *error_out)
Definition: args.cpp:421
const char *const BITCOIN_SETTINGS_FILENAME
Definition: args.cpp:36
bool ParseKeyValue(std::string &key, std::string &val)
Definition: args.cpp:177
std::optional< std::string > SettingToString(const util::SettingsValue &value)
Definition: args.cpp:505
bool CheckDataDirOption(const ArgsManager &args)
Definition: args.cpp:784
static const int screenWidth
Definition: args.cpp:743
ArgsManager gArgs
Definition: args.cpp:38
std::optional< int64_t > SettingToInt(const util::SettingsValue &value)
Definition: args.cpp:536
static std::string SettingName(const std::string &arg)
Definition: args.cpp:64
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
Definition: args.cpp:747
const char *const BITCOIN_CONF_FILENAME
Definition: args.cpp:35
util::SettingsValue InterpretOption(std::string &section, std::string &key, const std::string &value)
Interpret -nofoo as if the user supplied -foo=0.
Definition: args.cpp:87
static bool InterpretBool(const std::string &strValue)
Interpret a string argument as a boolean.
Definition: args.cpp:57
static const int optIndent
Definition: args.cpp:744
std::optional< bool > SettingToBool(const util::SettingsValue &value)
Definition: args.cpp:565
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
Definition: args.cpp:751
OptionsCategory
Definition: args.h:55
fs::path GetConfigFile(const ArgsManager &args, const fs::path &configuration_file_path)
Definition: configfile.cpp:29
int flags
Definition: bitcoin-tx.cpp:543
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
const std::set< std::string > GetUnsuitableSectionOnlyArgs() const
Log warnings for options in m_section_only_args when they are specified in the default section but no...
Definition: args.cpp:133
const fs::path & GetBlocksDirPath() const
Get blocks directory path.
Definition: args.cpp:289
bool IsArgNegated(const std::string &strArg) const
Return true if the argument was originally passed as a negated option, i.e.
Definition: args.cpp:490
@ NETWORK_ONLY
Definition: args.h:110
@ ALLOW_ANY
Definition: args.h:103
@ DEBUG_ONLY
Definition: args.h:104
@ ALLOW_BOOL
Definition: args.h:100
@ SENSITIVE
Definition: args.h:112
bool ReadSettingsFile(std::vector< std::string > *errors=nullptr)
Read settings file.
Definition: args.cpp:432
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: args.cpp:597
void logArgsPrefix(const std::string &prefix, const std::string &section, const std::map< std::string, std::vector< util::SettingsValue >> &args) const
Definition: args.cpp:843
bool InitSettings(std::string &error)
Read and update settings file with saved settings.
Definition: args.cpp:385
bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: args.cpp:201
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: args.cpp:371
util::SettingsValue GetPersistentSetting(const std::string &name) const
Get current setting from config file or read/write settings file, ignoring nonpersistent command line...
Definition: args.cpp:483
ArgsManager()
Definition: args.cpp:130
std::optional< unsigned int > GetArgFlags(const std::string &name) const
Return Flags for known arg.
Definition: args.cpp:264
const fs::path & GetDataDirBase() const
Get data directory path.
Definition: args.h:206
~ArgsManager()
Definition: args.cpp:131
void EnsureDataDir() const
If datadir does not exist, create it along with wallets/ subdirectory(s).
Definition: args.cpp:343
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:405
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn't already have a value.
Definition: args.cpp:579
void SelectConfigNetwork(const std::string &network)
Select the network in use.
Definition: args.cpp:172
std::string GetHelpMessage() const
Get the help string.
Definition: args.cpp:653
void ForceSetMultiArg(const std::string &strArg, const std::vector< std::string > &values)
This function is only used for testing purpose so so we should not worry about element uniqueness and...
Definition: args.cpp:608
void ClearPathCache()
Clear cached directory paths.
Definition: args.cpp:363
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: args.cpp:381
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: args.h:215
bool WriteSettingsFile(std::vector< std::string > *errors=nullptr, bool backup=false) const
Write settings file or backup settings file.
Definition: args.cpp:457
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
Definition: args.cpp:526
const fs::path & GetDataDir(bool net_specific) const
Get data directory path.
Definition: args.cpp:315
fs::path GetConfigFilePath() const
Return config file path (read-only)
Definition: args.cpp:789
void ClearForcedArg(const std::string &strArg)
Remove a forced arg setting, used only in testing.
Definition: args.cpp:648
std::vector< util::SettingsValue > GetSettingsList(const std::string &arg) const
Get list of setting values.
Definition: args.cpp:837
void LogArgs() const
Log the config file options and the command line arguments, useful for troubleshooting.
Definition: args.cpp:860
RecursiveMutex cs_args
Definition: args.h:122
bool UseDefaultSection(const std::string &arg) const EXCLUSIVE_LOCKS_REQUIRED(cs_args)
Returns true if settings values from the default section should be used, depending on the current net...
Definition: args.cpp:823
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:494
util::SettingsValue GetSetting(const std::string &arg) const
Get setting value.
Definition: args.cpp:828
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
Definition: args.cpp:589
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:556
void AddHiddenArgs(const std::vector< std::string > &args)
Add many hidden arguments.
Definition: args.cpp:642
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: args.cpp:620
fs::path GetPathArg(std::string arg, const fs::path &default_value={}) const
Return path argument or default value.
Definition: args.cpp:275
const std::list< SectionInfo > GetUnrecognizedSections() const
Log warnings for unrecognized section names in the config file.
Definition: args.cpp:157
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Definition: args.cpp:793
static const std::string REGTEST
static const std::string TESTNET
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
void push_back(UniValue val)
Definition: univalue.cpp:96
const std::string & get_str() const
bool isTrue() const
Definition: univalue.h:105
void setArray()
Definition: univalue.cpp:86
bool isNull() const
Definition: univalue.h:104
const std::string & getValStr() const
Definition: univalue.h:89
bool isBool() const
Definition: univalue.h:107
Int getInt() const
Definition: univalue.h:157
bool isNum() const
Definition: univalue.h:109
bool isFalse() const
Definition: univalue.h:106
bool get_bool() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
bool RenameOver(fs::path src, fs::path dest)
Definition: fs_helpers.cpp:272
bool error(const char *fmt, const Args &...args)
Definition: logging.h:226
#define LogPrintf(...)
Definition: logging.h:207
Definition: args.cpp:872
static path absolute(const path &p)
Definition: fs.h:96
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:179
static bool exists(const path &p)
Definition: fs.h:102
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:142
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:165
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:39
std::vector< SettingsValue > GetSettingsList(const Settings &settings, const std::string &section, const std::string &name, bool ignore_default_section_config)
Get combined setting value similar to GetSetting(), except if setting was specified multiple times,...
Definition: settings.cpp:209
SettingsValue GetSetting(const Settings &settings, const std::string &section, const std::string &name, bool ignore_default_section_config, bool ignore_nonpersistent, bool get_chain_name)
Get settings value from combined sources: forced settings, command line arguments,...
Definition: settings.cpp:142
bool ReadSettings(const fs::path &path, std::map< std::string, SettingsValue > &values, std::vector< std::string > &errors)
Read settings file.
Definition: settings.cpp:67
bool OnlyHasDefaultSectionSetting(const Settings &settings, const std::string &section, const std::string &name)
Return true if a setting is set in the default config file section, and not overridden by a higher pr...
Definition: settings.cpp:261
bool WriteSettings(const fs::path &path, const std::map< std::string, SettingsValue > &values, std::vector< std::string > &errors)
Write settings file.
Definition: settings.cpp:122
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
Definition: settings.h:115
const char * prefix
Definition: rest.cpp:817
const char * name
Definition: rest.cpp:47
static RPCHelpMan help()
Definition: server.cpp:182
std::string FormatParagraph(const std::string &in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line.
std::string ToLower(const std::string &str)
Returns the lowercase equivalent of the given string.
int atoi(const std::string &str)
int64_t atoi64(const std::string &str)
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
Definition: string.h:53
std::string m_name
Definition: args.h:77
Accessor for list of settings that skips negated values when iterated over.
Definition: settings.h:91
#define LOCK(cs)
Definition: sync.h:306
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
assert(!tx.IsCoinBase())