diff options
Diffstat (limited to 'src/init.cpp')
-rw-r--r-- | src/init.cpp | 338 |
1 files changed, 178 insertions, 160 deletions
diff --git a/src/init.cpp b/src/init.cpp index b943b8662b..828c525dcb 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) @@ -10,6 +10,7 @@ #include "init.h" #include "addrman.h" +#include "amount.h" #include "checkpoints.h" #include "compat/sanity.h" #include "key.h" @@ -17,6 +18,7 @@ #include "miner.h" #include "net.h" #include "rpcserver.h" +#include "script/standard.h" #include "txdb.h" #include "ui_interface.h" #include "util.h" @@ -41,12 +43,12 @@ #include <boost/thread.hpp> #include <openssl/crypto.h> -using namespace boost; using namespace std; #ifdef ENABLE_WALLET CWallet* pwalletMain = NULL; #endif +bool fFeeEstimatesInitialized = false; #ifdef WIN32 // Win32 LevelDB doesn't use filedescriptors, and the ones used for @@ -57,7 +59,7 @@ CWallet* pwalletMain = NULL; #define MIN_CORE_FILEDESCRIPTORS 150 #endif -// Used to pass flags to the Bind() function +/** Used to pass flags to the Bind() function */ enum BindFlags { BF_NONE = 0, BF_EXPLICIT = (1U << 0), @@ -109,7 +111,28 @@ bool ShutdownRequested() return fRequestShutdown; } +class CCoinsViewErrorCatcher : public CCoinsViewBacked +{ +public: + CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {} + bool GetCoins(const uint256 &txid, CCoins &coins) const { + try { + return CCoinsViewBacked::GetCoins(txid, coins); + } catch(const std::runtime_error& e) { + uiInterface.ThreadSafeMessageBox(_("Error reading from database, shutting down."), "", CClientUIInterface::MSG_ERROR); + LogPrintf("Error reading from database: %s\n", e.what()); + // Starting the shutdown sequence and returning false to the caller would be + // interpreted as 'entry not found' (as opposed to unable to read data), and + // could lead to invalid interpration. Just exit immediately, as we can't + // continue anyway, and all writes should be atomic. + abort(); + } + } + // Writes do not need similar protection, as failure to write is handled by the caller. +}; + static CCoinsViewDB *pcoinsdbview = NULL; +static CCoinsViewErrorCatcher *pcoinscatcher = NULL; void Shutdown() { @@ -119,6 +142,10 @@ void Shutdown() if (!lockShutdown) return; + /// Note: Shutdown() must be able to handle cases in which AppInit2() failed part of the way, + /// 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"); mempool.AddTransactionsUpdated(1); StopRPCThreads(); @@ -130,27 +157,26 @@ void Shutdown() StopNode(); UnregisterNodeSignals(GetNodeSignals()); + if (fFeeEstimatesInitialized) { boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; CAutoFile est_fileout(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION); - if (est_fileout) + if (!est_fileout.IsNull()) mempool.WriteFeeEstimates(est_fileout); else LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string()); + fFeeEstimatesInitialized = false; } { LOCK(cs_main); -#ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->SetBestChain(chainActive.GetLocator()); -#endif - if (pblocktree) - pblocktree->Flush(); - if (pcoinsTip) - pcoinsTip->Flush(); + if (pcoinsTip != NULL) { + FlushStateToDisk(); + } delete pcoinsTip; pcoinsTip = NULL; + delete pcoinscatcher; + pcoinscatcher = NULL; delete pcoinsdbview; pcoinsdbview = NULL; delete pblocktree; @@ -163,7 +189,7 @@ void Shutdown() #ifndef WIN32 boost::filesystem::remove(GetPidFile()); #endif - UnregisterAllWallets(); + UnregisterAllValidationInterfaces(); #ifdef ENABLE_WALLET delete pwalletMain; pwalletMain = NULL; @@ -171,9 +197,9 @@ void Shutdown() LogPrintf("%s: done\n", __func__); } -// -// Signal handlers are very limited in what they are allowed to do, so: -// +/** + * Signal handlers are very limited in what they are allowed to do, so: + */ void HandleSIGTERM(int) { fRequestShutdown = true; @@ -215,9 +241,9 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -? " + _("This help message") + "\n"; strUsage += " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)") + "\n"; strUsage += " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n"; - strUsage += " -checkblocks=<n> " + _("How many blocks to check at startup (default: 288, 0 = all)") + "\n"; - strUsage += " -checklevel=<n> " + _("How thorough the block verification of -checkblocks is (0-4, default: 3)") + "\n"; - strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n"; + strUsage += " -checkblocks=<n> " + strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288) + "\n"; + strUsage += " -checklevel=<n> " + strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3) + "\n"; + strUsage += " -conf=<file> " + strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf") + "\n"; if (mode == HMM_BITCOIND) { #if !defined(WIN32) @@ -227,83 +253,83 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n"; strUsage += " -dbcache=<n> " + strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache) + "\n"; strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + " " + _("on startup") + "\n"; - strUsage += " -maxorphanblocks=<n> " + strprintf(_("Keep at most <n> unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n"; strUsage += " -maxorphantx=<n> " + strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS) + "\n"; strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n"; #ifndef WIN32 - strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n"; + strUsage += " -pid=<file> " + strprintf(_("Specify pid file (default: %s)"), "bitcoind.pid") + "\n"; #endif strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n"; #if !defined(WIN32) strUsage += " -sysperms " + _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)") + "\n"; #endif - strUsage += " -txindex " + _("Maintain a full transaction index (default: 0)") + "\n"; + strUsage += " -txindex " + strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), 0) + "\n"; strUsage += "\n" + _("Connection options:") + "\n"; strUsage += " -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n"; - strUsage += " -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n"; - strUsage += " -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n"; + strUsage += " -banscore=<n> " + strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), 100) + "\n"; + strUsage += " -bantime=<n> " + strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), 86400) + "\n"; strUsage += " -bind=<addr> " + _("Bind to given address and always listen on it. Use [host]:port notation for IPv6") + "\n"; strUsage += " -connect=<ip> " + _("Connect only to the specified node(s)") + "\n"; - strUsage += " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n"; + strUsage += " -discover " + _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)") + "\n"; strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + _("(default: 1)") + "\n"; strUsage += " -dnsseed " + _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)") + "\n"; strUsage += " -externalip=<ip> " + _("Specify your own public address") + "\n"; - strUsage += " -forcednsseed " + _("Always query for peer addresses via DNS lookup (default: 0)") + "\n"; + strUsage += " -forcednsseed " + strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), 0) + "\n"; strUsage += " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n"; - strUsage += " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n"; - strUsage += " -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)") + "\n"; - strUsage += " -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)") + "\n"; - strUsage += " -onion=<ip:port> " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n"; + strUsage += " -maxconnections=<n> " + strprintf(_("Maintain at most <n> connections to peers (default: %u)"), 125) + "\n"; + strUsage += " -maxreceivebuffer=<n> " + strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), 5000) + "\n"; + strUsage += " -maxsendbuffer=<n> " + strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), 1000) + "\n"; + strUsage += " -onion=<ip:port> " + strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy") + "\n"; strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)") + "\n"; - strUsage += " -permitbaremultisig " + _("Relay non-P2SH multisig (default: 1)") + "\n"; - strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n"; + strUsage += " -permitbaremultisig " + strprintf(_("Relay non-P2SH multisig (default: %u)"), 1) + "\n"; + strUsage += " -port=<port> " + strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), 8333, 18333) + "\n"; strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS5 proxy") + "\n"; strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n"; - strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n"; + strUsage += " -timeout=<n> " + strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT) + "\n"; #ifdef USE_UPNP #if USE_UPNP strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n"; #else - strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n"; + strUsage += " -upnp " + strprintf(_("Use UPnP to map the listening port (default: %u)"), 0) + "\n"; #endif #endif strUsage += " -whitebind=<addr> " + _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6") + "\n"; - strUsage += " -whitelist=<netmask> " + _("Whitelist peers connecting from the given netmask or ip. Can be specified multiple times.") + "\n"; + strUsage += " -whitelist=<netmask> " + _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + "\n"; strUsage += " " + _("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") + "\n"; #ifdef ENABLE_WALLET strUsage += "\n" + _("Wallet options:") + "\n"; strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n"; - strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n"; + strUsage += " -keypool=<n> " + strprintf(_("Set key pool size to <n> (default: %u)"), 100) + "\n"; if (GetBoolArg("-help-debug", false)) strUsage += " -mintxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CWallet::minTxFee.GetFeePerK())) + "\n"; strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n"; strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n"; - strUsage += " -respendnotify=<cmd> " + _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)") + "\n"; strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n"; - strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n"; - strUsage += " -txconfirmtarget=<n> " + _("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: 1)") + "\n"; + strUsage += " -sendfreetransactions " + strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0) + "\n"; + strUsage += " -spendzeroconfchange " + strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1) + "\n"; + strUsage += " -txconfirmtarget=<n> " + strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), 1) + "\n"; + strUsage += " -maxtxfee=<amt> " + strprintf(_("Maximum total fees to use in a single wallet transaction, setting too low may abort large transactions (default: %s)"), FormatMoney(maxTxFee)) + "\n"; strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n"; - strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n"; + strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat") + "\n"; strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + "\n"; - strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n"; + strUsage += " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n"; #endif strUsage += "\n" + _("Debugging/Testing options:") + "\n"; if (GetBoolArg("-help-debug", false)) { - strUsage += " -checkpoints " + _("Only accept block chain matching built-in checkpoints (default: 1)") + "\n"; - strUsage += " -dblogsize=<n> " + _("Flush database activity from memory pool to disk log every <n> megabytes (default: 100)") + "\n"; - strUsage += " -disablesafemode " + _("Disable safemode, override a real safe mode event (default: 0)") + "\n"; - strUsage += " -testsafemode " + _("Force safe mode (default: 0)") + "\n"; + strUsage += " -checkpoints " + strprintf(_("Only accept block chain matching built-in checkpoints (default: %u)"), 1) + "\n"; + strUsage += " -dblogsize=<n> " + strprintf(_("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)"), 100) + "\n"; + strUsage += " -disablesafemode " + strprintf(_("Disable safemode, override a real safe mode event (default: %u)"), 0) + "\n"; + strUsage += " -testsafemode " + strprintf(_("Force safe mode (default: %u)"), 0) + "\n"; strUsage += " -dropmessagestest=<n> " + _("Randomly drop 1 of every <n> network messages") + "\n"; strUsage += " -fuzzmessagestest=<n> " + _("Randomly fuzz 1 of every <n> network messages") + "\n"; - strUsage += " -flushwallet " + _("Run a thread to flush wallet periodically (default: 1)") + "\n"; - strUsage += " -stopafterblockimport " + _("Stop running after importing blocks from disk (default: 0)") + "\n"; + strUsage += " -flushwallet " + strprintf(_("Run a thread to flush wallet periodically (default: %u)"), 1) + "\n"; + strUsage += " -stopafterblockimport " + strprintf(_("Stop running after importing blocks from disk (default: %u)"), 0) + "\n"; } - strUsage += " -debug=<category> " + _("Output debugging information (default: 0, supplying <category> is optional)") + "\n"; + strUsage += " -debug=<category> " + strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + "\n"; strUsage += " " + _("If <category> is not supplied, output all debugging information.") + "\n"; strUsage += " " + _("<category> can be:"); strUsage += " addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below @@ -311,25 +337,24 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += ", qt"; strUsage += ".\n"; #ifdef ENABLE_WALLET - strUsage += " -gen " + _("Generate coins (default: 0)") + "\n"; - strUsage += " -genproclimit=<n> " + _("Set the processor limit for when generation is on (-1 = unlimited, default: -1)") + "\n"; + strUsage += " -gen " + strprintf(_("Generate coins (default: %u)"), 0) + "\n"; + strUsage += " -genproclimit=<n> " + strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1) + "\n"; #endif strUsage += " -help-debug " + _("Show all debugging options (usage: --help -help-debug)") + "\n"; - strUsage += " -logips " + _("Include IP addresses in debug output (default: 0)") + "\n"; - strUsage += " -logtimestamps " + _("Prepend debug output with timestamp (default: 1)") + "\n"; + strUsage += " -logips " + strprintf(_("Include IP addresses in debug output (default: %u)"), 0) + "\n"; + strUsage += " -logtimestamps " + strprintf(_("Prepend debug output with timestamp (default: %u)"), 1) + "\n"; if (GetBoolArg("-help-debug", false)) { - strUsage += " -limitfreerelay=<n> " + _("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15)") + "\n"; - strUsage += " -maxsigcachesize=<n> " + _("Limit size of signature cache to <n> entries (default: 50000)") + "\n"; + strUsage += " -limitfreerelay=<n> " + strprintf(_("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:%u)"), 15) + "\n"; + strUsage += " -relaypriority " + strprintf(_("Require high priority for relaying free or low-fee transactions (default:%u)"), 1) + "\n"; + strUsage += " -maxsigcachesize=<n> " + strprintf(_("Limit size of signature cache to <n> entries (default: %u)"), 50000) + "\n"; } strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())) + "\n"; strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; if (GetBoolArg("-help-debug", false)) { - strUsage += " -printblock=<hash> " + _("Print block on startup, if found in block index") + "\n"; - strUsage += " -printblocktree " + _("Print block tree on startup (default: 0)") + "\n"; - strUsage += " -printpriority " + _("Log transaction priority and fee per kB when mining blocks (default: 0)") + "\n"; - strUsage += " -privdb " + _("Sets the DB_PRIVATE flag in the wallet db environment (default: 1)") + "\n"; + strUsage += " -printpriority " + strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0) + "\n"; + strUsage += " -privdb " + strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1) + "\n"; strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; strUsage += " " + _("This is intended for regression testing tools and app development.") + "\n"; strUsage += " " + _("In this mode -genproclimit controls how many blocks are generated immediately.") + "\n"; @@ -338,27 +363,30 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -testnet " + _("Use the test network") + "\n"; strUsage += "\n" + _("Node relay options:") + "\n"; - strUsage += " -datacarrier " + _("Relay and mine data carrier transactions (default: 1)") + "\n"; + strUsage += " -datacarrier " + strprintf(_("Relay and mine data carrier transactions (default: %u)"), 1) + "\n"; + strUsage += " -datacarriersize " + strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY) + "\n"; strUsage += "\n" + _("Block creation options:") + "\n"; - strUsage += " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n"; + strUsage += " -blockminsize=<n> " + strprintf(_("Set minimum block size in bytes (default: %u)"), 0) + "\n"; strUsage += " -blockmaxsize=<n> " + strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE) + "\n"; strUsage += " -blockprioritysize=<n> " + strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE) + "\n"; strUsage += "\n" + _("RPC server options:") + "\n"; strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n"; + strUsage += " -rest " + strprintf(_("Accept public REST requests (default: %u)"), 0) + "\n"; strUsage += " -rpcbind=<addr> " + _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)") + "\n"; strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; - strUsage += " -rpcport=<port> " + _("Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332)") + "\n"; + strUsage += " -rpcport=<port> " + strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n"; strUsage += " -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") + "\n"; - strUsage += " -rpcthreads=<n> " + _("Set the number of threads to service RPC calls (default: 4)") + "\n"; + strUsage += " -rpcthreads=<n> " + strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4) + "\n"; + strUsage += " -rpckeepalive " + strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 1) + "\n"; strUsage += "\n" + _("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n"; - strUsage += " -rpcsslcertificatechainfile=<file.cert> " + _("Server certificate file (default: server.cert)") + "\n"; - strUsage += " -rpcsslprivatekeyfile=<file.pem> " + _("Server private key (default: server.pem)") + "\n"; - strUsage += " -rpcsslciphers=<ciphers> " + _("Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH)") + "\n"; + strUsage += " -rpcsslcertificatechainfile=<file.cert> " + strprintf(_("Server certificate file (default: %s)"), "server.cert") + "\n"; + strUsage += " -rpcsslprivatekeyfile=<file.pem> " + strprintf(_("Server private key (default: %s)"), "server.pem") + "\n"; + strUsage += " -rpcsslciphers=<ciphers> " + strprintf(_("Acceptable ciphers (default: %s)"), "TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH") + "\n"; return strUsage; } @@ -369,7 +397,7 @@ std::string LicenseInfo() "\n" + FormatParagraph(_("This is experimental software.")) + "\n" + "\n" + - FormatParagraph(_("Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.")) + "\n" + + FormatParagraph(_("Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.")) + "\n" + "\n" + FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.")) + "\n"; @@ -423,12 +451,12 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles) } // hardcoded $DATADIR/bootstrap.dat - filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; - if (filesystem::exists(pathBootstrap)) { + boost::filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; + if (boost::filesystem::exists(pathBootstrap)) { FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); if (file) { CImportingNow imp; - filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; + boost::filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; LogPrintf("Importing bootstrap.dat...\n"); LoadExternalBlockFile(file); RenameOver(pathBootstrap, pathBootstrapOld); @@ -542,51 +570,63 @@ bool AppInit2(boost::thread_group& threadGroup) // ********************************************************* Step 2: parameter interactions - if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) { - // when specifying an explicit binding address, you want to listen on it - // even when -connect or -proxy is specified + // Set this early so that parameter interactions go to console + fPrintToConsole = GetBoolArg("-printtoconsole", false); + fLogTimestamps = GetBoolArg("-logtimestamps", true); + fLogIPs = GetBoolArg("-logips", false); + + // when specifying an explicit binding address, you want to listen on it + // even when -connect or -proxy is specified + if (mapArgs.count("-bind")) { + if (SoftSetBoolArg("-listen", true)) + LogPrintf("%s: parameter interaction: -bind set -> setting -listen=1\n", __func__); + } + if (mapArgs.count("-whitebind")) { if (SoftSetBoolArg("-listen", true)) - LogPrintf("AppInit2 : parameter interaction: -bind or -whitebind set -> setting -listen=1\n"); + LogPrintf("%s: parameter interaction: -whitebind set -> setting -listen=1\n", __func__); } if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) { // when only connecting to trusted nodes, do not seed via DNS, or listen by default if (SoftSetBoolArg("-dnsseed", false)) - LogPrintf("AppInit2 : parameter interaction: -connect set -> setting -dnsseed=0\n"); + LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__); if (SoftSetBoolArg("-listen", false)) - LogPrintf("AppInit2 : parameter interaction: -connect set -> setting -listen=0\n"); + LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__); } if (mapArgs.count("-proxy")) { // to protect privacy, do not listen by default if a default proxy server is specified if (SoftSetBoolArg("-listen", false)) - LogPrintf("AppInit2 : parameter interaction: -proxy set -> setting -listen=0\n"); + LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__); + // to protect privacy, do not discover addresses by default + if (SoftSetBoolArg("-discover", false)) + LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__); } - if (!GetBoolArg("-listen", true)) { + if (!GetBoolArg("-listen", DEFAULT_LISTEN)) { // do not map ports or try to retrieve public IP when not listening (pointless) if (SoftSetBoolArg("-upnp", false)) - LogPrintf("AppInit2 : parameter interaction: -listen=0 -> setting -upnp=0\n"); + LogPrintf("%s: parameter interaction: -listen=0 -> setting -upnp=0\n", __func__); if (SoftSetBoolArg("-discover", false)) - LogPrintf("AppInit2 : parameter interaction: -listen=0 -> setting -discover=0\n"); + LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__); } if (mapArgs.count("-externalip")) { // if an explicit public IP is specified, do not try to find others if (SoftSetBoolArg("-discover", false)) - LogPrintf("AppInit2 : parameter interaction: -externalip set -> setting -discover=0\n"); + LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__); } if (GetBoolArg("-salvagewallet", false)) { // Rewrite just private keys: rescan to find transactions if (SoftSetBoolArg("-rescan", true)) - LogPrintf("AppInit2 : parameter interaction: -salvagewallet=1 -> setting -rescan=1\n"); + LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); } // -zapwallettx implies a rescan if (GetBoolArg("-zapwallettxes", false)) { if (SoftSetBoolArg("-rescan", true)) - LogPrintf("AppInit2 : parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n"); + LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__); } // Make sure enough file descriptors are available @@ -634,19 +674,13 @@ bool AppInit2(boost::thread_group& threadGroup) nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS; fServer = GetBoolArg("-server", false); - fPrintToConsole = GetBoolArg("-printtoconsole", false); - fLogTimestamps = GetBoolArg("-logtimestamps", true); - fLogIPs = GetBoolArg("-logips", false); #ifdef ENABLE_WALLET bool fDisableWallet = GetBoolArg("-disablewallet", false); #endif - if (mapArgs.count("-timeout")) - { - int nNewTimeout = GetArg("-timeout", 5000); - if (nNewTimeout > 0 && nNewTimeout < 600000) - nConnectTimeout = nNewTimeout; - } + nConnectTimeout = GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); + if (nConnectTimeout <= 0) + nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; // Continue to put "/P2SH/" in the coinbase to monitor // BIP16 support. @@ -692,13 +726,29 @@ bool AppInit2(boost::thread_group& threadGroup) mapArgs["-paytxfee"], ::minRelayTxFee.ToString())); } } + if (mapArgs.count("-maxtxfee")) + { + CAmount nMaxFee = 0; + if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee)) + return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s'"), mapArgs["-maptxfee"])); + if (nMaxFee > nHighTransactionMaxFeeWarning) + InitWarning(_("Warning: -maxtxfee is set very high! Fees this large could be paid on a single transaction.")); + maxTxFee = nMaxFee; + if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee) + { + return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), + mapArgs["-maxtxfee"], ::minRelayTxFee.ToString())); + } + } nTxConfirmTarget = GetArg("-txconfirmtarget", 1); bSpendZeroConfChange = GetArg("-spendzeroconfchange", true); + fSendFreeTransactions = GetArg("-sendfreetransactions", false); std::string strWalletFile = GetArg("-wallet", "wallet.dat"); #endif // ENABLE_WALLET fIsBareMultisigStd = GetArg("-permitbaremultisig", true) != 0; + nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes); // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log @@ -738,12 +788,23 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); std::ostringstream strErrors; + LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads); if (nScriptCheckThreads) { - LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads); for (int i=0; i<nScriptCheckThreads-1; i++) threadGroup.create_thread(&ThreadScriptCheck); } + /* Start the RPC server already. It will be started in "warmup" mode + * and not really process calls already (but it will signify connections + * that the server is there and will be ready later). Warmup mode will + * be disabled when initialisation is finished. + */ + if (fServer) + { + uiInterface.InitMessage.connect(SetRPCWarmupStatus); + StartRPCThreads(); + } + int64_t nStart; // ********************************************************* Step 5: verify wallet database integrity @@ -760,7 +821,7 @@ bool AppInit2(boost::thread_group& threadGroup) try { boost::filesystem::rename(pathDatabase, pathDatabaseBak); LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string()); - } catch(boost::filesystem::filesystem_error &error) { + } catch (const boost::filesystem::filesystem_error&) { // failure is ok (well, not really, but it's not worse than what we started with) } @@ -779,7 +840,7 @@ bool AppInit2(boost::thread_group& threadGroup) return false; } - if (filesystem::exists(GetDataDir() / strWalletFile)) + if (boost::filesystem::exists(GetDataDir() / strWalletFile)) { CDBEnv::VerifyResult r = bitdb.Verify(strWalletFile, CWalletDB::Recover); if (r == CDBEnv::RECOVER_OK) @@ -830,10 +891,8 @@ bool AppInit2(boost::thread_group& threadGroup) if (!addrProxy.IsValid()) return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"])); - if (!IsLimited(NET_IPV4)) - SetProxy(NET_IPV4, addrProxy); - if (!IsLimited(NET_IPV6)) - SetProxy(NET_IPV6, addrProxy); + SetProxy(NET_IPV4, addrProxy); + SetProxy(NET_IPV6, addrProxy); SetNameProxy(addrProxy); fProxy = true; } @@ -902,20 +961,20 @@ bool AppInit2(boost::thread_group& threadGroup) fReindex = GetBoolArg("-reindex", false); // Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/ - filesystem::path blocksDir = GetDataDir() / "blocks"; - if (!filesystem::exists(blocksDir)) + boost::filesystem::path blocksDir = GetDataDir() / "blocks"; + if (!boost::filesystem::exists(blocksDir)) { - filesystem::create_directories(blocksDir); + boost::filesystem::create_directories(blocksDir); bool linked = false; for (unsigned int i = 1; i < 10000; i++) { - filesystem::path source = GetDataDir() / strprintf("blk%04u.dat", i); - if (!filesystem::exists(source)) break; - filesystem::path dest = blocksDir / strprintf("blk%05u.dat", i-1); + boost::filesystem::path source = GetDataDir() / strprintf("blk%04u.dat", i); + if (!boost::filesystem::exists(source)) break; + boost::filesystem::path dest = blocksDir / strprintf("blk%05u.dat", i-1); try { - filesystem::create_hard_link(source, dest); + boost::filesystem::create_hard_link(source, dest); LogPrintf("Hardlinked %s -> %s\n", source.string(), dest.string()); linked = true; - } catch (filesystem::filesystem_error & e) { + } catch (const boost::filesystem::filesystem_error& e) { // Note: hardlink creation failing is not a disaster, it just means // blocks will get re-downloaded from peers. LogPrintf("Error hardlinking blk%04u.dat : %s\n", i, e.what()); @@ -955,11 +1014,13 @@ bool AppInit2(boost::thread_group& threadGroup) UnloadBlockIndex(); delete pcoinsTip; delete pcoinsdbview; + delete pcoinscatcher; delete pblocktree; pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); - pcoinsTip = new CCoinsViewCache(*pcoinsdbview); + pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); + pcoinsTip = new CCoinsViewCache(pcoinscatcher); if (fReindex) pblocktree->WriteReindexing(true); @@ -971,7 +1032,7 @@ bool AppInit2(boost::thread_group& threadGroup) // If the loaded chain has a wrong genesis, bail out immediately // (we're likely using a testnet datadir, or the other way around). - if (!mapBlockIndex.empty() && chainActive.Genesis() == NULL) + if (!mapBlockIndex.empty() && mapBlockIndex.count(Params().HashGenesisBlock()) == 0) return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); // Initialize the block index (no-op if non-empty database was already loaded) @@ -992,7 +1053,7 @@ bool AppInit2(boost::thread_group& threadGroup) strLoadError = _("Corrupted block database detected"); break; } - } catch(std::exception &e) { + } catch (const std::exception& e) { if (fDebug) LogPrintf("%s\n", e.what()); strLoadError = _("Error opening block database"); break; @@ -1030,39 +1091,12 @@ bool AppInit2(boost::thread_group& threadGroup) } LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); - if (GetBoolArg("-printblockindex", false) || GetBoolArg("-printblocktree", false)) - { - PrintBlockTree(); - return false; - } - - if (mapArgs.count("-printblock")) - { - string strMatch = mapArgs["-printblock"]; - int nFound = 0; - for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) - { - uint256 hash = (*mi).first; - if (boost::algorithm::starts_with(hash.ToString(), strMatch)) - { - CBlockIndex* pindex = (*mi).second; - CBlock block; - ReadBlockFromDisk(block, pindex); - block.BuildMerkleTree(); - LogPrintf("%s\n", block.ToString()); - nFound++; - } - } - if (nFound == 0) - LogPrintf("No blocks matching %s were found\n", strMatch); - return false; - } - boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); // Allowed to fail as this file IS missing on first startup. - if (est_filein) + if (!est_filein.IsNull()) mempool.ReadFeeEstimates(est_filein); + fFeeEstimatesInitialized = true; // ********************************************************* Step 8: load wallet #ifdef ENABLE_WALLET @@ -1150,7 +1184,7 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("%s", strErrors.str()); LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); - RegisterWallet(pwalletMain); + RegisterValidationInterface(pwalletMain); CBlockIndex *pindexRescan = chainActive.Tip(); if (GetBoolArg("-rescan", false)) @@ -1221,22 +1255,7 @@ bool AppInit2(boost::thread_group& threadGroup) } threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); - // ********************************************************* Step 10: load peers - - uiInterface.InitMessage(_("Loading addresses...")); - - nStart = GetTimeMillis(); - - { - CAddrDB adb; - if (!adb.Read(addrman)) - LogPrintf("Invalid or missing peers.dat; recreating\n"); - } - - LogPrintf("Loaded %i addresses from peers.dat %dms\n", - addrman.size(), GetTimeMillis() - nStart); - - // ********************************************************* Step 11: start node + // ********************************************************* Step 10: start node if (!CheckDiskSpace()) return false; @@ -1256,17 +1275,16 @@ bool AppInit2(boost::thread_group& threadGroup) #endif StartNode(threadGroup); - if (fServer) - StartRPCThreads(); #ifdef ENABLE_WALLET // Generate coins in the background if (pwalletMain) - GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", -1)); + GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1)); #endif - // ********************************************************* Step 12: finished + // ********************************************************* Step 11: finished + SetRPCWarmupFinished(); uiInterface.InitMessage(_("Done loading")); #ifdef ENABLE_WALLET |