diff options
Diffstat (limited to 'src/init.cpp')
| -rw-r--r-- | src/init.cpp | 358 |
1 files changed, 225 insertions, 133 deletions
diff --git a/src/init.cpp b/src/init.cpp index 3ab97be32..6625080c6 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -11,14 +11,16 @@ #include <addrman.h> #include <amount.h> +#include <banman.h> +#include <blockfilter.h> #include <chain.h> #include <chainparams.h> -#include <checkpoints.h> #include <compat/sanity.h> #include <consensus/validation.h> #include <fs.h> #include <httpserver.h> #include <httprpc.h> +#include <index/blockfilterindex.h> #include <interfaces/chain.h> #include <index/txindex.h> #include <key.h> @@ -30,6 +32,7 @@ #include <policy/feerate.h> #include <policy/fees.h> #include <policy/policy.h> +#include <policy/settings.h> #include <rpc/server.h> #include <rpc/register.h> #include <rpc/blockchain.h> @@ -38,6 +41,7 @@ #include <script/sigcache.h> #include <scheduler.h> #include <shutdown.h> +#include <util/threadnames.h> #include <timedata.h> #include <txdb.h> #include <txmempool.h> @@ -45,13 +49,15 @@ #include <ui_interface.h> #include <util/system.h> #include <util/moneystr.h> +#include <util/validation.h> #include <validationinterface.h> -#include <warnings.h> #include <walletinitinterface.h> #include <stdint.h> #include <stdio.h> #ifndef WIN32 +#include <attributes.h> +#include <cerrno> #include <signal.h> #include <sys/stat.h> #endif @@ -59,9 +65,7 @@ #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> -#include <boost/bind.hpp> #include <boost/thread.hpp> -#include <openssl/crypto.h> #if ENABLE_ZMQ #include <zmq/zmqabstractnotifier.h> @@ -69,13 +73,17 @@ #include <zmq/zmqrpc.h> #endif -bool fFeeEstimatesInitialized = false; +static bool fFeeEstimatesInitialized = false; static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_REST_ENABLE = false; static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false; +// Dump addresses to banlist.dat every 15 minutes (900s) +static constexpr int DUMP_BANS_INTERVAL = 60 * 15; + std::unique_ptr<CConnman> g_connman; std::unique_ptr<PeerLogicValidation> peerLogic; +std::unique_ptr<BanMan> g_banman; #ifdef WIN32 // Win32 LevelDB doesn't use filedescriptors, and the ones used for @@ -88,6 +96,31 @@ std::unique_ptr<PeerLogicValidation> peerLogic; static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; +/** + * The PID file facilities. + */ +static const char* BITCOIN_PID_FILENAME = "bitcoind.pid"; + +static fs::path GetPidFile() +{ + return AbsPathForConfigVal(fs::path(gArgs.GetArg("-pid", BITCOIN_PID_FILENAME))); +} + +NODISCARD static bool CreatePidFile() +{ + fsbridge::ofstream file{GetPidFile()}; + if (file) { +#ifdef WIN32 + tfm::format(file, "%d\n", GetCurrentProcessId()); +#else + tfm::format(file, "%d\n", getpid()); +#endif + return true; + } else { + return InitError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile().string(), std::strerror(errno))); + } +} + ////////////////////////////////////////////////////////////////////////////// // // Shutdown @@ -157,6 +190,7 @@ void Interrupt() if (g_txindex) { g_txindex->Interrupt(); } + ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Interrupt(); }); } void Shutdown(InitInterfaces& interfaces) @@ -171,7 +205,7 @@ void Shutdown(InitInterfaces& interfaces) /// for example if the data directory was found to be locked. /// Be sure that anything that writes files or flushes caches only does this if the respective /// module was initialized. - RenameThread("bitcoin-shutoff"); + util::ThreadRename("shutoff"); mempool.AddTransactionsUpdated(1); StopHTTPRPC(); @@ -188,6 +222,7 @@ void Shutdown(InitInterfaces& interfaces) if (peerLogic) UnregisterValidationInterface(peerLogic.get()); if (g_connman) g_connman->Stop(); if (g_txindex) g_txindex->Stop(); + ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Stop(); }); StopTorControl(); @@ -200,10 +235,12 @@ void Shutdown(InitInterfaces& interfaces) // destruct and reset all to nullptr. peerLogic.reset(); g_connman.reset(); + g_banman.reset(); g_txindex.reset(); + DestroyAllBlockFilterIndexes(); - if (g_is_mempool_loaded && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { - DumpMempool(); + if (::mempool.IsLoaded() && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { + DumpMempool(::mempool); } if (fFeeEstimatesInitialized) @@ -220,7 +257,7 @@ void Shutdown(InitInterfaces& interfaces) // FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing if (pcoinsTip != nullptr) { - FlushStateToDisk(); + ::ChainstateActive().ForceFlushStateToDisk(); } // After there are no more peers/RPC left to give us new data which may generate @@ -236,7 +273,7 @@ void Shutdown(InitInterfaces& interfaces) { LOCK(cs_main); if (pcoinsTip != nullptr) { - FlushStateToDisk(); + ::ChainstateActive().ForceFlushStateToDisk(); } pcoinsTip.reset(); pcoinscatcher.reset(); @@ -255,17 +292,17 @@ void Shutdown(InitInterfaces& interfaces) } #endif -#ifndef WIN32 try { - fs::remove(GetPidFile()); + if (!fs::remove(GetPidFile())) { + LogPrintf("%s: Unable to remove PID file: File does not exist\n", __func__); + } } catch (const fs::filesystem_error& e) { - LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what()); + LogPrintf("%s: Unable to remove PID file: %s\n", __func__, fsbridge::get_filesystem_error_message(e)); } -#endif + interfaces.chain_clients.clear(); UnregisterAllValidationInterfaces(); GetMainSignals().UnregisterBackgroundSignalScheduler(); GetMainSignals().UnregisterWithMempoolSignals(mempool); - interfaces.chain_clients.clear(); globalVerifyHandle.reset(); ECC_Stop(); LogPrintf("%s: done\n", __func__); @@ -284,7 +321,7 @@ static void HandleSIGTERM(int) static void HandleSIGHUP(int) { - g_logger->m_reopen_file = true; + LogInstance().m_reopen_file = true; } #else static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType) @@ -306,14 +343,15 @@ static void registerSignalHandler(int signal, void(*handler)(int)) } #endif +static boost::signals2::connection rpc_notify_block_change_connection; static void OnRPCStarted() { - uiInterface.NotifyBlockTip_connect(&RPCNotifyBlockChange); + rpc_notify_block_change_connection = uiInterface.NotifyBlockTip_connect(&RPCNotifyBlockChange); } static void OnRPCStopped() { - uiInterface.NotifyBlockTip_disconnect(&RPCNotifyBlockChange); + rpc_notify_block_change_connection.disconnect(); RPCNotifyBlockChange(false, nullptr); g_best_block_cv.notify_all(); LogPrint(BCLog::RPC, "RPC stopped.\n"); @@ -321,6 +359,9 @@ static void OnRPCStopped() void SetupServerArgs() { + SetupHelpOptions(gArgs); + gArgs.AddArg("-help-debug", "Print help message with debugging options and exit", false, OptionsCategory::DEBUG_TEST); // server-only for now + const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN); const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET); const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST); @@ -329,25 +370,22 @@ void SetupServerArgs() const auto regtestChainParams = CreateChainParams(CBaseChainParams::REGTEST); // Hidden Options - std::vector<std::string> hidden_args = {"-h", "-help", + std::vector<std::string> hidden_args = { "-dbcrashratio", "-forcecompactdb", // GUI args. These will be overwritten by SetupUIArgs for the GUI "-allowselfsignedrootcertificates", "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-rootcertificates=<file>", "-splash", "-uiplatform"}; - // Set all of the args and their help - // When adding new options to the categories, please keep and ensure alphabetical ordering. - gArgs.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS); gArgs.AddArg("-version", "Print version and exit", false, OptionsCategory::OPTIONS); gArgs.AddArg("-alertnotify=<cmd>", "Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)", false, OptionsCategory::OPTIONS); gArgs.AddArg("-assumevalid=<hex>", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()), false, OptionsCategory::OPTIONS); - gArgs.AddArg("-blocksdir=<dir>", "Specify blocks directory (default: <datadir>/blocks)", false, OptionsCategory::OPTIONS); + gArgs.AddArg("-blocksdir=<dir>", "Specify directory to hold blocks subdirectory for *.dat files (default: <datadir>)", false, OptionsCategory::OPTIONS); gArgs.AddArg("-blocknotify=<cmd>", "Execute command when the best block changes (%s in cmd is replaced by block hash)", false, OptionsCategory::OPTIONS); gArgs.AddArg("-blockreconstructionextratxn=<n>", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), false, OptionsCategory::OPTIONS); - gArgs.AddArg("-blocksonly", strprintf("Whether to operate in a blocks only mode (default: %u)", DEFAULT_BLOCKSONLY), true, OptionsCategory::OPTIONS); + gArgs.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Transactions from the wallet or RPC are not affected. (default: %u)", DEFAULT_BLOCKSONLY), false, OptionsCategory::OPTIONS); gArgs.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), false, OptionsCategory::OPTIONS); gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS); gArgs.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), true, OptionsCategory::OPTIONS); - gArgs.AddArg("-dbcache=<n>", strprintf("Set database cache size in megabytes (%d to %d, default: %d)", nMinDbCache, nMaxDbCache, nDefaultDbCache), false, OptionsCategory::OPTIONS); + gArgs.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (%d to %d, default: %d). In addition, unused mempool memory is shared for this cache (see -maxmempool).", nMinDbCache, nMaxDbCache, nDefaultDbCache), false, OptionsCategory::OPTIONS); gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (-nodebuglogfile to disable; default: %s)", DEFAULT_DEBUGLOGFILE), false, OptionsCategory::OPTIONS); gArgs.AddArg("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER), true, OptionsCategory::OPTIONS); gArgs.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", false, OptionsCategory::OPTIONS); @@ -359,11 +397,7 @@ void SetupServerArgs() gArgs.AddArg("-par=<n>", strprintf("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)", -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), false, OptionsCategory::OPTIONS); gArgs.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), false, OptionsCategory::OPTIONS); -#ifndef WIN32 gArgs.AddArg("-pid=<file>", strprintf("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", BITCOIN_PID_FILENAME), false, OptionsCategory::OPTIONS); -#else - hidden_args.emplace_back("-pid"); -#endif gArgs.AddArg("-prune=<n>", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. " "Warning: Reverting this setting requires re-downloading the entire blockchain. " "(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), false, OptionsCategory::OPTIONS); @@ -375,6 +409,10 @@ void SetupServerArgs() hidden_args.emplace_back("-sysperms"); #endif gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), false, OptionsCategory::OPTIONS); + gArgs.AddArg("-blockfilterindex=<type>", + strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) + + " If <type> is not supplied or if <type> = 1, indexes for all known types are enabled.", + false, OptionsCategory::OPTIONS); gArgs.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info). This option can be specified multiple times to add multiple nodes.", false, OptionsCategory::CONNECTION); gArgs.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), false, OptionsCategory::CONNECTION); @@ -403,6 +441,7 @@ void SetupServerArgs() gArgs.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), false, OptionsCategory::CONNECTION); gArgs.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes.", false, OptionsCategory::CONNECTION); gArgs.AddArg("-timeout=<n>", strprintf("Specify connection timeout in milliseconds (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT), false, OptionsCategory::CONNECTION); + gArgs.AddArg("-peertimeout=<n>", strprintf("Specify p2p connection timeout in seconds. This option determines the amount of time a peer may be inactive before the connection to it is dropped. (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), true, OptionsCategory::CONNECTION); gArgs.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control port to use if onion listening enabled (default: %s)", DEFAULT_TOR_CONTROL), false, OptionsCategory::CONNECTION); gArgs.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", false, OptionsCategory::CONNECTION); #ifdef USE_UPNP @@ -416,7 +455,7 @@ void SetupServerArgs() #endif gArgs.AddArg("-whitebind=<addr>", "Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6", false, OptionsCategory::CONNECTION); gArgs.AddArg("-whitelist=<IP address or network>", "Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times." - " Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway", false, OptionsCategory::CONNECTION); + " Whitelisted peers cannot be DoS banned", false, OptionsCategory::CONNECTION); g_wallet_init_interface.AddWalletOptions(); @@ -449,7 +488,7 @@ void SetupServerArgs() "and level 4 tries to reconnect the blocks, " "each level includes the checks of the previous levels " "(0-4, default: %u)", DEFAULT_CHECKLEVEL), true, OptionsCategory::DEBUG_TEST); - gArgs.AddArg("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST); + gArgs.AddArg("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, ::ChainActive() and mapBlocksUnlinked occasionally. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", true, OptionsCategory::DEBUG_TEST); @@ -464,15 +503,13 @@ void SetupServerArgs() gArgs.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). " "If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + ListLogCategories() + ".", false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-debugexclude=<category>", strprintf("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."), false, OptionsCategory::DEBUG_TEST); - gArgs.AddArg("-help-debug", "Print help message with debugging options and exit", false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), false, OptionsCategory::DEBUG_TEST); + gArgs.AddArg("-logthreadnames", strprintf("Prepend debug output with name of the originating thread (only available on platforms supporting thread_local) (default: %u)", DEFAULT_LOGTHREADNAMES), false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-mocktime=<n>", "Replace actual time with <n> seconds since epoch (default: 0)", true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE), true, OptionsCategory::DEBUG_TEST); - gArgs.AddArg("-maxtxfee=<amt>", strprintf("Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)", - CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-printpriority", strprintf("Log transaction fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -daemon. To disable logging to file, set -nodebuglogfile)", false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-shrinkdebugfile", "Shrink debug.log file on client startup (default: 1 when no -debug)", false, OptionsCategory::DEBUG_TEST); @@ -482,14 +519,13 @@ void SetupServerArgs() gArgs.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !testnetChainParams->RequireStandard()), true, OptionsCategory::NODE_RELAY); gArgs.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), true, OptionsCategory::NODE_RELAY); - gArgs.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to defined 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)), true, OptionsCategory::NODE_RELAY); + gArgs.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), true, OptionsCategory::NODE_RELAY); gArgs.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), false, OptionsCategory::NODE_RELAY); gArgs.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), false, OptionsCategory::NODE_RELAY); gArgs.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), false, OptionsCategory::NODE_RELAY); - gArgs.AddArg("-mempoolreplacement", strprintf("Enable transaction replacement in the memory pool (default: %u)", DEFAULT_ENABLE_REPLACEMENT), false, OptionsCategory::NODE_RELAY); gArgs.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), false, OptionsCategory::NODE_RELAY); - gArgs.AddArg("-whitelistforcerelay", strprintf("Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)", DEFAULT_WHITELISTFORCERELAY), false, OptionsCategory::NODE_RELAY); + gArgs.AddArg("-whitelistforcerelay", strprintf("Force relay of transactions from whitelisted peers even if the transactions were already in the mempool or violate local relay policy (default: %d)", DEFAULT_WHITELISTFORCERELAY), false, OptionsCategory::NODE_RELAY); gArgs.AddArg("-whitelistrelay", strprintf("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)", DEFAULT_WHITELISTRELAY), false, OptionsCategory::NODE_RELAY); @@ -499,8 +535,8 @@ void SetupServerArgs() gArgs.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), false, OptionsCategory::RPC); gArgs.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times", false, OptionsCategory::RPC); - gArgs.AddArg("-rpcauth=<userpw>", "Username and 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", false, OptionsCategory::RPC); - gArgs.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)", false, OptionsCategory::RPC); + gArgs.AddArg("-rpcauth=<userpw>", "Username and HMAC-SHA-256 hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcauth. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times", false, OptionsCategory::RPC); + gArgs.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost)", false, OptionsCategory::RPC); gArgs.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", false, OptionsCategory::RPC); gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", false, OptionsCategory::RPC); gArgs.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), false, OptionsCategory::RPC); @@ -629,7 +665,7 @@ static void CleanupBlockRevFiles() static void ThreadImport(std::vector<fs::path> vImportFiles) { const CChainParams& chainparams = Params(); - RenameThread("bitcoin-loadblk"); + util::ThreadRename("loadblk"); ScheduleBatchPriority(); { @@ -639,8 +675,8 @@ static void ThreadImport(std::vector<fs::path> vImportFiles) if (fReindex) { int nFile = 0; while (true) { - CDiskBlockPos pos(nFile, 0); - if (!fs::exists(GetBlockPosFilename(pos, "blk"))) + FlatFilePos pos(nFile, 0); + if (!fs::exists(GetBlockPosFilename(pos))) break; // No block files left to reindex FILE *file = OpenBlockFile(pos, true); if (!file) @@ -696,9 +732,9 @@ static void ThreadImport(std::vector<fs::path> vImportFiles) } } // End scope of CImportingNow if (gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { - LoadMempool(); + LoadMempool(::mempool); } - g_is_mempool_loaded = !ShutdownRequested(); + ::mempool.SetIsLoaded(!ShutdownRequested()); } /** Sanity checks @@ -799,11 +835,6 @@ void InitParameterInteraction() if (gArgs.SoftSetBoolArg("-whitelistrelay", true)) LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__); } - - // Warn if network-specific options (-addnode, -connect, etc) are - // specified in default section of config file, but not overridden - // on the command line or in this network's section of the config file. - gArgs.WarnForSectionOnlyArgs(); } static std::string ResolveErrMsg(const char * const optname, const std::string& strBind) @@ -819,17 +850,12 @@ static std::string ResolveErrMsg(const char * const optname, const std::string& */ void InitLogging() { - g_logger->m_print_to_file = !gArgs.IsArgNegated("-debuglogfile"); - g_logger->m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE)); - - // Add newlines to the logfile to distinguish this execution from the last - // one; called before console logging is set up, so this is only sent to - // debug.log. - LogPrintf("\n\n\n\n\n"); - - g_logger->m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false)); - g_logger->m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS); - g_logger->m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS); + LogInstance().m_print_to_file = !gArgs.IsArgNegated("-debuglogfile"); + LogInstance().m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE)); + LogInstance().m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false)); + LogInstance().m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS); + LogInstance().m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS); + LogInstance().m_log_threadnames = gArgs.GetBoolArg("-logthreadnames", DEFAULT_LOGTHREADNAMES); fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS); @@ -848,6 +874,8 @@ int nMaxConnections; int nUserMaxConnections; int nFD; ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED); +int64_t peer_connect_timeout; +std::vector<BlockFilterType> g_enabled_filter_types; } // namespace @@ -876,16 +904,7 @@ bool AppInitBasicSetup() #endif #ifdef WIN32 // Enable Data Execution Prevention (DEP) - // Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008 - // A failure is non-critical and needs no further attention! -#ifndef PROCESS_DEP_ENABLE - // We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7), - // which is not correct. Can be removed, when GCCs winbase.h is fixed! -#define PROCESS_DEP_ENABLE 0x00000001 -#endif - typedef BOOL (WINAPI *PSETPROCDEPPOL)(DWORD); - PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy"); - if (setProcDEPPol != nullptr) setProcDEPPol(PROCESS_DEP_ENABLE); + SetProcessDEPPolicy(PROCESS_DEP_ENABLE); #endif if (!SetupNetworking()) @@ -921,14 +940,46 @@ bool AppInitParameterInteraction() // also see: InitParameterInteraction() - if (!fs::is_directory(GetBlocksDir(false))) { + // Warn if network-specific options (-addnode, -connect, etc) are + // specified in default section of config file, but not overridden + // on the command line or in this network's section of the config file. + std::string network = gArgs.GetChainName(); + for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) { + return InitError(strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, network, network)); + } + + // Warn if unrecognized section name are present in the config file. + for (const auto& section : gArgs.GetUnrecognizedSections()) { + InitWarning(strprintf("%s:%i " + _("Section [%s] is not recognized."), section.m_file, section.m_line, section.m_name)); + } + + if (!fs::is_directory(GetBlocksDir())) { return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str())); } + // parse and validate enabled filter types + std::string blockfilterindex_value = gArgs.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX); + if (blockfilterindex_value == "" || blockfilterindex_value == "1") { + g_enabled_filter_types = AllBlockFilterTypes(); + } else if (blockfilterindex_value != "0") { + const std::vector<std::string> names = gArgs.GetArgs("-blockfilterindex"); + g_enabled_filter_types.reserve(names.size()); + for (const auto& name : names) { + BlockFilterType filter_type; + if (!BlockFilterTypeByName(name, filter_type)) { + return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name)); + } + g_enabled_filter_types.push_back(filter_type); + } + } + // if using block pruning, then disallow txindex if (gArgs.GetArg("-prune", 0)) { if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) return InitError(_("Prune mode is incompatible with -txindex.")); + if (!g_enabled_filter_types.empty()) { + return InitError(_("Prune mode is incompatible with -blockfilterindex.")); + } } // -bind and -whitebind can't be set when not listening @@ -944,8 +995,13 @@ bool AppInitParameterInteraction() // Trim requested connection counts, to fit into system limitations // <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695 - nMaxConnections = std::max(std::min<int>(nMaxConnections, FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0); nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS); +#ifdef USE_POLL + int fd_max = nFD; +#else + int fd_max = FD_SETSIZE; +#endif + nMaxConnections = std::max(std::min<int>(nMaxConnections, fd_max - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0); if (nFD < MIN_CORE_FILEDESCRIPTORS) return InitError(_("Not enough file descriptors available.")); nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, nMaxConnections); @@ -961,7 +1017,7 @@ bool AppInitParameterInteraction() if (std::none_of(categories.begin(), categories.end(), [](std::string cat){return cat == "0" || cat == "none";})) { for (const auto& cat : categories) { - if (!g_logger->EnableCategory(cat)) { + if (!LogInstance().EnableCategory(cat)) { InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat)); } } @@ -970,7 +1026,7 @@ bool AppInitParameterInteraction() // Now remove the logging categories which were explicitly excluded for (const std::string& cat : gArgs.GetArgs("-debugexclude")) { - if (!g_logger->DisableCategory(cat)) { + if (!LogInstance().DisableCategory(cat)) { InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat)); } } @@ -1041,13 +1097,19 @@ bool AppInitParameterInteraction() if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); } - LogPrintf("Prune configured to target %uMiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024); + LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024); fPruneMode = true; } nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); - if (nConnectTimeout <= 0) + if (nConnectTimeout <= 0) { nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; + } + + peer_connect_timeout = gArgs.GetArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT); + if (peer_connect_timeout <= 0) { + return InitError("peertimeout cannot be configured with a negative value."); + } if (gArgs.IsArgSet("-minrelaytxfee")) { CAmount n = 0; @@ -1106,15 +1168,6 @@ bool AppInitParameterInteraction() nMaxTipAge = gArgs.GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE); - fEnableReplacement = gArgs.GetBoolArg("-mempoolreplacement", DEFAULT_ENABLE_REPLACEMENT); - if ((!fEnableReplacement) && gArgs.IsArgSet("-mempoolreplacement")) { - // Minimal effort at forwards compatibility - std::string strReplacementModeList = gArgs.GetArg("-mempoolreplacement", ""); // default is impossible - std::vector<std::string> vstrReplacementModes; - boost::split(vstrReplacementModes, strReplacementModeList, boost::is_any_of(",")); - fEnableReplacement = (std::find(vstrReplacementModes.begin(), vstrReplacementModes.end(), "fee") != vstrReplacementModes.end()); - } - return true; } @@ -1168,22 +1221,23 @@ bool AppInitMain(InitInterfaces& interfaces) { const CChainParams& chainparams = Params(); // ********************************************************* Step 4a: application initialization -#ifndef WIN32 - CreatePidFile(GetPidFile(), getpid()); -#endif - if (g_logger->m_print_to_file) { - if (gArgs.GetBoolArg("-shrinkdebugfile", g_logger->DefaultShrinkDebugFile())) { + if (!CreatePidFile()) { + // Detailed error printed inside CreatePidFile(). + return false; + } + if (LogInstance().m_print_to_file) { + if (gArgs.GetBoolArg("-shrinkdebugfile", LogInstance().DefaultShrinkDebugFile())) { // Do this first since it both loads a bunch of debug.log into memory, // and because this needs to happen before any other debug.log printing - g_logger->ShrinkDebugFile(); + LogInstance().ShrinkDebugFile(); } - if (!g_logger->OpenDebugLog()) { + } + if (!LogInstance().StartLogging()) { return InitError(strprintf("Could not open debug log file %s", - g_logger->m_file_path.string())); - } + LogInstance().m_file_path.string())); } - if (!g_logger->m_log_timestamps) + if (!LogInstance().m_log_timestamps) LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime())); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); LogPrintf("Using data directory %s\n", GetDataDir().string()); @@ -1217,12 +1271,12 @@ bool AppInitMain(InitInterfaces& interfaces) LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads); if (nScriptCheckThreads) { for (int i=0; i<nScriptCheckThreads-1; i++) - threadGroup.create_thread(&ThreadScriptCheck); + threadGroup.create_thread([i]() { return ThreadScriptCheck(i); }); } // Start the lightweight task scheduler thread - CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler); - threadGroup.create_thread(boost::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop)); + CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler); + threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop)); GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); GetMainSignals().RegisterWithMempoolSignals(mempool); @@ -1270,11 +1324,12 @@ bool AppInitMain(InitInterfaces& interfaces) // is not yet setup and may end up being set up twice if we // need to reindex later. + assert(!g_banman); + g_banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, gArgs.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME)); assert(!g_connman); g_connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()))); - CConnman& connman = *g_connman; - peerLogic.reset(new PeerLogicValidation(&connman, scheduler, gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61))); + peerLogic.reset(new PeerLogicValidation(g_connman.get(), g_banman.get(), scheduler, gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61))); RegisterValidationInterface(peerLogic.get()); // sanitize comments per BIP-0014, format user agent and check total size @@ -1301,7 +1356,7 @@ bool AppInitMain(InitInterfaces& interfaces) for (int n = 0; n < NET_MAX; n++) { enum Network net = (enum Network)n; if (!nets.count(net)) - SetLimited(net); + SetReachable(net, false); } } @@ -1312,7 +1367,7 @@ bool AppInitMain(InitInterfaces& interfaces) // -proxy sets a proxy for all outgoing network traffic // -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default std::string proxyArg = gArgs.GetArg("-proxy", ""); - SetLimited(NET_ONION); + SetReachable(NET_ONION, false); if (proxyArg != "" && proxyArg != "0") { CService proxyAddr; if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) { @@ -1327,7 +1382,7 @@ bool AppInitMain(InitInterfaces& interfaces) SetProxy(NET_IPV6, addrProxy); SetProxy(NET_ONION, addrProxy); SetNameProxy(addrProxy); - SetLimited(NET_ONION, false); // by default, -proxy sets onion as reachable, unless -noonion later + SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later } // -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses @@ -1336,7 +1391,7 @@ bool AppInitMain(InitInterfaces& interfaces) std::string onionArg = gArgs.GetArg("-onion", ""); if (onionArg != "") { if (onionArg == "0") { // Handle -noonion/-onion=0 - SetLimited(NET_ONION); // set onions as unreachable + SetReachable(NET_ONION, false); } else { CService onionProxy; if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) { @@ -1346,14 +1401,14 @@ bool AppInitMain(InitInterfaces& interfaces) if (!addrOnion.IsValid()) return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg)); SetProxy(NET_ONION, addrOnion); - SetLimited(NET_ONION, false); + SetReachable(NET_ONION, true); } } // see Step 2: parameter interactions for more information about these fListen = gArgs.GetBoolArg("-listen", DEFAULT_LISTEN); fDiscover = gArgs.GetBoolArg("-discover", true); - fRelayTxes = !gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); + g_relay_txes = !gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); for (const std::string& strAddr : gArgs.GetArgs("-externalip")) { CService addrLocal; @@ -1390,18 +1445,29 @@ bool AppInitMain(InitInterfaces& interfaces) nTotalCache -= nBlockTreeDBCache; int64_t nTxIndexCache = std::min(nTotalCache / 8, gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxTxIndexCache << 20 : 0); nTotalCache -= nTxIndexCache; + int64_t filter_index_cache = 0; + if (!g_enabled_filter_types.empty()) { + size_t n_indexes = g_enabled_filter_types.size(); + int64_t max_cache = std::min(nTotalCache / 8, max_filter_index_cache << 20); + filter_index_cache = max_cache / n_indexes; + nTotalCache -= filter_index_cache * n_indexes; + } int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache nTotalCache -= nCoinDBCache; nCoinCacheUsage = nTotalCache; // the rest goes to in-memory cache int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; LogPrintf("Cache configuration:\n"); - LogPrintf("* Using %.1fMiB for block index database\n", nBlockTreeDBCache * (1.0 / 1024 / 1024)); + LogPrintf("* Using %.1f MiB for block index database\n", nBlockTreeDBCache * (1.0 / 1024 / 1024)); if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { - LogPrintf("* Using %.1fMiB for transaction index database\n", nTxIndexCache * (1.0 / 1024 / 1024)); + LogPrintf("* Using %.1f MiB for transaction index database\n", nTxIndexCache * (1.0 / 1024 / 1024)); + } + for (BlockFilterType filter_type : g_enabled_filter_types) { + LogPrintf("* Using %.1f MiB for %s block filter index database\n", + filter_index_cache * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type)); } - LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024)); - LogPrintf("* Using %.1fMiB for in-memory UTXO set (plus up to %.1fMiB of unused mempool space)\n", nCoinCacheUsage * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024)); + LogPrintf("* Using %.1f MiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024)); + 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)); bool fLoaded = false; while (!fLoaded && !ShutdownRequested()) { @@ -1410,11 +1476,11 @@ bool AppInitMain(InitInterfaces& interfaces) uiInterface.InitMessage(_("Loading block index...")); - LOCK(cs_main); - do { const int64_t load_block_index_start_time = GetTimeMillis(); + bool is_coinsview_empty; try { + LOCK(cs_main); UnloadBlockIndex(); pcoinsTip.reset(); pcoinsdbview.reset(); @@ -1438,6 +1504,7 @@ bool AppInitMain(InitInterfaces& interfaces) // Note that it also sets fReindex based on the disk flag! // From here on out fReindex and fReset mean something different! if (!LoadBlockIndex(chainparams)) { + if (ShutdownRequested()) break; strLoadError = _("Error loading block database"); break; } @@ -1486,27 +1553,34 @@ bool AppInitMain(InitInterfaces& interfaces) // The on-disk coinsdb is now in a good state, create the cache pcoinsTip.reset(new CCoinsViewCache(pcoinscatcher.get())); - bool is_coinsview_empty = fReset || fReindexChainState || pcoinsTip->GetBestBlock().IsNull(); + is_coinsview_empty = fReset || fReindexChainState || pcoinsTip->GetBestBlock().IsNull(); if (!is_coinsview_empty) { - // LoadChainTip sets chainActive based on pcoinsTip's best block + // LoadChainTip sets ::ChainActive() based on pcoinsTip's best block if (!LoadChainTip(chainparams)) { strLoadError = _("Error initializing block database"); break; } - assert(chainActive.Tip() != nullptr); + assert(::ChainActive().Tip() != nullptr); } + } catch (const std::exception& e) { + LogPrintf("%s\n", e.what()); + strLoadError = _("Error opening block database"); + break; + } - if (!fReset) { - // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate. - // It both disconnects blocks based on chainActive, and drops block data in - // mapBlockIndex based on lack of available witness data. - uiInterface.InitMessage(_("Rewinding blocks...")); - if (!RewindBlockIndex(chainparams)) { - strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain"); - break; - } + if (!fReset) { + // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate. + // It both disconnects blocks based on ::ChainActive(), and drops block data in + // mapBlockIndex based on lack of available witness data. + uiInterface.InitMessage(_("Rewinding blocks...")); + if (!RewindBlockIndex(chainparams)) { + strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain"); + break; } + } + try { + LOCK(cs_main); if (!is_coinsview_empty) { uiInterface.InitMessage(_("Verifying blocks...")); if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) { @@ -1514,7 +1588,7 @@ bool AppInitMain(InitInterfaces& interfaces) MIN_BLOCKS_TO_KEEP); } - CBlockIndex* tip = chainActive.Tip(); + CBlockIndex* tip = ::ChainActive().Tip(); RPCNotifyBlockChange(true, tip); if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) { strLoadError = _("The block database contains a block which appears to be from the future. " @@ -1580,6 +1654,11 @@ bool AppInitMain(InitInterfaces& interfaces) g_txindex->Start(); } + for (const auto& filter_type : g_enabled_filter_types) { + InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex); + GetBlockFilterIndex(filter_type)->Start(); + } + // ********************************************************* Step 9: load wallet for (const auto& client : interfaces.chain_clients) { if (!client->load()) { @@ -1596,7 +1675,7 @@ bool AppInitMain(InitInterfaces& interfaces) nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK); if (!fReindex) { uiInterface.InitMessage(_("Pruning blockstore...")); - PruneAndFlush(); + ::ChainstateActive().PruneAndFlush(); } } @@ -1611,13 +1690,20 @@ bool AppInitMain(InitInterfaces& interfaces) // ********************************************************* Step 11: import blocks - if (!CheckDiskSpace() && !CheckDiskSpace(0, true)) + if (!CheckDiskSpace(GetDataDir())) { + InitError(strprintf(_("Error: Disk space is low for %s"), GetDataDir())); return false; + } + if (!CheckDiskSpace(GetBlocksDir())) { + InitError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir())); + return false; + } // Either install a handler to notify us when genesis activates, or set fHaveGenesis directly. // No locking, as this happens before any background thread is started. - if (chainActive.Tip() == nullptr) { - uiInterface.NotifyBlockTip_connect(BlockNotifyGenesisWait); + boost::signals2::connection block_notify_genesis_wait_connection; + if (::ChainActive().Tip() == nullptr) { + block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(BlockNotifyGenesisWait); } else { fHaveGenesis = true; } @@ -1630,7 +1716,7 @@ bool AppInitMain(InitInterfaces& interfaces) vImportFiles.push_back(strFile); } - threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); + threadGroup.create_thread(std::bind(&ThreadImport, vImportFiles)); // Wait for genesis block to be processed { @@ -1641,7 +1727,7 @@ bool AppInitMain(InitInterfaces& interfaces) while (!fHaveGenesis && !ShutdownRequested()) { g_genesis_wait_cv.wait_for(lock, std::chrono::milliseconds(500)); } - uiInterface.NotifyBlockTip_disconnect(BlockNotifyGenesisWait); + block_notify_genesis_wait_connection.disconnect(); } if (ShutdownRequested()) { @@ -1656,7 +1742,7 @@ bool AppInitMain(InitInterfaces& interfaces) { LOCK(cs_main); LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); - chain_active_height = chainActive.Height(); + chain_active_height = ::ChainActive().Height(); } LogPrintf("nBestHeight = %d\n", chain_active_height); @@ -1678,6 +1764,7 @@ bool AppInitMain(InitInterfaces& interfaces) connOptions.nMaxFeeler = 1; connOptions.nBestHeight = chain_active_height; connOptions.uiInterface = &uiInterface; + connOptions.m_banman = g_banman.get(); connOptions.m_msgproc = peerLogic.get(); connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); @@ -1685,6 +1772,7 @@ bool AppInitMain(InitInterfaces& interfaces) connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; connOptions.nMaxOutboundLimit = nMaxOutboundLimit; + connOptions.m_peer_connect_timeout = peer_connect_timeout; for (const std::string& strBind : gArgs.GetArgs("-bind")) { CService addrBind; @@ -1722,7 +1810,7 @@ bool AppInitMain(InitInterfaces& interfaces) connOptions.m_specified_outgoing = connect; } } - if (!connman.Start(scheduler, connOptions)) { + if (!g_connman->Start(scheduler, connOptions)) { return false; } @@ -1735,5 +1823,9 @@ bool AppInitMain(InitInterfaces& interfaces) client->start(scheduler); } + scheduler.scheduleEvery([]{ + g_banman->DumpBanlist(); + }, DUMP_BANS_INTERVAL * 1000); + return true; } |