Bitcoin ABC  0.22.13
P2P Digital Currency
bitcoind.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2019 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 #if defined(HAVE_CONFIG_H)
7 #include <config/bitcoin-config.h>
8 #endif
9 
10 #include <chainparams.h>
11 #include <clientversion.h>
12 #include <compat.h>
13 #include <config.h>
14 #include <httprpc.h>
15 #include <init.h>
16 #include <interfaces/chain.h>
17 #include <network.h>
18 #include <node/context.h>
19 #include <node/ui_interface.h>
20 #include <noui.h>
21 #include <shutdown.h>
22 #include <util/ref.h>
23 #include <util/strencodings.h>
24 #include <util/system.h>
25 #include <util/threadnames.h>
26 #include <util/translation.h>
27 
28 #include <functional>
29 
30 const std::function<std::string(const char *)> G_TRANSLATION_FUN = nullptr;
31 
32 static void WaitForShutdown(NodeContext &node) {
33  while (!ShutdownRequested()) {
34  UninterruptibleSleep(std::chrono::milliseconds{200});
35  }
36  Interrupt(node);
37 }
38 
40 //
41 // Start
42 //
43 static bool AppInit(int argc, char *argv[]) {
44  // FIXME: Ideally, we'd like to build the config here, but that's currently
45  // not possible as the whole application has too many global state. However,
46  // this is a first step.
47  auto &config = const_cast<Config &>(GetConfig());
48 
49  RPCServer rpcServer;
50 
51  NodeContext node;
52  util::Ref context{node};
53 
54  HTTPRPCRequestProcessor httpRPCRequestProcessor(config, rpcServer, context);
55 
56  bool fRet = false;
57 
59 
60  // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's
61  // main()
62  SetupServerArgs(node);
63  ArgsManager &args = *Assert(node.args);
64  std::string error;
65  if (!args.ParseParameters(argc, argv, error)) {
66  return InitError(Untranslated(
67  strprintf("Error parsing command line arguments: %s\n", error)));
68  }
69 
70  // Process help and version before taking care about datadir
71  if (HelpRequested(args) || args.IsArgSet("-version")) {
72  std::string strUsage = PACKAGE_NAME " version " + FormatFullVersion() +
73  " (" + NETWORK_NAME + " network)\n";
74 
75  if (args.IsArgSet("-version")) {
76  strUsage += FormatParagraph(LicenseInfo()) + "\n";
77  } else {
78  strUsage += "\nUsage: bitcoind [options] "
79  "Start " PACKAGE_NAME "\n";
80  strUsage += "\n" + args.GetHelpMessage();
81  }
82 
83  tfm::format(std::cout, "%s", strUsage);
84  return true;
85  }
86 
87  try {
88  if (!CheckDataDirOption()) {
89  return InitError(Untranslated(
90  strprintf("Specified data directory \"%s\" does not exist.\n",
91  args.GetArg("-datadir", ""))));
92  }
93  if (!args.ReadConfigFiles(error, true)) {
94  return InitError(Untranslated(
95  strprintf("Error reading configuration file: %s\n", error)));
96  }
97  // Check for -chain, -testnet or -regtest parameter (Params() calls are
98  // only valid after this clause)
99  try {
100  SelectParams(args.GetChainName());
101  node.chain = interfaces::MakeChain(node, config.GetChainParams());
102  } catch (const std::exception &e) {
103  return InitError(Untranslated(strprintf("%s\n", e.what())));
104  }
105 
106  // Make sure we create the net-specific data directory early on: if it
107  // is new, this has a side effect of also creating
108  // <datadir>/<net>/wallets/.
109  //
110  // TODO: this should be removed once GetDataDir() no longer creates the
111  // wallets/ subdirectory.
112  // See more info at:
113  // https://reviews.bitcoinabc.org/D3312
114  GetDataDir(true);
115 
116  // Error out when loose non-argument tokens are encountered on command
117  // line
118  for (int i = 1; i < argc; i++) {
119  if (!IsSwitchChar(argv[i][0])) {
120  return InitError(Untranslated(
121  strprintf("Command line contains unexpected token '%s', "
122  "see bitcoind -h for a list of options.\n",
123  argv[i])));
124  }
125  }
126 
127  if (!args.InitSettings(error)) {
128  InitError(Untranslated(error));
129  return false;
130  }
131 
132  // -server defaults to true for bitcoind but not for the GUI so do this
133  // here
134  args.SoftSetBoolArg("-server", true);
135  // Set this early so that parameter interactions go to console
136  InitLogging(args);
138  if (!AppInitBasicSetup(args)) {
139  // InitError will have been called with detailed error, which ends
140  // up on console
141  return false;
142  }
143  if (!AppInitParameterInteraction(config, args)) {
144  // InitError will have been called with detailed error, which ends
145  // up on console
146  return false;
147  }
148  if (!AppInitSanityChecks()) {
149  // InitError will have been called with detailed error, which ends
150  // up on console
151  return false;
152  }
153  if (args.GetBoolArg("-daemon", false)) {
154 #if HAVE_DECL_DAEMON
155 #if defined(MAC_OSX)
156 #pragma GCC diagnostic push
157 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
158 #endif
159  tfm::format(std::cout, PACKAGE_NAME " starting\n");
160 
161  // Daemonize
162  if (daemon(1, 0)) {
163  // don't chdir (1), do close FDs (0)
164  return InitError(Untranslated(
165  strprintf("daemon() failed: %s\n", strerror(errno))));
166  }
167 #if defined(MAC_OSX)
168 #pragma GCC diagnostic pop
169 #endif
170 #else
171  return InitError(Untranslated(
172  "-daemon is not supported on this operating system\n"));
173 #endif // HAVE_DECL_DAEMON
174  }
175 
176  // Lock data directory after daemonization
177  if (!AppInitLockDataDirectory()) {
178  // If locking the data directory failed, exit immediately
179  return false;
180  }
181  fRet = AppInitMain(config, rpcServer, httpRPCRequestProcessor, node);
182  } catch (const std::exception &e) {
183  PrintExceptionContinue(&e, "AppInit()");
184  } catch (...) {
185  PrintExceptionContinue(nullptr, "AppInit()");
186  }
187 
188  if (!fRet) {
189  Interrupt(node);
190  } else {
191  WaitForShutdown(node);
192  }
193  Shutdown(node);
194 
195  return fRet;
196 }
197 
198 int main(int argc, char *argv[]) {
199 #ifdef WIN32
200  util::WinCmdLineArgs winArgs;
201  std::tie(argc, argv) = winArgs.get();
202 #endif
204 
205  // Connect bitcoind signal handlers
206  noui_connect();
207 
208  return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
209 }
NODISCARD bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
Definition: system.cpp:911
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:390
bool ShutdownRequested()
Definition: shutdown.cpp:18
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...
const std::string NETWORK_NAME
Definition: network.cpp:7
void InitLogging(const ArgsManager &args)
Initialize global loggers.
Definition: init.cpp:1609
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn&#39;t already have a value.
Definition: system.cpp:515
void Shutdown(NodeContext &node)
Definition: init.cpp:178
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:36
std::unique_ptr< interfaces::Chain > chain
Definition: context.h:45
void SetupEnvironment()
Definition: system.cpp:1287
NODISCARD bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: system.cpp:318
void noui_connect()
Connect all bitcoind signal handlers.
Definition: noui.cpp:59
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:498
std::string LicenseInfo()
Returns licensing information (for -version)
Definition: init.cpp:1245
void SetupServerArgs(NodeContext &node)
Register all arguments with the ArgsManager.
Definition: init.cpp:376
int main(int argc, char *argv[])
Definition: bitcoind.cpp:198
std::string GetHelpMessage() const
Get the help string.
Definition: system.cpp:579
bool CheckDataDirOption()
Definition: system.cpp:799
bool AppInitSanityChecks()
Initialization sanity checks: ecc init, sanity checks, dir lock.
Definition: init.cpp:2065
Definition: config.h:19
NodeContext struct containing references to chain state and connection state.
Definition: context.h:35
void Interrupt(NodeContext &node)
Interrupt threads.
Definition: init.cpp:157
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given BIP70 chain name.
void format(std::ostream &out, const char *fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1111
bool HelpRequested(const ArgsManager &args)
Definition: system.cpp:652
const fs::path & GetDataDir(bool fNetSpecific)
Definition: system.cpp:760
const Config & GetConfig()
Definition: config.cpp:34
Class for registering and managing all RPC calls.
Definition: server.h:41
bool InitError(const bilingual_str &str)
Show error message.
static bool AppInit(int argc, char *argv[])
Definition: bitcoind.cpp:43
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
Definition: system.cpp:697
std::string FormatFullVersion()
Type-safe dynamic reference.
Definition: ref.h:21
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate string to current locale using Qt.
Definition: bitcoind.cpp:30
void ThreadSetInternalName(std::string &&)
Set the internal (in-memory) name of the current thread only.
Definition: threadnames.cpp:53
ArgsManager * args
Definition: context.h:44
bool InitSettings(std::string &error)
Read and update settings file with saved settings.
Definition: system.cpp:394
void UninterruptibleSleep(const std::chrono::microseconds &n)
Definition: time.cpp:20
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:479
bool AppInitBasicSetup(ArgsManager &args)
Initialize bitcoin: Basic context setup.
Definition: init.cpp:1656
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Definition: system.cpp:1014
bool IsSwitchChar(char c)
Definition: system.h:115
bool AppInitLockDataDirectory()
Lock bitcoin data directory.
Definition: init.cpp:2088
static void WaitForShutdown(NodeContext &node)
Definition: bitcoind.cpp:32
bool error(const char *fmt, const Args &... args)
Definition: system.h:47
void InitParameterInteraction(ArgsManager &args)
Parameter interaction: change current parameters depending on various rules.
Definition: init.cpp:1497
bool AppInitMain(Config &config, RPCServer &rpcServer, HTTPRPCRequestProcessor &httpRPCRequestProcessor, NodeContext &node)
Bitcoin main initialization.
Definition: init.cpp:2100
#define Assert(val)
Identity function.
Definition: check.h:57
bool AppInitParameterInteraction(Config &config, const ArgsManager &args)
Initialization: parameter interaction.
Definition: init.cpp:1699
std::unique_ptr< Chain > MakeChain(NodeContext &node, const CChainParams &params)
Return implementation of Chain interface.
Definition: chain.cpp:448