diff options
Diffstat (limited to 'src/init.cpp')
| -rw-r--r-- | src/init.cpp | 174 |
1 files changed, 91 insertions, 83 deletions
diff --git a/src/init.cpp b/src/init.cpp index 93568c97a..e495a68d5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -19,6 +19,7 @@ #include <fs.h> #include <httpserver.h> #include <httprpc.h> +#include <interfaces/chain.h> #include <index/txindex.h> #include <key.h> #include <validation.h> @@ -32,6 +33,7 @@ #include <rpc/server.h> #include <rpc/register.h> #include <rpc/blockchain.h> +#include <rpc/util.h> #include <script/standard.h> #include <script/sigcache.h> #include <scheduler.h> @@ -41,8 +43,8 @@ #include <txmempool.h> #include <torcontrol.h> #include <ui_interface.h> -#include <util.h> -#include <utilmoneystr.h> +#include <util/system.h> +#include <util/moneystr.h> #include <validationinterface.h> #include <warnings.h> #include <walletinitinterface.h> @@ -57,11 +59,11 @@ #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> #include <zmq/zmqnotificationinterface.h> #include <zmq/zmqrpc.h> #endif @@ -156,7 +158,7 @@ void Interrupt() } } -void Shutdown() +void Shutdown(InitInterfaces& interfaces) { LogPrintf("%s: In progress...\n", __func__); static CCriticalSection cs_Shutdown; @@ -175,7 +177,9 @@ void Shutdown() StopREST(); StopRPC(); StopHTTPServer(); - g_wallet_init_interface.Flush(); + for (const auto& client : interfaces.chain_clients) { + client->flush(); + } StopMapPort(); // Because these depend on each-other, we make sure that neither can be @@ -238,7 +242,9 @@ void Shutdown() pcoinsdbview.reset(); pblocktree.reset(); } - g_wallet_init_interface.Stop(); + for (const auto& client : interfaces.chain_clients) { + client->stop(); + } #if ENABLE_ZMQ if (g_zmq_notification_interface) { @@ -255,10 +261,10 @@ void Shutdown() LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what()); } #endif + interfaces.chain_clients.clear(); UnregisterAllValidationInterfaces(); GetMainSignals().UnregisterBackgroundSignalScheduler(); GetMainSignals().UnregisterWithMempoolSignals(mempool); - g_wallet_init_interface.Close(); globalVerifyHandle.reset(); ECC_Stop(); LogPrintf("%s: done\n", __func__); @@ -322,8 +328,8 @@ void SetupServerArgs() const auto regtestChainParams = CreateChainParams(CBaseChainParams::REGTEST); // Hidden Options - std::vector<std::string> hidden_args = {"-rpcssl", "-benchmark", "-h", "-help", "-socks", "-tor", "-debugnet", "-whitelistalwaysrelay", - "-prematurewitness", "-walletprematurewitness", "-promiscuousmempoolflags", "-blockminsize", "-dbcrashratio", "-forcecompactdb", "-usehd", + std::vector<std::string> hidden_args = {"-h", "-help", + "-dbcrashratio", "-forcecompactdb", // GUI args. These will be overwritten by SetupUIArgs for the GUI "-allowselfsignedrootcertificates", "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-rootcertificates=<file>", "-splash", "-uiplatform"}; @@ -396,6 +402,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 @@ -418,11 +425,19 @@ void SetupServerArgs() gArgs.AddArg("-zmqpubhashtx=<address>", "Enable publish hash transaction in <address>", false, OptionsCategory::ZMQ); gArgs.AddArg("-zmqpubrawblock=<address>", "Enable publish raw block in <address>", false, OptionsCategory::ZMQ); gArgs.AddArg("-zmqpubrawtx=<address>", "Enable publish raw transaction in <address>", false, OptionsCategory::ZMQ); + gArgs.AddArg("-zmqpubhashblockhwm=<n>", strprintf("Set publish hash block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ); + gArgs.AddArg("-zmqpubhashtxhwm=<n>", strprintf("Set publish hash transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ); + gArgs.AddArg("-zmqpubrawblockhwm=<n>", strprintf("Set publish raw block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ); + gArgs.AddArg("-zmqpubrawtxhwm=<n>", strprintf("Set publish raw transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ); #else hidden_args.emplace_back("-zmqpubhashblock=<address>"); hidden_args.emplace_back("-zmqpubhashtx=<address>"); hidden_args.emplace_back("-zmqpubrawblock=<address>"); hidden_args.emplace_back("-zmqpubrawtx=<address>"); + hidden_args.emplace_back("-zmqpubhashblockhwm=<n>"); + hidden_args.emplace_back("-zmqpubhashtxhwm=<n>"); + hidden_args.emplace_back("-zmqpubrawblockhwm=<n>"); + hidden_args.emplace_back("-zmqpubrawtxhwm=<n>"); #endif gArgs.AddArg("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), true, OptionsCategory::DEBUG_TEST); @@ -445,7 +460,6 @@ void SetupServerArgs() gArgs.AddArg("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT), true, OptionsCategory::DEBUG_TEST); - gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest-only)", true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-addrmantest", "Allows to test address relay on localhost", true, OptionsCategory::DEBUG_TEST); 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); @@ -485,8 +499,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); @@ -691,7 +705,7 @@ static void ThreadImport(std::vector<fs::path> vImportFiles) * Ensure that Bitcoin is running in a usable environment with all * necessary library support. */ -static bool InitSanityCheck(void) +static bool InitSanityCheck() { if(!ECC_InitSanityCheck()) { InitError("Elliptic curve cryptography sanity check failure. Aborting."); @@ -789,7 +803,15 @@ void InitParameterInteraction() // 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(); + std::string network = gArgs.GetChainName(); + for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) { + InitWarning(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(_("Section [%s] is not recognized."), section)); + } } static std::string ResolveErrMsg(const char * const optname, const std::string& strBind) @@ -834,6 +856,7 @@ int nMaxConnections; int nUserMaxConnections; int nFD; ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED); +int64_t peer_connect_timeout; } // namespace @@ -907,7 +930,7 @@ bool AppInitParameterInteraction() // also see: InitParameterInteraction() - if (!fs::is_directory(GetBlocksDir(false))) { + if (!fs::is_directory(GetBlocksDir())) { return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str())); } @@ -930,8 +953,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,25 +989,6 @@ bool AppInitParameterInteraction() } } - // Check for -debugnet - if (gArgs.GetBoolArg("-debugnet", false)) - InitWarning(_("Unsupported argument -debugnet ignored, use -debug=net.")); - // Check for -socks - as this is a privacy risk to continue, exit here - if (gArgs.IsArgSet("-socks")) - return InitError(_("Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.")); - // Check for -tor - as this is a privacy risk to continue, exit here - if (gArgs.GetBoolArg("-tor", false)) - return InitError(_("Unsupported argument -tor found, use -onion.")); - - if (gArgs.GetBoolArg("-benchmark", false)) - InitWarning(_("Unsupported argument -benchmark ignored, use -debug=bench.")); - - if (gArgs.GetBoolArg("-whitelistalwaysrelay", false)) - InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.")); - - if (gArgs.IsArgSet("-blockminsize")) - InitWarning("Unsupported argument -blockminsize ignored."); - // Checkmempool and checkblockindex default to true in regtest mode int ratio = std::min<int>(std::max<int>(gArgs.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); if (ratio != 0) { @@ -1051,8 +1060,14 @@ bool AppInitParameterInteraction() } 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; @@ -1120,39 +1135,6 @@ bool AppInitParameterInteraction() fEnableReplacement = (std::find(vstrReplacementModes.begin(), vstrReplacementModes.end(), "fee") != vstrReplacementModes.end()); } - if (gArgs.IsArgSet("-vbparams")) { - // Allow overriding version bits parameters for testing - if (!chainparams.MineBlocksOnDemand()) { - return InitError("Version bits parameters may only be overridden on regtest."); - } - for (const std::string& strDeployment : gArgs.GetArgs("-vbparams")) { - std::vector<std::string> vDeploymentParams; - boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":")); - if (vDeploymentParams.size() != 3) { - return InitError("Version bits parameters malformed, expecting deployment:start:end"); - } - int64_t nStartTime, nTimeout; - if (!ParseInt64(vDeploymentParams[1], &nStartTime)) { - return InitError(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1])); - } - if (!ParseInt64(vDeploymentParams[2], &nTimeout)) { - return InitError(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2])); - } - bool found = false; - for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) - { - if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) { - UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout); - found = true; - LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout); - break; - } - } - if (!found) { - return InitError(strprintf("Invalid deployment (%s)", vDeploymentParams[0])); - } - } - } return true; } @@ -1202,7 +1184,7 @@ bool AppInitLockDataDirectory() return true; } -bool AppInitMain() +bool AppInitMain(InitInterfaces& interfaces) { const CChainParams& chainparams = Params(); // ********************************************************* Step 4a: application initialization @@ -1259,17 +1241,26 @@ bool AppInitMain() } // 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); + // Create client interfaces for wallets that are supposed to be loaded + // according to -wallet and -disablewallet options. This only constructs + // the interfaces, it doesn't load wallet data. Wallets actually get loaded + // when load() and start() interface methods are called below. + g_wallet_init_interface.Construct(interfaces); + /* Register RPC commands regardless of -server setting so they will be * available in the GUI RPC console even if external calls are disabled. */ RegisterAllCoreRPCCommands(tableRPC); - g_wallet_init_interface.RegisterRPC(tableRPC); + for (const auto& client : interfaces.chain_clients) { + client->registerRpcs(); + } + g_rpc_interfaces = &interfaces; #if ENABLE_ZMQ RegisterZMQRPCCommands(tableRPC); #endif @@ -1287,7 +1278,11 @@ bool AppInitMain() } // ********************************************************* Step 5: verify wallet database integrity - if (!g_wallet_init_interface.Verify()) return false; + for (const auto& client : interfaces.chain_clients) { + if (!client->verify()) { + return false; + } + } // ********************************************************* Step 6: network initialization // Note that we absolutely cannot open any actual connections @@ -1326,7 +1321,7 @@ bool AppInitMain() for (int n = 0; n < NET_MAX; n++) { enum Network net = (enum Network)n; if (!nets.count(net)) - SetLimited(net); + SetReachable(net, false); } } @@ -1337,7 +1332,7 @@ bool AppInitMain() // -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)) { @@ -1352,7 +1347,7 @@ bool AppInitMain() 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 @@ -1361,7 +1356,7 @@ bool AppInitMain() 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)) { @@ -1371,7 +1366,7 @@ bool AppInitMain() 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); } } @@ -1606,7 +1601,11 @@ bool AppInitMain() } // ********************************************************* Step 9: load wallet - if (!g_wallet_init_interface.Open()) return false; + for (const auto& client : interfaces.chain_clients) { + if (!client->load()) { + return false; + } + } // ********************************************************* Step 10: data directory maintenance @@ -1632,8 +1631,14 @@ bool AppInitMain() // ********************************************************* Step 11: import blocks - if (!CheckDiskSpace() && !CheckDiskSpace(0, true)) + if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ false)) { + InitError(strprintf(_("Error: Disk space is low for %s"), GetDataDir())); return false; + } + if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ true)) { + 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. @@ -1651,7 +1656,7 @@ bool AppInitMain() 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 { @@ -1706,6 +1711,7 @@ bool AppInitMain() connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; connOptions.nMaxOutboundLimit = nMaxOutboundLimit; + connOptions.m_peer_connect_timeout = peer_connect_timeout; for (const std::string& strBind : gArgs.GetArgs("-bind")) { CService addrBind; @@ -1752,7 +1758,9 @@ bool AppInitMain() SetRPCWarmupFinished(); uiInterface.InitMessage(_("Done loading")); - g_wallet_init_interface.Start(scheduler); + for (const auto& client : interfaces.chain_clients) { + client->start(scheduler); + } return true; } |