LCOV - code coverage report
Current view: top level - src - init.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 352 1653 21.3 %
Date: 2020-06-05 16:23:38 Functions: 4 38 10.5 %
Legend: Lines: hit, modifiedhit, not modified not hit, modifiednot hit, not modified

          Line data    Source code
#       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
#       2             : // Copyright (c) 2009-2020 The Bitcoin Core developers
#       3             : // Distributed under the MIT software license, see the accompanying
#       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       5             : 
#       6             : #if defined(HAVE_CONFIG_H)
#       7             : #include <config/bitcoin-config.h>
#       8             : #endif
#       9             : 
#      10             : #include <init.h>
#      11             : 
#      12             : #include <addrman.h>
#      13             : #include <amount.h>
#      14             : #include <banman.h>
#      15             : #include <blockfilter.h>
#      16             : #include <chain.h>
#      17             : #include <chainparams.h>
#      18             : #include <compat/sanity.h>
#      19             : #include <consensus/validation.h>
#      20             : #include <fs.h>
#      21             : #include <httprpc.h>
#      22             : #include <httpserver.h>
#      23             : #include <index/blockfilterindex.h>
#      24             : #include <index/txindex.h>
#      25             : #include <interfaces/chain.h>
#      26             : #include <key.h>
#      27             : #include <miner.h>
#      28             : #include <net.h>
#      29             : #include <net_permissions.h>
#      30             : #include <net_processing.h>
#      31             : #include <netbase.h>
#      32             : #include <node/context.h>
#      33             : #include <policy/feerate.h>
#      34             : #include <policy/fees.h>
#      35             : #include <policy/policy.h>
#      36             : #include <policy/settings.h>
#      37             : #include <rpc/blockchain.h>
#      38             : #include <rpc/register.h>
#      39             : #include <rpc/server.h>
#      40             : #include <rpc/util.h>
#      41             : #include <scheduler.h>
#      42             : #include <script/sigcache.h>
#      43             : #include <script/standard.h>
#      44             : #include <shutdown.h>
#      45             : #include <timedata.h>
#      46             : #include <torcontrol.h>
#      47             : #include <txdb.h>
#      48             : #include <txmempool.h>
#      49             : #include <ui_interface.h>
#      50             : #include <util/asmap.h>
#      51             : #include <util/moneystr.h>
#      52             : #include <util/system.h>
#      53             : #include <util/threadnames.h>
#      54             : #include <util/translation.h>
#      55             : #include <validation.h>
#      56             : #include <hash.h>
#      57             : 
#      58             : 
#      59             : #include <validationinterface.h>
#      60             : #include <walletinitinterface.h>
#      61             : 
#      62             : #include <functional>
#      63             : #include <set>
#      64             : #include <stdint.h>
#      65             : #include <stdio.h>
#      66             : 
#      67             : #ifndef WIN32
#      68             : #include <attributes.h>
#      69             : #include <cerrno>
#      70             : #include <signal.h>
#      71             : #include <sys/stat.h>
#      72             : #endif
#      73             : 
#      74             : #include <boost/algorithm/string/classification.hpp>
#      75             : #include <boost/algorithm/string/replace.hpp>
#      76             : #include <boost/algorithm/string/split.hpp>
#      77             : #include <boost/signals2/signal.hpp>
#      78             : #include <boost/thread.hpp>
#      79             : 
#      80             : #if ENABLE_ZMQ
#      81             : #include <zmq/zmqabstractnotifier.h>
#      82             : #include <zmq/zmqnotificationinterface.h>
#      83             : #include <zmq/zmqrpc.h>
#      84             : #endif
#      85             : 
#      86             : static bool fFeeEstimatesInitialized = false;
#      87             : static const bool DEFAULT_PROXYRANDOMIZE = true;
#      88             : static const bool DEFAULT_REST_ENABLE = false;
#      89             : static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
#      90             : 
#      91             : #ifdef WIN32
#      92             : // Win32 LevelDB doesn't use filedescriptors, and the ones used for
#      93             : // accessing block files don't count towards the fd_set size limit
#      94             : // anyway.
#      95             : #define MIN_CORE_FILEDESCRIPTORS 0
#      96             : #else
#      97        3012 : #define MIN_CORE_FILEDESCRIPTORS 150
#      98             : #endif
#      99             : 
#     100             : static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
#     101             : 
#     102             : static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map";
#     103             : 
#     104             : /**
#     105             :  * The PID file facilities.
#     106             :  */
#     107             : static const char* BITCOIN_PID_FILENAME = "bitcoind.pid";
#     108             : 
#     109             : static fs::path GetPidFile()
#     110           0 : {
#     111           0 :     return AbsPathForConfigVal(fs::path(gArgs.GetArg("-pid", BITCOIN_PID_FILENAME)));
#     112           0 : }
#     113             : 
#     114             : NODISCARD static bool CreatePidFile()
#     115           0 : {
#     116           0 :     fsbridge::ofstream file{GetPidFile()};
#     117           0 :     if (file) {
#     118             : #ifdef WIN32
#     119             :         tfm::format(file, "%d\n", GetCurrentProcessId());
#     120             : #else
#     121             :         tfm::format(file, "%d\n", getpid());
#     122           0 : #endif
#     123           0 :         return true;
#     124           0 :     } else {
#     125           0 :         return InitError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile().string(), std::strerror(errno)));
#     126           0 :     }
#     127           0 : }
#     128             : 
#     129             : //////////////////////////////////////////////////////////////////////////////
#     130             : //
#     131             : // Shutdown
#     132             : //
#     133             : 
#     134             : //
#     135             : // Thread management and startup/shutdown:
#     136             : //
#     137             : // The network-processing threads are all part of a thread group
#     138             : // created by AppInit() or the Qt main() function.
#     139             : //
#     140             : // A clean exit happens when StartShutdown() or the SIGTERM
#     141             : // signal handler sets ShutdownRequested(), which makes main thread's
#     142             : // WaitForShutdown() interrupts the thread group.
#     143             : // And then, WaitForShutdown() makes all other on-going threads
#     144             : // in the thread group join the main thread.
#     145             : // Shutdown() is then called to clean up database connections, and stop other
#     146             : // threads that should only be stopped after the main network-processing
#     147             : // threads have exited.
#     148             : //
#     149             : // Shutdown for Qt is very similar, only it uses a QTimer to detect
#     150             : // ShutdownRequested() getting set, and then does the normal Qt
#     151             : // shutdown thing.
#     152             : //
#     153             : 
#     154             : static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
#     155             : 
#     156             : static boost::thread_group threadGroup;
#     157             : 
#     158             : void Interrupt(NodeContext& node)
#     159           0 : {
#     160           0 :     InterruptHTTPServer();
#     161           0 :     InterruptHTTPRPC();
#     162           0 :     InterruptRPC();
#     163           0 :     InterruptREST();
#     164           0 :     InterruptTorControl();
#     165           0 :     InterruptMapPort();
#     166           0 :     if (node.connman)
#     167           0 :         node.connman->Interrupt();
#     168           0 :     if (g_txindex) {
#     169           0 :         g_txindex->Interrupt();
#     170           0 :     }
#     171           0 :     ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Interrupt(); });
#     172           0 : }
#     173             : 
#     174             : void Shutdown(NodeContext& node)
#     175           0 : {
#     176           0 :     LogPrintf("%s: In progress...\n", __func__);
#     177           0 :     static RecursiveMutex cs_Shutdown;
#     178           0 :     TRY_LOCK(cs_Shutdown, lockShutdown);
#     179           0 :     if (!lockShutdown)
#     180           0 :         return;
#     181           0 : 
#     182           0 :     /// Note: Shutdown() must be able to handle cases in which initialization failed part of the way,
#     183           0 :     /// for example if the data directory was found to be locked.
#     184           0 :     /// Be sure that anything that writes files or flushes caches only does this if the respective
#     185           0 :     /// module was initialized.
#     186           0 :     util::ThreadRename("shutoff");
#     187           0 :     mempool.AddTransactionsUpdated(1);
#     188           0 : 
#     189           0 :     StopHTTPRPC();
#     190           0 :     StopREST();
#     191           0 :     StopRPC();
#     192           0 :     StopHTTPServer();
#     193           0 :     for (const auto& client : node.chain_clients) {
#     194           0 :         client->flush();
#     195           0 :     }
#     196           0 :     StopMapPort();
#     197           0 : 
#     198           0 :     // Because these depend on each-other, we make sure that neither can be
#     199           0 :     // using the other before destroying them.
#     200           0 :     if (node.peer_logic) UnregisterValidationInterface(node.peer_logic.get());
#     201           0 :     // Follow the lock order requirements:
#     202           0 :     // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount
#     203           0 :     //   which locks cs_vNodes.
#     204           0 :     // * ProcessMessage locks cs_main and g_cs_orphans before indirectly calling ForEachNode which
#     205           0 :     //   locks cs_vNodes.
#     206           0 :     // * CConnman::Stop calls DeleteNode, which calls FinalizeNode, which locks cs_main and calls
#     207           0 :     //   EraseOrphansFor, which locks g_cs_orphans.
#     208           0 :     //
#     209           0 :     // Thus the implicit locking order requirement is: (1) cs_main, (2) g_cs_orphans, (3) cs_vNodes.
#     210           0 :     if (node.connman) {
#     211           0 :         node.connman->StopThreads();
#     212           0 :         LOCK2(::cs_main, ::g_cs_orphans);
#     213           0 :         node.connman->StopNodes();
#     214           0 :     }
#     215           0 : 
#     216           0 :     StopTorControl();
#     217           0 : 
#     218           0 :     // After everything has been shut down, but before things get flushed, stop the
#     219           0 :     // CScheduler/checkqueue threadGroup
#     220           0 :     if (node.scheduler) node.scheduler->stop();
#     221           0 :     threadGroup.interrupt_all();
#     222           0 :     threadGroup.join_all();
#     223           0 : 
#     224           0 :     // After the threads that potentially access these pointers have been stopped,
#     225           0 :     // destruct and reset all to nullptr.
#     226           0 :     node.peer_logic.reset();
#     227           0 :     node.connman.reset();
#     228           0 :     node.banman.reset();
#     229           0 : 
#     230           0 :     if (::mempool.IsLoaded() && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
#     231           0 :         DumpMempool(::mempool);
#     232           0 :     }
#     233           0 : 
#     234           0 :     if (fFeeEstimatesInitialized)
#     235           0 :     {
#     236           0 :         ::feeEstimator.FlushUnconfirmed();
#     237           0 :         fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
#     238           0 :         CAutoFile est_fileout(fsbridge::fopen(est_path, "wb"), SER_DISK, CLIENT_VERSION);
#     239           0 :         if (!est_fileout.IsNull())
#     240           0 :             ::feeEstimator.Write(est_fileout);
#     241           0 :         else
#     242           0 :             LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
#     243           0 :         fFeeEstimatesInitialized = false;
#     244           0 :     }
#     245           0 : 
#     246           0 :     // FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
#     247           0 :     if (node.chainman) {
#     248           0 :         LOCK(cs_main);
#     249           0 :         for (CChainState* chainstate : node.chainman->GetAll()) {
#     250           0 :             if (chainstate->CanFlushToDisk()) {
#     251           0 :                 chainstate->ForceFlushStateToDisk();
#     252           0 :             }
#     253           0 :         }
#     254           0 :     }
#     255           0 : 
#     256           0 :     // After there are no more peers/RPC left to give us new data which may generate
#     257           0 :     // CValidationInterface callbacks, flush them...
#     258           0 :     GetMainSignals().FlushBackgroundCallbacks();
#     259           0 : 
#     260           0 :     // Stop and delete all indexes only after flushing background callbacks.
#     261           0 :     if (g_txindex) {
#     262           0 :         g_txindex->Stop();
#     263           0 :         g_txindex.reset();
#     264           0 :     }
#     265           0 :     ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Stop(); });
#     266           0 :     DestroyAllBlockFilterIndexes();
#     267           0 : 
#     268           0 :     // Any future callbacks will be dropped. This should absolutely be safe - if
#     269           0 :     // missing a callback results in an unrecoverable situation, unclean shutdown
#     270           0 :     // would too. The only reason to do the above flushes is to let the wallet catch
#     271           0 :     // up with our current chain to avoid any strange pruning edge cases and make
#     272           0 :     // next startup faster by avoiding rescan.
#     273           0 : 
#     274           0 :     if (node.chainman) {
#     275           0 :         LOCK(cs_main);
#     276           0 :         for (CChainState* chainstate : node.chainman->GetAll()) {
#     277           0 :             if (chainstate->CanFlushToDisk()) {
#     278           0 :                 chainstate->ForceFlushStateToDisk();
#     279           0 :                 chainstate->ResetCoinsViews();
#     280           0 :             }
#     281           0 :         }
#     282           0 :         pblocktree.reset();
#     283           0 :     }
#     284           0 :     for (const auto& client : node.chain_clients) {
#     285           0 :         client->stop();
#     286           0 :     }
#     287           0 : 
#     288           0 : #if ENABLE_ZMQ
#     289           0 :     if (g_zmq_notification_interface) {
#     290           0 :         UnregisterValidationInterface(g_zmq_notification_interface);
#     291           0 :         delete g_zmq_notification_interface;
#     292           0 :         g_zmq_notification_interface = nullptr;
#     293           0 :     }
#     294           0 : #endif
#     295           0 : 
#     296           0 :     node.chain_clients.clear();
#     297           0 :     UnregisterAllValidationInterfaces();
#     298           0 :     GetMainSignals().UnregisterBackgroundSignalScheduler();
#     299           0 :     globalVerifyHandle.reset();
#     300           0 :     ECC_Stop();
#     301           0 :     node.args = nullptr;
#     302           0 :     node.mempool = nullptr;
#     303           0 :     node.chainman = nullptr;
#     304           0 :     node.scheduler.reset();
#     305           0 : 
#     306           0 :     try {
#     307           0 :         if (!fs::remove(GetPidFile())) {
#     308           0 :             LogPrintf("%s: Unable to remove PID file: File does not exist\n", __func__);
#     309           0 :         }
#     310           0 :     } catch (const fs::filesystem_error& e) {
#     311           0 :         LogPrintf("%s: Unable to remove PID file: %s\n", __func__, fsbridge::get_filesystem_error_message(e));
#     312           0 :     }
#     313           0 : 
#     314           0 :     LogPrintf("%s: done\n", __func__);
#     315           0 : }
#     316             : 
#     317             : /**
#     318             :  * Signal handlers are very limited in what they are allowed to do.
#     319             :  * The execution context the handler is invoked in is not guaranteed,
#     320             :  * so we restrict handler operations to just touching variables:
#     321             :  */
#     322             : #ifndef WIN32
#     323             : static void HandleSIGTERM(int)
#     324           0 : {
#     325           0 :     StartShutdown();
#     326           0 : }
#     327             : 
#     328             : static void HandleSIGHUP(int)
#     329           0 : {
#     330           0 :     LogInstance().m_reopen_file = true;
#     331           0 : }
#     332             : #else
#     333             : static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType)
#     334             : {
#     335             :     StartShutdown();
#     336             :     Sleep(INFINITE);
#     337             :     return true;
#     338             : }
#     339             : #endif
#     340             : 
#     341             : #ifndef WIN32
#     342             : static void registerSignalHandler(int signal, void(*handler)(int))
#     343           0 : {
#     344           0 :     struct sigaction sa;
#     345           0 :     sa.sa_handler = handler;
#     346           0 :     sigemptyset(&sa.sa_mask);
#     347           0 :     sa.sa_flags = 0;
#     348           0 :     sigaction(signal, &sa, nullptr);
#     349           0 : }
#     350             : #endif
#     351             : 
#     352             : static boost::signals2::connection rpc_notify_block_change_connection;
#     353             : static void OnRPCStarted()
#     354           0 : {
#     355           0 :     rpc_notify_block_change_connection = uiInterface.NotifyBlockTip_connect(std::bind(RPCNotifyBlockChange, std::placeholders::_2));
#     356           0 : }
#     357             : 
#     358             : static void OnRPCStopped()
#     359           0 : {
#     360           0 :     rpc_notify_block_change_connection.disconnect();
#     361           0 :     RPCNotifyBlockChange(nullptr);
#     362           0 :     g_best_block_cv.notify_all();
#     363           0 :     LogPrint(BCLog::RPC, "RPC stopped.\n");
#     364           0 : }
#     365             : 
#     366             : void SetupServerArgs(NodeContext& node)
#     367         753 : {
#     368         753 :     assert(!node.args);
#     369         753 :     node.args = &gArgs;
#     370         753 : 
#     371         753 :     SetupHelpOptions(gArgs);
#     372         753 :     gArgs.AddArg("-help-debug", "Print help message with debugging options and exit", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); // server-only for now
#     373         753 : 
#     374         753 :     const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
#     375         753 :     const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
#     376         753 :     const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
#     377         753 :     const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
#     378         753 :     const auto testnetChainParams = CreateChainParams(CBaseChainParams::TESTNET);
#     379         753 :     const auto regtestChainParams = CreateChainParams(CBaseChainParams::REGTEST);
#     380         753 : 
#     381         753 :     // Hidden Options
#     382         753 :     std::vector<std::string> hidden_args = {
#     383         753 :         "-dbcrashratio", "-forcecompactdb",
#     384         753 :         // GUI args. These will be overwritten by SetupUIArgs for the GUI
#     385         753 :         "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-splash", "-uiplatform"};
#     386         753 : 
#     387         753 :     gArgs.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     388         753 : #if HAVE_SYSTEM
#     389         753 :     gArgs.AddArg("-alertnotify=<cmd>", "Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     390         753 : #endif
#     391         753 :     gArgs.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, testnet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     392         753 :     gArgs.AddArg("-blocksdir=<dir>", "Specify directory to hold blocks subdirectory for *.dat files (default: <datadir>)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     393         753 : #if HAVE_SYSTEM
#     394         753 :     gArgs.AddArg("-blocknotify=<cmd>", "Execute command when the best block changes (%s in cmd is replaced by block hash)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     395         753 : #endif
#     396         753 :     gArgs.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);
#     397         753 :     gArgs.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Automatic broadcast and rebroadcast of any transactions from inbound peers is disabled, unless '-whitelistforcerelay' is '1', in which case whitelisted peers' transactions will be relayed. RPC transactions are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     398         753 :     gArgs.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     399         753 :     gArgs.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     400         753 :     gArgs.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
#     401         753 :     gArgs.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (%d to %d, default: %d). In addition, unused mempool memory is shared for this cache (see -maxmempool).", nMinDbCache, nMaxDbCache, nDefaultDbCache), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     402         753 :     gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (-nodebuglogfile to disable; default: %s)", DEFAULT_DEBUGLOGFILE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     403         753 :     gArgs.AddArg("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
#     404         753 :     gArgs.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);
#     405         753 :     gArgs.AddArg("-loadblock=<file>", "Imports blocks from external file on startup", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     406         753 :     gArgs.AddArg("-maxmempool=<n>", strprintf("Keep the transaction memory pool below <n> megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     407         753 :     gArgs.AddArg("-maxorphantx=<n>", strprintf("Keep at most <n> unconnectable transactions in memory (default: %u)", DEFAULT_MAX_ORPHAN_TRANSACTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     408         753 :     gArgs.AddArg("-mempoolexpiry=<n>", strprintf("Do not keep transactions in the mempool longer than <n> hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     409         753 :     gArgs.AddArg("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
#     410         753 :     gArgs.AddArg("-par=<n>", strprintf("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)",
#     411         753 :         -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     412         753 :     gArgs.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     413         753 :     gArgs.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);
#     414         753 :     gArgs.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 and -rescan. "
#     415         753 :             "Warning: Reverting this setting requires re-downloading the entire blockchain. "
#     416         753 :             "(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);
#     417         753 :     gArgs.AddArg("-reindex", "Rebuild chain state and block index from the blk*.dat files on disk", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     418         753 :     gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks. When in pruning mode or if blocks on disk might be corrupted, use full -reindex instead.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     419         753 : #ifndef WIN32
#     420         753 :     gArgs.AddArg("-sysperms", "Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     421             : #else
#     422             :     hidden_args.emplace_back("-sysperms");
#     423             : #endif
#     424         753 :     gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     425         753 :     gArgs.AddArg("-blockfilterindex=<type>",
#     426         753 :                  strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) +
#     427         753 :                  " If <type> is not supplied or if <type> = 1, indexes for all known types are enabled.",
#     428         753 :                  ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     429         753 : 
#     430         753 :     gArgs.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info). This option can be specified multiple times to add multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
#     431         753 :     gArgs.AddArg("-asmap=<file>", strprintf("Specify asn mapping used for bucketing of the peers (default: %s). Relative paths will be prefixed by the net-specific datadir location.", DEFAULT_ASMAP_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     432         753 :     gArgs.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     433         753 :     gArgs.AddArg("-bantime=<n>", strprintf("Number of seconds to keep misbehaving peers from reconnecting (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     434         753 :     gArgs.AddArg("-bind=<addr>", "Bind to given address and always listen on it. Use [host]:port notation for IPv6", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
#     435         753 :     gArgs.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);
#     436         753 :     gArgs.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     437         753 :     gArgs.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     438         753 :     gArgs.AddArg("-dnsseed", "Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     439         753 :     gArgs.AddArg("-externalip=<ip>", "Specify your own public address", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     440         753 :     gArgs.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     441         753 :     gArgs.AddArg("-listen", "Accept connections from outside (default: 1 if no -proxy or -connect)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     442         753 :     gArgs.AddArg("-listenonion", strprintf("Automatically create Tor hidden service (default: %d)", DEFAULT_LISTEN_ONION), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     443         753 :     gArgs.AddArg("-maxconnections=<n>", strprintf("Maintain at most <n> connections to peers (default: %u)", DEFAULT_MAX_PEER_CONNECTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     444         753 :     gArgs.AddArg("-maxreceivebuffer=<n>", strprintf("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXRECEIVEBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     445         753 :     gArgs.AddArg("-maxsendbuffer=<n>", strprintf("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXSENDBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     446         753 :     gArgs.AddArg("-maxtimeadjustment", strprintf("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)", DEFAULT_MAX_TIME_ADJUSTMENT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     447         753 :     gArgs.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)", DEFAULT_MAX_UPLOAD_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     448         753 :     gArgs.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor hidden services, set -noonion to disable (default: -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     449         753 :     gArgs.AddArg("-onlynet=<net>", "Make outgoing connections only through network <net> (ipv4, ipv6 or onion). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     450         753 :     gArgs.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     451         753 :     gArgs.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     452         753 :     gArgs.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     453         753 :     gArgs.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet: %u, regtest: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
#     454         753 :     gArgs.AddArg("-proxy=<ip:port>", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     455         753 :     gArgs.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     456         753 :     gArgs.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.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     457         753 :     gArgs.AddArg("-timeout=<n>", strprintf("Specify connection timeout in milliseconds (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     458         753 :     gArgs.AddArg("-peertimeout=<n>", strprintf("Specify p2p connection timeout in seconds. This option determines the amount of time a peer may be inactive before the connection to it is dropped. (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
#     459         753 :     gArgs.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control port to use if onion listening enabled (default: %s)", DEFAULT_TOR_CONTROL), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     460         753 :     gArgs.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::CONNECTION);
#     461         753 : #ifdef USE_UPNP
#     462             : #if USE_UPNP
#     463             :     gArgs.AddArg("-upnp", "Use UPnP to map the listening port (default: 1 when listening and no -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     464             : #else
#     465         753 :     gArgs.AddArg("-upnp", strprintf("Use UPnP to map the listening port (default: %u)", 0), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     466         753 : #endif
#     467             : #else
#     468             :     hidden_args.emplace_back("-upnp");
#     469             : #endif
#     470             :     gArgs.AddArg("-whitebind=<[permissions@]addr>", "Bind to given address and whitelist peers connecting to it. "
#     471         753 :         "Use [host]:port notation for IPv6. Allowed permissions are bloomfilter (allow requesting BIP37 filtered blocks and transactions), "
#     472         753 :         "noban (do not ban for misbehavior), "
#     473         753 :         "forcerelay (relay transactions that are already in the mempool; implies relay), "
#     474         753 :         "relay (relay even in -blocksonly mode), "
#     475         753 :         "and mempool (allow requesting BIP35 mempool contents). "
#     476         753 :         "Specify multiple permissions separated by commas (default: noban,mempool,relay). Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     477         753 : 
#     478         753 :     gArgs.AddArg("-whitelist=<[permissions@]IP address or network>", "Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or "
#     479         753 :         "CIDR notated network(e.g. 1.2.3.0/24). Uses same permissions as "
#     480         753 :         "-whitebind. Can be specified multiple times." , ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#     481         753 : 
#     482         753 :     g_wallet_init_interface.AddWalletOptions();
#     483         753 : 
#     484         753 : #if ENABLE_ZMQ
#     485         753 :     gArgs.AddArg("-zmqpubhashblock=<address>", "Enable publish hash block in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
#     486         753 :     gArgs.AddArg("-zmqpubhashtx=<address>", "Enable publish hash transaction in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
#     487         753 :     gArgs.AddArg("-zmqpubrawblock=<address>", "Enable publish raw block in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
#     488         753 :     gArgs.AddArg("-zmqpubrawtx=<address>", "Enable publish raw transaction in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
#     489         753 :     gArgs.AddArg("-zmqpubhashblockhwm=<n>", strprintf("Set publish hash block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
#     490         753 :     gArgs.AddArg("-zmqpubhashtxhwm=<n>", strprintf("Set publish hash transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
#     491         753 :     gArgs.AddArg("-zmqpubrawblockhwm=<n>", strprintf("Set publish raw block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
#     492         753 :     gArgs.AddArg("-zmqpubrawtxhwm=<n>", strprintf("Set publish raw transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
#     493             : #else
#     494             :     hidden_args.emplace_back("-zmqpubhashblock=<address>");
#     495             :     hidden_args.emplace_back("-zmqpubhashtx=<address>");
#     496             :     hidden_args.emplace_back("-zmqpubrawblock=<address>");
#     497             :     hidden_args.emplace_back("-zmqpubrawtx=<address>");
#     498             :     hidden_args.emplace_back("-zmqpubhashblockhwm=<n>");
#     499             :     hidden_args.emplace_back("-zmqpubhashtxhwm=<n>");
#     500             :     hidden_args.emplace_back("-zmqpubrawblockhwm=<n>");
#     501             :     hidden_args.emplace_back("-zmqpubrawtxhwm=<n>");
#     502             : #endif
#     503             : 
#     504         753 :     gArgs.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);
#     505         753 :     gArgs.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is: "
#     506         753 :         "level 0 reads the blocks from disk, "
#     507         753 :         "level 1 verifies block validity, "
#     508         753 :         "level 2 verifies undo data, "
#     509         753 :         "level 3 checks disconnection of tip blocks, "
#     510         753 :         "and level 4 tries to reconnect the blocks, "
#     511         753 :         "each level includes the checks of the previous levels "
#     512         753 :         "(0-4, default: %u)", DEFAULT_CHECKLEVEL), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     513         753 :     gArgs.AddArg("-checkblockindex", strprintf("Do a consistency check for the block tree, chainstate, and other validation data structures occasionally. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     514         753 :     gArgs.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     515         753 :     gArgs.AddArg("-checkpoints", strprintf("Enable rejection of any forks from the known historical chain until block 295000 (default: %u)", DEFAULT_CHECKPOINTS_ENABLED), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     516         753 :     gArgs.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     517         753 :     gArgs.AddArg("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     518         753 :     gArgs.AddArg("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     519         753 :     gArgs.AddArg("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u)", DEFAULT_STOPATHEIGHT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     520         753 :     gArgs.AddArg("-limitancestorcount=<n>", strprintf("Do not accept transactions if number of in-mempool ancestors is <n> or more (default: %u)", DEFAULT_ANCESTOR_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     521         753 :     gArgs.AddArg("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     522         753 :     gArgs.AddArg("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     523         753 :     gArgs.AddArg("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     524         753 :     gArgs.AddArg("-addrmantest", "Allows to test address relay on localhost", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     525         753 :     gArgs.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). "
#     526         753 :         "If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + LogInstance().LogCategoriesString() + ".",
#     527         753 :         ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#     528         753 :     gArgs.AddArg("-debugexclude=<category>", strprintf("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#     529         753 :     gArgs.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#     530         753 :     gArgs.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#     531             : #ifdef HAVE_THREAD_LOCAL
#     532             :     gArgs.AddArg("-logthreadnames", strprintf("Prepend debug output with name of the originating thread (only available on platforms supporting thread_local) (default: %u)", DEFAULT_LOGTHREADNAMES), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#     533             : #else
#     534             :     hidden_args.emplace_back("-logthreadnames");
#     535         753 : #endif
#     536         753 :     gArgs.AddArg("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     537         753 :     gArgs.AddArg("-mocktime=<n>", "Replace actual time with " + UNIX_EPOCH_TIME + " (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     538         753 :     gArgs.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     539         753 :     gArgs.AddArg("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     540         753 :     gArgs.AddArg("-printpriority", strprintf("Log transaction fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#     541         753 :     gArgs.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -daemon. To disable logging to file, set -nodebuglogfile)", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#     542         753 :     gArgs.AddArg("-shrinkdebugfile", "Shrink debug.log file on client startup (default: 1 when no -debug)", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#     543         753 :     gArgs.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#     544         753 : 
#     545         753 :     SetupChainParamsBaseOptions();
#     546         753 : 
#     547         753 :     gArgs.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !testnetChainParams->RequireStandard()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
#     548         753 :     gArgs.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
#     549         753 :     gArgs.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) 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);
#     550         753 :     gArgs.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);
#     551         753 :     gArgs.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
#     552         753 :     gArgs.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
#     553         753 :     gArgs.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)",
#     554         753 :         CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
#     555         753 :     gArgs.AddArg("-whitelistforcerelay", strprintf("Add 'forcerelay' permission to whitelisted inbound 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);
#     556         753 :     gArgs.AddArg("-whitelistrelay", strprintf("Add 'relay' permission to whitelisted inbound peers with default permissions. This will accept relayed transactions even when not relaying transactions (default: %d)", DEFAULT_WHITELISTRELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
#     557         753 : 
#     558         753 : 
#     559         753 :     gArgs.AddArg("-blockmaxweight=<n>", strprintf("Set maximum BIP141 block weight (default: %d)", DEFAULT_BLOCK_MAX_WEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
#     560         753 :     gArgs.AddArg("-blockmintxfee=<amt>", strprintf("Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
#     561         753 :     gArgs.AddArg("-blockversion=<n>", "Override block version to test forking scenarios", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::BLOCK_CREATION);
#     562         753 : 
#     563         753 :     gArgs.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
#     564         753 :     gArgs.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid 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) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
#     565         753 :     gArgs.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);
#     566         753 :     gArgs.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 | ArgsManager::SENSITIVE, OptionsCategory::RPC);
#     567         753 :     gArgs.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);
#     568         753 :     gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
#     569         753 :     gArgs.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC);
#     570         753 :     gArgs.AddArg("-rpcserialversion", strprintf("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)", DEFAULT_RPC_SERIALIZE_VERSION), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
#     571         753 :     gArgs.AddArg("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
#     572         753 :     gArgs.AddArg("-rpcthreads=<n>", strprintf("Set the number of threads to service RPC calls (default: %d)", DEFAULT_HTTP_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
#     573         753 :     gArgs.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
#     574         753 :     gArgs.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);
#     575         753 :     gArgs.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_BOOL, OptionsCategory::RPC);
#     576         753 :     gArgs.AddArg("-rpcworkqueue=<n>", strprintf("Set the depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
#     577         753 :     gArgs.AddArg("-server", "Accept command line and JSON-RPC commands", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
#     578         753 : 
#     579         753 : #if HAVE_DECL_DAEMON
#     580         753 :     gArgs.AddArg("-daemon", "Run in the background as a daemon and accept commands", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#     581             : #else
#     582             :     hidden_args.emplace_back("-daemon");
#     583             : #endif
#     584             : 
#     585         753 :     // Add the hidden options
#     586         753 :     gArgs.AddHiddenArgs(hidden_args);
#     587         753 : }
#     588             : 
#     589             : std::string LicenseInfo()
#     590           0 : {
#     591           0 :     const std::string URL_SOURCE_CODE = "<https://github.com/bitcoin/bitcoin>";
#     592           0 : 
#     593           0 :     return CopyrightHolders(strprintf(_("Copyright (C) %i-%i").translated, 2009, COPYRIGHT_YEAR) + " ") + "\n" +
#     594           0 :            "\n" +
#     595           0 :            strprintf(_("Please contribute if you find %s useful. "
#     596           0 :                        "Visit %s for further information about the software.").translated,
#     597           0 :                PACKAGE_NAME, "<" PACKAGE_URL ">") +
#     598           0 :            "\n" +
#     599           0 :            strprintf(_("The source code is available from %s.").translated,
#     600           0 :                URL_SOURCE_CODE) +
#     601           0 :            "\n" +
#     602           0 :            "\n" +
#     603           0 :            _("This is experimental software.").translated + "\n" +
#     604           0 :            strprintf(_("Distributed under the MIT software license, see the accompanying file %s or %s").translated, "COPYING", "<https://opensource.org/licenses/MIT>") +
#     605           0 :            "\n";
#     606           0 : }
#     607             : 
#     608             : #if HAVE_SYSTEM
#     609             : static void BlockNotifyCallback(SynchronizationState sync_state, const CBlockIndex* pBlockIndex)
#     610           0 : {
#     611           0 :     if (sync_state != SynchronizationState::POST_INIT || !pBlockIndex)
#     612           0 :         return;
#     613           0 : 
#     614           0 :     std::string strCmd = gArgs.GetArg("-blocknotify", "");
#     615           0 :     if (!strCmd.empty()) {
#     616           0 :         boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex());
#     617           0 :         std::thread t(runCommand, strCmd);
#     618           0 :         t.detach(); // thread runs free
#     619           0 :     }
#     620           0 : }
#     621             : #endif
#     622             : 
#     623             : static bool fHaveGenesis = false;
#     624             : static Mutex g_genesis_wait_mutex;
#     625             : static std::condition_variable g_genesis_wait_cv;
#     626             : 
#     627             : static void BlockNotifyGenesisWait(const CBlockIndex* pBlockIndex)
#     628           0 : {
#     629           0 :     if (pBlockIndex != nullptr) {
#     630           0 :         {
#     631           0 :             LOCK(g_genesis_wait_mutex);
#     632           0 :             fHaveGenesis = true;
#     633           0 :         }
#     634           0 :         g_genesis_wait_cv.notify_all();
#     635           0 :     }
#     636           0 : }
#     637             : 
#     638             : struct CImportingNow
#     639             : {
#     640           0 :     CImportingNow() {
#     641           0 :         assert(fImporting == false);
#     642           0 :         fImporting = true;
#     643           0 :     }
#     644             : 
#     645           0 :     ~CImportingNow() {
#     646           0 :         assert(fImporting == true);
#     647           0 :         fImporting = false;
#     648           0 :     }
#     649             : };
#     650             : 
#     651             : 
#     652             : // If we're using -prune with -reindex, then delete block files that will be ignored by the
#     653             : // reindex.  Since reindexing works by starting at block file 0 and looping until a blockfile
#     654             : // is missing, do the same here to delete any later block files after a gap.  Also delete all
#     655             : // rev files since they'll be rewritten by the reindex anyway.  This ensures that vinfoBlockFile
#     656             : // is in sync with what's actually on disk by the time we start downloading, so that pruning
#     657             : // works correctly.
#     658             : static void CleanupBlockRevFiles()
#     659           0 : {
#     660           0 :     std::map<std::string, fs::path> mapBlockFiles;
#     661           0 : 
#     662           0 :     // Glob all blk?????.dat and rev?????.dat files from the blocks directory.
#     663           0 :     // Remove the rev files immediately and insert the blk file paths into an
#     664           0 :     // ordered map keyed by block file index.
#     665           0 :     LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
#     666           0 :     fs::path blocksdir = GetBlocksDir();
#     667           0 :     for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) {
#     668           0 :         if (fs::is_regular_file(*it) &&
#     669           0 :             it->path().filename().string().length() == 12 &&
#     670           0 :             it->path().filename().string().substr(8,4) == ".dat")
#     671           0 :         {
#     672           0 :             if (it->path().filename().string().substr(0,3) == "blk")
#     673           0 :                 mapBlockFiles[it->path().filename().string().substr(3,5)] = it->path();
#     674           0 :             else if (it->path().filename().string().substr(0,3) == "rev")
#     675           0 :                 remove(it->path());
#     676           0 :         }
#     677           0 :     }
#     678           0 : 
#     679           0 :     // Remove all block files that aren't part of a contiguous set starting at
#     680           0 :     // zero by walking the ordered map (keys are block file indices) by
#     681           0 :     // keeping a separate counter.  Once we hit a gap (or if 0 doesn't exist)
#     682           0 :     // start removing block files.
#     683           0 :     int nContigCounter = 0;
#     684           0 :     for (const std::pair<const std::string, fs::path>& item : mapBlockFiles) {
#     685           0 :         if (atoi(item.first) == nContigCounter) {
#     686           0 :             nContigCounter++;
#     687           0 :             continue;
#     688           0 :         }
#     689           0 :         remove(item.second);
#     690           0 :     }
#     691           0 : }
#     692             : 
#     693             : static void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles)
#     694           0 : {
#     695           0 :     const CChainParams& chainparams = Params();
#     696           0 :     util::ThreadRename("loadblk");
#     697           0 :     ScheduleBatchPriority();
#     698           0 : 
#     699           0 :     {
#     700           0 :     CImportingNow imp;
#     701           0 : 
#     702           0 :     // -reindex
#     703           0 :     if (fReindex) {
#     704           0 :         int nFile = 0;
#     705           0 :         while (true) {
#     706           0 :             FlatFilePos pos(nFile, 0);
#     707           0 :             if (!fs::exists(GetBlockPosFilename(pos)))
#     708           0 :                 break; // No block files left to reindex
#     709           0 :             FILE *file = OpenBlockFile(pos, true);
#     710           0 :             if (!file)
#     711           0 :                 break; // This error is logged in OpenBlockFile
#     712           0 :             LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
#     713           0 :             LoadExternalBlockFile(chainparams, file, &pos);
#     714           0 :             if (ShutdownRequested()) {
#     715           0 :                 LogPrintf("Shutdown requested. Exit %s\n", __func__);
#     716           0 :                 return;
#     717           0 :             }
#     718           0 :             nFile++;
#     719           0 :         }
#     720           0 :         pblocktree->WriteReindexing(false);
#     721           0 :         fReindex = false;
#     722           0 :         LogPrintf("Reindexing finished\n");
#     723           0 :         // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
#     724           0 :         LoadGenesisBlock(chainparams);
#     725           0 :     }
#     726           0 : 
#     727           0 :     // -loadblock=
#     728           0 :     for (const fs::path& path : vImportFiles) {
#     729           0 :         FILE *file = fsbridge::fopen(path, "rb");
#     730           0 :         if (file) {
#     731           0 :             LogPrintf("Importing blocks file %s...\n", path.string());
#     732           0 :             LoadExternalBlockFile(chainparams, file);
#     733           0 :             if (ShutdownRequested()) {
#     734           0 :                 LogPrintf("Shutdown requested. Exit %s\n", __func__);
#     735           0 :                 return;
#     736           0 :             }
#     737           0 :         } else {
#     738           0 :             LogPrintf("Warning: Could not open blocks file %s\n", path.string());
#     739           0 :         }
#     740           0 :     }
#     741           0 : 
#     742           0 :     // scan for better chains in the block chain database, that are not yet connected in the active best chain
#     743           0 : 
#     744           0 :     // We can't hold cs_main during ActivateBestChain even though we're accessing
#     745           0 :     // the chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve
#     746           0 :     // the relevant pointers before the ABC call.
#     747           0 :     for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
#     748           0 :         BlockValidationState state;
#     749           0 :         if (!chainstate->ActivateBestChain(state, chainparams, nullptr)) {
#     750           0 :             LogPrintf("Failed to connect best block (%s)\n", state.ToString());
#     751           0 :             StartShutdown();
#     752           0 :             return;
#     753           0 :         }
#     754           0 :     }
#     755           0 : 
#     756           0 :     if (gArgs.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) {
#     757           0 :         LogPrintf("Stopping after block import\n");
#     758           0 :         StartShutdown();
#     759           0 :         return;
#     760           0 :     }
#     761           0 :     } // End scope of CImportingNow
#     762           0 :     if (gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
#     763           0 :         LoadMempool(::mempool);
#     764           0 :     }
#     765           0 :     ::mempool.SetIsLoaded(!ShutdownRequested());
#     766           0 : }
#     767             : 
#     768             : /** Sanity checks
#     769             :  *  Ensure that Bitcoin is running in a usable environment with all
#     770             :  *  necessary library support.
#     771             :  */
#     772             : static bool InitSanityCheck()
#     773           0 : {
#     774           0 :     if (!ECC_InitSanityCheck()) {
#     775           0 :         return InitError(Untranslated("Elliptic curve cryptography sanity check failure. Aborting."));
#     776           0 :     }
#     777           0 : 
#     778           0 :     if (!glibc_sanity_test() || !glibcxx_sanity_test())
#     779           0 :         return false;
#     780           0 : 
#     781           0 :     if (!Random_SanityCheck()) {
#     782           0 :         return InitError(Untranslated("OS cryptographic RNG sanity check failure. Aborting."));
#     783           0 :     }
#     784           0 : 
#     785           0 :     return true;
#     786           0 : }
#     787             : 
#     788             : static bool AppInitServers(const util::Ref& context)
#     789           0 : {
#     790           0 :     RPCServer::OnStarted(&OnRPCStarted);
#     791           0 :     RPCServer::OnStopped(&OnRPCStopped);
#     792           0 :     if (!InitHTTPServer())
#     793           0 :         return false;
#     794           0 :     StartRPC();
#     795           0 :     if (!StartHTTPRPC(context))
#     796           0 :         return false;
#     797           0 :     if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE)) StartREST(context);
#     798           0 :     StartHTTPServer();
#     799           0 :     return true;
#     800           0 : }
#     801             : 
#     802             : // Parameter interaction based on rules
#     803             : void InitParameterInteraction()
#     804           0 : {
#     805           0 :     // when specifying an explicit binding address, you want to listen on it
#     806           0 :     // even when -connect or -proxy is specified
#     807           0 :     if (gArgs.IsArgSet("-bind")) {
#     808           0 :         if (gArgs.SoftSetBoolArg("-listen", true))
#     809           0 :             LogPrintf("%s: parameter interaction: -bind set -> setting -listen=1\n", __func__);
#     810           0 :     }
#     811           0 :     if (gArgs.IsArgSet("-whitebind")) {
#     812           0 :         if (gArgs.SoftSetBoolArg("-listen", true))
#     813           0 :             LogPrintf("%s: parameter interaction: -whitebind set -> setting -listen=1\n", __func__);
#     814           0 :     }
#     815           0 : 
#     816           0 :     if (gArgs.IsArgSet("-connect")) {
#     817           0 :         // when only connecting to trusted nodes, do not seed via DNS, or listen by default
#     818           0 :         if (gArgs.SoftSetBoolArg("-dnsseed", false))
#     819           0 :             LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__);
#     820           0 :         if (gArgs.SoftSetBoolArg("-listen", false))
#     821           0 :             LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__);
#     822           0 :     }
#     823           0 : 
#     824           0 :     if (gArgs.IsArgSet("-proxy")) {
#     825           0 :         // to protect privacy, do not listen by default if a default proxy server is specified
#     826           0 :         if (gArgs.SoftSetBoolArg("-listen", false))
#     827           0 :             LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__);
#     828           0 :         // to protect privacy, do not use UPNP when a proxy is set. The user may still specify -listen=1
#     829           0 :         // to listen locally, so don't rely on this happening through -listen below.
#     830           0 :         if (gArgs.SoftSetBoolArg("-upnp", false))
#     831           0 :             LogPrintf("%s: parameter interaction: -proxy set -> setting -upnp=0\n", __func__);
#     832           0 :         // to protect privacy, do not discover addresses by default
#     833           0 :         if (gArgs.SoftSetBoolArg("-discover", false))
#     834           0 :             LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__);
#     835           0 :     }
#     836           0 : 
#     837           0 :     if (!gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) {
#     838           0 :         // do not map ports or try to retrieve public IP when not listening (pointless)
#     839           0 :         if (gArgs.SoftSetBoolArg("-upnp", false))
#     840           0 :             LogPrintf("%s: parameter interaction: -listen=0 -> setting -upnp=0\n", __func__);
#     841           0 :         if (gArgs.SoftSetBoolArg("-discover", false))
#     842           0 :             LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__);
#     843           0 :         if (gArgs.SoftSetBoolArg("-listenonion", false))
#     844           0 :             LogPrintf("%s: parameter interaction: -listen=0 -> setting -listenonion=0\n", __func__);
#     845           0 :     }
#     846           0 : 
#     847           0 :     if (gArgs.IsArgSet("-externalip")) {
#     848           0 :         // if an explicit public IP is specified, do not try to find others
#     849           0 :         if (gArgs.SoftSetBoolArg("-discover", false))
#     850           0 :             LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__);
#     851           0 :     }
#     852           0 : 
#     853           0 :     // disable whitelistrelay in blocksonly mode
#     854           0 :     if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) {
#     855           0 :         if (gArgs.SoftSetBoolArg("-whitelistrelay", false))
#     856           0 :             LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n", __func__);
#     857           0 :     }
#     858           0 : 
#     859           0 :     // Forcing relay from whitelisted hosts implies we will accept relays from them in the first place.
#     860           0 :     if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) {
#     861           0 :         if (gArgs.SoftSetBoolArg("-whitelistrelay", true))
#     862           0 :             LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__);
#     863           0 :     }
#     864           0 : }
#     865             : 
#     866             : /**
#     867             :  * Initialize global loggers.
#     868             :  *
#     869             :  * Note that this is called very early in the process lifetime, so you should be
#     870             :  * careful about what global state you rely on here.
#     871             :  */
#     872             : void InitLogging()
#     873         753 : {
#     874         753 :     LogInstance().m_print_to_file = !gArgs.IsArgNegated("-debuglogfile");
#     875         753 :     LogInstance().m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
#     876         753 :     LogInstance().m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false));
#     877         753 :     LogInstance().m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
#     878         753 :     LogInstance().m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
#     879             : #ifdef HAVE_THREAD_LOCAL
#     880             :     LogInstance().m_log_threadnames = gArgs.GetBoolArg("-logthreadnames", DEFAULT_LOGTHREADNAMES);
#     881             : #endif
#     882             : 
#     883         753 :     fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);
#     884         753 : 
#     885         753 :     std::string version_string = FormatFullVersion();
#     886         753 : #ifdef DEBUG
#     887         753 :     version_string += " (debug build)";
#     888             : #else
#     889             :     version_string += " (release build)";
#     890             : #endif
#     891         753 :     LogPrintf(PACKAGE_NAME " version %s\n", version_string);
#     892         753 : }
#     893             : 
#     894             : namespace { // Variables internal to initialization process only
#     895             : 
#     896             : int nMaxConnections;
#     897             : int nUserMaxConnections;
#     898             : int nFD;
#     899             : ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED | NODE_ADDRv2);
#     900             : int64_t peer_connect_timeout;
#     901             : std::set<BlockFilterType> g_enabled_filter_types;
#     902             : 
#     903             : } // namespace
#     904             : 
#     905             : [[noreturn]] static void new_handler_terminate()
#     906           0 : {
#     907           0 :     // Rather than throwing std::bad-alloc if allocation fails, terminate
#     908           0 :     // immediately to (try to) avoid chain corruption.
#     909           0 :     // Since LogPrintf may itself allocate memory, set the handler directly
#     910           0 :     // to terminate first.
#     911           0 :     std::set_new_handler(std::terminate);
#     912           0 :     LogPrintf("Error: Out of memory. Terminating.\n");
#     913           0 : 
#     914           0 :     // The log was successful, terminate now.
#     915           0 :     std::terminate();
#     916           0 : };
#     917             : 
#     918             : bool AppInitBasicSetup()
#     919           0 : {
#     920           0 :     // ********************************************************* Step 1: setup
#     921             : #ifdef _MSC_VER
#     922             :     // Turn off Microsoft heap dump noise
#     923             :     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
#     924             :     _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, 0));
#     925             :     // Disable confusing "helpful" text message on abort, Ctrl-C
#     926             :     _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
#     927             : #endif
#     928             : #ifdef WIN32
#     929             :     // Enable heap terminate-on-corruption
#     930             :     HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
#     931             : #endif
#     932             : 
#     933           0 :     if (!SetupNetworking()) {
#     934           0 :         return InitError(Untranslated("Initializing networking failed."));
#     935           0 :     }
#     936           0 : 
#     937           0 : #ifndef WIN32
#     938           0 :     if (!gArgs.GetBoolArg("-sysperms", false)) {
#     939           0 :         umask(077);
#     940           0 :     }
#     941           0 : 
#     942           0 :     // Clean shutdown on SIGTERM
#     943           0 :     registerSignalHandler(SIGTERM, HandleSIGTERM);
#     944           0 :     registerSignalHandler(SIGINT, HandleSIGTERM);
#     945           0 : 
#     946           0 :     // Reopen debug.log on SIGHUP
#     947           0 :     registerSignalHandler(SIGHUP, HandleSIGHUP);
#     948           0 : 
#     949           0 :     // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
#     950           0 :     signal(SIGPIPE, SIG_IGN);
#     951             : #else
#     952             :     SetConsoleCtrlHandler(consoleCtrlHandler, true);
#     953             : #endif
#     954             : 
#     955           0 :     std::set_new_handler(new_handler_terminate);
#     956           0 : 
#     957           0 :     return true;
#     958           0 : }
#     959             : 
#     960             : bool AppInitParameterInteraction()
#     961         753 : {
#     962         753 :     const CChainParams& chainparams = Params();
#     963         753 :     // ********************************************************* Step 2: parameter interactions
#     964         753 : 
#     965         753 :     // also see: InitParameterInteraction()
#     966         753 : 
#     967         753 :     // Warn if network-specific options (-addnode, -connect, etc) are
#     968         753 :     // specified in default section of config file, but not overridden
#     969         753 :     // on the command line or in this network's section of the config file.
#     970         753 :     std::string network = gArgs.GetChainName();
#     971         753 :     for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) {
#     972           0 :         return InitError(strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, network, network));
#     973           0 :     }
#     974         753 : 
#     975         753 :     // Warn if unrecognized section name are present in the config file.
#     976         753 :     for (const auto& section : gArgs.GetUnrecognizedSections()) {
#     977           0 :         InitWarning(strprintf(Untranslated("%s:%i ") + _("Section [%s] is not recognized."), section.m_file, section.m_line, section.m_name));
#     978           0 :     }
#     979         753 : 
#     980         753 :     if (!fs::is_directory(GetBlocksDir())) {
#     981           0 :         return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "")));
#     982           0 :     }
#     983         753 : 
#     984         753 :     // parse and validate enabled filter types
#     985         753 :     std::string blockfilterindex_value = gArgs.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX);
#     986         753 :     if (blockfilterindex_value == "" || blockfilterindex_value == "1") {
#     987           0 :         g_enabled_filter_types = AllBlockFilterTypes();
#     988         753 :     } else if (blockfilterindex_value != "0") {
#     989           0 :         const std::vector<std::string> names = gArgs.GetArgs("-blockfilterindex");
#     990           0 :         for (const auto& name : names) {
#     991           0 :             BlockFilterType filter_type;
#     992           0 :             if (!BlockFilterTypeByName(name, filter_type)) {
#     993           0 :                 return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name));
#     994           0 :             }
#     995           0 :             g_enabled_filter_types.insert(filter_type);
#     996           0 :         }
#     997           0 :     }
#     998         753 : 
#     999         753 :     // Basic filters are the only supported filters. The basic filters index must be enabled
#    1000         753 :     // to serve compact filters
#    1001         753 :     if (gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS) &&
#    1002         753 :         g_enabled_filter_types.count(BlockFilterType::BASIC) != 1) {
#    1003           0 :         return InitError(_("Cannot set -peerblockfilters without -blockfilterindex."));
#    1004           0 :     }
#    1005         753 : 
#    1006         753 :     // if using block pruning, then disallow txindex
#    1007         753 :     if (gArgs.GetArg("-prune", 0)) {
#    1008           0 :         if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX))
#    1009           0 :             return InitError(_("Prune mode is incompatible with -txindex."));
#    1010           0 :         if (!g_enabled_filter_types.empty()) {
#    1011           0 :             return InitError(_("Prune mode is incompatible with -blockfilterindex."));
#    1012           0 :         }
#    1013         753 :     }
#    1014         753 : 
#    1015         753 :     // -bind and -whitebind can't be set when not listening
#    1016         753 :     size_t nUserBind = gArgs.GetArgs("-bind").size() + gArgs.GetArgs("-whitebind").size();
#    1017         753 :     if (nUserBind != 0 && !gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) {
#    1018           0 :         return InitError(Untranslated("Cannot set -bind or -whitebind together with -listen=0"));
#    1019           0 :     }
#    1020         753 : 
#    1021         753 :     // Make sure enough file descriptors are available
#    1022         753 :     int nBind = std::max(nUserBind, size_t(1));
#    1023         753 :     nUserMaxConnections = gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
#    1024         753 :     nMaxConnections = std::max(nUserMaxConnections, 0);
#    1025         753 : 
#    1026         753 :     // Trim requested connection counts, to fit into system limitations
#    1027         753 :     // <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695
#    1028         753 :     nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS);
#    1029             : #ifdef USE_POLL
#    1030             :     int fd_max = nFD;
#    1031             : #else
#    1032             :     int fd_max = FD_SETSIZE;
#    1033         753 : #endif
#    1034         753 :     nMaxConnections = std::max(std::min<int>(nMaxConnections, fd_max - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0);
#    1035         753 :     if (nFD < MIN_CORE_FILEDESCRIPTORS)
#    1036         753 :         return InitError(_("Not enough file descriptors available."));
#    1037         753 :     nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, nMaxConnections);
#    1038         753 : 
#    1039         753 :     if (nMaxConnections < nUserMaxConnections)
#    1040           0 :         InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections));
#    1041         753 : 
#    1042         753 :     // ********************************************************* Step 3: parameter-to-internal-flags
#    1043         753 :     if (gArgs.IsArgSet("-debug")) {
#    1044         753 :         // Special-case: if -debug=0/-nodebug is set, turn off debugging messages
#    1045         753 :         const std::vector<std::string> categories = gArgs.GetArgs("-debug");
#    1046         753 : 
#    1047         753 :         if (std::none_of(categories.begin(), categories.end(),
#    1048         753 :             [](std::string cat){return cat == "0" || cat == "none";})) {
#    1049         753 :             for (const auto& cat : categories) {
#    1050         753 :                 if (!LogInstance().EnableCategory(cat)) {
#    1051           0 :                     InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat));
#    1052           0 :                 }
#    1053         753 :             }
#    1054         753 :         }
#    1055         753 :     }
#    1056         753 : 
#    1057         753 :     // Now remove the logging categories which were explicitly excluded
#    1058        1506 :     for (const std::string& cat : gArgs.GetArgs("-debugexclude")) {
#    1059        1506 :         if (!LogInstance().DisableCategory(cat)) {
#    1060           0 :             InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat));
#    1061           0 :         }
#    1062        1506 :     }
#    1063         753 : 
#    1064         753 :     // Checkmempool and checkblockindex default to true in regtest mode
#    1065         753 :     int ratio = std::min<int>(std::max<int>(gArgs.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
#    1066         753 :     if (ratio != 0) {
#    1067          51 :         mempool.setSanityCheck(1.0 / ratio);
#    1068          51 :     }
#    1069         753 :     fCheckBlockIndex = gArgs.GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks());
#    1070         753 :     fCheckpointsEnabled = gArgs.GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED);
#    1071         753 : 
#    1072         753 :     hashAssumeValid = uint256S(gArgs.GetArg("-assumevalid", chainparams.GetConsensus().defaultAssumeValid.GetHex()));
#    1073         753 :     if (!hashAssumeValid.IsNull())
#    1074         702 :         LogPrintf("Assuming ancestors of block %s have valid signatures.\n", hashAssumeValid.GetHex());
#    1075          51 :     else
#    1076          51 :         LogPrintf("Validating signatures for all blocks.\n");
#    1077         753 : 
#    1078         753 :     if (gArgs.IsArgSet("-minimumchainwork")) {
#    1079           0 :         const std::string minChainWorkStr = gArgs.GetArg("-minimumchainwork", "");
#    1080           0 :         if (!IsHexNumber(minChainWorkStr)) {
#    1081           0 :             return InitError(strprintf(Untranslated("Invalid non-hex (%s) minimum chain work value specified"), minChainWorkStr));
#    1082           0 :         }
#    1083           0 :         nMinimumChainWork = UintToArith256(uint256S(minChainWorkStr));
#    1084         753 :     } else {
#    1085         753 :         nMinimumChainWork = UintToArith256(chainparams.GetConsensus().nMinimumChainWork);
#    1086         753 :     }
#    1087         753 :     LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex());
#    1088         753 :     if (nMinimumChainWork < UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) {
#    1089           0 :         LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainparams.GetConsensus().nMinimumChainWork.GetHex());
#    1090           0 :     }
#    1091         753 : 
#    1092         753 :     // mempool limits
#    1093         753 :     int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
#    1094         753 :     int64_t nMempoolSizeMin = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40;
#    1095         753 :     if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin)
#    1096           0 :         return InitError(strprintf(_("-maxmempool must be at least %d MB"), std::ceil(nMempoolSizeMin / 1000000.0)));
#    1097         753 :     // incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool
#    1098         753 :     // and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.
#    1099         753 :     if (gArgs.IsArgSet("-incrementalrelayfee"))
#    1100           0 :     {
#    1101           0 :         CAmount n = 0;
#    1102           0 :         if (!ParseMoney(gArgs.GetArg("-incrementalrelayfee", ""), n))
#    1103           0 :             return InitError(AmountErrMsg("incrementalrelayfee", gArgs.GetArg("-incrementalrelayfee", "")));
#    1104           0 :         incrementalRelayFee = CFeeRate(n);
#    1105           0 :     }
#    1106         753 : 
#    1107         753 :     // block pruning; get the amount of disk space (in MiB) to allot for block & undo files
#    1108         753 :     int64_t nPruneArg = gArgs.GetArg("-prune", 0);
#    1109         753 :     if (nPruneArg < 0) {
#    1110           0 :         return InitError(_("Prune cannot be configured with a negative value."));
#    1111           0 :     }
#    1112         753 :     nPruneTarget = (uint64_t) nPruneArg * 1024 * 1024;
#    1113         753 :     if (nPruneArg == 1) {  // manual pruning: -prune=1
#    1114           0 :         LogPrintf("Block pruning enabled.  Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
#    1115           0 :         nPruneTarget = std::numeric_limits<uint64_t>::max();
#    1116           0 :         fPruneMode = true;
#    1117         753 :     } else if (nPruneTarget) {
#    1118           0 :         if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) {
#    1119           0 :             return InitError(strprintf(_("Prune configured below the minimum of %d MiB.  Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
#    1120           0 :         }
#    1121           0 :         LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024);
#    1122           0 :         fPruneMode = true;
#    1123           0 :     }
#    1124         753 : 
#    1125         753 :     nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT);
#    1126         753 :     if (nConnectTimeout <= 0) {
#    1127           0 :         nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
#    1128           0 :     }
#    1129         753 : 
#    1130         753 :     peer_connect_timeout = gArgs.GetArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT);
#    1131         753 :     if (peer_connect_timeout <= 0) {
#    1132           0 :         return InitError(Untranslated("peertimeout cannot be configured with a negative value."));
#    1133           0 :     }
#    1134         753 : 
#    1135         753 :     if (gArgs.IsArgSet("-minrelaytxfee")) {
#    1136           0 :         CAmount n = 0;
#    1137           0 :         if (!ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n)) {
#    1138           0 :             return InitError(AmountErrMsg("minrelaytxfee", gArgs.GetArg("-minrelaytxfee", "")));
#    1139           0 :         }
#    1140           0 :         // High fee check is done afterward in CWallet::CreateWalletFromFile()
#    1141           0 :         ::minRelayTxFee = CFeeRate(n);
#    1142         753 :     } else if (incrementalRelayFee > ::minRelayTxFee) {
#    1143           0 :         // Allow only setting incrementalRelayFee to control both
#    1144           0 :         ::minRelayTxFee = incrementalRelayFee;
#    1145           0 :         LogPrintf("Increasing minrelaytxfee to %s to match incrementalrelayfee\n",::minRelayTxFee.ToString());
#    1146           0 :     }
#    1147         753 : 
#    1148         753 :     // Sanity check argument for min fee for including tx in block
#    1149         753 :     // TODO: Harmonize which arguments need sanity checking and where that happens
#    1150         753 :     if (gArgs.IsArgSet("-blockmintxfee"))
#    1151           0 :     {
#    1152           0 :         CAmount n = 0;
#    1153           0 :         if (!ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n))
#    1154           0 :             return InitError(AmountErrMsg("blockmintxfee", gArgs.GetArg("-blockmintxfee", "")));
#    1155         753 :     }
#    1156         753 : 
#    1157         753 :     // Feerate used to define dust.  Shouldn't be changed lightly as old
#    1158         753 :     // implementations may inadvertently create non-standard transactions
#    1159         753 :     if (gArgs.IsArgSet("-dustrelayfee"))
#    1160           0 :     {
#    1161           0 :         CAmount n = 0;
#    1162           0 :         if (!ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n))
#    1163           0 :             return InitError(AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", "")));
#    1164           0 :         dustRelayFee = CFeeRate(n);
#    1165           0 :     }
#    1166         753 : 
#    1167         753 :     fRequireStandard = !gArgs.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
#    1168         753 :     if (!chainparams.IsTestChain() && !fRequireStandard) {
#    1169           0 :         return InitError(strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.NetworkIDString()));
#    1170           0 :     }
#    1171         753 :     nBytesPerSigOp = gArgs.GetArg("-bytespersigop", nBytesPerSigOp);
#    1172         753 : 
#    1173         753 :     if (!g_wallet_init_interface.ParameterInteraction()) return false;
#    1174         753 : 
#    1175         753 :     fIsBareMultisigStd = gArgs.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
#    1176         753 :     fAcceptDatacarrier = gArgs.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
#    1177         753 :     nMaxDatacarrierBytes = gArgs.GetArg("-datacarriersize", nMaxDatacarrierBytes);
#    1178         753 : 
#    1179         753 :     // Option to startup with mocktime set (used for regression testing):
#    1180         753 :     SetMockTime(gArgs.GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
#    1181         753 : 
#    1182         753 :     if (gArgs.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
#    1183           0 :         nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);
#    1184         753 : 
#    1185         753 :     if (gArgs.GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) < 0)
#    1186           0 :         return InitError(Untranslated("rpcserialversion must be non-negative."));
#    1187         753 : 
#    1188         753 :     if (gArgs.GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) > 1)
#    1189           0 :         return InitError(Untranslated("Unknown rpcserialversion requested."));
#    1190         753 : 
#    1191         753 :     nMaxTipAge = gArgs.GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE);
#    1192         753 : 
#    1193         753 :     return true;
#    1194         753 : }
#    1195             : 
#    1196             : static bool LockDataDirectory(bool probeOnly)
#    1197           0 : {
#    1198           0 :     // Make sure only a single Bitcoin process is using the data directory.
#    1199           0 :     fs::path datadir = GetDataDir();
#    1200           0 :     if (!DirIsWritable(datadir)) {
#    1201           0 :         return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), datadir.string()));
#    1202           0 :     }
#    1203           0 :     if (!LockDirectory(datadir, ".lock", probeOnly)) {
#    1204           0 :         return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), datadir.string(), PACKAGE_NAME));
#    1205           0 :     }
#    1206           0 :     return true;
#    1207           0 : }
#    1208             : 
#    1209             : bool AppInitSanityChecks()
#    1210           0 : {
#    1211           0 :     // ********************************************************* Step 4: sanity checks
#    1212           0 : 
#    1213           0 :     // Initialize elliptic curve code
#    1214           0 :     std::string sha256_algo = SHA256AutoDetect();
#    1215           0 :     LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo);
#    1216           0 :     RandomInit();
#    1217           0 :     ECC_Start();
#    1218           0 :     globalVerifyHandle.reset(new ECCVerifyHandle());
#    1219           0 : 
#    1220           0 :     // Sanity check
#    1221           0 :     if (!InitSanityCheck())
#    1222           0 :         return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), PACKAGE_NAME));
#    1223           0 : 
#    1224           0 :     // Probe the data directory lock to give an early error message, if possible
#    1225           0 :     // We cannot hold the data directory lock here, as the forking for daemon() hasn't yet happened,
#    1226           0 :     // and a fork will cause weird behavior to it.
#    1227           0 :     return LockDataDirectory(true);
#    1228           0 : }
#    1229             : 
#    1230             : bool AppInitLockDataDirectory()
#    1231           0 : {
#    1232           0 :     // After daemonization get the data directory lock again and hold on to it until exit
#    1233           0 :     // This creates a slight window for a race condition to happen, however this condition is harmless: it
#    1234           0 :     // will at most make us exit without printing a message to console.
#    1235           0 :     if (!LockDataDirectory(false)) {
#    1236           0 :         // Detailed error printed inside LockDataDirectory
#    1237           0 :         return false;
#    1238           0 :     }
#    1239           0 :     return true;
#    1240           0 : }
#    1241             : 
#    1242             : bool AppInitMain(const util::Ref& context, NodeContext& node)
#    1243           0 : {
#    1244           0 :     const CChainParams& chainparams = Params();
#    1245           0 :     // ********************************************************* Step 4a: application initialization
#    1246           0 :     if (!CreatePidFile()) {
#    1247           0 :         // Detailed error printed inside CreatePidFile().
#    1248           0 :         return false;
#    1249           0 :     }
#    1250           0 :     if (LogInstance().m_print_to_file) {
#    1251           0 :         if (gArgs.GetBoolArg("-shrinkdebugfile", LogInstance().DefaultShrinkDebugFile())) {
#    1252           0 :             // Do this first since it both loads a bunch of debug.log into memory,
#    1253           0 :             // and because this needs to happen before any other debug.log printing
#    1254           0 :             LogInstance().ShrinkDebugFile();
#    1255           0 :         }
#    1256           0 :     }
#    1257           0 :     if (!LogInstance().StartLogging()) {
#    1258           0 :             return InitError(strprintf(Untranslated("Could not open debug log file %s"),
#    1259           0 :                 LogInstance().m_file_path.string()));
#    1260           0 :     }
#    1261           0 : 
#    1262           0 :     if (!LogInstance().m_log_timestamps)
#    1263           0 :         LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
#    1264           0 :     LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
#    1265           0 :     LogPrintf("Using data directory %s\n", GetDataDir().string());
#    1266           0 : 
#    1267           0 :     // Only log conf file usage message if conf file actually exists.
#    1268           0 :     fs::path config_file_path = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
#    1269           0 :     if (fs::exists(config_file_path)) {
#    1270           0 :         LogPrintf("Config file: %s\n", config_file_path.string());
#    1271           0 :     } else if (gArgs.IsArgSet("-conf")) {
#    1272           0 :         // Warn if no conf file exists at path provided by user
#    1273           0 :         InitWarning(strprintf(_("The specified config file %s does not exist\n"), config_file_path.string()));
#    1274           0 :     } else {
#    1275           0 :         // Not categorizing as "Warning" because it's the default behavior
#    1276           0 :         LogPrintf("Config file: %s (not found, skipping)\n", config_file_path.string());
#    1277           0 :     }
#    1278           0 : 
#    1279           0 :     // Log the config arguments to debug.log
#    1280           0 :     gArgs.LogArgs();
#    1281           0 : 
#    1282           0 :     LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
#    1283           0 : 
#    1284           0 :     // Warn about relative -datadir path.
#    1285           0 :     if (gArgs.IsArgSet("-datadir") && !fs::path(gArgs.GetArg("-datadir", "")).is_absolute()) {
#    1286           0 :         LogPrintf("Warning: relative datadir option '%s' specified, which will be interpreted relative to the " /* Continued */
#    1287           0 :                   "current working directory '%s'. This is fragile, because if bitcoin is started in the future "
#    1288           0 :                   "from a different location, it will be unable to locate the current data files. There could "
#    1289           0 :                   "also be data loss if bitcoin is started while in a temporary directory.\n",
#    1290           0 :             gArgs.GetArg("-datadir", ""), fs::current_path().string());
#    1291           0 :     }
#    1292           0 : 
#    1293           0 :     InitSignatureCache();
#    1294           0 :     InitScriptExecutionCache();
#    1295           0 : 
#    1296           0 :     int script_threads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
#    1297           0 :     if (script_threads <= 0) {
#    1298           0 :         // -par=0 means autodetect (number of cores - 1 script threads)
#    1299           0 :         // -par=-n means "leave n cores free" (number of cores - n - 1 script threads)
#    1300           0 :         script_threads += GetNumCores();
#    1301           0 :     }
#    1302           0 : 
#    1303           0 :     // Subtract 1 because the main thread counts towards the par threads
#    1304           0 :     script_threads = std::max(script_threads - 1, 0);
#    1305           0 : 
#    1306           0 :     // Number of script-checking threads <= MAX_SCRIPTCHECK_THREADS
#    1307           0 :     script_threads = std::min(script_threads, MAX_SCRIPTCHECK_THREADS);
#    1308           0 : 
#    1309           0 :     LogPrintf("Script verification uses %d additional threads\n", script_threads);
#    1310           0 :     if (script_threads >= 1) {
#    1311           0 :         g_parallel_script_checks = true;
#    1312           0 :         for (int i = 0; i < script_threads; ++i) {
#    1313           0 :             threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
#    1314           0 :         }
#    1315           0 :     }
#    1316           0 : 
#    1317           0 :     assert(!node.scheduler);
#    1318           0 :     node.scheduler = MakeUnique<CScheduler>();
#    1319           0 : 
#    1320           0 :     // Start the lightweight task scheduler thread
#    1321           0 :     CScheduler::Function serviceLoop = [&node]{ node.scheduler->serviceQueue(); };
#    1322           0 :     threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
#    1323           0 : 
#    1324           0 :     // Gather some entropy once per minute.
#    1325           0 :     node.scheduler->scheduleEvery([]{
#    1326           0 :         RandAddPeriodic();
#    1327           0 :     }, std::chrono::minutes{1});
#    1328           0 : 
#    1329           0 :     GetMainSignals().RegisterBackgroundSignalScheduler(*node.scheduler);
#    1330           0 : 
#    1331           0 :     // Create client interfaces for wallets that are supposed to be loaded
#    1332           0 :     // according to -wallet and -disablewallet options. This only constructs
#    1333           0 :     // the interfaces, it doesn't load wallet data. Wallets actually get loaded
#    1334           0 :     // when load() and start() interface methods are called below.
#    1335           0 :     g_wallet_init_interface.Construct(node);
#    1336           0 : 
#    1337           0 :     /* Register RPC commands regardless of -server setting so they will be
#    1338           0 :      * available in the GUI RPC console even if external calls are disabled.
#    1339           0 :      */
#    1340           0 :     RegisterAllCoreRPCCommands(tableRPC);
#    1341           0 :     for (const auto& client : node.chain_clients) {
#    1342           0 :         client->registerRpcs();
#    1343           0 :     }
#    1344           0 : #if ENABLE_ZMQ
#    1345           0 :     RegisterZMQRPCCommands(tableRPC);
#    1346           0 : #endif
#    1347           0 : 
#    1348           0 :     /* Start the RPC server already.  It will be started in "warmup" mode
#    1349           0 :      * and not really process calls already (but it will signify connections
#    1350           0 :      * that the server is there and will be ready later).  Warmup mode will
#    1351           0 :      * be disabled when initialisation is finished.
#    1352           0 :      */
#    1353           0 :     if (gArgs.GetBoolArg("-server", false))
#    1354           0 :     {
#    1355           0 :         uiInterface.InitMessage_connect(SetRPCWarmupStatus);
#    1356           0 :         if (!AppInitServers(context))
#    1357           0 :             return InitError(_("Unable to start HTTP server. See debug log for details."));
#    1358           0 :     }
#    1359           0 : 
#    1360           0 :     // ********************************************************* Step 5: verify wallet database integrity
#    1361           0 :     for (const auto& client : node.chain_clients) {
#    1362           0 :         if (!client->verify()) {
#    1363           0 :             return false;
#    1364           0 :         }
#    1365           0 :     }
#    1366           0 : 
#    1367           0 :     // ********************************************************* Step 6: network initialization
#    1368           0 :     // Note that we absolutely cannot open any actual connections
#    1369           0 :     // until the very end ("start node") as the UTXO/block state
#    1370           0 :     // is not yet setup and may end up being set up twice if we
#    1371           0 :     // need to reindex later.
#    1372           0 : 
#    1373           0 :     assert(!node.banman);
#    1374           0 :     node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, gArgs.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
#    1375           0 :     assert(!node.connman);
#    1376           0 :     node.connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max())));
#    1377           0 :     // Make mempool generally available in the node context. For example the connection manager, wallet, or RPC threads,
#    1378           0 :     // which are all started after this, may use it from the node context.
#    1379           0 :     assert(!node.mempool);
#    1380           0 :     node.mempool = &::mempool;
#    1381           0 :     assert(!node.chainman);
#    1382           0 :     node.chainman = &g_chainman;
#    1383           0 :     ChainstateManager& chainman = EnsureChainman(node);
#    1384           0 : 
#    1385           0 :     node.peer_logic.reset(new PeerLogicValidation(node.connman.get(), node.banman.get(), *node.scheduler, *node.chainman, *node.mempool));
#    1386           0 :     RegisterValidationInterface(node.peer_logic.get());
#    1387           0 : 
#    1388           0 :     // sanitize comments per BIP-0014, format user agent and check total size
#    1389           0 :     std::vector<std::string> uacomments;
#    1390           0 :     for (const std::string& cmt : gArgs.GetArgs("-uacomment")) {
#    1391           0 :         if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
#    1392           0 :             return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt));
#    1393           0 :         uacomments.push_back(cmt);
#    1394           0 :     }
#    1395           0 :     strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments);
#    1396           0 :     if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
#    1397           0 :         return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments."),
#    1398           0 :             strSubVersion.size(), MAX_SUBVERSION_LENGTH));
#    1399           0 :     }
#    1400           0 : 
#    1401           0 :     if (gArgs.IsArgSet("-onlynet")) {
#    1402           0 :         std::set<enum Network> nets;
#    1403           0 :         for (const std::string& snet : gArgs.GetArgs("-onlynet")) {
#    1404           0 :             enum Network net = ParseNetwork(snet);
#    1405           0 :             if (net == NET_UNROUTABLE)
#    1406           0 :                 return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
#    1407           0 :             nets.insert(net);
#    1408           0 :         }
#    1409           0 :         for (int n = 0; n < NET_MAX; n++) {
#    1410           0 :             enum Network net = (enum Network)n;
#    1411           0 :             if (!nets.count(net))
#    1412           0 :                 SetReachable(net, false);
#    1413           0 :         }
#    1414           0 :     }
#    1415           0 : 
#    1416           0 :     // Check for host lookup allowed before parsing any network related parameters
#    1417           0 :     fNameLookup = gArgs.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
#    1418           0 : 
#    1419           0 :     bool proxyRandomize = gArgs.GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE);
#    1420           0 :     // -proxy sets a proxy for all outgoing network traffic
#    1421           0 :     // -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
#    1422           0 :     std::string proxyArg = gArgs.GetArg("-proxy", "");
#    1423           0 :     SetReachable(NET_ONION, false);
#    1424           0 :     if (proxyArg != "" && proxyArg != "0") {
#    1425           0 :         CService proxyAddr;
#    1426           0 :         if (!Lookup(proxyArg, proxyAddr, 9050, fNameLookup)) {
#    1427           0 :             return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg));
#    1428           0 :         }
#    1429           0 : 
#    1430           0 :         proxyType addrProxy = proxyType(proxyAddr, proxyRandomize);
#    1431           0 :         if (!addrProxy.IsValid())
#    1432           0 :             return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg));
#    1433           0 : 
#    1434           0 :         SetProxy(NET_IPV4, addrProxy);
#    1435           0 :         SetProxy(NET_IPV6, addrProxy);
#    1436           0 :         SetProxy(NET_ONION, addrProxy);
#    1437           0 :         SetNameProxy(addrProxy);
#    1438           0 :         SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
#    1439           0 :     }
#    1440           0 : 
#    1441           0 :     // -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
#    1442           0 :     // -noonion (or -onion=0) disables connecting to .onion entirely
#    1443           0 :     // An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none)
#    1444           0 :     std::string onionArg = gArgs.GetArg("-onion", "");
#    1445           0 :     if (onionArg != "") {
#    1446           0 :         if (onionArg == "0") { // Handle -noonion/-onion=0
#    1447           0 :             SetReachable(NET_ONION, false);
#    1448           0 :         } else {
#    1449           0 :             CService onionProxy;
#    1450           0 :             if (!Lookup(onionArg, onionProxy, 9050, fNameLookup)) {
#    1451           0 :                 return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
#    1452           0 :             }
#    1453           0 :             proxyType addrOnion = proxyType(onionProxy, proxyRandomize);
#    1454           0 :             if (!addrOnion.IsValid())
#    1455           0 :                 return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
#    1456           0 :             SetProxy(NET_ONION, addrOnion);
#    1457           0 :             SetReachable(NET_ONION, true);
#    1458           0 :         }
#    1459           0 :     }
#    1460           0 : 
#    1461           0 :     // see Step 2: parameter interactions for more information about these
#    1462           0 :     fListen = gArgs.GetBoolArg("-listen", DEFAULT_LISTEN);
#    1463           0 :     fDiscover = gArgs.GetBoolArg("-discover", true);
#    1464           0 :     g_relay_txes = !gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
#    1465           0 : 
#    1466           0 :     for (const std::string& strAddr : gArgs.GetArgs("-externalip")) {
#    1467           0 :         CService addrLocal;
#    1468           0 :         if (Lookup(strAddr, addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid())
#    1469           0 :             AddLocal(addrLocal, LOCAL_MANUAL);
#    1470           0 :         else
#    1471           0 :             return InitError(Untranslated(ResolveErrMsg("externalip", strAddr)));
#    1472           0 :     }
#    1473           0 : 
#    1474           0 :     // Read asmap file if configured
#    1475           0 :     if (gArgs.IsArgSet("-asmap")) {
#    1476           0 :         fs::path asmap_path = fs::path(gArgs.GetArg("-asmap", ""));
#    1477           0 :         if (asmap_path.empty()) {
#    1478           0 :             asmap_path = DEFAULT_ASMAP_FILENAME;
#    1479           0 :         }
#    1480           0 :         if (!asmap_path.is_absolute()) {
#    1481           0 :             asmap_path = GetDataDir() / asmap_path;
#    1482           0 :         }
#    1483           0 :         if (!fs::exists(asmap_path)) {
#    1484           0 :             InitError(strprintf(_("Could not find asmap file %s"), asmap_path));
#    1485           0 :             return false;
#    1486           0 :         }
#    1487           0 :         std::vector<bool> asmap = CAddrMan::DecodeAsmap(asmap_path);
#    1488           0 :         if (asmap.size() == 0) {
#    1489           0 :             InitError(strprintf(_("Could not parse asmap file %s"), asmap_path));
#    1490           0 :             return false;
#    1491           0 :         }
#    1492           0 :         const uint256 asmap_version = SerializeHash(asmap);
#    1493           0 :         node.connman->SetAsmap(std::move(asmap));
#    1494           0 :         LogPrintf("Using asmap version %s for IP bucketing\n", asmap_version.ToString());
#    1495           0 :     } else {
#    1496           0 :         LogPrintf("Using /16 prefix for IP bucketing\n");
#    1497           0 :     }
#    1498           0 : 
#    1499           0 : #if ENABLE_ZMQ
#    1500           0 :     g_zmq_notification_interface = CZMQNotificationInterface::Create();
#    1501           0 : 
#    1502           0 :     if (g_zmq_notification_interface) {
#    1503           0 :         RegisterValidationInterface(g_zmq_notification_interface);
#    1504           0 :     }
#    1505           0 : #endif
#    1506           0 :     uint64_t nMaxOutboundLimit = 0; //unlimited unless -maxuploadtarget is set
#    1507           0 :     uint64_t nMaxOutboundTimeframe = MAX_UPLOAD_TIMEFRAME;
#    1508           0 : 
#    1509           0 :     if (gArgs.IsArgSet("-maxuploadtarget")) {
#    1510           0 :         nMaxOutboundLimit = gArgs.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024;
#    1511           0 :     }
#    1512           0 : 
#    1513           0 :     // ********************************************************* Step 7: load block chain
#    1514           0 : 
#    1515           0 :     fReindex = gArgs.GetBoolArg("-reindex", false);
#    1516           0 :     bool fReindexChainState = gArgs.GetBoolArg("-reindex-chainstate", false);
#    1517           0 : 
#    1518           0 :     // cache size calculations
#    1519           0 :     int64_t nTotalCache = (gArgs.GetArg("-dbcache", nDefaultDbCache) << 20);
#    1520           0 :     nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache
#    1521           0 :     nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greater than nMaxDbcache
#    1522           0 :     int64_t nBlockTreeDBCache = std::min(nTotalCache / 8, nMaxBlockDBCache << 20);
#    1523           0 :     nTotalCache -= nBlockTreeDBCache;
#    1524           0 :     int64_t nTxIndexCache = std::min(nTotalCache / 8, gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxTxIndexCache << 20 : 0);
#    1525           0 :     nTotalCache -= nTxIndexCache;
#    1526           0 :     int64_t filter_index_cache = 0;
#    1527           0 :     if (!g_enabled_filter_types.empty()) {
#    1528           0 :         size_t n_indexes = g_enabled_filter_types.size();
#    1529           0 :         int64_t max_cache = std::min(nTotalCache / 8, max_filter_index_cache << 20);
#    1530           0 :         filter_index_cache = max_cache / n_indexes;
#    1531           0 :         nTotalCache -= filter_index_cache * n_indexes;
#    1532           0 :     }
#    1533           0 :     int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache
#    1534           0 :     nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache
#    1535           0 :     nTotalCache -= nCoinDBCache;
#    1536           0 :     nCoinCacheUsage = nTotalCache; // the rest goes to in-memory cache
#    1537           0 :     int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
#    1538           0 :     LogPrintf("Cache configuration:\n");
#    1539           0 :     LogPrintf("* Using %.1f MiB for block index database\n", nBlockTreeDBCache * (1.0 / 1024 / 1024));
#    1540           0 :     if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
#    1541           0 :         LogPrintf("* Using %.1f MiB for transaction index database\n", nTxIndexCache * (1.0 / 1024 / 1024));
#    1542           0 :     }
#    1543           0 :     for (BlockFilterType filter_type : g_enabled_filter_types) {
#    1544           0 :         LogPrintf("* Using %.1f MiB for %s block filter index database\n",
#    1545           0 :                   filter_index_cache * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type));
#    1546           0 :     }
#    1547           0 :     LogPrintf("* Using %.1f MiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
#    1548           0 :     LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", nCoinCacheUsage * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));
#    1549           0 : 
#    1550           0 :     bool fLoaded = false;
#    1551           0 :     while (!fLoaded && !ShutdownRequested()) {
#    1552           0 :         bool fReset = fReindex;
#    1553           0 :         auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
#    1554           0 :             return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull();
#    1555           0 :         };
#    1556           0 :         bilingual_str strLoadError;
#    1557           0 : 
#    1558           0 :         uiInterface.InitMessage(_("Loading block index...").translated);
#    1559           0 : 
#    1560           0 :         do {
#    1561           0 :             const int64_t load_block_index_start_time = GetTimeMillis();
#    1562           0 :             try {
#    1563           0 :                 LOCK(cs_main);
#    1564           0 :                 chainman.InitializeChainstate();
#    1565           0 :                 UnloadBlockIndex();
#    1566           0 : 
#    1567           0 :                 // new CBlockTreeDB tries to delete the existing file, which
#    1568           0 :                 // fails if it's still open from the previous loop. Close it first:
#    1569           0 :                 pblocktree.reset();
#    1570           0 :                 pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset));
#    1571           0 : 
#    1572           0 :                 if (fReset) {
#    1573           0 :                     pblocktree->WriteReindexing(true);
#    1574           0 :                     //If we're reindexing in prune mode, wipe away unusable block files and all undo data files
#    1575           0 :                     if (fPruneMode)
#    1576           0 :                         CleanupBlockRevFiles();
#    1577           0 :                 }
#    1578           0 : 
#    1579           0 :                 if (ShutdownRequested()) break;
#    1580           0 : 
#    1581           0 :                 // LoadBlockIndex will load fHavePruned if we've ever removed a
#    1582           0 :                 // block file from disk.
#    1583           0 :                 // Note that it also sets fReindex based on the disk flag!
#    1584           0 :                 // From here on out fReindex and fReset mean something different!
#    1585           0 :                 if (!chainman.LoadBlockIndex(chainparams)) {
#    1586           0 :                     if (ShutdownRequested()) break;
#    1587           0 :                     strLoadError = _("Error loading block database");
#    1588           0 :                     break;
#    1589           0 :                 }
#    1590           0 : 
#    1591           0 :                 // If the loaded chain has a wrong genesis, bail out immediately
#    1592           0 :                 // (we're likely using a testnet datadir, or the other way around).
#    1593           0 :                 if (!::BlockIndex().empty() &&
#    1594           0 :                         !LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
#    1595           0 :                     return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
#    1596           0 :                 }
#    1597           0 : 
#    1598           0 :                 // Check for changed -prune state.  What we are concerned about is a user who has pruned blocks
#    1599           0 :                 // in the past, but is now trying to run unpruned.
#    1600           0 :                 if (fHavePruned && !fPruneMode) {
#    1601           0 :                     strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode.  This will redownload the entire blockchain");
#    1602           0 :                     break;
#    1603           0 :                 }
#    1604           0 : 
#    1605           0 :                 // At this point blocktree args are consistent with what's on disk.
#    1606           0 :                 // If we're not mid-reindex (based on disk + args), add a genesis block on disk
#    1607           0 :                 // (otherwise we use the one already on disk).
#    1608           0 :                 // This is called again in ThreadImport after the reindex completes.
#    1609           0 :                 if (!fReindex && !LoadGenesisBlock(chainparams)) {
#    1610           0 :                     strLoadError = _("Error initializing block database");
#    1611           0 :                     break;
#    1612           0 :                 }
#    1613           0 : 
#    1614           0 :                 // At this point we're either in reindex or we've loaded a useful
#    1615           0 :                 // block tree into BlockIndex()!
#    1616           0 : 
#    1617           0 :                 bool failed_chainstate_init = false;
#    1618           0 : 
#    1619           0 :                 for (CChainState* chainstate : chainman.GetAll()) {
#    1620           0 :                     LogPrintf("Initializing chainstate %s\n", chainstate->ToString());
#    1621           0 :                     chainstate->InitCoinsDB(
#    1622           0 :                         /* cache_size_bytes */ nCoinDBCache,
#    1623           0 :                         /* in_memory */ false,
#    1624           0 :                         /* should_wipe */ fReset || fReindexChainState);
#    1625           0 : 
#    1626           0 :                     chainstate->CoinsErrorCatcher().AddReadErrCallback([]() {
#    1627           0 :                         uiInterface.ThreadSafeMessageBox(
#    1628           0 :                             _("Error reading from database, shutting down."),
#    1629           0 :                             "", CClientUIInterface::MSG_ERROR);
#    1630           0 :                     });
#    1631           0 : 
#    1632           0 :                     // If necessary, upgrade from older database format.
#    1633           0 :                     // This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
#    1634           0 :                     if (!chainstate->CoinsDB().Upgrade()) {
#    1635           0 :                         strLoadError = _("Error upgrading chainstate database");
#    1636           0 :                         failed_chainstate_init = true;
#    1637           0 :                         break;
#    1638           0 :                     }
#    1639           0 : 
#    1640           0 :                     // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
#    1641           0 :                     if (!chainstate->ReplayBlocks(chainparams)) {
#    1642           0 :                         strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.");
#    1643           0 :                         failed_chainstate_init = true;
#    1644           0 :                         break;
#    1645           0 :                     }
#    1646           0 : 
#    1647           0 :                     // The on-disk coinsdb is now in a good state, create the cache
#    1648           0 :                     chainstate->InitCoinsCache();
#    1649           0 :                     assert(chainstate->CanFlushToDisk());
#    1650           0 : 
#    1651           0 :                     if (!is_coinsview_empty(chainstate)) {
#    1652           0 :                         // LoadChainTip initializes the chain based on CoinsTip()'s best block
#    1653           0 :                         if (!chainstate->LoadChainTip(chainparams)) {
#    1654           0 :                             strLoadError = _("Error initializing block database");
#    1655           0 :                             failed_chainstate_init = true;
#    1656           0 :                             break; // out of the per-chainstate loop
#    1657           0 :                         }
#    1658           0 :                         assert(chainstate->m_chain.Tip() != nullptr);
#    1659           0 :                     }
#    1660           0 :                 }
#    1661           0 : 
#    1662           0 :                 if (failed_chainstate_init) {
#    1663           0 :                     break; // out of the chainstate activation do-while
#    1664           0 :                 }
#    1665           0 :             } catch (const std::exception& e) {
#    1666           0 :                 LogPrintf("%s\n", e.what());
#    1667           0 :                 strLoadError = _("Error opening block database");
#    1668           0 :                 break;
#    1669           0 :             }
#    1670           0 : 
#    1671           0 :             bool failed_rewind{false};
#    1672           0 :             // Can't hold cs_main while calling RewindBlockIndex, so retrieve the relevant
#    1673           0 :             // chainstates beforehand.
#    1674           0 :             for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
#    1675           0 :                 if (!fReset) {
#    1676           0 :                     // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
#    1677           0 :                     // It both disconnects blocks based on the chainstate, and drops block data in
#    1678           0 :                     // BlockIndex() based on lack of available witness data.
#    1679           0 :                     uiInterface.InitMessage(_("Rewinding blocks...").translated);
#    1680           0 :                     if (!chainstate->RewindBlockIndex(chainparams)) {
#    1681           0 :                         strLoadError = _(
#    1682           0 :                             "Unable to rewind the database to a pre-fork state. "
#    1683           0 :                             "You will need to redownload the blockchain");
#    1684           0 :                         failed_rewind = true;
#    1685           0 :                         break; // out of the per-chainstate loop
#    1686           0 :                     }
#    1687           0 :                 }
#    1688           0 :             }
#    1689           0 : 
#    1690           0 :             if (failed_rewind) {
#    1691           0 :                 break; // out of the chainstate activation do-while
#    1692           0 :             }
#    1693           0 : 
#    1694           0 :             bool failed_verification = false;
#    1695           0 : 
#    1696           0 :             try {
#    1697           0 :                 LOCK(cs_main);
#    1698           0 : 
#    1699           0 :                 for (CChainState* chainstate : chainman.GetAll()) {
#    1700           0 :                     if (!is_coinsview_empty(chainstate)) {
#    1701           0 :                         uiInterface.InitMessage(_("Verifying blocks...").translated);
#    1702           0 :                         if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
#    1703           0 :                             LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n",
#    1704           0 :                                 MIN_BLOCKS_TO_KEEP);
#    1705           0 :                         }
#    1706           0 : 
#    1707           0 :                         const CBlockIndex* tip = chainstate->m_chain.Tip();
#    1708           0 :                         RPCNotifyBlockChange(tip);
#    1709           0 :                         if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
#    1710           0 :                             strLoadError = _("The block database contains a block which appears to be from the future. "
#    1711           0 :                                     "This may be due to your computer's date and time being set incorrectly. "
#    1712           0 :                                     "Only rebuild the block database if you are sure that your computer's date and time are correct");
#    1713           0 :                             failed_verification = true;
#    1714           0 :                             break;
#    1715           0 :                         }
#    1716           0 : 
#    1717           0 :                         // Only verify the DB of the active chainstate. This is fixed in later
#    1718           0 :                         // work when we allow VerifyDB to be parameterized by chainstate.
#    1719           0 :                         if (&::ChainstateActive() == chainstate &&
#    1720           0 :                                 !CVerifyDB().VerifyDB(
#    1721           0 :                                 chainparams, &chainstate->CoinsDB(),
#    1722           0 :                                 gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
#    1723           0 :                                 gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
#    1724           0 :                             strLoadError = _("Corrupted block database detected");
#    1725           0 :                             failed_verification = true;
#    1726           0 :                             break;
#    1727           0 :                         }
#    1728           0 :                     }
#    1729           0 :                 }
#    1730           0 :             } catch (const std::exception& e) {
#    1731           0 :                 LogPrintf("%s\n", e.what());
#    1732           0 :                 strLoadError = _("Error opening block database");
#    1733           0 :                 failed_verification = true;
#    1734           0 :                 break;
#    1735           0 :             }
#    1736           0 : 
#    1737           0 :             if (!failed_verification) {
#    1738           0 :                 fLoaded = true;
#    1739           0 :                 LogPrintf(" block index %15dms\n", GetTimeMillis() - load_block_index_start_time);
#    1740           0 :             }
#    1741           0 :         } while(false);
#    1742           0 : 
#    1743           0 :         if (!fLoaded && !ShutdownRequested()) {
#    1744           0 :             // first suggest a reindex
#    1745           0 :             if (!fReset) {
#    1746           0 :                 bool fRet = uiInterface.ThreadSafeQuestion(
#    1747           0 :                     strLoadError + Untranslated(".\n\n") + _("Do you want to rebuild the block database now?"),
#    1748           0 :                     strLoadError.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.",
#    1749           0 :                     "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT);
#    1750           0 :                 if (fRet) {
#    1751           0 :                     fReindex = true;
#    1752           0 :                     AbortShutdown();
#    1753           0 :                 } else {
#    1754           0 :                     LogPrintf("Aborted block database rebuild. Exiting.\n");
#    1755           0 :                     return false;
#    1756           0 :                 }
#    1757           0 :             } else {
#    1758           0 :                 return InitError(strLoadError);
#    1759           0 :             }
#    1760           0 :         }
#    1761           0 :     }
#    1762           0 : 
#    1763           0 :     // As LoadBlockIndex can take several minutes, it's possible the user
#    1764           0 :     // requested to kill the GUI during the last operation. If so, exit.
#    1765           0 :     // As the program has not fully started yet, Shutdown() is possibly overkill.
#    1766           0 :     if (ShutdownRequested()) {
#    1767           0 :         LogPrintf("Shutdown requested. Exiting.\n");
#    1768           0 :         return false;
#    1769           0 :     }
#    1770           0 : 
#    1771           0 :     fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
#    1772           0 :     CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION);
#    1773           0 :     // Allowed to fail as this file IS missing on first startup.
#    1774           0 :     if (!est_filein.IsNull())
#    1775           0 :         ::feeEstimator.Read(est_filein);
#    1776           0 :     fFeeEstimatesInitialized = true;
#    1777           0 : 
#    1778           0 :     // ********************************************************* Step 8: start indexers
#    1779           0 :     if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
#    1780           0 :         g_txindex = MakeUnique<TxIndex>(nTxIndexCache, false, fReindex);
#    1781           0 :         g_txindex->Start();
#    1782           0 :     }
#    1783           0 : 
#    1784           0 :     for (const auto& filter_type : g_enabled_filter_types) {
#    1785           0 :         InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex);
#    1786           0 :         GetBlockFilterIndex(filter_type)->Start();
#    1787           0 :     }
#    1788           0 : 
#    1789           0 :     // ********************************************************* Step 9: load wallet
#    1790           0 :     for (const auto& client : node.chain_clients) {
#    1791           0 :         if (!client->load()) {
#    1792           0 :             return false;
#    1793           0 :         }
#    1794           0 :     }
#    1795           0 : 
#    1796           0 :     // ********************************************************* Step 10: data directory maintenance
#    1797           0 : 
#    1798           0 :     // if pruning, unset the service bit and perform the initial blockstore prune
#    1799           0 :     // after any wallet rescanning has taken place.
#    1800           0 :     if (fPruneMode) {
#    1801           0 :         LogPrintf("Unsetting NODE_NETWORK on prune mode\n");
#    1802           0 :         nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK);
#    1803           0 :         if (!fReindex) {
#    1804           0 :             LOCK(cs_main);
#    1805           0 :             for (CChainState* chainstate : chainman.GetAll()) {
#    1806           0 :                 uiInterface.InitMessage(_("Pruning blockstore...").translated);
#    1807           0 :                 chainstate->PruneAndFlush();
#    1808           0 :             }
#    1809           0 :         }
#    1810           0 :     }
#    1811           0 : 
#    1812           0 :     if (chainparams.GetConsensus().SegwitHeight != std::numeric_limits<int>::max()) {
#    1813           0 :         // Advertise witness capabilities.
#    1814           0 :         // The option to not set NODE_WITNESS is only used in the tests and should be removed.
#    1815           0 :         nLocalServices = ServiceFlags(nLocalServices | NODE_WITNESS);
#    1816           0 :     }
#    1817           0 : 
#    1818           0 :     // ********************************************************* Step 11: import blocks
#    1819           0 : 
#    1820           0 :     if (!CheckDiskSpace(GetDataDir())) {
#    1821           0 :         InitError(strprintf(_("Error: Disk space is low for %s"), GetDataDir()));
#    1822           0 :         return false;
#    1823           0 :     }
#    1824           0 :     if (!CheckDiskSpace(GetBlocksDir())) {
#    1825           0 :         InitError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir()));
#    1826           0 :         return false;
#    1827           0 :     }
#    1828           0 : 
#    1829           0 :     // Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
#    1830           0 :     // No locking, as this happens before any background thread is started.
#    1831           0 :     boost::signals2::connection block_notify_genesis_wait_connection;
#    1832           0 :     if (::ChainActive().Tip() == nullptr) {
#    1833           0 :         block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(std::bind(BlockNotifyGenesisWait, std::placeholders::_2));
#    1834           0 :     } else {
#    1835           0 :         fHaveGenesis = true;
#    1836           0 :     }
#    1837           0 : 
#    1838           0 : #if HAVE_SYSTEM
#    1839           0 :     if (gArgs.IsArgSet("-blocknotify"))
#    1840           0 :         uiInterface.NotifyBlockTip_connect(BlockNotifyCallback);
#    1841           0 : #endif
#    1842           0 : 
#    1843           0 :     std::vector<fs::path> vImportFiles;
#    1844           0 :     for (const std::string& strFile : gArgs.GetArgs("-loadblock")) {
#    1845           0 :         vImportFiles.push_back(strFile);
#    1846           0 :     }
#    1847           0 : 
#    1848           0 :     threadGroup.create_thread([=, &chainman] { ThreadImport(chainman, vImportFiles); });
#    1849           0 : 
#    1850           0 :     // Wait for genesis block to be processed
#    1851           0 :     {
#    1852           0 :         WAIT_LOCK(g_genesis_wait_mutex, lock);
#    1853           0 :         // We previously could hang here if StartShutdown() is called prior to
#    1854           0 :         // ThreadImport getting started, so instead we just wait on a timer to
#    1855           0 :         // check ShutdownRequested() regularly.
#    1856           0 :         while (!fHaveGenesis && !ShutdownRequested()) {
#    1857           0 :             g_genesis_wait_cv.wait_for(lock, std::chrono::milliseconds(500));
#    1858           0 :         }
#    1859           0 :         block_notify_genesis_wait_connection.disconnect();
#    1860           0 :     }
#    1861           0 : 
#    1862           0 :     if (ShutdownRequested()) {
#    1863           0 :         return false;
#    1864           0 :     }
#    1865           0 : 
#    1866           0 :     // ********************************************************* Step 12: start node
#    1867           0 : 
#    1868           0 :     int chain_active_height;
#    1869           0 : 
#    1870           0 :     //// debug print
#    1871           0 :     {
#    1872           0 :         LOCK(cs_main);
#    1873           0 :         LogPrintf("block tree size = %u\n", ::BlockIndex().size());
#    1874           0 :         chain_active_height = ::ChainActive().Height();
#    1875           0 :     }
#    1876           0 :     LogPrintf("nBestHeight = %d\n", chain_active_height);
#    1877           0 : 
#    1878           0 :     if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
#    1879           0 :         StartTorControl();
#    1880           0 : 
#    1881           0 :     Discover();
#    1882           0 : 
#    1883           0 :     // Map ports with UPnP
#    1884           0 :     if (gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)) {
#    1885           0 :         StartMapPort();
#    1886           0 :     }
#    1887           0 : 
#    1888           0 :     CConnman::Options connOptions;
#    1889           0 :     connOptions.nLocalServices = nLocalServices;
#    1890           0 :     connOptions.nMaxConnections = nMaxConnections;
#    1891           0 :     connOptions.m_max_outbound_full_relay = std::min(MAX_OUTBOUND_FULL_RELAY_CONNECTIONS, connOptions.nMaxConnections);
#    1892           0 :     connOptions.m_max_outbound_block_relay = std::min(MAX_BLOCKS_ONLY_CONNECTIONS, connOptions.nMaxConnections-connOptions.m_max_outbound_full_relay);
#    1893           0 :     connOptions.nMaxAddnode = MAX_ADDNODE_CONNECTIONS;
#    1894           0 :     connOptions.nMaxFeeler = MAX_FEELER_CONNECTIONS;
#    1895           0 :     connOptions.nBestHeight = chain_active_height;
#    1896           0 :     connOptions.uiInterface = &uiInterface;
#    1897           0 :     connOptions.m_banman = node.banman.get();
#    1898           0 :     connOptions.m_msgproc = node.peer_logic.get();
#    1899           0 :     connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
#    1900           0 :     connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
#    1901           0 :     connOptions.m_added_nodes = gArgs.GetArgs("-addnode");
#    1902           0 : 
#    1903           0 :     connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe;
#    1904           0 :     connOptions.nMaxOutboundLimit = nMaxOutboundLimit;
#    1905           0 :     connOptions.m_peer_connect_timeout = peer_connect_timeout;
#    1906           0 : 
#    1907           0 :     for (const std::string& strBind : gArgs.GetArgs("-bind")) {
#    1908           0 :         CService addrBind;
#    1909           0 :         if (!Lookup(strBind, addrBind, GetListenPort(), false)) {
#    1910           0 :             return InitError(Untranslated(ResolveErrMsg("bind", strBind)));
#    1911           0 :         }
#    1912           0 :         connOptions.vBinds.push_back(addrBind);
#    1913           0 :     }
#    1914           0 :     for (const std::string& strBind : gArgs.GetArgs("-whitebind")) {
#    1915           0 :         NetWhitebindPermissions whitebind;
#    1916           0 :         std::string error;
#    1917           0 :         if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) return InitError(Untranslated(error));
#    1918           0 :         connOptions.vWhiteBinds.push_back(whitebind);
#    1919           0 :     }
#    1920           0 : 
#    1921           0 :     for (const auto& net : gArgs.GetArgs("-whitelist")) {
#    1922           0 :         NetWhitelistPermissions subnet;
#    1923           0 :         std::string error;
#    1924           0 :         if (!NetWhitelistPermissions::TryParse(net, subnet, error)) return InitError(Untranslated(error));
#    1925           0 :         connOptions.vWhitelistedRange.push_back(subnet);
#    1926           0 :     }
#    1927           0 : 
#    1928           0 :     connOptions.vSeedNodes = gArgs.GetArgs("-seednode");
#    1929           0 : 
#    1930           0 :     // Initiate outbound connections unless connect=0
#    1931           0 :     connOptions.m_use_addrman_outgoing = !gArgs.IsArgSet("-connect");
#    1932           0 :     if (!connOptions.m_use_addrman_outgoing) {
#    1933           0 :         const auto connect = gArgs.GetArgs("-connect");
#    1934           0 :         if (connect.size() != 1 || connect[0] != "0") {
#    1935           0 :             connOptions.m_specified_outgoing = connect;
#    1936           0 :         }
#    1937           0 :     }
#    1938           0 :     if (!node.connman->Start(*node.scheduler, connOptions)) {
#    1939           0 :         return false;
#    1940           0 :     }
#    1941           0 : 
#    1942           0 :     // ********************************************************* Step 13: finished
#    1943           0 : 
#    1944           0 :     SetRPCWarmupFinished();
#    1945           0 :     uiInterface.InitMessage(_("Done loading").translated);
#    1946           0 : 
#    1947           0 :     for (const auto& client : node.chain_clients) {
#    1948           0 :         client->start(*node.scheduler);
#    1949           0 :     }
#    1950           0 : 
#    1951           0 :     BanMan* banman = node.banman.get();
#    1952           0 :     node.scheduler->scheduleEvery([banman]{
#    1953           0 :         banman->DumpBanlist();
#    1954           0 :     }, DUMP_BANS_INTERVAL);
#    1955           0 : 
#    1956           0 :     return true;
#    1957           0 : }

Generated by: LCOV version 1.14