/ src / init.cpp
init.cpp
   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present 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 <bitcoin-build-config.h> // IWYU pragma: keep
   7  
   8  #include <init.h>
   9  
  10  #include <kernel/checks.h>
  11  
  12  #include <addrman.h>
  13  #include <banman.h>
  14  #include <blockfilter.h>
  15  #include <chain.h>
  16  #include <chainparams.h>
  17  #include <chainparamsbase.h>
  18  #include <clientversion.h>
  19  #include <common/args.h>
  20  #include <common/system.h>
  21  #include <consensus/amount.h>
  22  #include <consensus/consensus.h>
  23  #include <deploymentstatus.h>
  24  #include <hash.h>
  25  #include <httprpc.h>
  26  #include <httpserver.h>
  27  #include <index/blockfilterindex.h>
  28  #include <index/coinstatsindex.h>
  29  #include <index/txindex.h>
  30  #include <init/common.h>
  31  #include <interfaces/chain.h>
  32  #include <interfaces/init.h>
  33  #include <interfaces/ipc.h>
  34  #include <interfaces/mining.h>
  35  #include <interfaces/node.h>
  36  #include <ipc/exception.h>
  37  #include <kernel/caches.h>
  38  #include <kernel/context.h>
  39  #include <key.h>
  40  #include <logging.h>
  41  #include <mapport.h>
  42  #include <net.h>
  43  #include <net_permissions.h>
  44  #include <net_processing.h>
  45  #include <netbase.h>
  46  #include <netgroup.h>
  47  #include <node/blockmanager_args.h>
  48  #include <node/blockstorage.h>
  49  #include <node/caches.h>
  50  #include <node/chainstate.h>
  51  #include <node/chainstatemanager_args.h>
  52  #include <node/context.h>
  53  #include <node/interface_ui.h>
  54  #include <node/kernel_notifications.h>
  55  #include <node/mempool_args.h>
  56  #include <node/mempool_persist.h>
  57  #include <node/mempool_persist_args.h>
  58  #include <node/miner.h>
  59  #include <node/peerman_args.h>
  60  #include <policy/feerate.h>
  61  #include <policy/fees/block_policy_estimator.h>
  62  #include <policy/fees/block_policy_estimator_args.h>
  63  #include <policy/policy.h>
  64  #include <policy/settings.h>
  65  #include <protocol.h>
  66  #include <rpc/blockchain.h>
  67  #include <rpc/register.h>
  68  #include <rpc/server.h>
  69  #include <rpc/util.h>
  70  #include <scheduler.h>
  71  #include <script/sigcache.h>
  72  #include <sync.h>
  73  #include <torcontrol.h>
  74  #include <txdb.h>
  75  #include <txmempool.h>
  76  #include <util/asmap.h>
  77  #include <util/batchpriority.h>
  78  #include <util/chaintype.h>
  79  #include <util/check.h>
  80  #include <util/fs.h>
  81  #include <util/fs_helpers.h>
  82  #include <util/moneystr.h>
  83  #include <util/result.h>
  84  #include <util/signalinterrupt.h>
  85  #include <util/strencodings.h>
  86  #include <util/string.h>
  87  #include <util/syserror.h>
  88  #include <util/thread.h>
  89  #include <util/threadnames.h>
  90  #include <util/time.h>
  91  #include <util/translation.h>
  92  #include <validation.h>
  93  #include <validationinterface.h>
  94  #include <walletinitinterface.h>
  95  
  96  #include <algorithm>
  97  #include <cerrno>
  98  #include <condition_variable>
  99  #include <cstdint>
 100  #include <cstdio>
 101  #include <fstream>
 102  #include <functional>
 103  #include <set>
 104  #include <string>
 105  #include <thread>
 106  #include <vector>
 107  
 108  #ifndef WIN32
 109  #include <csignal>
 110  #include <sys/stat.h>
 111  #endif
 112  
 113  #include <boost/signals2/signal.hpp>
 114  
 115  #ifdef ENABLE_ZMQ
 116  #include <zmq/zmqabstractnotifier.h>
 117  #include <zmq/zmqnotificationinterface.h>
 118  #include <zmq/zmqrpc.h>
 119  #endif
 120  
 121  using common::AmountErrMsg;
 122  using common::InvalidPortErrMsg;
 123  using common::ResolveErrMsg;
 124  
 125  using node::ApplyArgsManOptions;
 126  using node::BlockManager;
 127  using node::CalculateCacheSizes;
 128  using node::ChainstateLoadResult;
 129  using node::ChainstateLoadStatus;
 130  using node::DEFAULT_PERSIST_MEMPOOL;
 131  using node::DEFAULT_PRINT_MODIFIED_FEE;
 132  using node::DEFAULT_STOPATHEIGHT;
 133  using node::DumpMempool;
 134  using node::ImportBlocks;
 135  using node::KernelNotifications;
 136  using node::LoadChainstate;
 137  using node::LoadMempool;
 138  using node::MempoolPath;
 139  using node::NodeContext;
 140  using node::ShouldPersistMempool;
 141  using node::VerifyLoadedChainstate;
 142  using util::Join;
 143  using util::ReplaceAll;
 144  using util::ToString;
 145  
 146  static constexpr bool DEFAULT_PROXYRANDOMIZE{true};
 147  static constexpr bool DEFAULT_REST_ENABLE{false};
 148  static constexpr bool DEFAULT_I2P_ACCEPT_INCOMING{true};
 149  static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false};
 150  
 151  #ifdef WIN32
 152  // Win32 LevelDB doesn't use filedescriptors, and the ones used for
 153  // accessing block files don't count towards the fd_set size limit
 154  // anyway.
 155  #define MIN_LEVELDB_FDS 0
 156  #else
 157  #define MIN_LEVELDB_FDS 150
 158  #endif
 159  
 160  static constexpr int MIN_CORE_FDS = MIN_LEVELDB_FDS + NUM_FDS_MESSAGE_CAPTURE;
 161  
 162  /**
 163   * The PID file facilities.
 164   */
 165  static const char* BITCOIN_PID_FILENAME = "bitcoind.pid";
 166  /**
 167   * True if this process has created a PID file.
 168   * Used to determine whether we should remove the PID file on shutdown.
 169   */
 170  static bool g_generated_pid{false};
 171  
 172  static fs::path GetPidFile(const ArgsManager& args)
 173  {
 174      return AbsPathForConfigVal(args, args.GetPathArg("-pid", BITCOIN_PID_FILENAME));
 175  }
 176  
 177  [[nodiscard]] static bool CreatePidFile(const ArgsManager& args)
 178  {
 179      if (args.IsArgNegated("-pid")) return true;
 180  
 181      std::ofstream file{GetPidFile(args).std_path()};
 182      if (file) {
 183  #ifdef WIN32
 184          tfm::format(file, "%d\n", GetCurrentProcessId());
 185  #else
 186          tfm::format(file, "%d\n", getpid());
 187  #endif
 188          g_generated_pid = true;
 189          return true;
 190      } else {
 191          return InitError(strprintf(_("Unable to create the PID file '%s': %s"), fs::PathToString(GetPidFile(args)), SysErrorString(errno)));
 192      }
 193  }
 194  
 195  static void RemovePidFile(const ArgsManager& args)
 196  {
 197      if (!g_generated_pid) return;
 198      const auto pid_path{GetPidFile(args)};
 199      if (std::error_code error; !fs::remove(pid_path, error)) {
 200          std::string msg{error ? error.message() : "File does not exist"};
 201          LogWarning("Unable to remove PID file (%s): %s", fs::PathToString(pid_path), msg);
 202      }
 203  }
 204  
 205  static std::optional<util::SignalInterrupt> g_shutdown;
 206  
 207  void InitContext(NodeContext& node)
 208  {
 209      assert(!g_shutdown);
 210      g_shutdown.emplace();
 211  
 212      node.args = &gArgs;
 213      node.shutdown_signal = &*g_shutdown;
 214      node.shutdown_request = [&node] {
 215          assert(node.shutdown_signal);
 216          if (!(*node.shutdown_signal)()) return false;
 217          return true;
 218      };
 219  }
 220  
 221  //////////////////////////////////////////////////////////////////////////////
 222  //
 223  // Shutdown
 224  //
 225  
 226  //
 227  // Thread management and startup/shutdown:
 228  //
 229  // The network-processing threads are all part of a thread group
 230  // created by AppInit() or the Qt main() function.
 231  //
 232  // A clean exit happens when the SignalInterrupt object is triggered, which
 233  // makes the main thread's SignalInterrupt::wait() call return, and join all
 234  // other ongoing threads in the thread group to the main thread.
 235  // Shutdown() is then called to clean up database connections, and stop other
 236  // threads that should only be stopped after the main network-processing
 237  // threads have exited.
 238  //
 239  // Shutdown for Qt is very similar, only it uses a QTimer to detect
 240  // ShutdownRequested() getting set, and then does the normal Qt
 241  // shutdown thing.
 242  //
 243  
 244  bool ShutdownRequested(node::NodeContext& node)
 245  {
 246      return bool{*Assert(node.shutdown_signal)};
 247  }
 248  
 249  #if HAVE_SYSTEM
 250  static void ShutdownNotify(const ArgsManager& args)
 251  {
 252      std::vector<std::thread> threads;
 253      for (const auto& cmd : args.GetArgs("-shutdownnotify")) {
 254          threads.emplace_back(runCommand, cmd);
 255      }
 256      for (auto& t : threads) {
 257          t.join();
 258      }
 259  }
 260  #endif
 261  
 262  void Interrupt(NodeContext& node)
 263  {
 264  #if HAVE_SYSTEM
 265      ShutdownNotify(*node.args);
 266  #endif
 267      // Wake any threads that may be waiting for the tip to change.
 268      if (node.notifications) WITH_LOCK(node.notifications->m_tip_block_mutex, node.notifications->m_tip_block_cv.notify_all());
 269      InterruptHTTPServer();
 270      InterruptHTTPRPC();
 271      InterruptRPC();
 272      InterruptREST();
 273      InterruptTorControl();
 274      InterruptMapPort();
 275      if (node.connman)
 276          node.connman->Interrupt();
 277      for (auto* index : node.indexes) {
 278          index->Interrupt();
 279      }
 280  }
 281  
 282  void Shutdown(NodeContext& node)
 283  {
 284      static Mutex g_shutdown_mutex;
 285      TRY_LOCK(g_shutdown_mutex, lock_shutdown);
 286      if (!lock_shutdown) return;
 287      LogInfo("Shutdown in progress...");
 288      Assert(node.args);
 289  
 290      /// Note: Shutdown() must be able to handle cases in which initialization failed part of the way,
 291      /// for example if the data directory was found to be locked.
 292      /// Be sure that anything that writes files or flushes caches only does this if the respective
 293      /// module was initialized.
 294      util::ThreadRename("shutoff");
 295      if (node.mempool) node.mempool->AddTransactionsUpdated(1);
 296  
 297      StopHTTPRPC();
 298      StopREST();
 299      StopRPC();
 300      StopHTTPServer();
 301      for (auto& client : node.chain_clients) {
 302          try {
 303              client->stop();
 304          } catch (const ipc::Exception& e) {
 305              LogDebug(BCLog::IPC, "Chain client did not disconnect cleanly: %s", e.what());
 306              client.reset();
 307          }
 308      }
 309      StopMapPort();
 310  
 311      // Because these depend on each-other, we make sure that neither can be
 312      // using the other before destroying them.
 313      if (node.peerman && node.validation_signals) node.validation_signals->UnregisterValidationInterface(node.peerman.get());
 314      if (node.connman) node.connman->Stop();
 315  
 316      StopTorControl();
 317  
 318      if (node.background_init_thread.joinable()) node.background_init_thread.join();
 319      // After everything has been shut down, but before things get flushed, stop the
 320      // the scheduler. After this point, SyncWithValidationInterfaceQueue() should not be called anymore
 321      // as this would prevent the shutdown from completing.
 322      if (node.scheduler) node.scheduler->stop();
 323  
 324      // After the threads that potentially access these pointers have been stopped,
 325      // destruct and reset all to nullptr.
 326      node.peerman.reset();
 327      node.connman.reset();
 328      node.banman.reset();
 329      node.addrman.reset();
 330      node.netgroupman.reset();
 331  
 332      if (node.mempool && node.mempool->GetLoadTried() && ShouldPersistMempool(*node.args)) {
 333          DumpMempool(*node.mempool, MempoolPath(*node.args));
 334      }
 335  
 336      // Drop transactions we were still watching, record fee estimations and unregister
 337      // fee estimator from validation interface.
 338      if (node.fee_estimator) {
 339          node.fee_estimator->Flush();
 340          if (node.validation_signals) {
 341              node.validation_signals->UnregisterValidationInterface(node.fee_estimator.get());
 342          }
 343      }
 344  
 345      // FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
 346      if (node.chainman) {
 347          LOCK(cs_main);
 348          for (Chainstate* chainstate : node.chainman->GetAll()) {
 349              if (chainstate->CanFlushToDisk()) {
 350                  chainstate->ForceFlushStateToDisk();
 351              }
 352          }
 353      }
 354  
 355      // After there are no more peers/RPC left to give us new data which may generate
 356      // CValidationInterface callbacks, flush them...
 357      if (node.validation_signals) node.validation_signals->FlushBackgroundCallbacks();
 358  
 359      // Stop and delete all indexes only after flushing background callbacks.
 360      for (auto* index : node.indexes) index->Stop();
 361      if (g_txindex) g_txindex.reset();
 362      if (g_coin_stats_index) g_coin_stats_index.reset();
 363      DestroyAllBlockFilterIndexes();
 364      node.indexes.clear(); // all instances are nullptr now
 365  
 366      // Any future callbacks will be dropped. This should absolutely be safe - if
 367      // missing a callback results in an unrecoverable situation, unclean shutdown
 368      // would too. The only reason to do the above flushes is to let the wallet catch
 369      // up with our current chain to avoid any strange pruning edge cases and make
 370      // next startup faster by avoiding rescan.
 371  
 372      if (node.chainman) {
 373          LOCK(cs_main);
 374          for (Chainstate* chainstate : node.chainman->GetAll()) {
 375              if (chainstate->CanFlushToDisk()) {
 376                  chainstate->ForceFlushStateToDisk();
 377                  chainstate->ResetCoinsViews();
 378              }
 379          }
 380      }
 381  
 382      // If any -ipcbind clients are still connected, disconnect them now so they
 383      // do not block shutdown.
 384      if (interfaces::Ipc* ipc = node.init->ipc()) {
 385          ipc->disconnectIncoming();
 386      }
 387  
 388  #ifdef ENABLE_ZMQ
 389      if (g_zmq_notification_interface) {
 390          if (node.validation_signals) node.validation_signals->UnregisterValidationInterface(g_zmq_notification_interface.get());
 391          g_zmq_notification_interface.reset();
 392      }
 393  #endif
 394  
 395      node.chain_clients.clear();
 396      if (node.validation_signals) {
 397          node.validation_signals->UnregisterAllValidationInterfaces();
 398      }
 399      node.mempool.reset();
 400      node.fee_estimator.reset();
 401      node.chainman.reset();
 402      node.validation_signals.reset();
 403      node.scheduler.reset();
 404      node.ecc_context.reset();
 405      node.kernel.reset();
 406  
 407      RemovePidFile(*node.args);
 408  
 409      LogInfo("Shutdown done");
 410  }
 411  
 412  /**
 413   * Signal handlers are very limited in what they are allowed to do.
 414   * The execution context the handler is invoked in is not guaranteed,
 415   * so we restrict handler operations to just touching variables:
 416   */
 417  #ifndef WIN32
 418  static void HandleSIGTERM(int)
 419  {
 420      // Return value is intentionally ignored because there is not a better way
 421      // of handling this failure in a signal handler.
 422      (void)(*Assert(g_shutdown))();
 423  }
 424  
 425  static void HandleSIGHUP(int)
 426  {
 427      LogInstance().m_reopen_file = true;
 428  }
 429  #else
 430  static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType)
 431  {
 432      if (!(*Assert(g_shutdown))()) {
 433          LogError("Failed to send shutdown signal on Ctrl-C\n");
 434          return false;
 435      }
 436      Sleep(INFINITE);
 437      return true;
 438  }
 439  #endif
 440  
 441  #ifndef WIN32
 442  static void registerSignalHandler(int signal, void(*handler)(int))
 443  {
 444      struct sigaction sa;
 445      sa.sa_handler = handler;
 446      sigemptyset(&sa.sa_mask);
 447      sa.sa_flags = 0;
 448      sigaction(signal, &sa, nullptr);
 449  }
 450  #endif
 451  
 452  void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
 453  {
 454      SetupHelpOptions(argsman);
 455      argsman.AddArg("-help-debug", "Print help message with debugging options and exit", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); // server-only for now
 456  
 457      init::AddLoggingArgs(argsman);
 458  
 459      const auto defaultBaseParams = CreateBaseChainParams(ChainType::MAIN);
 460      const auto testnetBaseParams = CreateBaseChainParams(ChainType::TESTNET);
 461      const auto testnet4BaseParams = CreateBaseChainParams(ChainType::TESTNET4);
 462      const auto signetBaseParams = CreateBaseChainParams(ChainType::SIGNET);
 463      const auto regtestBaseParams = CreateBaseChainParams(ChainType::REGTEST);
 464      const auto defaultChainParams = CreateChainParams(argsman, ChainType::MAIN);
 465      const auto testnetChainParams = CreateChainParams(argsman, ChainType::TESTNET);
 466      const auto testnet4ChainParams = CreateChainParams(argsman, ChainType::TESTNET4);
 467      const auto signetChainParams = CreateChainParams(argsman, ChainType::SIGNET);
 468      const auto regtestChainParams = CreateChainParams(argsman, ChainType::REGTEST);
 469  
 470      // Hidden Options
 471      std::vector<std::string> hidden_args = {
 472          "-dbcrashratio", "-forcecompactdb",
 473          // GUI args. These will be overwritten by SetupUIArgs for the GUI
 474          "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-splash", "-uiplatform"};
 475  
 476      argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 477  #if HAVE_SYSTEM
 478      argsman.AddArg("-alertnotify=<cmd>", "Execute command when an alert is raised (%s in cmd is replaced by message)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 479  #endif
 480      argsman.AddArg("-assumevalid=<hex>", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet3: %s, testnet4: %s, signet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnet4ChainParams->GetConsensus().defaultAssumeValid.GetHex(), signetChainParams->GetConsensus().defaultAssumeValid.GetHex()), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 481      argsman.AddArg("-blocksdir=<dir>", "Specify directory to hold blocks subdirectory for *.dat files (default: <datadir>)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 482      argsman.AddArg("-blocksxor",
 483                     strprintf("Whether an XOR-key applies to blocksdir *.dat files. "
 484                               "The created XOR-key will be zeros for an existing blocksdir or when `-blocksxor=0` is "
 485                               "set, and random for a freshly initialized blocksdir. "
 486                               "(default: %u)",
 487                               kernel::DEFAULT_XOR_BLOCKSDIR),
 488                     ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 489      argsman.AddArg("-fastprune", "Use smaller block files and lower minimum prune height for testing purposes", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 490  #if HAVE_SYSTEM
 491      argsman.AddArg("-blocknotify=<cmd>", "Execute command when the best block changes (%s in cmd is replaced by block hash)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 492  #endif
 493      argsman.AddArg("-blockreconstructionextratxn=<n>", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 494      argsman.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Disables automatic broadcast and rebroadcast of transactions, unless the source peer has the 'forcerelay' permission. RPC transactions are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 495      argsman.AddArg("-coinstatsindex", strprintf("Maintain coinstats index used by the gettxoutsetinfo RPC (default: %u)", DEFAULT_COINSTATSINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 496      argsman.AddArg("-conf=<file>", strprintf("Specify path to read-only configuration file. Relative paths will be prefixed by datadir location (only useable from command line, not configuration file) (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 497      argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
 498      argsman.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", DEFAULT_DB_CACHE_BATCH), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
 499      argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (minimum %d, default: %d). Make sure you have enough RAM. In addition, unused memory allocated to the mempool is shared with this cache (see -maxmempool).", MIN_DB_CACHE >> 20, DEFAULT_DB_CACHE >> 20), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 500      argsman.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 501      argsman.AddArg("-allowignoredconf", strprintf("For backwards compatibility, treat an unused %s file in the datadir as a warning, not an error.", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 502      argsman.AddArg("-loadblock=<file>", "Imports blocks from external file on startup", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 503      argsman.AddArg("-maxmempool=<n>", strprintf("Keep the transaction memory pool below <n> megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE_MB), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 504      argsman.AddArg("-mempoolexpiry=<n>", strprintf("Do not keep transactions in the mempool longer than <n> hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY_HOURS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 505      argsman.AddArg("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet3: %s, testnet4: %s, signet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnet4ChainParams->GetConsensus().nMinimumChainWork.GetHex(), signetChainParams->GetConsensus().nMinimumChainWork.GetHex()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
 506      argsman.AddArg("-par=<n>", strprintf("Set the number of script verification threads (0 = auto, up to %d, <0 = leave that many cores free, default: %d)",
 507          MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 508      argsman.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 509      argsman.AddArg("-persistmempoolv1",
 510                     strprintf("Whether a mempool.dat file created by -persistmempool or the savemempool RPC will be written in the legacy format "
 511                               "(version 1) or the current format (version 2). This temporary option will be removed in the future. (default: %u)",
 512                               DEFAULT_PERSIST_V1_DAT),
 513                     ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 514      argsman.AddArg("-pid=<file>", strprintf("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", BITCOIN_PID_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 515      argsman.AddArg("-prune=<n>", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex. "
 516              "Warning: Reverting this setting requires re-downloading the entire blockchain. "
 517              "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >=%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 518      argsman.AddArg("-reindex", "If enabled, wipe chain state and block index, and rebuild them from blk*.dat files on disk. Also wipe and rebuild other optional indexes that are active. If an assumeutxo snapshot was loaded, its chainstate will be wiped as well. The snapshot can then be reloaded via RPC.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 519      argsman.AddArg("-reindex-chainstate", "If enabled, wipe chain state, and rebuild it from blk*.dat files on disk. If an assumeutxo snapshot was loaded, its chainstate will be wiped as well. The snapshot can then be reloaded via RPC.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 520      argsman.AddArg("-settings=<file>", strprintf("Specify path to dynamic settings data file. Can be disabled with -nosettings. File is written at runtime and not meant to be edited by users (use %s instead for custom settings). Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME, BITCOIN_SETTINGS_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 521  #if HAVE_SYSTEM
 522      argsman.AddArg("-startupnotify=<cmd>", "Execute command on startup.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 523      argsman.AddArg("-shutdownnotify=<cmd>", "Execute command immediately before beginning shutdown. The need for shutdown may be urgent, so be careful not to delay it long (if the command doesn't require interaction with the server, consider having it fork into the background).", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 524  #endif
 525      argsman.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 526      argsman.AddArg("-blockfilterindex=<type>",
 527                   strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) +
 528                   " If <type> is not supplied or if <type> = 1, indexes for all known types are enabled.",
 529                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 530  
 531      argsman.AddArg("-addnode=<ip>", strprintf("Add a node to connect to and attempt to keep the connection open (see the addnode RPC help for more info). This option can be specified multiple times to add multiple nodes; connections are limited to %u at a time and are counted separately from the -maxconnections limit.", MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
 532      argsman.AddArg("-asmap=<file>", "Specify asn mapping used for bucketing of the peers. Relative paths will be prefixed by the net-specific datadir location.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 533      argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 534      argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet3: 127.0.0.1:%u=onion, testnet4: 127.0.0.1:%u=onion, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultChainParams->GetDefaultPort() + 1, testnetChainParams->GetDefaultPort() + 1, testnet4ChainParams->GetDefaultPort() + 1, signetChainParams->GetDefaultPort() + 1, regtestChainParams->GetDefaultPort() + 1), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
 535      argsman.AddArg("-cjdnsreachable", "If set, then this host is configured for CJDNS (connecting to fc00::/8 addresses would lead us to the CJDNS network, see doc/cjdns.md) (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 536      argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
 537      argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 538      argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 539      argsman.AddArg("-dnsseed", strprintf("Query for peer addresses via DNS lookup, if low on addresses (default: %u unless -connect used or -maxconnections=0)", DEFAULT_DNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 540      argsman.AddArg("-externalip=<ip>", "Specify your own public address", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 541      argsman.AddArg("-fixedseeds", strprintf("Allow fixed seeds if DNS seeds don't provide peers (default: %u)", DEFAULT_FIXEDSEEDS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 542      argsman.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 543      argsman.AddArg("-listen", strprintf("Accept connections from outside (default: %u if no -proxy, -connect or -maxconnections=0)", DEFAULT_LISTEN), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 544      argsman.AddArg("-listenonion", strprintf("Automatically create Tor onion service (default: %d)", DEFAULT_LISTEN_ONION), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 545      argsman.AddArg("-maxconnections=<n>", strprintf("Maintain at most <n> automatic connections to peers (default: %u). This limit does not apply to connections manually added via -addnode or the addnode RPC, which have a separate limit of %u.", DEFAULT_MAX_PEER_CONNECTIONS, MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 546      argsman.AddArg("-maxreceivebuffer=<n>", strprintf("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXRECEIVEBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 547      argsman.AddArg("-maxsendbuffer=<n>", strprintf("Maximum per-connection memory usage for the send buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXSENDBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 548      argsman.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target per 24h. Limit does not apply to peers with 'download' permission or blocks created within past week. 0 = no limit (default: %s). Optional suffix units [k|K|m|M|g|G|t|T] (default: M). Lowercase is 1000 base while uppercase is 1024 base", DEFAULT_MAX_UPLOAD_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 549  #ifdef HAVE_SOCKADDR_UN
 550      argsman.AddArg("-onion=<ip:port|path>", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy). May be a local file path prefixed with 'unix:'.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 551  #else
 552      argsman.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 553  #endif
 554      argsman.AddArg("-i2psam=<ip:port>", "I2P SAM proxy to reach I2P peers and accept I2P connections", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 555      argsman.AddArg("-i2pacceptincoming", strprintf("Whether to accept inbound I2P connections (default: %i). Ignored if -i2psam is not set. Listening for inbound I2P connections is done through the SAM proxy, not by binding to a local address and port.", DEFAULT_I2P_ACCEPT_INCOMING), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 556      argsman.AddArg("-onlynet=<net>", "Make automatic outbound connections only to network <net> (" + Join(GetNetworkNames(), ", ") + "). Inbound and manual connections are not affected by this option. It can be specified multiple times to allow multiple networks.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 557      argsman.AddArg("-v2transport", strprintf("Support v2 transport (default: %u)", DEFAULT_V2_TRANSPORT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 558      argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 559      argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 560      argsman.AddArg("-txreconciliation", strprintf("Enable transaction reconciliations per BIP 330 (default: %d)", DEFAULT_TXRECONCILIATION_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
 561      argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md). If set to a value x, the default onion listening port will be set to x+1.", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), testnet4ChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
 562      const std::string proxy_doc_for_value =
 563  #ifdef HAVE_SOCKADDR_UN
 564          "<ip>[:<port>]|unix:<path>";
 565  #else
 566          "<ip>[:<port>]";
 567  #endif
 568      const std::string proxy_doc_for_unix_socket =
 569  #ifdef HAVE_SOCKADDR_UN
 570          "May be a local file path prefixed with 'unix:' if the proxy supports it. ";
 571  #else
 572          "";
 573  #endif
 574      argsman.AddArg("-proxy=" + proxy_doc_for_value + "[=<network>]",
 575                     "Connect through SOCKS5 proxy, set -noproxy to disable. " +
 576                     proxy_doc_for_unix_socket +
 577                     "Could end in =network to set the proxy only for that network. " +
 578                     "The network can be any of ipv4, ipv6, tor or cjdns. " +
 579                     "(default: disabled)",
 580                     ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_ELISION,
 581                     OptionsCategory::CONNECTION);
 582      argsman.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 583      argsman.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes. During startup, seednodes will be tried before dnsseeds.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 584      argsman.AddArg("-networkactive", "Enable all P2P network activity (default: 1). Can be changed by the setnetworkactive RPC command", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 585      argsman.AddArg("-timeout=<n>", strprintf("Specify socket connection timeout in milliseconds. If an initial attempt to connect is unsuccessful after this amount of time, drop it (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 586      argsman.AddArg("-peertimeout=<n>", strprintf("Specify a p2p connection timeout delay in seconds. After connecting to a peer, wait this amount of time before considering disconnection based on inactivity (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
 587      argsman.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control host and port to use if onion listening enabled (default: %s). If no port is specified, the default port of %i will be used.", DEFAULT_TOR_CONTROL, DEFAULT_TOR_CONTROL_PORT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 588      argsman.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::CONNECTION);
 589      argsman.AddArg("-natpmp", strprintf("Use PCP or NAT-PMP to map the listening port (default: %u)", DEFAULT_NATPMP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 590      argsman.AddArg("-whitebind=<[permissions@]addr>", "Bind to the given address and add permission flags to the peers connecting to it. "
 591          "Use [host]:port notation for IPv6. Allowed permissions: " + Join(NET_PERMISSIONS_DOC, ", ") + ". "
 592          "Specify multiple permissions separated by commas (default: download,noban,mempool,relay). Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 593  
 594      argsman.AddArg("-whitelist=<[permissions@]IP address or network>", "Add permission flags to the peers using the given IP address (e.g. 1.2.3.4) or "
 595          "CIDR-notated network (e.g. 1.2.3.0/24). Uses the same permissions as "
 596          "-whitebind. "
 597          "Additional flags \"in\" and \"out\" control whether permissions apply to incoming connections and/or manual (default: incoming only). "
 598          "Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
 599  
 600      g_wallet_init_interface.AddWalletOptions(argsman);
 601  
 602  #ifdef ENABLE_ZMQ
 603      argsman.AddArg("-zmqpubhashblock=<address>", "Enable publish hash block in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 604      argsman.AddArg("-zmqpubhashtx=<address>", "Enable publish hash transaction in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 605      argsman.AddArg("-zmqpubrawblock=<address>", "Enable publish raw block in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 606      argsman.AddArg("-zmqpubrawtx=<address>", "Enable publish raw transaction in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 607      argsman.AddArg("-zmqpubsequence=<address>", "Enable publish hash block and tx sequence in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 608      argsman.AddArg("-zmqpubhashblockhwm=<n>", strprintf("Set publish hash block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 609      argsman.AddArg("-zmqpubhashtxhwm=<n>", strprintf("Set publish hash transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 610      argsman.AddArg("-zmqpubrawblockhwm=<n>", strprintf("Set publish raw block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 611      argsman.AddArg("-zmqpubrawtxhwm=<n>", strprintf("Set publish raw transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 612      argsman.AddArg("-zmqpubsequencehwm=<n>", strprintf("Set publish hash sequence message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
 613  #else
 614      hidden_args.emplace_back("-zmqpubhashblock=<address>");
 615      hidden_args.emplace_back("-zmqpubhashtx=<address>");
 616      hidden_args.emplace_back("-zmqpubrawblock=<address>");
 617      hidden_args.emplace_back("-zmqpubrawtx=<address>");
 618      hidden_args.emplace_back("-zmqpubsequence=<n>");
 619      hidden_args.emplace_back("-zmqpubhashblockhwm=<n>");
 620      hidden_args.emplace_back("-zmqpubhashtxhwm=<n>");
 621      hidden_args.emplace_back("-zmqpubrawblockhwm=<n>");
 622      hidden_args.emplace_back("-zmqpubrawtxhwm=<n>");
 623      hidden_args.emplace_back("-zmqpubsequencehwm=<n>");
 624  #endif
 625  
 626      argsman.AddArg("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 627      argsman.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is: %s (0-4, default: %u)", Join(CHECKLEVEL_DOC, ", "), DEFAULT_CHECKLEVEL), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 628      argsman.AddArg("-checkblockindex", strprintf("Do a consistency check for the block tree, chainstate, and other validation data structures every <n> operations. Use 0 to disable. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 629      argsman.AddArg("-checkaddrman=<n>", strprintf("Run addrman consistency checks every <n> operations. Use 0 to disable. (default: %u)", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 630      argsman.AddArg("-checkmempool=<n>", strprintf("Run mempool consistency checks every <n> transactions. Use 0 to disable. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 631      // Checkpoints were removed. We keep `-checkpoints` as a hidden arg to display a more user friendly error when set.
 632      argsman.AddArg("-checkpoints", "", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN);
 633      argsman.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 634      argsman.AddArg("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 635      argsman.AddArg("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u)", DEFAULT_STOPATHEIGHT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 636      argsman.AddArg("-limitancestorcount=<n>", strprintf("Deprecated setting to not accept transactions if number of in-mempool ancestors is <n> or more (default: %u); replaced by cluster limits (see -limitclustercount) and only used by wallet for coin selection", DEFAULT_ANCESTOR_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 637      // Ancestor and descendant size limits were removed. We keep
 638      // -limitancestorsize/-limitdescendantsize as hidden args to display a more
 639      // user friendly error when set.
 640      argsman.AddArg("-limitancestorsize", "", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN);
 641      argsman.AddArg("-limitdescendantsize", "", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN);
 642      argsman.AddArg("-limitdescendantcount=<n>", strprintf("Deprecated setting to not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u); replaced by cluster limits (see -limitclustercount) and only used by wallet for coin selection", DEFAULT_DESCENDANT_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 643      argsman.AddArg("-test=<option>", "Pass a test-only option. Options include : " + Join(TEST_OPTIONS_DOC, ", ") + ".", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 644      argsman.AddArg("-limitclustercount=<n>", strprintf("Do not accept transactions into mempool which are directly or indirectly connected to <n> or more other unconfirmed transactions (default: %u, maximum: %u)", DEFAULT_CLUSTER_LIMIT, MAX_CLUSTER_COUNT_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 645      argsman.AddArg("-limitclustersize=<n>", strprintf("Do not accept transactions whose virtual size with all in-mempool connected transactions exceeds <n> kilobytes (default: %u)", DEFAULT_CLUSTER_SIZE_LIMIT_KVB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 646      argsman.AddArg("-capturemessages", "Capture all P2P messages to disk", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 647      argsman.AddArg("-mocktime=<n>", "Replace actual time with " + UNIX_EPOCH_TIME + " (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 648      argsman.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_VALIDATION_CACHE_BYTES >> 20), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 649      argsman.AddArg("-maxtipage=<n>",
 650                     strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)",
 651                               Ticks<std::chrono::seconds>(DEFAULT_MAX_TIP_AGE)),
 652                     ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 653      argsman.AddArg("-printpriority", strprintf("Log transaction fee rate in %s/kvB when mining blocks (default: %u)", CURRENCY_UNIT, DEFAULT_PRINT_MODIFIED_FEE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 654      argsman.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
 655  
 656      SetupChainParamsBaseOptions(argsman);
 657  
 658      argsman.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (test networks only; default: %u)", DEFAULT_ACCEPT_NON_STD_TXN), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
 659      argsman.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define cost of relay, used for mempool limiting and replacement policy. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
 660      argsman.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
 661      argsman.AddArg("-acceptstalefeeestimates", strprintf("Read fee estimates even if they are stale (%sdefault: %u) fee estimates are considered stale if they are %s hours old", "regtest only; ", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES, Ticks<std::chrono::hours>(MAX_FILE_AGE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
 662      argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
 663      argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
 664      argsman.AddArg("-datacarriersize",
 665                     strprintf("Relay and mine transactions whose data-carrying raw scriptPubKeys in aggregate "
 666                               "are of this size or less, allowing multiple outputs (default: %u)",
 667                               MAX_OP_RETURN_RELAY),
 668                     ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
 669      argsman.AddArg("-permitbaremultisig", strprintf("Relay transactions creating non-P2SH multisig outputs (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY,
 670                     OptionsCategory::NODE_RELAY);
 671      argsman.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kvB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)",
 672          CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
 673      argsman.AddArg("-whitelistforcerelay", strprintf("Add 'forcerelay' permission to whitelisted peers with default permissions. This will relay transactions even if the transactions were already in the mempool. (default: %d)", DEFAULT_WHITELISTFORCERELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
 674      argsman.AddArg("-whitelistrelay", strprintf("Add 'relay' permission to whitelisted peers with default permissions. This will accept relayed transactions even when not relaying transactions (default: %d)", DEFAULT_WHITELISTRELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
 675  
 676  
 677      argsman.AddArg("-blockmaxweight=<n>", strprintf("Set maximum BIP141 block weight (default: %d)", DEFAULT_BLOCK_MAX_WEIGHT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::BLOCK_CREATION);
 678      argsman.AddArg("-blockreservedweight=<n>", strprintf("Reserve space for the fixed-size block header plus the largest coinbase transaction the mining software may add to the block. (default: %d).", DEFAULT_BLOCK_RESERVED_WEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
 679      argsman.AddArg("-blockmintxfee=<amt>", strprintf("Set lowest fee rate (in %s/kvB) for transactions to be included in block creation. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
 680      argsman.AddArg("-blockversion=<n>", "Override block version to test forking scenarios", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::BLOCK_CREATION);
 681  
 682      argsman.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
 683      argsman.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid values for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0), a network/CIDR (e.g. 1.2.3.4/24), all ipv4 (0.0.0.0/0), or all ipv6 (::/0). RFC4193 is allowed only if -cjdnsreachable=0. This option can be specified multiple times", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
 684      argsman.AddArg("-rpcauth=<userpw>", "Username and HMAC-SHA-256 hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcauth. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
 685      argsman.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC);
 686      argsman.AddArg("-rpcdoccheck", strprintf("Throw a non-fatal error at runtime if the documentation for an RPC is incorrect (default: %u)", DEFAULT_RPC_DOC_CHECK), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
 687      argsman.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
 688      argsman.AddArg("-rpccookieperms=<readable-by>", strprintf("Set permissions on the RPC auth cookie file so that it is readable by [owner|group|all] (default: owner [via umask 0077])"), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
 689      argsman.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
 690      argsman.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), testnet4BaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC);
 691      argsman.AddArg("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
 692      argsman.AddArg("-rpcthreads=<n>", strprintf("Set the number of threads to service RPC calls (default: %d)", DEFAULT_HTTP_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
 693      argsman.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
 694      argsman.AddArg("-rpcwhitelist=<whitelist>", "Set a whitelist to filter incoming RPC calls for a specific user. The field <whitelist> comes in the format: <USERNAME>:<rpc 1>,<rpc 2>,...,<rpc n>. If multiple whitelists are set for a given user, they are set-intersected. See -rpcwhitelistdefault documentation for information on default whitelist behavior.", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
 695      argsman.AddArg("-rpcwhitelistdefault", "Sets default behavior for rpc whitelisting. Unless rpcwhitelistdefault is set to 0, if any -rpcwhitelist is set, the rpc server acts as if all rpc users are subject to empty-unless-otherwise-specified whitelists. If rpcwhitelistdefault is set to 1 and no -rpcwhitelist is set, rpc server acts as if all rpc users are subject to empty whitelists.", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
 696      argsman.AddArg("-rpcworkqueue=<n>", strprintf("Set the maximum depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
 697      argsman.AddArg("-server", "Accept command line and JSON-RPC commands", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
 698      if (can_listen_ipc) {
 699          argsman.AddArg("-ipcbind=<address>", "Bind to Unix socket address and listen for incoming connections. Valid address values are \"unix\" to listen on the default path, <datadir>/node.sock, or \"unix:/custom/path\" to specify a custom path. Can be specified multiple times to listen on multiple paths. Default behavior is not to listen on any path. If relative paths are specified, they are interpreted relative to the network data directory. If paths include any parent directory components and the parent directories do not exist, they will be created.", ArgsManager::ALLOW_ANY, OptionsCategory::IPC);
 700      }
 701  
 702  #if HAVE_DECL_FORK
 703      argsman.AddArg("-daemon", strprintf("Run in the background as a daemon and accept commands (default: %d)", DEFAULT_DAEMON), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 704      argsman.AddArg("-daemonwait", strprintf("Wait for initialization to be finished before exiting. This implies -daemon (default: %d)", DEFAULT_DAEMONWAIT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
 705  #else
 706      hidden_args.emplace_back("-daemon");
 707      hidden_args.emplace_back("-daemonwait");
 708  #endif
 709  
 710      // Add the hidden options
 711      argsman.AddHiddenArgs(hidden_args);
 712  }
 713  
 714  #if HAVE_SYSTEM
 715  static void StartupNotify(const ArgsManager& args)
 716  {
 717      std::string cmd = args.GetArg("-startupnotify", "");
 718      if (!cmd.empty()) {
 719          std::thread t(runCommand, cmd);
 720          t.detach(); // thread runs free
 721      }
 722  }
 723  #endif
 724  
 725  static bool AppInitServers(NodeContext& node)
 726  {
 727      const ArgsManager& args = *Assert(node.args);
 728      if (!InitHTTPServer(*Assert(node.shutdown_signal))) {
 729          return false;
 730      }
 731      StartRPC();
 732      node.rpc_interruption_point = RpcInterruptionPoint;
 733      if (!StartHTTPRPC(&node))
 734          return false;
 735      if (args.GetBoolArg("-rest", DEFAULT_REST_ENABLE)) StartREST(&node);
 736      StartHTTPServer();
 737      return true;
 738  }
 739  
 740  // Parameter interaction based on rules
 741  void InitParameterInteraction(ArgsManager& args)
 742  {
 743      // when specifying an explicit binding address, you want to listen on it
 744      // even when -connect or -proxy is specified
 745      if (!args.GetArgs("-bind").empty()) {
 746          if (args.SoftSetBoolArg("-listen", true))
 747              LogInfo("parameter interaction: -bind set -> setting -listen=1\n");
 748      }
 749      if (!args.GetArgs("-whitebind").empty()) {
 750          if (args.SoftSetBoolArg("-listen", true))
 751              LogInfo("parameter interaction: -whitebind set -> setting -listen=1\n");
 752      }
 753  
 754      if (!args.GetArgs("-connect").empty() || args.IsArgNegated("-connect") || args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS) <= 0) {
 755          // when only connecting to trusted nodes, do not seed via DNS, or listen by default
 756          // do the same when connections are disabled
 757          if (args.SoftSetBoolArg("-dnsseed", false))
 758              LogInfo("parameter interaction: -connect or -maxconnections=0 set -> setting -dnsseed=0\n");
 759          if (args.SoftSetBoolArg("-listen", false))
 760              LogInfo("parameter interaction: -connect or -maxconnections=0 set -> setting -listen=0\n");
 761      }
 762  
 763      std::string proxy_arg = args.GetArg("-proxy", "");
 764      if (proxy_arg != "" && proxy_arg != "0") {
 765          // to protect privacy, do not listen by default if a default proxy server is specified
 766          if (args.SoftSetBoolArg("-listen", false))
 767              LogInfo("parameter interaction: -proxy set -> setting -listen=0\n");
 768          // to protect privacy, do not map ports when a proxy is set. The user may still specify -listen=1
 769          // to listen locally, so don't rely on this happening through -listen below.
 770          if (args.SoftSetBoolArg("-natpmp", false)) {
 771              LogInfo("parameter interaction: -proxy set -> setting -natpmp=0\n");
 772          }
 773          // to protect privacy, do not discover addresses by default
 774          if (args.SoftSetBoolArg("-discover", false))
 775              LogInfo("parameter interaction: -proxy set -> setting -discover=0\n");
 776      }
 777  
 778      if (!args.GetBoolArg("-listen", DEFAULT_LISTEN)) {
 779          // do not map ports or try to retrieve public IP when not listening (pointless)
 780          if (args.SoftSetBoolArg("-natpmp", false)) {
 781              LogInfo("parameter interaction: -listen=0 -> setting -natpmp=0\n");
 782          }
 783          if (args.SoftSetBoolArg("-discover", false))
 784              LogInfo("parameter interaction: -listen=0 -> setting -discover=0\n");
 785          if (args.SoftSetBoolArg("-listenonion", false))
 786              LogInfo("parameter interaction: -listen=0 -> setting -listenonion=0\n");
 787          if (args.SoftSetBoolArg("-i2pacceptincoming", false)) {
 788              LogInfo("parameter interaction: -listen=0 -> setting -i2pacceptincoming=0\n");
 789          }
 790      }
 791  
 792      if (!args.GetArgs("-externalip").empty()) {
 793          // if an explicit public IP is specified, do not try to find others
 794          if (args.SoftSetBoolArg("-discover", false))
 795              LogInfo("parameter interaction: -externalip set -> setting -discover=0\n");
 796      }
 797  
 798      if (args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) {
 799          // disable whitelistrelay in blocksonly mode
 800          if (args.SoftSetBoolArg("-whitelistrelay", false))
 801              LogInfo("parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n");
 802          // Reduce default mempool size in blocksonly mode to avoid unexpected resource usage
 803          if (args.SoftSetArg("-maxmempool", ToString(DEFAULT_BLOCKSONLY_MAX_MEMPOOL_SIZE_MB)))
 804              LogInfo("parameter interaction: -blocksonly=1 -> setting -maxmempool=%d\n", DEFAULT_BLOCKSONLY_MAX_MEMPOOL_SIZE_MB);
 805      }
 806  
 807      // Forcing relay from whitelisted hosts implies we will accept relays from them in the first place.
 808      if (args.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) {
 809          if (args.SoftSetBoolArg("-whitelistrelay", true))
 810              LogInfo("parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n");
 811      }
 812      const auto onlynets = args.GetArgs("-onlynet");
 813      if (!onlynets.empty()) {
 814          bool clearnet_reachable = std::any_of(onlynets.begin(), onlynets.end(), [](const auto& net) {
 815              const auto n = ParseNetwork(net);
 816              return n == NET_IPV4 || n == NET_IPV6;
 817          });
 818          if (!clearnet_reachable && args.SoftSetBoolArg("-dnsseed", false)) {
 819              LogInfo("parameter interaction: -onlynet excludes IPv4 and IPv6 -> setting -dnsseed=0\n");
 820          }
 821      }
 822  }
 823  
 824  /**
 825   * Initialize global loggers.
 826   *
 827   * Note that this is called very early in the process lifetime, so you should be
 828   * careful about what global state you rely on here.
 829   */
 830  void InitLogging(const ArgsManager& args)
 831  {
 832      init::SetLoggingOptions(args);
 833      init::LogPackageVersion();
 834  }
 835  
 836  namespace { // Variables internal to initialization process only
 837  
 838  int nMaxConnections;
 839  int available_fds;
 840  ServiceFlags g_local_services = ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
 841  int64_t peer_connect_timeout;
 842  std::set<BlockFilterType> g_enabled_filter_types;
 843  
 844  } // namespace
 845  
 846  [[noreturn]] static void new_handler_terminate()
 847  {
 848      // Rather than throwing std::bad-alloc if allocation fails, terminate
 849      // immediately to (try to) avoid chain corruption.
 850      // Since logging may itself allocate memory, set the handler directly
 851      // to terminate first.
 852      std::set_new_handler(std::terminate);
 853      LogError("Out of memory. Terminating.\n");
 854  
 855      // The log was successful, terminate now.
 856      std::terminate();
 857  };
 858  
 859  bool AppInitBasicSetup(const ArgsManager& args, std::atomic<int>& exit_status)
 860  {
 861      // ********************************************************* Step 1: setup
 862  #ifdef _MSC_VER
 863      // Turn off Microsoft heap dump noise
 864      _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
 865      _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, 0));
 866      // Disable confusing "helpful" text message on abort, Ctrl-C
 867      _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
 868  #endif
 869  #ifdef WIN32
 870      // Enable heap terminate-on-corruption
 871      HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
 872  #endif
 873      if (!SetupNetworking()) {
 874          return InitError(Untranslated("Initializing networking failed."));
 875      }
 876  
 877  #ifndef WIN32
 878      // Clean shutdown on SIGTERM
 879      registerSignalHandler(SIGTERM, HandleSIGTERM);
 880      registerSignalHandler(SIGINT, HandleSIGTERM);
 881  
 882      // Reopen debug.log on SIGHUP
 883      registerSignalHandler(SIGHUP, HandleSIGHUP);
 884  
 885      // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
 886      signal(SIGPIPE, SIG_IGN);
 887  #else
 888      SetConsoleCtrlHandler(consoleCtrlHandler, true);
 889  #endif
 890  
 891      std::set_new_handler(new_handler_terminate);
 892  
 893      return true;
 894  }
 895  
 896  bool AppInitParameterInteraction(const ArgsManager& args)
 897  {
 898      const CChainParams& chainparams = Params();
 899      // ********************************************************* Step 2: parameter interactions
 900  
 901      // also see: InitParameterInteraction()
 902  
 903      // We removed checkpoints but keep the option to warn users who still have it in their config.
 904      if (args.IsArgSet("-checkpoints")) {
 905          InitWarning(_("Option '-checkpoints' is set but checkpoints were removed. This option has no effect."));
 906      }
 907      if (args.IsArgSet("-limitancestorsize")) {
 908          InitWarning(_("Option '-limitancestorsize' is given but ancestor size limits have been replaced with cluster size limits (see -limitclustersize). This option has no effect."));
 909      }
 910      if (args.IsArgSet("-limitdescendantsize")) {
 911          InitWarning(_("Option '-limitdescendantsize' is given but descendant size limits have been replaced with cluster size limits (see -limitclustersize). This option has no effect."));
 912      }
 913  
 914      // Error if network-specific options (-addnode, -connect, etc) are
 915      // specified in default section of config file, but not overridden
 916      // on the command line or in this chain's section of the config file.
 917      ChainType chain = args.GetChainType();
 918      if (chain == ChainType::SIGNET) {
 919          LogInfo("Signet derived magic (message start): %s", HexStr(chainparams.MessageStart()));
 920      }
 921      bilingual_str errors;
 922      for (const auto& arg : args.GetUnsuitableSectionOnlyArgs()) {
 923          errors += strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, ChainTypeToString(chain), ChainTypeToString(chain)) + Untranslated("\n");
 924      }
 925  
 926      if (!errors.empty()) {
 927          return InitError(errors);
 928      }
 929  
 930      // Testnet3 deprecation warning
 931      if (chain == ChainType::TESTNET) {
 932          LogInfo("Warning: Support for testnet3 is deprecated and will be removed in an upcoming release. Consider switching to testnet4.\n");
 933      }
 934  
 935      // Warn if unrecognized section name are present in the config file.
 936      bilingual_str warnings;
 937      for (const auto& section : args.GetUnrecognizedSections()) {
 938          warnings += Untranslated(strprintf("%s:%i ", section.m_file, section.m_line)) + strprintf(_("Section [%s] is not recognized."), section.m_name) + Untranslated("\n");
 939      }
 940  
 941      if (!warnings.empty()) {
 942          InitWarning(warnings);
 943      }
 944  
 945      if (!fs::is_directory(args.GetBlocksDirPath())) {
 946          return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), args.GetArg("-blocksdir", "")));
 947      }
 948  
 949      // parse and validate enabled filter types
 950      std::string blockfilterindex_value = args.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX);
 951      if (blockfilterindex_value == "" || blockfilterindex_value == "1") {
 952          g_enabled_filter_types = AllBlockFilterTypes();
 953      } else if (blockfilterindex_value != "0") {
 954          const std::vector<std::string> names = args.GetArgs("-blockfilterindex");
 955          for (const auto& name : names) {
 956              BlockFilterType filter_type;
 957              if (!BlockFilterTypeByName(name, filter_type)) {
 958                  return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name));
 959              }
 960              g_enabled_filter_types.insert(filter_type);
 961          }
 962      }
 963  
 964      // Signal NODE_P2P_V2 if BIP324 v2 transport is enabled.
 965      if (args.GetBoolArg("-v2transport", DEFAULT_V2_TRANSPORT)) {
 966          g_local_services = ServiceFlags(g_local_services | NODE_P2P_V2);
 967      }
 968  
 969      // Signal NODE_COMPACT_FILTERS if peerblockfilters and basic filters index are both enabled.
 970      if (args.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)) {
 971          if (g_enabled_filter_types.count(BlockFilterType::BASIC) != 1) {
 972              return InitError(_("Cannot set -peerblockfilters without -blockfilterindex."));
 973          }
 974  
 975          g_local_services = ServiceFlags(g_local_services | NODE_COMPACT_FILTERS);
 976      }
 977  
 978      if (args.GetIntArg("-prune", 0)) {
 979          if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX))
 980              return InitError(_("Prune mode is incompatible with -txindex."));
 981          if (args.GetBoolArg("-reindex-chainstate", false)) {
 982              return InitError(_("Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead."));
 983          }
 984      }
 985  
 986      // If -forcednsseed is set to true, ensure -dnsseed has not been set to false
 987      if (args.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED) && !args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED)){
 988          return InitError(_("Cannot set -forcednsseed to true when setting -dnsseed to false."));
 989      }
 990  
 991      // -bind and -whitebind can't be set when not listening
 992      size_t nUserBind = args.GetArgs("-bind").size() + args.GetArgs("-whitebind").size();
 993      if (nUserBind != 0 && !args.GetBoolArg("-listen", DEFAULT_LISTEN)) {
 994          return InitError(Untranslated("Cannot set -bind or -whitebind together with -listen=0"));
 995      }
 996  
 997      // if listen=0, then disallow listenonion=1
 998      if (!args.GetBoolArg("-listen", DEFAULT_LISTEN) && args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) {
 999          return InitError(Untranslated("Cannot set -listen=0 together with -listenonion=1"));
1000      }
1001  
1002      // Make sure enough file descriptors are available. We need to reserve enough FDs to account for the bare minimum,
1003      // plus all manual connections and all bound interfaces. Any remainder will be available for connection sockets
1004  
1005      // Number of bound interfaces (we have at least one)
1006      int nBind = std::max(nUserBind, size_t(1));
1007      // Maximum number of connections with other nodes, this accounts for all types of outbounds and inbounds except for manual
1008      int user_max_connection = args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
1009      if (user_max_connection < 0) {
1010          return InitError(Untranslated("-maxconnections must be greater or equal than zero"));
1011      }
1012      // Reserve enough FDs to account for the bare minimum, plus any manual connections, plus the bound interfaces
1013      int min_required_fds = MIN_CORE_FDS + MAX_ADDNODE_CONNECTIONS + nBind;
1014  
1015      // Try raising the FD limit to what we need (available_fds may be smaller than the requested amount if this fails)
1016      available_fds = RaiseFileDescriptorLimit(user_max_connection + min_required_fds);
1017      // If we are using select instead of poll, our actual limit may be even smaller
1018  #ifndef USE_POLL
1019      available_fds = std::min(FD_SETSIZE, available_fds);
1020  #endif
1021      if (available_fds < min_required_fds)
1022          return InitError(strprintf(_("Not enough file descriptors available. %d available, %d required."), available_fds, min_required_fds));
1023  
1024      // Trim requested connection counts, to fit into system limitations
1025      nMaxConnections = std::min(available_fds - min_required_fds, user_max_connection);
1026  
1027      if (nMaxConnections < user_max_connection)
1028          InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), user_max_connection, nMaxConnections));
1029  
1030      // ********************************************************* Step 3: parameter-to-internal-flags
1031      if (auto result{init::SetLoggingCategories(args)}; !result) return InitError(util::ErrorString(result));
1032      if (auto result{init::SetLoggingLevel(args)}; !result) return InitError(util::ErrorString(result));
1033  
1034      nConnectTimeout = args.GetIntArg("-timeout", DEFAULT_CONNECT_TIMEOUT);
1035      if (nConnectTimeout <= 0) {
1036          nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
1037      }
1038  
1039      peer_connect_timeout = args.GetIntArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT);
1040      if (peer_connect_timeout <= 0) {
1041          return InitError(Untranslated("peertimeout must be a positive integer."));
1042      }
1043  
1044      if (const auto arg{args.GetArg("-blockmintxfee")}) {
1045          if (!ParseMoney(*arg)) {
1046              return InitError(AmountErrMsg("blockmintxfee", *arg));
1047          }
1048      }
1049  
1050      {
1051          const auto max_block_weight = args.GetIntArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
1052          if (max_block_weight > MAX_BLOCK_WEIGHT) {
1053              return InitError(strprintf(_("Specified -blockmaxweight (%d) exceeds consensus maximum block weight (%d)"), max_block_weight, MAX_BLOCK_WEIGHT));
1054          }
1055      }
1056  
1057      {
1058          const auto block_reserved_weight = args.GetIntArg("-blockreservedweight", DEFAULT_BLOCK_RESERVED_WEIGHT);
1059          if (block_reserved_weight > MAX_BLOCK_WEIGHT) {
1060              return InitError(strprintf(_("Specified -blockreservedweight (%d) exceeds consensus maximum block weight (%d)"), block_reserved_weight, MAX_BLOCK_WEIGHT));
1061          }
1062          if (block_reserved_weight < MINIMUM_BLOCK_RESERVED_WEIGHT) {
1063              return InitError(strprintf(_("Specified -blockreservedweight (%d) is lower than minimum safety value of (%d)"), block_reserved_weight, MINIMUM_BLOCK_RESERVED_WEIGHT));
1064          }
1065      }
1066  
1067      nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
1068  
1069      if (!g_wallet_init_interface.ParameterInteraction()) return false;
1070  
1071      // Option to startup with mocktime set (used for regression testing):
1072      if (const auto mocktime{args.GetIntArg("-mocktime")}) {
1073          SetMockTime(std::chrono::seconds{*mocktime});
1074      }
1075  
1076      if (args.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
1077          g_local_services = ServiceFlags(g_local_services | NODE_BLOOM);
1078  
1079      const std::vector<std::string> test_options = args.GetArgs("-test");
1080      if (!test_options.empty()) {
1081          if (chainparams.GetChainType() != ChainType::REGTEST) {
1082              return InitError(Untranslated("-test=<option> can only be used with regtest"));
1083          }
1084          for (const std::string& option : test_options) {
1085              auto it = std::find_if(TEST_OPTIONS_DOC.begin(), TEST_OPTIONS_DOC.end(), [&option](const std::string& doc_option) {
1086                  size_t pos = doc_option.find(" (");
1087                  return (pos != std::string::npos) && (doc_option.substr(0, pos) == option);
1088              });
1089              if (it == TEST_OPTIONS_DOC.end()) {
1090                  InitWarning(strprintf(_("Unrecognised option \"%s\" provided in -test=<option>."), option));
1091              }
1092          }
1093      }
1094  
1095      // Also report errors from parsing before daemonization
1096      {
1097          kernel::Notifications notifications{};
1098          ChainstateManager::Options chainman_opts_dummy{
1099              .chainparams = chainparams,
1100              .datadir = args.GetDataDirNet(),
1101              .notifications = notifications,
1102          };
1103          auto chainman_result{ApplyArgsManOptions(args, chainman_opts_dummy)};
1104          if (!chainman_result) {
1105              return InitError(util::ErrorString(chainman_result));
1106          }
1107          BlockManager::Options blockman_opts_dummy{
1108              .chainparams = chainman_opts_dummy.chainparams,
1109              .blocks_dir = args.GetBlocksDirPath(),
1110              .notifications = chainman_opts_dummy.notifications,
1111              .block_tree_db_params = DBParams{
1112                  .path = args.GetDataDirNet() / "blocks" / "index",
1113                  .cache_bytes = 0,
1114              },
1115          };
1116          auto blockman_result{ApplyArgsManOptions(args, blockman_opts_dummy)};
1117          if (!blockman_result) {
1118              return InitError(util::ErrorString(blockman_result));
1119          }
1120          CTxMemPool::Options mempool_opts{};
1121          auto mempool_result{ApplyArgsManOptions(args, chainparams, mempool_opts)};
1122          if (!mempool_result) {
1123              return InitError(util::ErrorString(mempool_result));
1124          }
1125      }
1126  
1127      return true;
1128  }
1129  
1130  static bool LockDirectory(const fs::path& dir, bool probeOnly)
1131  {
1132      // Make sure only a single process is using the directory.
1133      switch (util::LockDirectory(dir, ".lock", probeOnly)) {
1134      case util::LockResult::ErrorWrite:
1135          return InitError(strprintf(_("Cannot write to directory '%s'; check permissions."), fs::PathToString(dir)));
1136      case util::LockResult::ErrorLock:
1137          return InitError(strprintf(_("Cannot obtain a lock on directory %s. %s is probably already running."), fs::PathToString(dir), CLIENT_NAME));
1138      case util::LockResult::Success: return true;
1139      } // no default case, so the compiler can warn about missing cases
1140      assert(false);
1141  }
1142  static bool LockDirectories(bool probeOnly)
1143  {
1144      return LockDirectory(gArgs.GetDataDirNet(), probeOnly) && \
1145             LockDirectory(gArgs.GetBlocksDirPath(), probeOnly);
1146  }
1147  
1148  bool AppInitSanityChecks(const kernel::Context& kernel)
1149  {
1150      // ********************************************************* Step 4: sanity checks
1151      auto result{kernel::SanityChecks(kernel)};
1152      if (!result) {
1153          InitError(util::ErrorString(result));
1154          return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), CLIENT_NAME));
1155      }
1156  
1157      if (!ECC_InitSanityCheck()) {
1158          return InitError(strprintf(_("Elliptic curve cryptography sanity check failure. %s is shutting down."), CLIENT_NAME));
1159      }
1160  
1161      // Probe the directory locks to give an early error message, if possible
1162      // We cannot hold the directory locks here, as the forking for daemon() hasn't yet happened,
1163      // and a fork will cause weird behavior to them.
1164      return LockDirectories(true);
1165  }
1166  
1167  bool AppInitLockDirectories()
1168  {
1169      // After daemonization get the directory locks again and hold on to them until exit
1170      // This creates a slight window for a race condition to happen, however this condition is harmless: it
1171      // will at most make us exit without printing a message to console.
1172      if (!LockDirectories(false)) {
1173          // Detailed error printed inside LockDirectory
1174          return false;
1175      }
1176      return true;
1177  }
1178  
1179  bool AppInitInterfaces(NodeContext& node)
1180  {
1181      node.chain = node.init->makeChain();
1182      node.mining = node.init->makeMining();
1183      return true;
1184  }
1185  
1186  bool CheckHostPortOptions(const ArgsManager& args) {
1187      for (const std::string port_option : {
1188          "-port",
1189          "-rpcport",
1190      }) {
1191          if (const auto port{args.GetArg(port_option)}) {
1192              const auto n{ToIntegral<uint16_t>(*port)};
1193              if (!n || *n == 0) {
1194                  return InitError(InvalidPortErrMsg(port_option, *port));
1195              }
1196          }
1197      }
1198  
1199      for ([[maybe_unused]] const auto& [param_name, unix, suffix_allowed] : std::vector<std::tuple<std::string, bool, bool>>{
1200          // arg name          UNIX socket support  =suffix allowed
1201          {"-i2psam",          false,               false},
1202          {"-onion",           true,                false},
1203          {"-proxy",           true,                true},
1204          {"-bind",            false,               true},
1205          {"-rpcbind",         false,               false},
1206          {"-torcontrol",      false,               false},
1207          {"-whitebind",       false,               false},
1208          {"-zmqpubhashblock", true,                false},
1209          {"-zmqpubhashtx",    true,                false},
1210          {"-zmqpubrawblock",  true,                false},
1211          {"-zmqpubrawtx",     true,                false},
1212          {"-zmqpubsequence",  true,                false},
1213      }) {
1214          for (const std::string& param_value : args.GetArgs(param_name)) {
1215              const std::string param_value_hostport{
1216                  suffix_allowed ? param_value.substr(0, param_value.rfind('=')) : param_value};
1217              std::string host_out;
1218              uint16_t port_out{0};
1219              if (!SplitHostPort(param_value_hostport, port_out, host_out)) {
1220  #ifdef HAVE_SOCKADDR_UN
1221                  // Allow unix domain sockets for some options e.g. unix:/some/file/path
1222                  if (!unix || !param_value.starts_with(ADDR_PREFIX_UNIX)) {
1223                      return InitError(InvalidPortErrMsg(param_name, param_value));
1224                  }
1225  #else
1226                  return InitError(InvalidPortErrMsg(param_name, param_value));
1227  #endif
1228              }
1229          }
1230      }
1231  
1232      return true;
1233  }
1234  
1235  /**
1236   * @brief Checks for duplicate bindings across all binding configurations.
1237   *
1238   * @param[in] conn_options Connection options containing the binding vectors to check
1239   * @return std::optional<CService> containing the first duplicate found, or std::nullopt if no duplicates
1240   */
1241  static std::optional<CService> CheckBindingConflicts(const CConnman::Options& conn_options)
1242  {
1243      std::set<CService> seen;
1244  
1245      // Check all whitelisted bindings
1246      for (const auto& wb : conn_options.vWhiteBinds) {
1247          if (!seen.insert(wb.m_service).second) {
1248              return wb.m_service;
1249          }
1250      }
1251  
1252      // Check regular bindings
1253      for (const auto& bind : conn_options.vBinds) {
1254          if (!seen.insert(bind).second) {
1255              return bind;
1256          }
1257      }
1258  
1259      // Check onion bindings
1260      for (const auto& onion_bind : conn_options.onion_binds) {
1261          if (!seen.insert(onion_bind).second) {
1262              return onion_bind;
1263          }
1264      }
1265  
1266      return std::nullopt;
1267  }
1268  
1269  // A GUI user may opt to retry once with do_reindex set if there is a failure during chainstate initialization.
1270  // The function therefore has to support re-entry.
1271  static ChainstateLoadResult InitAndLoadChainstate(
1272      NodeContext& node,
1273      bool do_reindex,
1274      const bool do_reindex_chainstate,
1275      const kernel::CacheSizes& cache_sizes,
1276      const ArgsManager& args)
1277  {
1278      // This function may be called twice, so any dirty state must be reset.
1279      node.notifications.reset(); // Drop state, such as a cached tip block
1280      node.mempool.reset();
1281      node.chainman.reset(); // Drop state, such as an initialized m_block_tree_db
1282  
1283      const CChainParams& chainparams = Params();
1284  
1285      Assert(!node.notifications); // Was reset above
1286      node.notifications = std::make_unique<KernelNotifications>(Assert(node.shutdown_request), node.exit_status, *Assert(node.warnings));
1287      ReadNotificationArgs(args, *node.notifications);
1288  
1289      CTxMemPool::Options mempool_opts{
1290          .check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0,
1291          .signals = node.validation_signals.get(),
1292      };
1293      Assert(ApplyArgsManOptions(args, chainparams, mempool_opts)); // no error can happen, already checked in AppInitParameterInteraction
1294      bilingual_str mempool_error;
1295      Assert(!node.mempool); // Was reset above
1296      node.mempool = std::make_unique<CTxMemPool>(mempool_opts, mempool_error);
1297      if (!mempool_error.empty()) {
1298          return {ChainstateLoadStatus::FAILURE_FATAL, mempool_error};
1299      }
1300      LogInfo("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)",
1301              cache_sizes.coins * (1.0 / 1024 / 1024),
1302              mempool_opts.max_size_bytes * (1.0 / 1024 / 1024));
1303      ChainstateManager::Options chainman_opts{
1304          .chainparams = chainparams,
1305          .datadir = args.GetDataDirNet(),
1306          .notifications = *node.notifications,
1307          .signals = node.validation_signals.get(),
1308      };
1309      Assert(ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction
1310  
1311      BlockManager::Options blockman_opts{
1312          .chainparams = chainman_opts.chainparams,
1313          .blocks_dir = args.GetBlocksDirPath(),
1314          .notifications = chainman_opts.notifications,
1315          .block_tree_db_params = DBParams{
1316              .path = args.GetDataDirNet() / "blocks" / "index",
1317              .cache_bytes = cache_sizes.block_tree_db,
1318              .wipe_data = do_reindex,
1319          },
1320      };
1321      Assert(ApplyArgsManOptions(args, blockman_opts)); // no error can happen, already checked in AppInitParameterInteraction
1322  
1323      // Creating the chainstate manager internally creates a BlockManager, opens
1324      // the blocks tree db, and wipes existing block files in case of a reindex.
1325      // The coinsdb is opened at a later point on LoadChainstate.
1326      Assert(!node.chainman); // Was reset above
1327      try {
1328          node.chainman = std::make_unique<ChainstateManager>(*Assert(node.shutdown_signal), chainman_opts, blockman_opts);
1329      } catch (dbwrapper_error& e) {
1330          LogError("%s", e.what());
1331          return {ChainstateLoadStatus::FAILURE, _("Error opening block database")};
1332      } catch (std::exception& e) {
1333          return {ChainstateLoadStatus::FAILURE_FATAL, Untranslated(strprintf("Failed to initialize ChainstateManager: %s", e.what()))};
1334      }
1335      ChainstateManager& chainman = *node.chainman;
1336      if (chainman.m_interrupt) return {ChainstateLoadStatus::INTERRUPTED, {}};
1337  
1338      // This is defined and set here instead of inline in validation.h to avoid a hard
1339      // dependency between validation and index/base, since the latter is not in
1340      // libbitcoinkernel.
1341      chainman.snapshot_download_completed = [&node]() {
1342          if (!node.chainman->m_blockman.IsPruneMode()) {
1343              LogInfo("[snapshot] re-enabling NODE_NETWORK services");
1344              node.connman->AddLocalServices(NODE_NETWORK);
1345          }
1346          LogInfo("[snapshot] restarting indexes");
1347          // Drain the validation interface queue to ensure that the old indexes
1348          // don't have any pending work.
1349          Assert(node.validation_signals)->SyncWithValidationInterfaceQueue();
1350          for (auto* index : node.indexes) {
1351              index->Interrupt();
1352              index->Stop();
1353              if (!(index->Init() && index->StartBackgroundSync())) {
1354                  LogWarning("[snapshot] Failed to restart index %s on snapshot chain", index->GetName());
1355              }
1356          }
1357      };
1358      node::ChainstateLoadOptions options;
1359      options.mempool = Assert(node.mempool.get());
1360      options.wipe_chainstate_db = do_reindex || do_reindex_chainstate;
1361      options.prune = chainman.m_blockman.IsPruneMode();
1362      options.check_blocks = args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
1363      options.check_level = args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
1364      options.require_full_verification = args.IsArgSet("-checkblocks") || args.IsArgSet("-checklevel");
1365      options.coins_error_cb = [] {
1366          uiInterface.ThreadSafeMessageBox(
1367              _("Error reading from database, shutting down."),
1368              "", CClientUIInterface::MSG_ERROR);
1369      };
1370      uiInterface.InitMessage(_("Loading block index…"));
1371      auto catch_exceptions = [](auto&& f) -> ChainstateLoadResult {
1372          try {
1373              return f();
1374          } catch (const std::exception& e) {
1375              LogError("%s\n", e.what());
1376              return std::make_tuple(node::ChainstateLoadStatus::FAILURE, _("Error loading databases"));
1377          }
1378      };
1379      auto [status, error] = catch_exceptions([&] { return LoadChainstate(chainman, cache_sizes, options); });
1380      if (status == node::ChainstateLoadStatus::SUCCESS) {
1381          uiInterface.InitMessage(_("Verifying blocks…"));
1382          if (chainman.m_blockman.m_have_pruned && options.check_blocks > MIN_BLOCKS_TO_KEEP) {
1383              LogWarning("pruned datadir may not have more than %d blocks; only checking available blocks\n",
1384                         MIN_BLOCKS_TO_KEEP);
1385          }
1386          std::tie(status, error) = catch_exceptions([&] { return VerifyLoadedChainstate(chainman, options); });
1387          if (status == node::ChainstateLoadStatus::SUCCESS) {
1388              LogInfo("Block index and chainstate loaded");
1389          }
1390      }
1391      return {status, error};
1392  };
1393  
1394  bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
1395  {
1396      const ArgsManager& args = *Assert(node.args);
1397      const CChainParams& chainparams = Params();
1398  
1399      auto opt_max_upload = ParseByteUnits(args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET), ByteUnit::M);
1400      if (!opt_max_upload) {
1401          return InitError(strprintf(_("Unable to parse -maxuploadtarget: '%s'"), args.GetArg("-maxuploadtarget", "")));
1402      }
1403  
1404      // ********************************************************* Step 4a: application initialization
1405      if (!CreatePidFile(args)) {
1406          // Detailed error printed inside CreatePidFile().
1407          return false;
1408      }
1409      if (!init::StartLogging(args)) {
1410          // Detailed error printed inside StartLogging().
1411          return false;
1412      }
1413  
1414      LogInfo("Using at most %i automatic connections (%i file descriptors available)", nMaxConnections, available_fds);
1415  
1416      // Warn about relative -datadir path.
1417      if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) {
1418          LogWarning("Relative datadir option '%s' specified, which will be interpreted relative to the "
1419                     "current working directory '%s'. This is fragile, because if bitcoin is started in the future "
1420                     "from a different location, it will be unable to locate the current data files. There could "
1421                     "also be data loss if bitcoin is started while in a temporary directory.",
1422                     args.GetArg("-datadir", ""), fs::PathToString(fs::current_path()));
1423      }
1424  
1425      assert(!node.scheduler);
1426      node.scheduler = std::make_unique<CScheduler>();
1427      auto& scheduler = *node.scheduler;
1428  
1429      // Start the lightweight task scheduler thread
1430      scheduler.m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { scheduler.serviceQueue(); });
1431  
1432      // Gather some entropy once per minute.
1433      scheduler.scheduleEvery([]{
1434          RandAddPeriodic();
1435      }, std::chrono::minutes{1});
1436  
1437      // Check disk space every 5 minutes to avoid db corruption.
1438      scheduler.scheduleEvery([&args, &node]{
1439          constexpr uint64_t min_disk_space = 50 << 20; // 50 MB
1440          if (!CheckDiskSpace(args.GetBlocksDirPath(), min_disk_space)) {
1441              LogError("Shutting down due to lack of disk space!\n");
1442              if (!(Assert(node.shutdown_request))()) {
1443                  LogError("Failed to send shutdown signal after disk space check\n");
1444              }
1445          }
1446      }, std::chrono::minutes{5});
1447  
1448      if (args.GetBoolArg("-logratelimit", BCLog::DEFAULT_LOGRATELIMIT)) {
1449          LogInstance().SetRateLimiting(BCLog::LogRateLimiter::Create(
1450              [&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); },
1451              BCLog::RATELIMIT_MAX_BYTES,
1452              BCLog::RATELIMIT_WINDOW));
1453      } else {
1454          LogInfo("Log rate limiting disabled");
1455      }
1456  
1457      assert(!node.validation_signals);
1458      node.validation_signals = std::make_unique<ValidationSignals>(std::make_unique<SerialTaskRunner>(scheduler));
1459      auto& validation_signals = *node.validation_signals;
1460  
1461      // Create client interfaces for wallets that are supposed to be loaded
1462      // according to -wallet and -disablewallet options. This only constructs
1463      // the interfaces, it doesn't load wallet data. Wallets actually get loaded
1464      // when load() and start() interface methods are called below.
1465      g_wallet_init_interface.Construct(node);
1466      uiInterface.InitWallet();
1467  
1468      if (interfaces::Ipc* ipc = node.init->ipc()) {
1469          for (std::string address : gArgs.GetArgs("-ipcbind")) {
1470              try {
1471                  ipc->listenAddress(address);
1472              } catch (const std::exception& e) {
1473                  return InitError(Untranslated(strprintf("Unable to bind to IPC address '%s'. %s", address, e.what())));
1474              }
1475              LogInfo("Listening for IPC requests on address %s", address);
1476          }
1477      }
1478  
1479      /* Register RPC commands regardless of -server setting so they will be
1480       * available in the GUI RPC console even if external calls are disabled.
1481       */
1482      RegisterAllCoreRPCCommands(tableRPC);
1483      for (const auto& client : node.chain_clients) {
1484          client->registerRpcs();
1485      }
1486  #ifdef ENABLE_ZMQ
1487      RegisterZMQRPCCommands(tableRPC);
1488  #endif
1489  
1490      // Check port numbers
1491      if (!CheckHostPortOptions(args)) return false;
1492  
1493      // Configure reachable networks before we start the RPC server.
1494      // This is necessary for -rpcallowip to distinguish CJDNS from other RFC4193
1495      const auto onlynets = args.GetArgs("-onlynet");
1496      if (!onlynets.empty()) {
1497          g_reachable_nets.RemoveAll();
1498          for (const std::string& snet : onlynets) {
1499              enum Network net = ParseNetwork(snet);
1500              if (net == NET_UNROUTABLE)
1501                  return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
1502              g_reachable_nets.Add(net);
1503          }
1504      }
1505  
1506      if (!args.IsArgSet("-cjdnsreachable")) {
1507          if (!onlynets.empty() && g_reachable_nets.Contains(NET_CJDNS)) {
1508              return InitError(
1509                  _("Outbound connections restricted to CJDNS (-onlynet=cjdns) but "
1510                    "-cjdnsreachable is not provided"));
1511          }
1512          g_reachable_nets.Remove(NET_CJDNS);
1513      }
1514      // Now g_reachable_nets.Contains(NET_CJDNS) is true if:
1515      // 1. -cjdnsreachable is given and
1516      // 2.1. -onlynet is not given or
1517      // 2.2. -onlynet=cjdns is given
1518  
1519      /* Start the RPC server already.  It will be started in "warmup" mode
1520       * and not really process calls already (but it will signify connections
1521       * that the server is there and will be ready later).  Warmup mode will
1522       * be disabled when initialisation is finished.
1523       */
1524      if (args.GetBoolArg("-server", false)) {
1525          uiInterface.InitMessage_connect(SetRPCWarmupStatus);
1526          if (!AppInitServers(node))
1527              return InitError(_("Unable to start HTTP server. See debug log for details."));
1528      }
1529  
1530      // ********************************************************* Step 5: verify wallet database integrity
1531      for (const auto& client : node.chain_clients) {
1532          if (!client->verify()) {
1533              return false;
1534          }
1535      }
1536  
1537      // ********************************************************* Step 6: network initialization
1538      // Note that we absolutely cannot open any actual connections
1539      // until the very end ("start node") as the UTXO/block state
1540      // is not yet setup and may end up being set up twice if we
1541      // need to reindex later.
1542  
1543      fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
1544      fDiscover = args.GetBoolArg("-discover", true);
1545  
1546      PeerManager::Options peerman_opts{};
1547      ApplyArgsManOptions(args, peerman_opts);
1548  
1549      {
1550  
1551          // Read asmap file if configured
1552          std::vector<bool> asmap;
1553          if (args.IsArgSet("-asmap") && !args.IsArgNegated("-asmap")) {
1554              fs::path asmap_path = args.GetPathArg("-asmap");
1555              if (asmap_path.empty()) {
1556                  InitError(_("-asmap requires a file path. Use -asmap=<file>."));
1557                  return false;
1558              }
1559              if (!asmap_path.is_absolute()) {
1560                  asmap_path = args.GetDataDirNet() / asmap_path;
1561              }
1562              if (!fs::exists(asmap_path)) {
1563                  InitError(strprintf(_("Could not find asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
1564                  return false;
1565              }
1566              asmap = DecodeAsmap(asmap_path);
1567              if (asmap.size() == 0) {
1568                  InitError(strprintf(_("Could not parse asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
1569                  return false;
1570              }
1571              const uint256 asmap_version = (HashWriter{} << asmap).GetHash();
1572              LogInfo("Using asmap version %s for IP bucketing", asmap_version.ToString());
1573          } else {
1574              LogInfo("Using /16 prefix for IP bucketing");
1575          }
1576  
1577          // Initialize netgroup manager
1578          assert(!node.netgroupman);
1579          node.netgroupman = std::make_unique<NetGroupManager>(std::move(asmap));
1580  
1581          // Initialize addrman
1582          assert(!node.addrman);
1583          uiInterface.InitMessage(_("Loading P2P addresses…"));
1584          auto addrman{LoadAddrman(*node.netgroupman, args)};
1585          if (!addrman) return InitError(util::ErrorString(addrman));
1586          node.addrman = std::move(*addrman);
1587      }
1588  
1589      FastRandomContext rng;
1590      assert(!node.banman);
1591      node.banman = std::make_unique<BanMan>(args.GetDataDirNet() / "banlist", &uiInterface, args.GetIntArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
1592      assert(!node.connman);
1593      node.connman = std::make_unique<CConnman>(rng.rand64(),
1594                                                rng.rand64(),
1595                                                *node.addrman, *node.netgroupman, chainparams, args.GetBoolArg("-networkactive", true));
1596  
1597      assert(!node.fee_estimator);
1598      // Don't initialize fee estimation with old data if we don't relay transactions,
1599      // as they would never get updated.
1600      if (!peerman_opts.ignore_incoming_txs) {
1601          bool read_stale_estimates = args.GetBoolArg("-acceptstalefeeestimates", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES);
1602          if (read_stale_estimates && (chainparams.GetChainType() != ChainType::REGTEST)) {
1603              return InitError(strprintf(_("acceptstalefeeestimates is not supported on %s chain."), chainparams.GetChainTypeString()));
1604          }
1605          node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(args), read_stale_estimates);
1606  
1607          // Flush estimates to disk periodically
1608          CBlockPolicyEstimator* fee_estimator = node.fee_estimator.get();
1609          scheduler.scheduleEvery([fee_estimator] { fee_estimator->FlushFeeEstimates(); }, FEE_FLUSH_INTERVAL);
1610          validation_signals.RegisterValidationInterface(fee_estimator);
1611      }
1612  
1613      for (const std::string& socket_addr : args.GetArgs("-bind")) {
1614          std::string host_out;
1615          uint16_t port_out{0};
1616          std::string bind_socket_addr = socket_addr.substr(0, socket_addr.rfind('='));
1617          if (!SplitHostPort(bind_socket_addr, port_out, host_out)) {
1618              return InitError(InvalidPortErrMsg("-bind", socket_addr));
1619          }
1620      }
1621  
1622      // sanitize comments per BIP-0014, format user agent and check total size
1623      std::vector<std::string> uacomments;
1624      for (const std::string& cmt : args.GetArgs("-uacomment")) {
1625          if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
1626              return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt));
1627          uacomments.push_back(cmt);
1628      }
1629      strSubVersion = FormatSubVersion(UA_NAME, CLIENT_VERSION, uacomments);
1630      if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
1631          return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments."),
1632              strSubVersion.size(), MAX_SUBVERSION_LENGTH));
1633      }
1634  
1635      // Requesting DNS seeds entails connecting to IPv4/IPv6, which -onlynet options may prohibit:
1636      // If -dnsseed=1 is explicitly specified, abort. If it's left unspecified by the user, we skip
1637      // the DNS seeds by adjusting -dnsseed in InitParameterInteraction.
1638      if (args.GetBoolArg("-dnsseed") == true && !g_reachable_nets.Contains(NET_IPV4) && !g_reachable_nets.Contains(NET_IPV6)) {
1639          return InitError(strprintf(_("Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")));
1640      };
1641  
1642      // Check for host lookup allowed before parsing any network related parameters
1643      fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
1644  
1645      bool proxyRandomize = args.GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE);
1646      // -proxy sets a proxy for outgoing network traffic, possibly per network.
1647      // -noproxy, -proxy=0 or -proxy="" can be used to remove the proxy setting, this is the default
1648      Proxy ipv4_proxy;
1649      Proxy ipv6_proxy;
1650      Proxy onion_proxy;
1651      Proxy name_proxy;
1652      Proxy cjdns_proxy;
1653      for (const std::string& param_value : args.GetArgs("-proxy")) {
1654          const auto eq_pos{param_value.rfind('=')};
1655          const std::string proxy_str{param_value.substr(0, eq_pos)}; // e.g. 127.0.0.1:9050=ipv4 -> 127.0.0.1:9050
1656          std::string net_str;
1657          if (eq_pos != std::string::npos) {
1658              if (eq_pos + 1 == param_value.length()) {
1659                  return InitError(strprintf(_("Invalid -proxy address or hostname, ends with '=': '%s'"), param_value));
1660              }
1661              net_str = ToLower(param_value.substr(eq_pos + 1)); // e.g. 127.0.0.1:9050=ipv4 -> ipv4
1662          }
1663  
1664          Proxy proxy;
1665          if (!proxy_str.empty() && proxy_str != "0") {
1666              if (IsUnixSocketPath(proxy_str)) {
1667                  proxy = Proxy{proxy_str, /*tor_stream_isolation=*/proxyRandomize};
1668              } else {
1669                  const std::optional<CService> addr{Lookup(proxy_str, DEFAULT_TOR_SOCKS_PORT, fNameLookup)};
1670                  if (!addr.has_value()) {
1671                      return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxy_str));
1672                  }
1673                  proxy = Proxy{addr.value(), /*tor_stream_isolation=*/proxyRandomize};
1674              }
1675              if (!proxy.IsValid()) {
1676                  return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxy_str));
1677              }
1678          }
1679  
1680          if (net_str.empty()) { // For all networks.
1681              ipv4_proxy = ipv6_proxy = name_proxy = cjdns_proxy = onion_proxy = proxy;
1682          } else if (net_str == "ipv4") {
1683              ipv4_proxy = name_proxy = proxy;
1684          } else if (net_str == "ipv6") {
1685              ipv6_proxy = name_proxy = proxy;
1686          } else if (net_str == "tor" || net_str == "onion") {
1687              onion_proxy = proxy;
1688          } else if (net_str == "cjdns") {
1689              cjdns_proxy = proxy;
1690          } else {
1691              return InitError(strprintf(_("Unrecognized network in -proxy='%s': '%s'"), param_value, net_str));
1692          }
1693      }
1694      if (ipv4_proxy.IsValid()) {
1695          SetProxy(NET_IPV4, ipv4_proxy);
1696      }
1697      if (ipv6_proxy.IsValid()) {
1698          SetProxy(NET_IPV6, ipv6_proxy);
1699      }
1700      if (name_proxy.IsValid()) {
1701          SetNameProxy(name_proxy);
1702      }
1703      if (cjdns_proxy.IsValid()) {
1704          SetProxy(NET_CJDNS, cjdns_proxy);
1705      }
1706  
1707      const bool onlynet_used_with_onion{!onlynets.empty() && g_reachable_nets.Contains(NET_ONION)};
1708  
1709      // -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
1710      // -noonion (or -onion=0) disables connecting to .onion entirely
1711      // An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none)
1712      std::string onionArg = args.GetArg("-onion", "");
1713      if (onionArg != "") {
1714          if (onionArg == "0") { // Handle -noonion/-onion=0
1715              onion_proxy = Proxy{};
1716              if (onlynet_used_with_onion) {
1717                  return InitError(
1718                      _("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
1719                        "reaching the Tor network is explicitly forbidden: -onion=0"));
1720              }
1721          } else {
1722              if (IsUnixSocketPath(onionArg)) {
1723                  onion_proxy = Proxy(onionArg, /*tor_stream_isolation=*/proxyRandomize);
1724              } else {
1725                  const std::optional<CService> addr{Lookup(onionArg, DEFAULT_TOR_SOCKS_PORT, fNameLookup)};
1726                  if (!addr.has_value() || !addr->IsValid()) {
1727                      return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
1728                  }
1729  
1730                  onion_proxy = Proxy(addr.value(), /*tor_stream_isolation=*/proxyRandomize);
1731              }
1732          }
1733      }
1734  
1735      if (onion_proxy.IsValid()) {
1736          SetProxy(NET_ONION, onion_proxy);
1737      } else {
1738          // If -listenonion is set, then we will (try to) connect to the Tor control port
1739          // later from the torcontrol thread and may retrieve the onion proxy from there.
1740          const bool listenonion_disabled{!args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)};
1741          if (onlynet_used_with_onion && listenonion_disabled) {
1742              return InitError(
1743                  _("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
1744                    "reaching the Tor network is not provided: none of -proxy, -onion or "
1745                    "-listenonion is given"));
1746          }
1747          g_reachable_nets.Remove(NET_ONION);
1748      }
1749  
1750      for (const std::string& strAddr : args.GetArgs("-externalip")) {
1751          const std::optional<CService> addrLocal{Lookup(strAddr, GetListenPort(), fNameLookup)};
1752          if (addrLocal.has_value() && addrLocal->IsValid())
1753              AddLocal(addrLocal.value(), LOCAL_MANUAL);
1754          else
1755              return InitError(ResolveErrMsg("externalip", strAddr));
1756      }
1757  
1758  #ifdef ENABLE_ZMQ
1759      g_zmq_notification_interface = CZMQNotificationInterface::Create(
1760          [&chainman = node.chainman](std::vector<std::byte>& block, const CBlockIndex& index) {
1761              assert(chainman);
1762              return chainman->m_blockman.ReadRawBlock(block, WITH_LOCK(cs_main, return index.GetBlockPos()));
1763          });
1764  
1765      if (g_zmq_notification_interface) {
1766          validation_signals.RegisterValidationInterface(g_zmq_notification_interface.get());
1767      }
1768  #endif
1769  
1770      // ********************************************************* Step 7: load block chain
1771  
1772      // cache size calculations
1773      node::LogOversizedDbCache(args);
1774      const auto [index_cache_sizes, kernel_cache_sizes] = CalculateCacheSizes(args, g_enabled_filter_types.size());
1775  
1776      LogInfo("Cache configuration:");
1777      LogInfo("* Using %.1f MiB for block index database", kernel_cache_sizes.block_tree_db * (1.0 / 1024 / 1024));
1778      if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
1779          LogInfo("* Using %.1f MiB for transaction index database", index_cache_sizes.tx_index * (1.0 / 1024 / 1024));
1780      }
1781      for (BlockFilterType filter_type : g_enabled_filter_types) {
1782          LogInfo("* Using %.1f MiB for %s block filter index database",
1783                    index_cache_sizes.filter_index * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type));
1784      }
1785      LogInfo("* Using %.1f MiB for chain state database", kernel_cache_sizes.coins_db * (1.0 / 1024 / 1024));
1786  
1787      assert(!node.mempool);
1788      assert(!node.chainman);
1789  
1790      bool do_reindex{args.GetBoolArg("-reindex", false)};
1791      const bool do_reindex_chainstate{args.GetBoolArg("-reindex-chainstate", false)};
1792  
1793      // Chainstate initialization and loading may be retried once with reindexing by GUI users
1794      auto [status, error] = InitAndLoadChainstate(
1795          node,
1796          do_reindex,
1797          do_reindex_chainstate,
1798          kernel_cache_sizes,
1799          args);
1800      if (status == ChainstateLoadStatus::FAILURE && !do_reindex && !ShutdownRequested(node)) {
1801          // suggest a reindex
1802          bool do_retry{HasTestOption(args, "reindex_after_failure_noninteractive_yes") ||
1803              uiInterface.ThreadSafeQuestion(
1804              error + Untranslated(".\n\n") + _("Do you want to rebuild the databases now?"),
1805              error.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.",
1806              "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT)};
1807          if (!do_retry) {
1808              return false;
1809          }
1810          do_reindex = true;
1811          if (!Assert(node.shutdown_signal)->reset()) {
1812              LogError("Internal error: failed to reset shutdown signal.\n");
1813          }
1814          std::tie(status, error) = InitAndLoadChainstate(
1815              node,
1816              do_reindex,
1817              do_reindex_chainstate,
1818              kernel_cache_sizes,
1819              args);
1820      }
1821      if (status != ChainstateLoadStatus::SUCCESS && status != ChainstateLoadStatus::INTERRUPTED) {
1822          return InitError(error);
1823      }
1824  
1825      // As LoadBlockIndex can take several minutes, it's possible the user
1826      // requested to kill the GUI during the last operation. If so, exit.
1827      if (ShutdownRequested(node)) {
1828          LogInfo("Shutdown requested. Exiting.");
1829          return false;
1830      }
1831  
1832      ChainstateManager& chainman = *Assert(node.chainman);
1833      auto& kernel_notifications{*Assert(node.notifications)};
1834  
1835      assert(!node.peerman);
1836      node.peerman = PeerManager::make(*node.connman, *node.addrman,
1837                                       node.banman.get(), chainman,
1838                                       *node.mempool, *node.warnings,
1839                                       peerman_opts);
1840      validation_signals.RegisterValidationInterface(node.peerman.get());
1841  
1842      // ********************************************************* Step 8: start indexers
1843  
1844      if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
1845          g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), index_cache_sizes.tx_index, false, do_reindex);
1846          node.indexes.emplace_back(g_txindex.get());
1847      }
1848  
1849      for (const auto& filter_type : g_enabled_filter_types) {
1850          InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, index_cache_sizes.filter_index, false, do_reindex);
1851          node.indexes.emplace_back(GetBlockFilterIndex(filter_type));
1852      }
1853  
1854      if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {
1855          g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /*cache_size=*/0, false, do_reindex);
1856          node.indexes.emplace_back(g_coin_stats_index.get());
1857      }
1858  
1859      // Init indexes
1860      for (auto index : node.indexes) if (!index->Init()) return false;
1861  
1862      // ********************************************************* Step 9: load wallet
1863      for (const auto& client : node.chain_clients) {
1864          if (!client->load()) {
1865              return false;
1866          }
1867      }
1868  
1869      // ********************************************************* Step 10: data directory maintenance
1870  
1871      // if pruning, perform the initial blockstore prune
1872      // after any wallet rescanning has taken place.
1873      if (chainman.m_blockman.IsPruneMode()) {
1874          if (chainman.m_blockman.m_blockfiles_indexed) {
1875              LOCK(cs_main);
1876              for (Chainstate* chainstate : chainman.GetAll()) {
1877                  uiInterface.InitMessage(_("Pruning blockstore…"));
1878                  chainstate->PruneAndFlush();
1879              }
1880          }
1881      } else {
1882          // Prior to setting NODE_NETWORK, check if we can provide historical blocks.
1883          if (!WITH_LOCK(chainman.GetMutex(), return chainman.BackgroundSyncInProgress())) {
1884              LogInfo("Setting NODE_NETWORK in non-prune mode");
1885              g_local_services = ServiceFlags(g_local_services | NODE_NETWORK);
1886          } else {
1887              LogInfo("Running node in NODE_NETWORK_LIMITED mode until snapshot background sync completes");
1888          }
1889      }
1890  
1891      // ********************************************************* Step 11: import blocks
1892  
1893      if (!CheckDiskSpace(args.GetDataDirNet())) {
1894          InitError(strprintf(_("Error: Disk space is low for %s"), fs::quoted(fs::PathToString(args.GetDataDirNet()))));
1895          return false;
1896      }
1897      if (!CheckDiskSpace(args.GetBlocksDirPath())) {
1898          InitError(strprintf(_("Error: Disk space is low for %s"), fs::quoted(fs::PathToString(args.GetBlocksDirPath()))));
1899          return false;
1900      }
1901  
1902      int chain_active_height = WITH_LOCK(cs_main, return chainman.ActiveChain().Height());
1903  
1904      // On first startup, warn on low block storage space
1905      if (!do_reindex && !do_reindex_chainstate && chain_active_height <= 1) {
1906          uint64_t assumed_chain_bytes{chainparams.AssumedBlockchainSize() * 1024 * 1024 * 1024};
1907          uint64_t additional_bytes_needed{
1908              chainman.m_blockman.IsPruneMode() ?
1909                  std::min(chainman.m_blockman.GetPruneTarget(), assumed_chain_bytes) :
1910                  assumed_chain_bytes};
1911  
1912          if (!CheckDiskSpace(args.GetBlocksDirPath(), additional_bytes_needed)) {
1913              InitWarning(strprintf(_(
1914                      "Disk space for %s may not accommodate the block files. " \
1915                      "Approximately %u GB of data will be stored in this directory."
1916                  ),
1917                  fs::quoted(fs::PathToString(args.GetBlocksDirPath())),
1918                  chainparams.AssumedBlockchainSize()
1919              ));
1920          }
1921      }
1922  
1923  #ifdef __APPLE__
1924      auto check_and_warn_fs{[&](const fs::path& path, std::string_view desc) {
1925          const auto path_desc{strprintf("%s (\"%s\")", desc, fs::PathToString(path))};
1926          switch (GetFilesystemType(path)) {
1927          case FSType::EXFAT:
1928              InitWarning(strprintf(_("The %s path uses exFAT, which is known to have intermittent corruption problems on macOS. "
1929                  "Move this directory to a different filesystem to avoid data loss."), path_desc));
1930              break;
1931          case FSType::ERROR:
1932              LogInfo("Failed to detect filesystem type for %s", path_desc);
1933              break;
1934          case FSType::OTHER:
1935              break;
1936          }
1937      }};
1938  
1939      check_and_warn_fs(args.GetDataDirNet(), "data directory");
1940      check_and_warn_fs(args.GetBlocksDirPath(), "blocks directory");
1941  #endif
1942  
1943  #if HAVE_SYSTEM
1944      const std::string block_notify = args.GetArg("-blocknotify", "");
1945      if (!block_notify.empty()) {
1946          uiInterface.NotifyBlockTip_connect([block_notify](SynchronizationState sync_state, const CBlockIndex& block, double /* verification_progress */) {
1947              if (sync_state != SynchronizationState::POST_INIT) return;
1948              std::string command = block_notify;
1949              ReplaceAll(command, "%s", block.GetBlockHash().GetHex());
1950              std::thread t(runCommand, command);
1951              t.detach(); // thread runs free
1952          });
1953      }
1954  #endif
1955  
1956      std::vector<fs::path> vImportFiles;
1957      for (const std::string& strFile : args.GetArgs("-loadblock")) {
1958          vImportFiles.push_back(fs::PathFromString(strFile));
1959      }
1960  
1961      node.background_init_thread = std::thread(&util::TraceThread, "initload", [=, &chainman, &args, &node] {
1962          ScheduleBatchPriority();
1963          // Import blocks and ActivateBestChain()
1964          ImportBlocks(chainman, vImportFiles);
1965          if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) {
1966              LogInfo("Stopping after block import");
1967              if (!(Assert(node.shutdown_request))()) {
1968                  LogError("Failed to send shutdown signal after finishing block import\n");
1969              }
1970              return;
1971          }
1972  
1973          // Start indexes initial sync
1974          if (!StartIndexBackgroundSync(node)) {
1975              bilingual_str err_str = _("Failed to start indexes, shutting down…");
1976              chainman.GetNotifications().fatalError(err_str);
1977              return;
1978          }
1979          // Load mempool from disk
1980          if (auto* pool{chainman.ActiveChainstate().GetMempool()}) {
1981              LoadMempool(*pool, ShouldPersistMempool(args) ? MempoolPath(args) : fs::path{}, chainman.ActiveChainstate(), {});
1982              pool->SetLoadTried(!chainman.m_interrupt);
1983          }
1984      });
1985  
1986      /*
1987       * Wait for genesis block to be processed. Typically kernel_notifications.m_tip_block
1988       * has already been set by a call to LoadChainTip() in CompleteChainstateInitialization().
1989       * But this is skipped if the chainstate doesn't exist yet or is being wiped:
1990       *
1991       * 1. first startup with an empty datadir
1992       * 2. reindex
1993       * 3. reindex-chainstate
1994       *
1995       * In these case it's connected by a call to ActivateBestChain() in the initload thread.
1996       */
1997      {
1998          WAIT_LOCK(kernel_notifications.m_tip_block_mutex, lock);
1999          kernel_notifications.m_tip_block_cv.wait(lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(kernel_notifications.m_tip_block_mutex) {
2000              return kernel_notifications.TipBlock() || ShutdownRequested(node);
2001          });
2002      }
2003  
2004      if (ShutdownRequested(node)) {
2005          return false;
2006      }
2007  
2008      // ********************************************************* Step 12: start node
2009  
2010      int64_t best_block_time{};
2011      {
2012          LOCK(chainman.GetMutex());
2013          const auto& tip{*Assert(chainman.ActiveTip())};
2014          LogInfo("block tree size = %u", chainman.BlockIndex().size());
2015          chain_active_height = tip.nHeight;
2016          best_block_time = tip.GetBlockTime();
2017          if (tip_info) {
2018              tip_info->block_height = chain_active_height;
2019              tip_info->block_time = best_block_time;
2020              tip_info->verification_progress = chainman.GuessVerificationProgress(&tip);
2021          }
2022          if (tip_info && chainman.m_best_header) {
2023              tip_info->header_height = chainman.m_best_header->nHeight;
2024              tip_info->header_time = chainman.m_best_header->GetBlockTime();
2025          }
2026      }
2027      LogInfo("nBestHeight = %d", chain_active_height);
2028      if (node.peerman) node.peerman->SetBestBlock(chain_active_height, std::chrono::seconds{best_block_time});
2029  
2030      // Map ports with NAT-PMP
2031      StartMapPort(args.GetBoolArg("-natpmp", DEFAULT_NATPMP));
2032  
2033      CConnman::Options connOptions;
2034      connOptions.m_local_services = g_local_services;
2035      connOptions.m_max_automatic_connections = nMaxConnections;
2036      connOptions.uiInterface = &uiInterface;
2037      connOptions.m_banman = node.banman.get();
2038      connOptions.m_msgproc = node.peerman.get();
2039      connOptions.nSendBufferMaxSize = 1000 * args.GetIntArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
2040      connOptions.nReceiveFloodSize = 1000 * args.GetIntArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
2041      connOptions.m_added_nodes = args.GetArgs("-addnode");
2042      connOptions.nMaxOutboundLimit = *opt_max_upload;
2043      connOptions.m_peer_connect_timeout = peer_connect_timeout;
2044      connOptions.whitelist_forcerelay = args.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY);
2045      connOptions.whitelist_relay = args.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY);
2046  
2047      // Port to bind to if `-bind=addr` is provided without a `:port` suffix.
2048      const uint16_t default_bind_port =
2049          static_cast<uint16_t>(args.GetIntArg("-port", Params().GetDefaultPort()));
2050  
2051      const uint16_t default_bind_port_onion = default_bind_port + 1;
2052  
2053      const auto BadPortWarning = [](const char* prefix, uint16_t port) {
2054          return strprintf(_("%s request to listen on port %u. This port is considered \"bad\" and "
2055                             "thus it is unlikely that any peer will connect to it. See "
2056                             "doc/p2p-bad-ports.md for details and a full list."),
2057                           prefix,
2058                           port);
2059      };
2060  
2061      for (const std::string& bind_arg : args.GetArgs("-bind")) {
2062          std::optional<CService> bind_addr;
2063          const size_t index = bind_arg.rfind('=');
2064          if (index == std::string::npos) {
2065              bind_addr = Lookup(bind_arg, default_bind_port, /*fAllowLookup=*/false);
2066              if (bind_addr.has_value()) {
2067                  connOptions.vBinds.push_back(bind_addr.value());
2068                  if (IsBadPort(bind_addr.value().GetPort())) {
2069                      InitWarning(BadPortWarning("-bind", bind_addr.value().GetPort()));
2070                  }
2071                  continue;
2072              }
2073          } else {
2074              const std::string network_type = bind_arg.substr(index + 1);
2075              if (network_type == "onion") {
2076                  const std::string truncated_bind_arg = bind_arg.substr(0, index);
2077                  bind_addr = Lookup(truncated_bind_arg, default_bind_port_onion, false);
2078                  if (bind_addr.has_value()) {
2079                      connOptions.onion_binds.push_back(bind_addr.value());
2080                      continue;
2081                  }
2082              }
2083          }
2084          return InitError(ResolveErrMsg("bind", bind_arg));
2085      }
2086  
2087      for (const std::string& strBind : args.GetArgs("-whitebind")) {
2088          NetWhitebindPermissions whitebind;
2089          bilingual_str error;
2090          if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) return InitError(error);
2091          connOptions.vWhiteBinds.push_back(whitebind);
2092      }
2093  
2094      // If the user did not specify -bind= or -whitebind= then we bind
2095      // on any address - 0.0.0.0 (IPv4) and :: (IPv6).
2096      connOptions.bind_on_any = args.GetArgs("-bind").empty() && args.GetArgs("-whitebind").empty();
2097  
2098      // Emit a warning if a bad port is given to -port= but only if -bind and -whitebind are not
2099      // given, because if they are, then -port= is ignored.
2100      if (connOptions.bind_on_any && args.IsArgSet("-port")) {
2101          const uint16_t port_arg = args.GetIntArg("-port", 0);
2102          if (IsBadPort(port_arg)) {
2103              InitWarning(BadPortWarning("-port", port_arg));
2104          }
2105      }
2106  
2107      CService onion_service_target;
2108      if (!connOptions.onion_binds.empty()) {
2109          onion_service_target = connOptions.onion_binds.front();
2110      } else if (!connOptions.vBinds.empty()) {
2111          onion_service_target = connOptions.vBinds.front();
2112      } else {
2113          onion_service_target = DefaultOnionServiceTarget(default_bind_port_onion);
2114          connOptions.onion_binds.push_back(onion_service_target);
2115      }
2116  
2117      if (args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) {
2118          if (connOptions.onion_binds.size() > 1) {
2119              InitWarning(strprintf(_("More than one onion bind address is provided. Using %s "
2120                                      "for the automatically created Tor onion service."),
2121                                    onion_service_target.ToStringAddrPort()));
2122          }
2123          StartTorControl(onion_service_target);
2124      }
2125  
2126      if (connOptions.bind_on_any) {
2127          // Only add all IP addresses of the machine if we would be listening on
2128          // any address - 0.0.0.0 (IPv4) and :: (IPv6).
2129          Discover();
2130      }
2131  
2132      for (const auto& net : args.GetArgs("-whitelist")) {
2133          NetWhitelistPermissions subnet;
2134          ConnectionDirection connection_direction;
2135          bilingual_str error;
2136          if (!NetWhitelistPermissions::TryParse(net, subnet, connection_direction, error)) return InitError(error);
2137          if (connection_direction & ConnectionDirection::In) {
2138              connOptions.vWhitelistedRangeIncoming.push_back(subnet);
2139          }
2140          if (connection_direction & ConnectionDirection::Out) {
2141              connOptions.vWhitelistedRangeOutgoing.push_back(subnet);
2142          }
2143      }
2144  
2145      connOptions.vSeedNodes = args.GetArgs("-seednode");
2146  
2147      const auto connect = args.GetArgs("-connect");
2148      if (!connect.empty() || args.IsArgNegated("-connect")) {
2149          // Do not initiate other outgoing connections when connecting to trusted
2150          // nodes, or when -noconnect is specified.
2151          connOptions.m_use_addrman_outgoing = false;
2152  
2153          if (connect.size() != 1 || connect[0] != "0") {
2154              connOptions.m_specified_outgoing = connect;
2155          }
2156          if (!connOptions.m_specified_outgoing.empty() && !connOptions.vSeedNodes.empty()) {
2157              LogInfo("-seednode is ignored when -connect is used");
2158          }
2159  
2160          if (args.IsArgSet("-dnsseed") && args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED) && args.IsArgSet("-proxy")) {
2161              LogInfo("-dnsseed is ignored when -connect is used and -proxy is specified");
2162          }
2163      }
2164  
2165      const std::string& i2psam_arg = args.GetArg("-i2psam", "");
2166      if (!i2psam_arg.empty()) {
2167          const std::optional<CService> addr{Lookup(i2psam_arg, 7656, fNameLookup)};
2168          if (!addr.has_value() || !addr->IsValid()) {
2169              return InitError(strprintf(_("Invalid -i2psam address or hostname: '%s'"), i2psam_arg));
2170          }
2171          SetProxy(NET_I2P, Proxy{addr.value()});
2172      } else {
2173          if (!onlynets.empty() && g_reachable_nets.Contains(NET_I2P)) {
2174              return InitError(
2175                  _("Outbound connections restricted to i2p (-onlynet=i2p) but "
2176                    "-i2psam is not provided"));
2177          }
2178          g_reachable_nets.Remove(NET_I2P);
2179      }
2180  
2181      connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", DEFAULT_I2P_ACCEPT_INCOMING);
2182  
2183      if (auto conflict = CheckBindingConflicts(connOptions)) {
2184          return InitError(strprintf(
2185              _("Duplicate binding configuration for address %s. "
2186                  "Please check your -bind, -bind=...=onion and -whitebind settings."),
2187                      conflict->ToStringAddrPort()));
2188      }
2189  
2190      if (!node.connman->Start(scheduler, connOptions)) {
2191          return false;
2192      }
2193  
2194      // ********************************************************* Step 13: finished
2195  
2196      // At this point, the RPC is "started", but still in warmup, which means it
2197      // cannot yet be called. Before we make it callable, we need to make sure
2198      // that the RPC's view of the best block is valid and consistent with
2199      // ChainstateManager's active tip.
2200      SetRPCWarmupFinished();
2201  
2202      uiInterface.InitMessage(_("Done loading"));
2203  
2204      for (const auto& client : node.chain_clients) {
2205          client->start(scheduler);
2206      }
2207  
2208      BanMan* banman = node.banman.get();
2209      scheduler.scheduleEvery([banman]{
2210          banman->DumpBanlist();
2211      }, DUMP_BANS_INTERVAL);
2212  
2213      if (node.peerman) node.peerman->StartScheduledTasks(scheduler);
2214  
2215  #if HAVE_SYSTEM
2216      StartupNotify(args);
2217  #endif
2218  
2219      return true;
2220  }
2221  
2222  bool StartIndexBackgroundSync(NodeContext& node)
2223  {
2224      // Find the oldest block among all indexes.
2225      // This block is used to verify that we have the required blocks' data stored on disk,
2226      // starting from that point up to the current tip.
2227      // indexes_start_block='nullptr' means "start from height 0".
2228      std::optional<const CBlockIndex*> indexes_start_block;
2229      std::string older_index_name;
2230      ChainstateManager& chainman = *Assert(node.chainman);
2231      const Chainstate& chainstate = WITH_LOCK(::cs_main, return chainman.GetChainstateForIndexing());
2232      const CChain& index_chain = chainstate.m_chain;
2233  
2234      for (auto index : node.indexes) {
2235          const IndexSummary& summary = index->GetSummary();
2236          if (summary.synced) continue;
2237  
2238          // Get the last common block between the index best block and the active chain
2239          LOCK(::cs_main);
2240          const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(summary.best_block_hash);
2241          if (!index_chain.Contains(pindex)) {
2242              pindex = index_chain.FindFork(pindex);
2243          }
2244  
2245          if (!indexes_start_block || !pindex || pindex->nHeight < indexes_start_block.value()->nHeight) {
2246              indexes_start_block = pindex;
2247              older_index_name = summary.name;
2248              if (!pindex) break; // Starting from genesis so no need to look for earlier block.
2249          }
2250      };
2251  
2252      // Verify all blocks needed to sync to current tip are present.
2253      if (indexes_start_block) {
2254          LOCK(::cs_main);
2255          const CBlockIndex* start_block = *indexes_start_block;
2256          if (!start_block) start_block = chainman.ActiveChain().Genesis();
2257          if (!chainman.m_blockman.CheckBlockDataAvailability(*index_chain.Tip(), *Assert(start_block))) {
2258              return InitError(Untranslated(strprintf("%s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)", older_index_name)));
2259          }
2260      }
2261  
2262      // Start threads
2263      for (auto index : node.indexes) if (!index->StartBackgroundSync()) return false;
2264      return true;
2265  }