LCOV - code coverage report
Current view: top level - src - init.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 902 1109 81.3 %
Date: 2020-09-26 01:30:44 Functions: 61 68 89.7 %

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

Generated by: LCOV version 1.15