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