diff options
Diffstat (limited to 'src/init.cpp')
| -rw-r--r-- | src/init.cpp | 156 |
1 files changed, 98 insertions, 58 deletions
diff --git a/src/init.cpp b/src/init.cpp index 085e04fdf..7c3c18acd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -16,6 +16,8 @@ #include "checkpoints.h" #include "compat/sanity.h" #include "consensus/validation.h" +#include "httpserver.h" +#include "httprpc.h" #include "key.h" #include "main.h" #include "miner.h" @@ -36,7 +38,6 @@ #include "wallet/wallet.h" #include "wallet/walletdb.h" #endif - #include <stdint.h> #include <stdio.h> @@ -53,6 +54,10 @@ #include <boost/thread.hpp> #include <openssl/crypto.h> +#if ENABLE_ZMQ +#include "zmq/zmqnotificationinterface.h" +#endif + using namespace std; #ifdef ENABLE_WALLET @@ -60,6 +65,10 @@ CWallet* pwalletMain = NULL; #endif bool fFeeEstimatesInitialized = false; +#if ENABLE_ZMQ +static CZMQNotificationInterface* pzmqNotificationInterface = NULL; +#endif + #ifdef WIN32 // Win32 LevelDB doesn't use filedescriptors, and the ones used for // accessing block files don't count towards the fd_set size limit @@ -144,6 +153,15 @@ public: static CCoinsViewDB *pcoinsdbview = NULL; static CCoinsViewErrorCatcher *pcoinscatcher = NULL; +void Interrupt(boost::thread_group& threadGroup) +{ + InterruptHTTPServer(); + InterruptHTTPRPC(); + InterruptRPC(); + InterruptREST(); + threadGroup.interrupt_all(); +} + void Shutdown() { LogPrintf("%s: In progress...\n", __func__); @@ -158,7 +176,11 @@ void Shutdown() /// module was initialized. RenameThread("bitcoin-shutoff"); mempool.AddTransactionsUpdated(1); - StopRPCThreads(); + + StopHTTPRPC(); + StopREST(); + StopRPC(); + StopHTTPServer(); #ifdef ENABLE_WALLET if (pwalletMain) pwalletMain->Flush(false); @@ -196,6 +218,16 @@ void Shutdown() if (pwalletMain) pwalletMain->Flush(true); #endif + +#if ENABLE_ZMQ + if (pzmqNotificationInterface) { + UnregisterValidationInterface(pzmqNotificationInterface); + pzmqNotificationInterface->Shutdown(); + delete pzmqNotificationInterface; + pzmqNotificationInterface = NULL; + } +#endif + #ifndef WIN32 try { boost::filesystem::remove(GetPidFile()); @@ -293,7 +325,7 @@ std::string HelpMessage(HelpMessageMode mode) #ifndef WIN32 strUsage += HelpMessageOpt("-pid=<file>", strprintf(_("Specify pid file (default: %s)"), "bitcoind.pid")); #endif - strUsage += HelpMessageOpt("-prune=<n>", strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode disables wallet support and is incompatible with -txindex. " + strUsage += HelpMessageOpt("-prune=<n>", strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. " "Warning: Reverting this setting requires re-downloading the entire blockchain. " "(default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files)"), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); strUsage += HelpMessageOpt("-reindex", _("Rebuild block chain index from current blk000??.dat files on startup")); @@ -335,7 +367,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-whitebind=<addr>", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6")); strUsage += HelpMessageOpt("-whitelist=<netmask>", _("Whitelist peers connecting from the given netmask or IP address. 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")); - strUsage += HelpMessageOpt("-whiteconnections=<n>", strprintf(_("Reserve this many inbound connections for whitelisted peers (default: %d)"), 0)); #ifdef ENABLE_WALLET strUsage += HelpMessageGroup(_("Wallet options:")); @@ -361,6 +392,14 @@ std::string HelpMessage(HelpMessageMode mode) " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)")); #endif +#if ENABLE_ZMQ + strUsage += HelpMessageGroup(_("ZeroMQ notification options:")); + strUsage += HelpMessageOpt("-zmqpubhashblock=<address>", _("Enable publish hash block in <address>")); + strUsage += HelpMessageOpt("-zmqpubhashtransaction=<address>", _("Enable publish hash transaction in <address>")); + strUsage += HelpMessageOpt("-zmqpubrawblock=<address>", _("Enable publish raw block in <address>")); + strUsage += HelpMessageOpt("-zmqpubrawtransaction=<address>", _("Enable publish raw transaction in <address>")); +#endif + strUsage += HelpMessageGroup(_("Debugging/Testing options:")); if (showDebug) { @@ -372,8 +411,12 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", "Randomly fuzz 1 of every <n> network messages"); strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", 1)); strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", 0)); + strUsage += HelpMessageOpt("-limitancestorcount=<n>", strprintf("Do not accept transactions if number of in-mempool ancestors is <n> or more (default: %u)", DEFAULT_ANCESTOR_LIMIT)); + strUsage += HelpMessageOpt("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT)); + strUsage += HelpMessageOpt("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT)); + strUsage += HelpMessageOpt("-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)); } - string debugCategories = "addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, mempoolrej, net, proxy, prune"; // Don't translate these and qt below + string debugCategories = "addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, mempoolrej, net, proxy, prune, http, libevent"; // Don't translate these and qt below if (mode == HMM_BITCOIN_QT) debugCategories += ", qt"; strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " + @@ -423,14 +466,11 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections")); strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), 8332, 18332)); strUsage += HelpMessageOpt("-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")); - strUsage += HelpMessageOpt("-rpcthreads=<n>", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4)); - strUsage += HelpMessageOpt("-rpckeepalive", strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 1)); - - strUsage += HelpMessageGroup(_("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)")); - strUsage += HelpMessageOpt("-rpcssl", _("Use OpenSSL (https) for JSON-RPC connections")); - strUsage += HelpMessageOpt("-rpcsslcertificatechainfile=<file.cert>", strprintf(_("Server certificate file (default: %s)"), "server.cert")); - strUsage += HelpMessageOpt("-rpcsslprivatekeyfile=<file.pem>", strprintf(_("Server private key (default: %s)"), "server.pem")); - strUsage += HelpMessageOpt("-rpcsslciphers=<ciphers>", strprintf(_("Acceptable ciphers (default: %s)"), "TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH")); + strUsage += HelpMessageOpt("-rpcthreads=<n>", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), DEFAULT_HTTP_THREADS)); + if (showDebug) { + strUsage += HelpMessageOpt("-rpcworkqueue=<n>", strprintf("Set the depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE)); + strUsage += HelpMessageOpt("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT)); + } if (mode == HMM_BITCOIN_QT) { @@ -602,6 +642,23 @@ bool InitSanityCheck(void) return true; } +bool AppInitServers(boost::thread_group& threadGroup) +{ + RPCServer::OnStopped(&OnRPCStopped); + RPCServer::OnPreCommand(&OnRPCPreCommand); + if (!InitHTTPServer()) + return false; + if (!StartRPC()) + return false; + if (!StartHTTPRPC()) + return false; + if (GetBoolArg("-rest", false) && !StartREST()) + return false; + if (!StartHTTPServer(threadGroup)) + return false; + return true; +} + /** Initialize bitcoin. * @pre Parameters should be parsed and config file should be read. */ @@ -629,17 +686,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) typedef BOOL (WINAPI *PSETPROCDEPPOL)(DWORD); PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy"); if (setProcDEPPol != NULL) setProcDEPPol(PROCESS_DEP_ENABLE); - - // Initialize Windows Sockets - WSADATA wsadata; - int ret = WSAStartup(MAKEWORD(2,2), &wsadata); - if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2) - { - return InitError(strprintf("Error: Winsock library failed to start (WSAStartup returned error %d)", ret)); - } #endif -#ifndef WIN32 + if (!SetupNetworking()) + return InitError("Error: Initializing networking failed"); + +#ifndef WIN32 if (GetBoolArg("-sysperms", false)) { #ifdef ENABLE_WALLET if (!GetBoolArg("-disablewallet", false)) @@ -664,11 +716,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) sa_hup.sa_flags = 0; sigaction(SIGHUP, &sa_hup, NULL); -#if defined (__SVR4) && defined (__sun) - // ignore SIGPIPE on Solaris + // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly signal(SIGPIPE, SIG_IGN); #endif -#endif // ********************************************************* Step 2: parameter interactions const CChainParams& chainparams = Params(); @@ -754,25 +804,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1); int nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); nMaxConnections = std::max(nUserMaxConnections, 0); - int nUserWhiteConnections = GetArg("-whiteconnections", 0); - nWhiteConnections = std::max(nUserWhiteConnections, 0); - - if ((mapArgs.count("-whitelist")) || (mapArgs.count("-whitebind"))) { - if (!(mapArgs.count("-maxconnections"))) { - // User is using whitelist feature, - // but did not specify -maxconnections parameter. - // Silently increase the default to compensate, - // so that the whitelist connection reservation feature - // does not inadvertently reduce the default - // inbound connection capacity of the network. - nMaxConnections += nWhiteConnections; - } - } else { - // User not using whitelist feature. - // Silently disable connection reservation, - // for the same reason as above. - nWhiteConnections = 0; - } // Trim requested connection counts, to fit into system limitations nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0); @@ -784,13 +815,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (nMaxConnections < nUserMaxConnections) InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections)); - // Connection capacity is prioritized in this order: - // outbound connections (hardcoded to 8), - // then whitelisted connections, - // then non-whitelisted connections get whatever's left (if any). - if ((nWhiteConnections > 0) && (nWhiteConnections >= (nMaxConnections - 8))) - InitWarning(strprintf(_("All non-whitelisted incoming connections will be dropped, because -whiteconnections is %d and -maxconnections is only %d."), nWhiteConnections, nMaxConnections)); - // ********************************************************* Step 3: parameter-to-internal-flags fDebug = !mapMultiArgs["-debug"].empty(); @@ -921,6 +945,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Option to startup with mocktime set (used for regression testing): SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op + if (GetBoolArg("-peerbloomfilters", true)) + nLocalServices |= NODE_BLOOM; + // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log // Initialize elliptic curve code @@ -968,8 +995,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Using data directory %s\n", strDataDir); LogPrintf("Using config file %s\n", GetConfigFile().string()); LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); - if (nWhiteConnections > 0) - LogPrintf("Reserving %i of these connections for whitelisted inbound peers\n", nWhiteConnections); std::ostringstream strErrors; LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads); @@ -990,9 +1015,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (fServer) { uiInterface.InitMessage.connect(SetRPCWarmupStatus); - RPCServer::OnStopped(&OnRPCStopped); - RPCServer::OnPreCommand(&OnRPCPreCommand); - StartRPCThreads(); + if (!AppInitServers(threadGroup)) + return InitError(_("Unable to start HTTP server. See debug log for details.")); } int64_t nStart; @@ -1020,8 +1044,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) RegisterNodeSignals(GetNodeSignals()); - // format user agent, check total size - strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, mapMultiArgs.count("-uacomment") ? mapMultiArgs["-uacomment"] : std::vector<string>()); + // sanitize comments per BIP-0014, format user agent and check total size + std::vector<string> uacomments; + BOOST_FOREACH(string cmt, mapMultiArgs["-uacomment"]) + { + if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)) + return InitError(strprintf("User Agent comment (%s) contains unsafe characters.", cmt)); + uacomments.push_back(SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)); + } + strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments); if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) { return InitError(strprintf("Total length of network version string %i exceeds maximum of %i characters. Reduce the number and/or size of uacomments.", strSubVersion.size(), MAX_SUBVERSION_LENGTH)); @@ -1128,6 +1159,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) BOOST_FOREACH(const std::string& strDest, mapMultiArgs["-seednode"]) AddOneShot(strDest); +#if ENABLE_ZMQ + pzmqNotificationInterface = CZMQNotificationInterface::CreateWithArguments(mapArgs); + + if (pzmqNotificationInterface) { + pzmqNotificationInterface->Initialize(); + RegisterValidationInterface(pzmqNotificationInterface); + } +#endif + // ********************************************************* Step 7: load block chain fReindex = GetBoolArg("-reindex", false); |