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