-
Notifications
You must be signed in to change notification settings - Fork 1.2k
backport: Bitcoin Core v0.26 backports (batch 3) #7433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4c8f13c
0663ec9
f7999f7
a69ad0c
be0337e
1e4bea7
5b499d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
|
|
||
| #include <chainparams.h> | ||
| #include <clientversion.h> | ||
| #include <common/init.h> | ||
| #include <common/url.h> | ||
| #include <compat/compat.h> | ||
| #include <init.h> | ||
|
|
@@ -109,20 +110,32 @@ int fork_daemon(bool nochdir, bool noclose, TokenPipeEnd& endpoint) | |
|
|
||
| #endif | ||
|
|
||
| static bool AppInit(NodeContext& node, int argc, char* argv[]) | ||
| static bool ParseArgs(ArgsManager& args, int argc, char* argv[]) | ||
| { | ||
| bool fRet = false; | ||
|
|
||
| util::ThreadSetInternalName("init"); | ||
|
|
||
| // If Qt is used, parameters/dash.conf are parsed in qt/bitcoin.cpp's main() | ||
| ArgsManager& args = *Assert(node.args); | ||
| SetupServerArgs(args); | ||
| std::string error; | ||
| if (!args.ParseParameters(argc, argv, error)) { | ||
| return InitError(Untranslated(strprintf("Error parsing command line arguments: %s\n", error))); | ||
| return InitError(Untranslated(strprintf("Error parsing command line arguments: %s", error))); | ||
| } | ||
|
|
||
| if (args.IsArgSet("-printcrashinfo")) return true; | ||
|
|
||
| if (auto error = common::InitConfig(args)) { | ||
| return InitError(error->message, error->details); | ||
|
thepastaclaw marked this conversation as resolved.
|
||
| } | ||
|
|
||
| // Error out when loose non-argument tokens are encountered on command line | ||
| for (int i = 1; i < argc; i++) { | ||
| if (!IsSwitchChar(argv[i][0])) { | ||
| return InitError(Untranslated(strprintf("Command line contains unexpected token '%s', see dashd -h for a list of options.", argv[i]))); | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| static bool ProcessInitCommands(ArgsManager& args) | ||
| { | ||
| if (args.IsArgSet("-printcrashinfo")) { | ||
| std::cout << GetCrashInfoStrFromSerializedStr(args.GetArg("-printcrashinfo", "")) << std::endl; | ||
| return true; | ||
|
|
@@ -144,6 +157,14 @@ static bool AppInit(NodeContext& node, int argc, char* argv[]) | |
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| static bool AppInit(NodeContext& node) | ||
| { | ||
| bool fRet = false; | ||
| ArgsManager& args = *Assert(node.args); | ||
|
|
||
| CoreContext context{node}; | ||
| #if HAVE_DECL_FORK | ||
| // Communication with parent after daemonizing. This is used for signalling in the following ways: | ||
|
|
@@ -155,37 +176,12 @@ static bool AppInit(NodeContext& node, int argc, char* argv[]) | |
| #endif | ||
| try | ||
| { | ||
| if (!CheckDataDirOption()) { | ||
| return InitError(Untranslated(strprintf("Specified data directory \"%s\" does not exist.\n", args.GetArg("-datadir", "")))); | ||
| } | ||
| if (!args.ReadConfigFiles(error, true)) { | ||
| return InitError(Untranslated(strprintf("Error reading configuration file: %s\n", error))); | ||
| } | ||
| // Check for chain settings (Params() calls are only valid after this clause) | ||
| try { | ||
| SelectParams(args.GetChainName()); | ||
| } catch (const std::exception& e) { | ||
| return InitError(Untranslated(strprintf("%s\n", e.what()))); | ||
| } | ||
|
|
||
| // Error out when loose non-argument tokens are encountered on command line | ||
| for (int i = 1; i < argc; i++) { | ||
| if (!IsSwitchChar(argv[i][0])) { | ||
| return InitError(Untranslated(strprintf("Command line contains unexpected token '%s', see dashd -h for a list of options.\n", argv[i]))); | ||
| } | ||
| } | ||
|
|
||
| if (!gArgs.InitSettings(error)) { | ||
| InitError(Untranslated(error)); | ||
| return false; | ||
| } | ||
|
|
||
| // -server defaults to true for dashd but not for the GUI so do this here | ||
| args.SoftSetBoolArg("-server", true); | ||
| // Set this early so that parameter interactions go to console | ||
| InitLogging(args); | ||
| InitParameterInteraction(args); | ||
| if (!AppInitBasicSetup(args)) { | ||
| if (!AppInitBasicSetup(args, node.exit_status)) { | ||
| // InitError will have been called with detailed error, which ends up on console | ||
| return false; | ||
| } | ||
|
|
@@ -215,7 +211,7 @@ static bool AppInit(NodeContext& node, int argc, char* argv[]) | |
| } | ||
| break; | ||
| case -1: // Error happened. | ||
| return InitError(Untranslated(strprintf("fork_daemon() failed: %s\n", SysErrorString(errno)))); | ||
| return InitError(Untranslated(strprintf("fork_daemon() failed: %s", SysErrorString(errno)))); | ||
| default: { // Parent: wait and exit. | ||
| int token = daemon_ep.TokenRead(); | ||
| if (token) { // Success | ||
|
|
@@ -227,7 +223,7 @@ static bool AppInit(NodeContext& node, int argc, char* argv[]) | |
| } | ||
| } | ||
| #else | ||
| return InitError(Untranslated("-daemon is not supported on this operating system\n")); | ||
| return InitError(Untranslated("-daemon is not supported on this operating system")); | ||
| #endif // HAVE_DECL_FORK | ||
| } | ||
| // Lock data directory after daemonization | ||
|
|
@@ -248,12 +244,6 @@ static bool AppInit(NodeContext& node, int argc, char* argv[]) | |
| daemon_ep.Close(); | ||
| } | ||
| #endif | ||
| if (fRet) { | ||
| WaitForShutdown(); | ||
| } | ||
| Interrupt(node); | ||
| Shutdown(node); | ||
|
|
||
| return fRet; | ||
| } | ||
|
|
||
|
|
@@ -279,5 +269,22 @@ MAIN_FUNCTION | |
| // Connect dashd signal handlers | ||
| noui_connect(); | ||
|
|
||
| return (AppInit(node, argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE); | ||
| util::ThreadSetInternalName("init"); | ||
|
|
||
| // Interpret command line arguments | ||
| ArgsManager& args = *Assert(node.args); | ||
| if (!ParseArgs(args, argc, argv)) return EXIT_FAILURE; | ||
| // Process early info return commands such as -help or -version | ||
| if (ProcessInitCommands(args)) return EXIT_SUCCESS; | ||
|
|
||
| // Start application | ||
| if (AppInit(node)) { | ||
| WaitForShutdown(); | ||
| } else { | ||
| node.exit_status = EXIT_FAILURE; | ||
| } | ||
| Interrupt(node); | ||
| Shutdown(node); | ||
|
thepastaclaw marked this conversation as resolved.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When AGENTS.md reference: AGENTS.md:L169-L171 Useful? React with 👍 / 👎. |
||
|
|
||
| return node.exit_status; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| // Copyright (c) 2023 The Bitcoin Core developers | ||
| // Distributed under the MIT software license, see the accompanying | ||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
|
||
| #include <common/init.h> | ||
| #include <chainparams.h> | ||
| #include <util/fs.h> | ||
| #include <tinyformat.h> | ||
| #include <util/system.h> | ||
| #include <util/translation.h> | ||
|
|
||
| #include <algorithm> | ||
| #include <exception> | ||
| #include <optional> | ||
|
|
||
| namespace common { | ||
| std::optional<ConfigError> InitConfig(ArgsManager& args, SettingsAbortFn settings_abort_fn) | ||
| { | ||
| try { | ||
| if (!CheckDataDirOption(args)) { | ||
| return ConfigError{ConfigStatus::FAILED, strprintf(_("Specified data directory \"%s\" does not exist."), args.GetArg("-datadir", ""))}; | ||
| } | ||
| std::string error; | ||
| if (!args.ReadConfigFiles(error, true)) { | ||
| return ConfigError{ConfigStatus::FAILED, strprintf(_("Error reading configuration file: %s"), error)}; | ||
| } | ||
|
|
||
| // Check for chain settings (Params() calls are only valid after this clause) | ||
| SelectParams(args.GetChainName()); | ||
|
|
||
| // Create datadir if it does not exist. | ||
| const auto base_path{args.GetDataDirBase()}; | ||
| if (!fs::exists(base_path)) { | ||
| // When creating a *new* datadir, also create a "wallets" subdirectory, | ||
| // whether or not the wallet is enabled now, so if the wallet is enabled | ||
| // in the future, it will use the "wallets" subdirectory for creating | ||
| // and listing wallets, rather than the top-level directory where | ||
| // wallets could be mixed up with other files. For backwards | ||
| // compatibility, wallet code will use the "wallets" subdirectory only | ||
| // if it already exists, but never create it itself. There is discussion | ||
| // in https://github.com/bitcoin/bitcoin/issues/16220 about ways to | ||
| // change wallet code so it would no longer be necessary to create | ||
| // "wallets" subdirectories here. | ||
| fs::create_directories(base_path / "wallets"); | ||
| } | ||
| const auto net_path{args.GetDataDirNet()}; | ||
| if (!fs::exists(net_path)) { | ||
| fs::create_directories(net_path / "wallets"); | ||
| } | ||
|
|
||
| // Create settings.json if -nosettings was not specified. | ||
| if (args.GetSettingsPath()) { | ||
| std::vector<std::string> details; | ||
| if (!args.ReadSettingsFile(&details)) { | ||
| const bilingual_str& message = _("Settings file could not be read"); | ||
| if (!settings_abort_fn) { | ||
| return ConfigError{ConfigStatus::FAILED, message, details}; | ||
| } else if (settings_abort_fn(message, details)) { | ||
| return ConfigError{ConfigStatus::ABORTED, message, details}; | ||
| } else { | ||
| details.clear(); // User chose to ignore the error and proceed. | ||
| } | ||
| } | ||
| if (!args.WriteSettingsFile(&details)) { | ||
| const bilingual_str& message = _("Settings file could not be written"); | ||
| return ConfigError{ConfigStatus::FAILED_WRITE, message, details}; | ||
| } | ||
| } | ||
| } catch (const std::exception& e) { | ||
| return ConfigError{ConfigStatus::FAILED, Untranslated(e.what())}; | ||
| } | ||
| return {}; | ||
| } | ||
| } // namespace common |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| // Copyright (c) 2023 The Bitcoin Core developers | ||
| // Distributed under the MIT software license, see the accompanying | ||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
|
||
| #ifndef BITCOIN_COMMON_INIT_H | ||
| #define BITCOIN_COMMON_INIT_H | ||
|
|
||
| #include <util/translation.h> | ||
|
|
||
| #include <functional> | ||
| #include <optional> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| class ArgsManager; | ||
|
|
||
| namespace common { | ||
| enum class ConfigStatus { | ||
| FAILED, //!< Failed generically. | ||
| FAILED_WRITE, //!< Failed to write settings.json | ||
| ABORTED, //!< Aborted by user | ||
| }; | ||
|
|
||
| struct ConfigError { | ||
| ConfigStatus status; | ||
| bilingual_str message{}; | ||
| std::vector<std::string> details{}; | ||
| }; | ||
|
|
||
| //! Callback function to let the user decide whether to abort loading if | ||
| //! settings.json file exists and can't be parsed, or to ignore the error and | ||
| //! overwrite the file. | ||
| using SettingsAbortFn = std::function<bool(const bilingual_str& message, const std::vector<std::string>& details)>; | ||
|
|
||
| /* Read config files, and create datadir and settings.json if they don't exist. */ | ||
| std::optional<ConfigError> InitConfig(ArgsManager& args, SettingsAbortFn settings_abort_fn = nullptr); | ||
| } // namespace common | ||
|
|
||
| #endif // BITCOIN_COMMON_INIT_H |
Uh oh!
There was an error while loading. Please reload this page.