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