2011-05-14 20:10:21 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2014-02-08 22:50:24 +01:00
// Copyright (c) 2009-2014 The Bitcoin developers
2011-05-14 20:10:21 +02:00
// Distributed under the MIT/X11 software license, see the accompanying
2012-05-18 16:02:28 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2012-11-05 08:04:21 +01:00
2013-05-28 01:55:01 +02:00
# if defined(HAVE_CONFIG_H)
2014-06-23 20:04:24 +02:00
# include "config/bitcoin-config.h"
2013-05-28 01:55:01 +02:00
# endif
2013-01-07 17:07:51 +01:00
# include "init.h"
2013-04-13 07:13:08 +02:00
# include "addrman.h"
# include "checkpoints.h"
2014-06-03 01:21:03 +02:00
# include "key.h"
2013-12-13 08:50:07 +01:00
# include "main.h"
2013-07-31 15:43:35 +02:00
# include "miner.h"
2013-04-13 07:13:08 +02:00
# include "net.h"
2013-12-13 08:50:07 +01:00
# include "rpcserver.h"
2013-04-13 07:13:08 +02:00
# include "txdb.h"
2012-04-15 22:10:54 +02:00
# include "ui_interface.h"
2013-04-13 07:13:08 +02:00
# include "util.h"
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2013-12-18 20:46:43 +01:00
# include "db.h"
2013-04-13 07:13:08 +02:00
# include "wallet.h"
# include "walletdb.h"
2013-11-29 16:04:29 +01:00
# endif
2012-11-05 08:04:21 +01:00
2013-04-13 07:13:08 +02:00
# include <stdint.h>
2014-05-11 15:29:16 +02:00
# include <stdio.h>
2011-05-14 20:10:21 +02:00
2012-04-15 22:10:54 +02:00
# ifndef WIN32
# include <signal.h>
2012-03-18 23:14:03 +01:00
# endif
2014-06-14 01:23:01 +02:00
# include "compat/sanity.h"
2011-10-07 16:46:56 +02:00
2013-04-13 07:13:08 +02:00
# include <boost/algorithm/string/predicate.hpp>
# include <boost/filesystem.hpp>
# include <boost/interprocess/sync/file_lock.hpp>
# include <openssl/crypto.h>
2011-05-14 20:10:21 +02:00
using namespace std ;
using namespace boost ;
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2011-06-26 19:23:24 +02:00
CWallet * pwalletMain ;
2013-11-29 16:04:29 +01:00
# endif
2011-06-26 19:23:24 +02:00
2013-04-26 00:46:47 +02:00
# ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
// accessing block files, don't count towards to fd_set size limit
// anyway.
# define MIN_CORE_FILEDESCRIPTORS 0
# else
# define MIN_CORE_FILEDESCRIPTORS 150
# endif
2012-09-03 15:54:47 +02:00
// Used to pass flags to the Bind() function
enum BindFlags {
2012-11-14 16:07:40 +01:00
BF_NONE = 0 ,
BF_EXPLICIT = ( 1U < < 0 ) ,
BF_REPORT_ERROR = ( 1U < < 1 )
2012-09-03 15:54:47 +02:00
} ;
2014-03-17 13:19:54 +01:00
static const char * FEE_ESTIMATES_FILENAME = " fee_estimates.dat " ;
2013-01-07 16:35:31 +01:00
2011-05-14 20:10:21 +02:00
//////////////////////////////////////////////////////////////////////////////
//
// Shutdown
//
2013-03-09 18:02:57 +01:00
//
// Thread management and startup/shutdown:
//
// The network-processing threads are all part of a thread group
// created by AppInit() or the Qt main() function.
//
// A clean exit happens when StartShutdown() or the SIGTERM
// signal handler sets fRequestShutdown, which triggers
// the DetectShutdownThread(), which interrupts the main thread group.
// DetectShutdownThread() then exits, which causes AppInit() to
// continue (it .joins the shutdown thread).
// Shutdown() is then
// called to clean up database connections, and stop other
// threads that should only be stopped after the main network-processing
// threads have exited.
//
// Note that if running -daemon the parent process returns from AppInit2
// before adding any threads to the threadGroup, so .join_all() returns
// immediately and the parent exits from main().
//
// Shutdown for Qt is very similar, only it uses a QTimer to detect
2013-03-23 23:14:12 +01:00
// fRequestShutdown getting set, and then does the normal Qt
// shutdown thing.
2013-03-09 18:02:57 +01:00
//
volatile bool fRequestShutdown = false ;
2011-05-14 20:10:21 +02:00
2012-06-11 07:40:14 +02:00
void StartShutdown ( )
{
2013-03-09 18:02:57 +01:00
fRequestShutdown = true ;
2012-06-11 07:40:14 +02:00
}
2013-03-23 23:14:12 +01:00
bool ShutdownRequested ( )
{
return fRequestShutdown ;
}
2012-06-11 07:40:14 +02:00
2012-07-06 16:33:34 +02:00
static CCoinsViewDB * pcoinsdbview ;
2013-03-09 18:02:57 +01:00
void Shutdown ( )
2011-05-14 20:10:21 +02:00
{
2013-10-01 09:44:56 +02:00
LogPrintf ( " Shutdown : In progress... \n " ) ;
2011-05-14 20:10:21 +02:00
static CCriticalSection cs_Shutdown ;
2013-03-09 18:02:57 +01:00
TRY_LOCK ( cs_Shutdown , lockShutdown ) ;
if ( ! lockShutdown ) return ;
2012-06-24 17:03:57 +02:00
RenameThread ( " bitcoin-shutoff " ) ;
2013-08-27 07:51:57 +02:00
mempool . AddTransactionsUpdated ( 1 ) ;
2013-03-07 04:31:26 +01:00
StopRPCThreads ( ) ;
2013-12-08 15:26:08 +01:00
# ifdef ENABLE_WALLET
2013-08-25 06:00:02 +02:00
if ( pwalletMain )
bitdb . Flush ( false ) ;
2013-11-21 05:07:55 +01:00
GenerateBitcoins ( false , NULL , 0 ) ;
2013-11-29 16:04:29 +01:00
# endif
2013-03-07 04:31:26 +01:00
StopNode ( ) ;
2013-11-18 01:25:17 +01:00
UnregisterNodeSignals ( GetNodeSignals ( ) ) ;
2014-03-17 13:19:54 +01:00
boost : : filesystem : : path est_path = GetDataDir ( ) / FEE_ESTIMATES_FILENAME ;
CAutoFile est_fileout = CAutoFile ( fopen ( est_path . string ( ) . c_str ( ) , " wb " ) , SER_DISK , CLIENT_VERSION ) ;
if ( est_fileout )
mempool . WriteFeeEstimates ( est_fileout ) ;
else
LogPrintf ( " failed to write fee estimates " ) ;
2011-05-14 20:10:21 +02:00
{
2013-03-09 18:02:57 +01:00
LOCK ( cs_main ) ;
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2013-05-24 21:52:52 +02:00
if ( pwalletMain )
2013-10-12 15:18:08 +02:00
pwalletMain - > SetBestChain ( chainActive . GetLocator ( ) ) ;
2013-11-29 16:04:29 +01:00
# endif
2013-03-09 18:02:57 +01:00
if ( pblocktree )
pblocktree - > Flush ( ) ;
if ( pcoinsTip )
pcoinsTip - > Flush ( ) ;
delete pcoinsTip ; pcoinsTip = NULL ;
delete pcoinsdbview ; pcoinsdbview = NULL ;
delete pblocktree ; pblocktree = NULL ;
2011-05-14 20:10:21 +02:00
}
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2013-08-25 06:00:02 +02:00
if ( pwalletMain )
bitdb . Flush ( true ) ;
2013-11-29 16:04:29 +01:00
# endif
2013-03-09 18:02:57 +01:00
boost : : filesystem : : remove ( GetPidFile ( ) ) ;
2013-01-23 21:48:35 +01:00
UnregisterAllWallets ( ) ;
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2013-08-25 06:00:02 +02:00
if ( pwalletMain )
delete pwalletMain ;
2013-11-29 16:04:29 +01:00
# endif
2013-10-01 09:44:56 +02:00
LogPrintf ( " Shutdown : done \n " ) ;
2011-05-14 20:10:21 +02:00
}
2013-03-07 04:16:05 +01:00
//
// Signal handlers are very limited in what they are allowed to do, so:
//
2011-05-14 20:10:21 +02:00
void HandleSIGTERM ( int )
{
fRequestShutdown = true ;
}
2012-03-02 20:31:16 +01:00
void HandleSIGHUP ( int )
{
fReopenDebugLog = true ;
}
2011-05-14 20:10:21 +02:00
2012-05-13 12:35:39 +02:00
bool static InitError ( const std : : string & str )
{
2013-12-16 18:13:31 +01:00
uiInterface . ThreadSafeMessageBox ( str , " " , CClientUIInterface : : MSG_ERROR | CClientUIInterface : : NOSHOWGUI ) ;
2012-05-13 12:35:39 +02:00
return false ;
}
bool static InitWarning ( const std : : string & str )
{
2013-12-16 18:13:31 +01:00
uiInterface . ThreadSafeMessageBox ( str , " " , CClientUIInterface : : MSG_WARNING | CClientUIInterface : : NOSHOWGUI ) ;
2012-05-13 12:35:39 +02:00
return true ;
}
2012-11-14 16:07:40 +01:00
bool static Bind ( const CService & addr , unsigned int flags ) {
2012-09-03 15:54:47 +02:00
if ( ! ( flags & BF_EXPLICIT ) & & IsLimited ( addr ) )
2012-05-11 15:28:59 +02:00
return false ;
std : : string strError ;
2012-05-24 19:02:21 +02:00
if ( ! BindListenPort ( addr , strError ) ) {
2012-09-03 15:54:47 +02:00
if ( flags & BF_REPORT_ERROR )
2012-05-24 19:02:21 +02:00
return InitError ( strError ) ;
return false ;
}
2012-05-11 15:28:59 +02:00
return true ;
}
2014-06-17 09:13:52 +02:00
std : : string HelpMessage ( HelpMessageMode mode )
2012-05-13 11:36:10 +02:00
{
2014-06-17 09:13:52 +02:00
// When adding new options to the categories, please keep and ensure alphabetical ordering.
2013-05-26 20:05:53 +02:00
string strUsage = _ ( " Options: " ) + " \n " ;
strUsage + = " -? " + _ ( " This help message " ) + " \n " ;
2014-02-03 07:23:20 +01:00
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 " ;
2013-05-26 20:05:53 +02:00
strUsage + = " -conf=<file> " + _ ( " Specify configuration file (default: bitcoin.conf) " ) + " \n " ;
2014-06-17 09:13:52 +02:00
if ( mode = = HMM_BITCOIND )
2014-02-03 07:23:20 +01:00
{
# if !defined(WIN32)
strUsage + = " -daemon " + _ ( " Run in the background as a daemon and accept commands " ) + " \n " ;
# endif
}
2013-05-26 20:05:53 +02:00
strUsage + = " -datadir=<dir> " + _ ( " Specify data directory " ) + " \n " ;
2014-02-16 22:00:12 +01:00
strUsage + = " -dbcache=<n> " + strprintf ( _ ( " Set database cache size in megabytes (%d to %d, default: %d) " ) , nMinDbCache , nMaxDbCache , nDefaultDbCache ) + " \n " ;
2014-02-03 07:23:20 +01:00
strUsage + = " -keypool=<n> " + _ ( " Set key pool size to <n> (default: 100) " ) + " \n " ;
strUsage + = " -loadblock=<file> " + _ ( " Imports blocks from external blk000??.dat file " ) + " " + _ ( " on startup " ) + " \n " ;
2014-05-30 14:35:23 +02:00
strUsage + = " -maxorphanblocks=<n> " + strprintf ( _ ( " Keep at most <n> unconnectable blocks in memory (default: %u) " ) , DEFAULT_MAX_ORPHAN_BLOCKS ) + " \n " ;
2014-02-18 12:48:16 +01:00
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 " ;
2014-02-03 07:23:20 +01:00
strUsage + = " -pid=<file> " + _ ( " Specify pid file (default: bitcoind.pid) " ) + " \n " ;
strUsage + = " -reindex " + _ ( " Rebuild block chain index from current blk000??.dat files " ) + " " + _ ( " on startup " ) + " \n " ;
strUsage + = " -txindex " + _ ( " Maintain a full transaction index (default: 0) " ) + " \n " ;
strUsage + = " \n " + _ ( " Connection options: " ) + " \n " ;
2013-11-27 15:41:12 +01:00
strUsage + = " -addnode=<ip> " + _ ( " Add a node to connect to and attempt to keep the connection open " ) + " \n " ;
2014-02-03 07:23:20 +01:00
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 + = " -bind=<addr> " + _ ( " Bind to given address and always listen on it. Use [host]:port notation for IPv6 " ) + " \n " ;
2013-11-27 15:41:12 +01:00
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 " ;
2014-02-03 07:23:20 +01:00
strUsage + = " -dns " + _ ( " Allow DNS lookups for -addnode, -seednode and -connect " ) + " " + _ ( " (default: 1) " ) + " \n " ;
2013-11-27 15:41:12 +01:00
strUsage + = " -dnsseed " + _ ( " Find peers using DNS lookup (default: 1 unless -connect) " ) + " \n " ;
2014-02-03 07:23:20 +01:00
strUsage + = " -externalip=<ip> " + _ ( " Specify your own public address " ) + " \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 " ;
2013-11-27 15:41:12 +01:00
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 " ;
2014-02-03 07:23:20 +01:00
strUsage + = " -onion=<ip:port> " + _ ( " Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy) " ) + " \n " ;
strUsage + = " -onlynet=<net> " + _ ( " Only connect to nodes in network <net> (IPv4, IPv6 or Tor) " ) + " \n " ;
strUsage + = " -port=<port> " + _ ( " Listen for connections on <port> (default: 8333 or testnet: 18333) " ) + " \n " ;
strUsage + = " -proxy=<ip:port> " + _ ( " Connect through SOCKS proxy " ) + " \n " ;
strUsage + = " -seednode=<ip> " + _ ( " Connect to a node to retrieve peer addresses, and disconnect " ) + " \n " ;
strUsage + = " -socks=<n> " + _ ( " Select SOCKS version for -proxy (4 or 5, default: 5) " ) + " \n " ;
strUsage + = " -timeout=<n> " + _ ( " Specify connection timeout in milliseconds (default: 5000) " ) + " \n " ;
2012-05-13 11:36:10 +02:00
# ifdef USE_UPNP
# if USE_UPNP
2013-11-27 15:41:12 +01:00
strUsage + = " -upnp " + _ ( " Use UPnP to map the listening port (default: 1 when listening) " ) + " \n " ;
2012-05-13 11:36:10 +02:00
# else
2013-11-27 15:41:12 +01:00
strUsage + = " -upnp " + _ ( " Use UPnP to map the listening port (default: 0) " ) + " \n " ;
2013-10-11 23:09:59 +02:00
# endif
2012-05-13 11:36:10 +02:00
# endif
2014-02-03 07:23:20 +01:00
# ifdef ENABLE_WALLET
strUsage + = " \n " + _ ( " Wallet options: " ) + " \n " ;
strUsage + = " -disablewallet " + _ ( " Do not load the wallet and disable wallet RPC calls " ) + " \n " ;
strUsage + = " -paytxfee=<amt> " + _ ( " Fee per kB to add to transactions you send " ) + " \n " ;
strUsage + = " -rescan " + _ ( " Rescan the block chain for missing wallet transactions " ) + " " + _ ( " on startup " ) + " \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 + = " -upgradewallet " + _ ( " Upgrade wallet to latest format " ) + " " + _ ( " on startup " ) + " \n " ;
strUsage + = " -wallet=<file> " + _ ( " Specify wallet file (within data directory) " ) + " " + _ ( " (default: wallet.dat) " ) + " \n " ;
strUsage + = " -walletnotify=<cmd> " + _ ( " Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) " ) + " \n " ;
2014-02-14 18:27:15 +01:00
strUsage + = " -zapwallettxes=<mode> " + _ ( " Delete all wallet transactions and only recover those part 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 " ;
2014-02-03 07:23:20 +01:00
# endif
strUsage + = " \n " + _ ( " Debugging/Testing options: " ) + " \n " ;
if ( GetBoolArg ( " -help-debug " , false ) )
{
strUsage + = " -benchmark " + _ ( " Show benchmark information (default: 0) " ) + " \n " ;
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 + = " -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 " ;
2014-05-07 20:10:48 +02:00
strUsage + = " -stopafterblockimport " + _ ( " Stop running after importing blocks from disk (default: 0) " ) + " \n " ;
2014-02-03 07:23:20 +01:00
}
2013-11-27 15:41:12 +01:00
strUsage + = " -debug=<category> " + _ ( " Output debugging information (default: 0, supplying <category> is optional) " ) + " \n " ;
2013-12-18 13:31:25 +01:00
strUsage + = " " + _ ( " If <category> is not supplied, output all debugging information. " ) + " \n " ;
strUsage + = " " + _ ( " <category> can be: " ) ;
2013-11-27 15:41:12 +01:00
strUsage + = " addrman, alert, coindb, db, lock, rand, rpc, selectcoins, mempool, net " ; // Don't translate these and qt below
2014-06-17 09:13:52 +02:00
if ( mode = = HMM_BITCOIN_QT )
2014-02-03 07:23:20 +01:00
strUsage + = " , qt " ;
strUsage + = " . \n " ;
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 + = " -help-debug " + _ ( " Show all debugging options (usage: --help -help-debug) " ) + " \n " ;
strUsage + = " -logtimestamps " + _ ( " Prepend debug output with timestamp (default: 1) " ) + " \n " ;
if ( GetBoolArg ( " -help-debug " , false ) )
2013-10-08 12:09:40 +02:00
{
2014-02-03 07:23:20 +01:00
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 " ;
2013-10-08 12:09:40 +02:00
}
2014-04-10 20:14:18 +02:00
strUsage + = " -mintxfee=<amt> " + _ ( " Fees smaller than this are considered zero fee (for transaction creation) (default: " ) + " " + FormatMoney ( CTransaction : : minTxFee . GetFeePerK ( ) ) + " ) " + " \n " ;
strUsage + = " -minrelaytxfee=<amt> " + _ ( " Fees smaller than this are considered zero fee (for relaying) (default: " ) + " " + FormatMoney ( CTransaction : : minRelayTxFee . GetFeePerK ( ) ) + " ) " + " \n " ;
2014-02-03 07:23:20 +01:00
strUsage + = " -printtoconsole " + _ ( " Send trace/debug info to console instead of debug.log file " ) + " \n " ;
if ( GetBoolArg ( " -help-debug " , false ) )
2013-10-08 12:09:40 +02:00
{
2014-02-03 07:23:20 +01:00
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 + = " -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 " ;
2013-10-08 12:09:40 +02:00
}
2013-11-27 15:41:12 +01:00
strUsage + = " -shrinkdebugfile " + _ ( " Shrink debug.log file on client startup (default: 1 when no -debug) " ) + " \n " ;
2014-02-03 07:23:20 +01:00
strUsage + = " -testnet " + _ ( " Use the test network " ) + " \n " ;
2013-10-11 23:09:59 +02:00
2014-02-03 07:23:20 +01:00
strUsage + = " \n " + _ ( " Block creation options: " ) + " \n " ;
strUsage + = " -blockminsize=<n> " + _ ( " Set minimum block size in bytes (default: 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 " ;
2013-10-11 23:09:59 +02:00
2014-02-03 07:23:20 +01:00
strUsage + = " \n " + _ ( " RPC server options: " ) + " \n " ;
strUsage + = " -server " + _ ( " Accept command line and JSON-RPC commands " ) + " \n " ;
2014-02-17 17:35:40 +01:00
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 " ;
2013-05-26 20:05:53 +02:00
strUsage + = " -rpcuser=<user> " + _ ( " Username for JSON-RPC connections " ) + " \n " ;
strUsage + = " -rpcpassword=<pw> " + _ ( " Password for JSON-RPC connections " ) + " \n " ;
2013-11-27 15:41:12 +01:00
strUsage + = " -rpcport=<port> " + _ ( " Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332) " ) + " \n " ;
2014-02-17 17:35:40 +01:00
strUsage + = " -rpcallowip=<ip> " + _ ( " Allow JSON-RPC connections from specified IP address. This option can be specified multiple times " ) + " \n " ;
2013-11-27 15:41:12 +01:00
strUsage + = " -rpcthreads=<n> " + _ ( " Set the number of threads to service RPC calls (default: 4) " ) + " \n " ;
2012-05-13 11:36:10 +02:00
2014-02-03 07:23:20 +01:00
strUsage + = " \n " + _ ( " RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions) " ) + " \n " ;
2013-05-26 20:05:53 +02:00
strUsage + = " -rpcssl " + _ ( " Use OpenSSL (https) for JSON-RPC connections " ) + " \n " ;
2013-11-27 15:41:12 +01:00
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 " ;
2012-05-13 11:36:10 +02:00
return strUsage ;
}
2014-06-10 16:02:46 +02:00
std : : string LicenseInfo ( )
{
return FormatParagraph ( strprintf ( _ ( " Copyright (C) 2009-%i The Bitcoin Core Developers " ) , COPYRIGHT_YEAR ) ) + " \n " +
" \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 " +
" \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 " ;
}
2012-10-22 22:45:26 +02:00
struct CImportingNow
{
CImportingNow ( ) {
assert ( fImporting = = false ) ;
fImporting = true ;
}
~ CImportingNow ( ) {
assert ( fImporting = = true ) ;
fImporting = false ;
}
} ;
2013-03-07 04:31:26 +01:00
void ThreadImport ( std : : vector < boost : : filesystem : : path > vImportFiles )
{
2012-10-22 22:45:26 +02:00
RenameThread ( " bitcoin-loadblk " ) ;
2012-10-21 21:23:13 +02:00
// -reindex
if ( fReindex ) {
CImportingNow imp ;
int nFile = 0 ;
2013-03-07 04:31:26 +01:00
while ( true ) {
2012-12-03 10:14:54 +01:00
CDiskBlockPos pos ( nFile , 0 ) ;
2012-10-21 21:23:13 +02:00
FILE * file = OpenBlockFile ( pos , true ) ;
if ( ! file )
break ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " Reindexing block file blk%05u.dat... \n " , ( unsigned int ) nFile ) ;
2012-10-21 21:23:13 +02:00
LoadExternalBlockFile ( file , & pos ) ;
nFile + + ;
}
2013-03-07 04:31:26 +01:00
pblocktree - > WriteReindexing ( false ) ;
fReindex = false ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " Reindexing finished \n " ) ;
2013-03-07 04:31:26 +01:00
// To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
InitBlockIndex ( ) ;
2012-10-22 22:45:26 +02:00
}
// hardcoded $DATADIR/bootstrap.dat
filesystem : : path pathBootstrap = GetDataDir ( ) / " bootstrap.dat " ;
2013-03-07 04:31:26 +01:00
if ( filesystem : : exists ( pathBootstrap ) ) {
2012-10-22 22:45:26 +02:00
FILE * file = fopen ( pathBootstrap . string ( ) . c_str ( ) , " rb " ) ;
if ( file ) {
2012-10-21 21:23:13 +02:00
CImportingNow imp ;
2012-10-22 22:45:26 +02:00
filesystem : : path pathBootstrapOld = GetDataDir ( ) / " bootstrap.dat.old " ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " Importing bootstrap.dat... \n " ) ;
2012-10-22 22:45:26 +02:00
LoadExternalBlockFile ( file ) ;
RenameOver ( pathBootstrap , pathBootstrapOld ) ;
2014-02-08 11:35:02 +01:00
} else {
LogPrintf ( " Warning: Could not open bootstrap file %s \n " , pathBootstrap . string ( ) ) ;
2012-10-22 22:45:26 +02:00
}
}
2012-10-21 21:23:13 +02:00
// -loadblock=
2013-03-07 04:31:26 +01:00
BOOST_FOREACH ( boost : : filesystem : : path & path , vImportFiles ) {
2012-10-21 21:23:13 +02:00
FILE * file = fopen ( path . string ( ) . c_str ( ) , " rb " ) ;
if ( file ) {
CImportingNow imp ;
2014-02-08 11:35:02 +01:00
LogPrintf ( " Importing blocks file %s... \n " , path . string ( ) ) ;
2012-10-21 21:23:13 +02:00
LoadExternalBlockFile ( file ) ;
2014-02-08 11:35:02 +01:00
} else {
LogPrintf ( " Warning: Could not open blocks file %s \n " , path . string ( ) ) ;
2012-10-21 21:23:13 +02:00
}
}
2014-05-07 20:10:48 +02:00
if ( GetBoolArg ( " -stopafterblockimport " , false ) ) {
LogPrintf ( " Stopping after block import \n " ) ;
StartShutdown ( ) ;
}
2012-10-22 22:45:26 +02:00
}
2014-06-03 01:21:03 +02:00
/** Sanity checks
* Ensure that Bitcoin is running in a usable environment with all
* necessary library support .
*/
bool InitSanityCheck ( void )
{
if ( ! ECC_InitSanityCheck ( ) ) {
InitError ( " OpenSSL appears to lack support for elliptic curve cryptography. For more "
" information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries " ) ;
return false ;
}
2014-06-14 01:23:01 +02:00
if ( ! glibc_sanity_test ( ) | | ! glibcxx_sanity_test ( ) )
return false ;
2014-06-03 01:21:03 +02:00
return true ;
}
2012-05-13 11:36:10 +02:00
/** Initialize bitcoin.
* @ pre Parameters should be parsed and config file should be read .
*/
2013-12-20 11:48:22 +01:00
bool AppInit2 ( boost : : thread_group & threadGroup )
2011-05-14 20:10:21 +02:00
{
2012-05-21 16:47:29 +02:00
// ********************************************************* Step 1: setup
2011-05-14 20:10:21 +02:00
# ifdef _MSC_VER
2012-07-26 02:48:39 +02:00
// Turn off Microsoft heap dump noise
2011-05-14 20:10:21 +02:00
_CrtSetReportMode ( _CRT_WARN , _CRTDBG_MODE_FILE ) ;
_CrtSetReportFile ( _CRT_WARN , CreateFileA ( " NUL " , GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ) ;
# endif
# if _MSC_VER >= 1400
2012-07-26 02:48:39 +02:00
// Disable confusing "helpful" text message on abort, Ctrl-C
2011-05-14 20:10:21 +02:00
_set_abort_behavior ( 0 , _WRITE_ABORT_MSG | _CALL_REPORTFAULT ) ;
# endif
2012-07-20 08:45:49 +02:00
# 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
2013-10-01 09:47:16 +02:00
// 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!
2012-07-20 08:45:49 +02:00
# define PROCESS_DEP_ENABLE 0x00000001
# endif
typedef BOOL ( WINAPI * PSETPROCDEPPOL ) ( DWORD ) ;
PSETPROCDEPPOL setProcDEPPol = ( PSETPROCDEPPOL ) GetProcAddress ( GetModuleHandleA ( " Kernel32.dll " ) , " SetProcessDEPPolicy " ) ;
if ( setProcDEPPol ! = NULL ) setProcDEPPol ( PROCESS_DEP_ENABLE ) ;
2013-04-28 08:51:49 +02:00
// Initialize Windows Sockets
WSADATA wsadata ;
int ret = WSAStartup ( MAKEWORD ( 2 , 2 ) , & wsadata ) ;
2013-04-30 18:16:07 +02:00
if ( ret ! = NO_ERROR | | LOBYTE ( wsadata . wVersion ) ! = 2 | | HIBYTE ( wsadata . wVersion ) ! = 2 )
2013-04-28 08:51:49 +02:00
{
2013-04-30 18:16:07 +02:00
return InitError ( strprintf ( " Error: Winsock library failed to start (WSAStartup returned error %d) " , ret)) ;
2013-04-28 08:51:49 +02:00
}
2011-05-14 20:10:21 +02:00
# endif
2011-10-07 17:02:21 +02:00
# ifndef WIN32
2012-07-20 08:45:49 +02:00
umask ( 077 ) ;
2011-05-14 20:10:21 +02:00
// Clean shutdown on SIGTERM
struct sigaction sa ;
sa . sa_handler = HandleSIGTERM ;
sigemptyset ( & sa . sa_mask ) ;
sa . sa_flags = 0 ;
sigaction ( SIGTERM , & sa , NULL ) ;
sigaction ( SIGINT , & sa , NULL ) ;
2012-03-02 20:31:16 +01:00
// Reopen debug.log on SIGHUP
struct sigaction sa_hup ;
sa_hup . sa_handler = HandleSIGHUP ;
sigemptyset ( & sa_hup . sa_mask ) ;
sa_hup . sa_flags = 0 ;
sigaction ( SIGHUP , & sa_hup , NULL ) ;
2013-05-05 07:37:03 +02:00
# if defined (__SVR4) && defined (__sun)
// ignore SIGPIPE on Solaris
signal ( SIGPIPE , SIG_IGN ) ;
# endif
2011-05-14 20:10:21 +02:00
# endif
2012-05-21 16:47:29 +02:00
// ********************************************************* Step 2: parameter interactions
2012-05-24 19:02:21 +02:00
if ( mapArgs . count ( " -bind " ) ) {
// when specifying an explicit binding address, you want to listen on it
// even when -connect or -proxy is specified
2014-01-27 11:26:30 +01:00
if ( SoftSetBoolArg ( " -listen " , true ) )
LogPrintf ( " AppInit2 : parameter interaction: -bind set -> setting -listen=1 \n " ) ;
2012-05-24 19:02:21 +02:00
}
2012-05-21 16:47:29 +02:00
2012-08-21 17:32:04 +02:00
if ( mapArgs . count ( " -connect " ) & & mapMultiArgs [ " -connect " ] . size ( ) > 0 ) {
2012-05-24 19:02:21 +02:00
// when only connecting to trusted nodes, do not seed via DNS, or listen by default
2014-01-27 11:26:30 +01:00
if ( SoftSetBoolArg ( " -dnsseed " , false ) )
LogPrintf ( " AppInit2 : parameter interaction: -connect set -> setting -dnsseed=0 \n " ) ;
if ( SoftSetBoolArg ( " -listen " , false ) )
LogPrintf ( " AppInit2 : parameter interaction: -connect set -> setting -listen=0 \n " ) ;
2012-05-24 19:02:21 +02:00
}
if ( mapArgs . count ( " -proxy " ) ) {
2014-01-27 11:26:30 +01:00
// 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 " ) ;
2012-05-24 19:02:21 +02:00
}
2012-06-17 18:12:56 +02:00
if ( ! GetBoolArg ( " -listen " , true ) ) {
2012-05-24 19:02:21 +02:00
// do not map ports or try to retrieve public IP when not listening (pointless)
2014-01-27 11:26:30 +01:00
if ( SoftSetBoolArg ( " -upnp " , false ) )
LogPrintf ( " AppInit2 : parameter interaction: -listen=0 -> setting -upnp=0 \n " ) ;
if ( SoftSetBoolArg ( " -discover " , false ) )
LogPrintf ( " AppInit2 : parameter interaction: -listen=0 -> setting -discover=0 \n " ) ;
2012-05-21 16:47:29 +02:00
}
2012-05-24 19:02:21 +02:00
if ( mapArgs . count ( " -externalip " ) ) {
// if an explicit public IP is specified, do not try to find others
2014-01-27 11:26:30 +01:00
if ( SoftSetBoolArg ( " -discover " , false ) )
LogPrintf ( " AppInit2 : parameter interaction: -externalip set -> setting -discover=0 \n " ) ;
2012-05-24 19:02:21 +02:00
}
2013-04-28 17:37:50 +02:00
if ( GetBoolArg ( " -salvagewallet " , false ) ) {
2012-09-18 20:30:47 +02:00
// Rewrite just private keys: rescan to find transactions
2014-01-27 11:26:30 +01:00
if ( SoftSetBoolArg ( " -rescan " , true ) )
LogPrintf ( " AppInit2 : parameter interaction: -salvagewallet=1 -> setting -rescan=1 \n " ) ;
2012-09-18 20:30:47 +02:00
}
2014-02-14 17:33:07 +01:00
// -zapwallettx implies a rescan
if ( GetBoolArg ( " -zapwallettxes " , false ) ) {
if ( SoftSetBoolArg ( " -rescan " , true ) )
2014-02-14 18:27:15 +01:00
LogPrintf ( " AppInit2 : parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1 \n " ) ;
2014-02-14 17:33:07 +01:00
}
2013-04-26 00:46:47 +02:00
// Make sure enough file descriptors are available
int nBind = std : : max ( ( int ) mapArgs . count ( " -bind " ) , 1 ) ;
nMaxConnections = GetArg ( " -maxconnections " , 125 ) ;
2013-05-24 15:40:51 +02:00
nMaxConnections = std : : max ( std : : min ( nMaxConnections , ( int ) ( FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS ) ) , 0 ) ;
2013-04-26 00:46:47 +02:00
int nFD = RaiseFileDescriptorLimit ( nMaxConnections + MIN_CORE_FILEDESCRIPTORS ) ;
if ( nFD < MIN_CORE_FILEDESCRIPTORS )
return InitError ( _ ( " Not enough file descriptors available. " ) ) ;
if ( nFD - MIN_CORE_FILEDESCRIPTORS < nMaxConnections )
nMaxConnections = nFD - MIN_CORE_FILEDESCRIPTORS ;
2012-05-21 16:47:29 +02:00
// ********************************************************* Step 3: parameter-to-internal-flags
2013-10-08 12:09:40 +02:00
fDebug = ! mapMultiArgs [ " -debug " ] . empty ( ) ;
// Special-case: if -debug=0/-nodebug is set, turn off debugging messages
const vector < string > & categories = mapMultiArgs [ " -debug " ] ;
if ( GetBoolArg ( " -nodebug " , false ) | | find ( categories . begin ( ) , categories . end ( ) , string ( " 0 " ) ) ! = categories . end ( ) )
fDebug = false ;
// Check for -debugnet (deprecated)
if ( GetBoolArg ( " -debugnet " , false ) )
InitWarning ( _ ( " Warning: Deprecated argument -debugnet ignored, use -debug=net " ) ) ;
2014-05-05 20:32:56 +02:00
// Check for -tor - as this is a privacy risk to continue, exit here
if ( GetBoolArg ( " -tor " , false ) )
return InitError ( _ ( " Error: Unsupported argument -tor found, use -onion. " ) ) ;
2013-10-08 12:09:40 +02:00
2013-04-28 17:37:50 +02:00
fBenchmark = GetBoolArg ( " -benchmark " , false ) ;
2014-03-10 02:35:41 +01:00
// Checkmempool defaults to true in regtest mode
mempool . setSanityCheck ( GetBoolArg ( " -checkmempool " , Params ( ) . DefaultCheckMemPool ( ) ) ) ;
2013-08-25 13:25:21 +02:00
Checkpoints : : fEnabled = GetBoolArg ( " -checkpoints " , true ) ;
2012-06-22 19:11:57 +02:00
2012-12-01 23:04:14 +01:00
// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
2014-02-18 12:48:16 +01:00
nScriptCheckThreads = GetArg ( " -par " , DEFAULT_SCRIPTCHECK_THREADS ) ;
2013-04-29 19:35:47 +02:00
if ( nScriptCheckThreads < = 0 )
nScriptCheckThreads + = boost : : thread : : hardware_concurrency ( ) ;
2013-01-18 15:07:05 +01:00
if ( nScriptCheckThreads < = 1 )
2012-12-01 23:04:14 +01:00
nScriptCheckThreads = 0 ;
else if ( nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS )
nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS ;
2013-12-20 11:48:22 +01:00
fServer = GetBoolArg ( " -server " , false ) ;
2013-04-28 17:37:50 +02:00
fPrintToConsole = GetBoolArg ( " -printtoconsole " , false ) ;
2013-10-30 11:36:51 +01:00
fLogTimestamps = GetBoolArg ( " -logtimestamps " , true ) ;
2014-05-11 15:29:16 +02:00
setvbuf ( stdout , NULL , _IOLBF , 0 ) ;
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2013-10-02 17:19:10 +02:00
bool fDisableWallet = GetBoolArg ( " -disablewallet " , false ) ;
2013-11-29 16:04:29 +01:00
# endif
2011-05-14 20:10:21 +02:00
2012-05-21 16:47:29 +02:00
if ( mapArgs . count ( " -timeout " ) )
{
int nNewTimeout = GetArg ( " -timeout " , 5000 ) ;
if ( nNewTimeout > 0 & & nNewTimeout < 600000 )
nConnectTimeout = nNewTimeout ;
}
// Continue to put "/P2SH/" in the coinbase to monitor
// BIP16 support.
// This can be removed eventually...
const char * pszP2SH = " /P2SH/ " ;
COINBASE_FLAGS < < std : : vector < unsigned char > ( pszP2SH , pszP2SH + strlen ( pszP2SH ) ) ;
2013-04-26 02:11:27 +02:00
// Fee-per-kilobyte amount considered the same as "free"
// If you are mining, be careful setting this:
// if you set it to zero then
// a transaction spammer can cheaply fill blocks using
// 1-satoshi-fee transactions. It should be set above the real
// cost to you of processing a transaction.
if ( mapArgs . count ( " -mintxfee " ) )
{
2013-04-13 07:13:08 +02:00
int64_t n = 0 ;
2013-04-26 02:11:27 +02:00
if ( ParseMoney ( mapArgs [ " -mintxfee " ] , n ) & & n > 0 )
2014-04-10 20:14:18 +02:00
CTransaction : : minTxFee = CFeeRate ( n ) ;
2013-04-26 02:11:27 +02:00
else
2014-01-16 16:15:27 +01:00
return InitError ( strprintf ( _ ( " Invalid amount for -mintxfee=<amount>: '%s' " ) , mapArgs [ " -mintxfee " ] ) ) ;
2013-04-26 02:11:27 +02:00
}
if ( mapArgs . count ( " -minrelaytxfee " ) )
{
2013-04-13 07:13:08 +02:00
int64_t n = 0 ;
2013-04-26 02:11:27 +02:00
if ( ParseMoney ( mapArgs [ " -minrelaytxfee " ] , n ) & & n > 0 )
2014-04-10 20:14:18 +02:00
CTransaction : : minRelayTxFee = CFeeRate ( n ) ;
2013-04-26 02:11:27 +02:00
else
2014-01-16 16:15:27 +01:00
return InitError ( strprintf ( _ ( " Invalid amount for -minrelaytxfee=<amount>: '%s' " ) , mapArgs [ " -minrelaytxfee " ] ) ) ;
2013-04-26 02:11:27 +02:00
}
2012-05-21 16:47:29 +02:00
2013-12-13 16:14:48 +01:00
# ifdef ENABLE_WALLET
2012-05-21 16:47:29 +02:00
if ( mapArgs . count ( " -paytxfee " ) )
{
2014-04-10 20:14:18 +02:00
int64_t nFeePerK = 0 ;
if ( ! ParseMoney ( mapArgs [ " -paytxfee " ] , nFeePerK ) )
2014-01-16 16:15:27 +01:00
return InitError ( strprintf ( _ ( " Invalid amount for -paytxfee=<amount>: '%s' " ) , mapArgs [ " -paytxfee " ] ) ) ;
2014-04-10 20:14:18 +02:00
if ( nFeePerK > nHighTransactionFeeWarning )
2012-07-27 08:36:43 +02:00
InitWarning ( _ ( " Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. " ) ) ;
2014-04-10 20:14:18 +02:00
payTxFee = CFeeRate ( nFeePerK , 1000 ) ;
2012-05-21 16:47:29 +02:00
}
2014-02-11 12:49:33 +01:00
bSpendZeroConfChange = GetArg ( " -spendzeroconfchange " , true ) ;
2012-05-21 16:47:29 +02:00
2014-06-05 14:52:07 +02:00
std : : string strWalletFile = GetArg ( " -wallet " , " wallet.dat " ) ;
2013-11-29 16:04:29 +01:00
# endif
2012-05-21 16:47:29 +02:00
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
2014-06-03 01:21:03 +02:00
// Sanity check
if ( ! InitSanityCheck ( ) )
return InitError ( _ ( " Initialization sanity check failed. Bitcoin Core is shutting down. " ) ) ;
2012-05-21 16:47:29 +02:00
2012-10-12 03:09:05 +02:00
std : : string strDataDir = GetDataDir ( ) . string ( ) ;
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2012-06-03 01:19:07 +02:00
// Wallet file must be a plain filename without a directory
if ( strWalletFile ! = boost : : filesystem : : basename ( strWalletFile ) + boost : : filesystem : : extension ( strWalletFile ) )
2014-01-16 16:15:27 +01:00
return InitError ( strprintf ( _ ( " Wallet %s resides outside data directory %s " ) , strWalletFile , strDataDir ) ) ;
2013-11-29 16:04:29 +01:00
# endif
2012-05-21 16:47:29 +02:00
// Make sure only a single Bitcoin process is using the data directory.
boost : : filesystem : : path pathLockFile = GetDataDir ( ) / " .lock " ;
FILE * file = fopen ( pathLockFile . string ( ) . c_str ( ) , " a " ) ; // empty lock file; created if it doesn't exist.
if ( file ) fclose ( file ) ;
static boost : : interprocess : : file_lock lock ( pathLockFile . string ( ) . c_str ( ) ) ;
if ( ! lock . try_lock ( ) )
2014-03-12 21:14:11 +01:00
return InitError ( strprintf ( _ ( " Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. " ) , strDataDir ) ) ;
2012-05-21 16:47:29 +02:00
2012-05-29 18:13:15 +02:00
if ( GetBoolArg ( " -shrinkdebugfile " , ! fDebug ) )
2011-05-14 20:10:21 +02:00
ShrinkDebugFile ( ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n " ) ;
2014-01-16 16:15:27 +01:00
LogPrintf ( " Bitcoin version %s (%s) \n " , FormatFullVersion ( ) , CLIENT_DATE ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " Using OpenSSL version %s \n " , SSLeay_version ( SSLEAY_VERSION ) ) ;
2014-05-01 09:44:45 +02:00
# ifdef ENABLE_WALLET
LogPrintf ( " Using BerkeleyDB version %s \n " , DbEnv : : version ( 0 , 0 , 0 ) ) ;
# endif
2012-09-04 18:24:08 +02:00
if ( ! fLogTimestamps )
2014-01-16 16:15:27 +01:00
LogPrintf ( " Startup time: %s \n " , DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , GetTime ( ) ) ) ;
LogPrintf ( " Default data directory %s \n " , GetDefaultDataDir ( ) . string ( ) ) ;
LogPrintf ( " Using data directory %s \n " , strDataDir ) ;
2014-06-04 21:19:22 +02:00
LogPrintf ( " Using config file %s \n " , GetConfigFile ( ) . string ( ) ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " Using at most %i connections (%i file descriptors available) \n " , nMaxConnections , nFD ) ;
2012-05-21 16:47:29 +02:00
std : : ostringstream strErrors ;
2011-05-14 20:10:21 +02:00
2012-12-01 23:04:14 +01:00
if ( nScriptCheckThreads ) {
2013-09-18 12:38:08 +02:00
LogPrintf ( " Using %u threads for script verification \n " , nScriptCheckThreads ) ;
2012-12-01 23:04:14 +01:00
for ( int i = 0 ; i < nScriptCheckThreads - 1 ; i + + )
2013-03-07 04:31:26 +01:00
threadGroup . create_thread ( & ThreadScriptCheck ) ;
2012-12-01 23:04:14 +01:00
}
2013-04-13 07:13:08 +02:00
int64_t nStart ;
2012-05-21 16:47:29 +02:00
2013-01-11 23:18:00 +01:00
// ********************************************************* Step 5: verify wallet database integrity
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2013-10-02 17:19:10 +02:00
if ( ! fDisableWallet ) {
2014-03-05 16:15:04 +01:00
LogPrintf ( " Using wallet %s \n " , strWalletFile ) ;
2013-10-02 17:15:51 +02:00
uiInterface . InitMessage ( _ ( " Verifying wallet... " ) ) ;
2012-09-18 20:30:47 +02:00
2013-10-02 17:15:51 +02:00
if ( ! bitdb . Open ( GetDataDir ( ) ) )
{
// try moving the database env out of the way
boost : : filesystem : : path pathDatabase = GetDataDir ( ) / " database " ;
2014-02-24 09:08:56 +01:00
boost : : filesystem : : path pathDatabaseBak = GetDataDir ( ) / strprintf ( " database.%d.bak " , GetTime ( ) ) ;
2013-10-02 17:15:51 +02:00
try {
boost : : filesystem : : rename ( pathDatabase , pathDatabaseBak ) ;
2014-01-16 16:15:27 +01:00
LogPrintf ( " Moved old %s to %s. Retrying. \n " , pathDatabase . string ( ) , pathDatabaseBak . string ( ) ) ;
2013-10-02 17:15:51 +02:00
} catch ( boost : : filesystem : : filesystem_error & error ) {
// failure is ok (well, not really, but it's not worse than what we started with)
}
2013-04-24 00:41:04 +02:00
2013-10-02 17:15:51 +02:00
// try again
if ( ! bitdb . Open ( GetDataDir ( ) ) ) {
// if it still fails, it probably means we can't even create the database env
2014-01-16 16:15:27 +01:00
string msg = strprintf ( _ ( " Error initializing wallet database environment %s! " ) , strDataDir ) ;
2013-10-02 17:15:51 +02:00
return InitError ( msg ) ;
}
2013-04-24 00:41:04 +02:00
}
2012-09-18 20:30:47 +02:00
2013-10-02 17:15:51 +02:00
if ( GetBoolArg ( " -salvagewallet " , false ) )
{
// Recover readable keypairs:
if ( ! CWalletDB : : Recover ( bitdb , strWalletFile , true ) )
return false ;
}
2012-09-18 20:30:47 +02:00
2013-10-02 17:15:51 +02:00
if ( filesystem : : exists ( GetDataDir ( ) / strWalletFile ) )
2012-10-06 01:26:54 +02:00
{
2013-10-02 17:15:51 +02:00
CDBEnv : : VerifyResult r = bitdb . Verify ( strWalletFile , CWalletDB : : Recover ) ;
if ( r = = CDBEnv : : RECOVER_OK )
{
string msg = strprintf ( _ ( " Warning: wallet.dat corrupt, data salvaged! "
" Original wallet.dat saved as wallet.{timestamp}.bak in %s; if "
" your balance or transactions are incorrect you should "
2014-01-16 16:15:27 +01:00
" restore from a backup. " ) , strDataDir ) ;
2013-10-02 17:15:51 +02:00
InitWarning ( msg ) ;
}
if ( r = = CDBEnv : : RECOVER_FAIL )
return InitError ( _ ( " wallet.dat corrupt, salvage failed " ) ) ;
2012-10-06 01:26:54 +02:00
}
2013-10-02 17:19:10 +02:00
} // (!fDisableWallet)
2013-11-29 16:04:29 +01:00
# endif // ENABLE_WALLET
2012-09-18 20:30:47 +02:00
// ********************************************************* Step 6: network initialization
2012-05-21 16:47:29 +02:00
2013-06-06 05:21:41 +02:00
RegisterNodeSignals ( GetNodeSignals ( ) ) ;
2013-05-07 15:16:25 +02:00
2012-05-24 19:02:21 +02:00
int nSocksVersion = GetArg ( " -socks " , 5 ) ;
2012-05-21 16:47:29 +02:00
if ( nSocksVersion ! = 4 & & nSocksVersion ! = 5 )
return InitError ( strprintf ( _ ( " Unknown -socks proxy version requested: %i " ) , nSocksVersion ) ) ;
2011-05-14 20:10:21 +02:00
2012-05-21 16:47:29 +02:00
if ( mapArgs . count ( " -onlynet " ) ) {
std : : set < enum Network > nets ;
BOOST_FOREACH ( std : : string snet , mapMultiArgs [ " -onlynet " ] ) {
enum Network net = ParseNetwork ( snet ) ;
if ( net = = NET_UNROUTABLE )
2014-01-16 16:15:27 +01:00
return InitError ( strprintf ( _ ( " Unknown network specified in -onlynet: '%s' " ) , snet ) ) ;
2012-05-21 16:47:29 +02:00
nets . insert ( net ) ;
}
for ( int n = 0 ; n < NET_MAX ; n + + ) {
enum Network net = ( enum Network ) n ;
if ( ! nets . count ( net ) )
SetLimited ( net ) ;
}
}
2012-05-01 21:04:07 +02:00
CService addrProxy ;
bool fProxy = false ;
2012-05-24 19:02:21 +02:00
if ( mapArgs . count ( " -proxy " ) ) {
2012-05-01 21:04:07 +02:00
addrProxy = CService ( mapArgs [ " -proxy " ] , 9050 ) ;
2012-05-24 19:02:21 +02:00
if ( ! addrProxy . IsValid ( ) )
2014-01-16 16:15:27 +01:00
return InitError ( strprintf ( _ ( " Invalid -proxy address: '%s' " ) , mapArgs [ " -proxy " ] ) ) ;
2012-05-24 19:02:21 +02:00
if ( ! IsLimited ( NET_IPV4 ) )
SetProxy ( NET_IPV4 , addrProxy , nSocksVersion ) ;
if ( nSocksVersion > 4 ) {
if ( ! IsLimited ( NET_IPV6 ) )
SetProxy ( NET_IPV6 , addrProxy , nSocksVersion ) ;
SetNameProxy ( addrProxy , nSocksVersion ) ;
}
2012-05-01 21:04:07 +02:00
fProxy = true ;
}
2013-09-08 13:54:06 +02:00
// -onion can override normal proxy, -noonion disables tor entirely
if ( ! ( mapArgs . count ( " -onion " ) & & mapArgs [ " -onion " ] = = " 0 " ) & &
2014-05-05 20:32:56 +02:00
( fProxy | | mapArgs . count ( " -onion " ) ) ) {
2012-05-01 21:04:07 +02:00
CService addrOnion ;
2014-05-05 20:32:56 +02:00
if ( ! mapArgs . count ( " -onion " ) )
2012-05-01 21:04:07 +02:00
addrOnion = addrProxy ;
else
2014-05-05 20:32:56 +02:00
addrOnion = CService ( mapArgs [ " -onion " ] , 9050 ) ;
2012-05-01 21:04:07 +02:00
if ( ! addrOnion . IsValid ( ) )
2014-05-05 20:32:56 +02:00
return InitError ( strprintf ( _ ( " Invalid -onion address: '%s' " ) , mapArgs [ " -onion " ] ) ) ;
2012-05-01 21:04:07 +02:00
SetProxy ( NET_TOR , addrOnion , 5 ) ;
SetReachable ( NET_TOR ) ;
2012-05-24 19:02:21 +02:00
}
// see Step 2: parameter interactions for more information about these
2014-05-29 13:02:22 +02:00
fListen = GetBoolArg ( " -listen " , DEFAULT_LISTEN ) ;
2012-05-24 19:02:21 +02:00
fDiscover = GetBoolArg ( " -discover " , true ) ;
fNameLookup = GetBoolArg ( " -dns " , true ) ;
2012-05-17 04:11:19 +02:00
2012-05-21 16:47:29 +02:00
bool fBound = false ;
2014-05-29 12:33:17 +02:00
if ( fListen ) {
2012-05-21 16:47:29 +02:00
if ( mapArgs . count ( " -bind " ) ) {
BOOST_FOREACH ( std : : string strBind , mapMultiArgs [ " -bind " ] ) {
CService addrBind ;
if ( ! Lookup ( strBind . c_str ( ) , addrBind , GetListenPort ( ) , false ) )
2014-01-16 16:15:27 +01:00
return InitError ( strprintf ( _ ( " Cannot resolve -bind address: '%s' " ) , strBind ) ) ;
2012-09-03 15:54:47 +02:00
fBound | = Bind ( addrBind , ( BF_EXPLICIT | BF_REPORT_ERROR ) ) ;
2012-05-21 16:47:29 +02:00
}
2012-09-03 15:54:47 +02:00
}
else {
2012-05-21 16:47:29 +02:00
struct in_addr inaddr_any ;
inaddr_any . s_addr = INADDR_ANY ;
2012-09-03 15:54:47 +02:00
fBound | = Bind ( CService ( in6addr_any , GetListenPort ( ) ) , BF_NONE ) ;
fBound | = Bind ( CService ( inaddr_any , GetListenPort ( ) ) , ! fBound ? BF_REPORT_ERROR : BF_NONE ) ;
2012-05-21 16:47:29 +02:00
}
if ( ! fBound )
2012-05-24 19:02:21 +02:00
return InitError ( _ ( " Failed to listen on any port. Use -listen=0 if you want this. " ) ) ;
2012-05-17 04:11:19 +02:00
}
2012-09-03 15:54:47 +02:00
if ( mapArgs . count ( " -externalip " ) ) {
2012-05-21 16:47:29 +02:00
BOOST_FOREACH ( string strAddr , mapMultiArgs [ " -externalip " ] ) {
CService addrLocal ( strAddr , GetListenPort ( ) , fNameLookup ) ;
if ( ! addrLocal . IsValid ( ) )
2014-01-16 16:15:27 +01:00
return InitError ( strprintf ( _ ( " Cannot resolve -externalip address: '%s' " ) , strAddr ) ) ;
2012-05-21 16:47:29 +02:00
AddLocal ( CService ( strAddr , GetListenPort ( ) , fNameLookup ) , LOCAL_MANUAL ) ;
}
}
2012-05-24 19:02:21 +02:00
BOOST_FOREACH ( string strDest , mapMultiArgs [ " -seednode " ] )
AddOneShot ( strDest ) ;
2012-10-05 19:22:21 +02:00
// ********************************************************* Step 7: load block chain
2012-05-21 16:47:29 +02:00
2013-04-28 17:37:50 +02:00
fReindex = GetBoolArg ( " -reindex " , false ) ;
2012-10-21 21:23:13 +02:00
2012-12-12 22:11:52 +01:00
// Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/
filesystem : : path blocksDir = GetDataDir ( ) / " blocks " ;
if ( ! filesystem : : exists ( blocksDir ) )
{
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 ) ;
try {
filesystem : : create_hard_link ( source , dest ) ;
2014-01-16 16:15:27 +01:00
LogPrintf ( " Hardlinked %s -> %s \n " , source . string ( ) , dest . string ( ) ) ;
2012-12-12 22:11:52 +01:00
linked = true ;
} catch ( filesystem : : filesystem_error & e ) {
// Note: hardlink creation failing is not a disaster, it just means
// blocks will get re-downloaded from peers.
2013-09-18 12:38:08 +02:00
LogPrintf ( " Error hardlinking blk%04u.dat : %s \n " , i , e . what ( ) ) ;
2012-12-12 22:11:52 +01:00
break ;
}
}
if ( linked )
{
fReindex = true ;
}
}
2012-11-04 17:11:48 +01:00
// cache size calculations
2014-02-16 22:00:12 +01:00
size_t nTotalCache = ( GetArg ( " -dbcache " , nDefaultDbCache ) < < 20 ) ;
if ( nTotalCache < ( nMinDbCache < < 20 ) )
nTotalCache = ( nMinDbCache < < 20 ) ; // total cache cannot be less than nMinDbCache
else if ( nTotalCache > ( nMaxDbCache < < 20 ) )
nTotalCache = ( nMaxDbCache < < 20 ) ; // total cache cannot be greater than nMaxDbCache
2012-11-04 17:11:48 +01:00
size_t nBlockTreeDBCache = nTotalCache / 8 ;
2013-01-11 01:47:57 +01:00
if ( nBlockTreeDBCache > ( 1 < < 21 ) & & ! GetBoolArg ( " -txindex " , false ) )
2012-11-04 17:11:48 +01:00
nBlockTreeDBCache = ( 1 < < 21 ) ; // block tree db cache shouldn't be larger than 2 MiB
nTotalCache - = nBlockTreeDBCache ;
size_t nCoinDBCache = nTotalCache / 2 ; // use half of the remaining cache for coindb cache
nTotalCache - = nCoinDBCache ;
nCoinCacheSize = nTotalCache / 300 ; // coins in memory require around 300 bytes
2013-02-16 17:58:45 +01:00
bool fLoaded = false ;
while ( ! fLoaded ) {
bool fReset = fReindex ;
std : : string strLoadError ;
2013-01-11 22:57:22 +01:00
2013-02-16 17:58:45 +01:00
uiInterface . InitMessage ( _ ( " Loading block index... " ) ) ;
2012-07-06 16:33:34 +02:00
2013-02-16 17:58:45 +01:00
nStart = GetTimeMillis ( ) ;
do {
try {
UnloadBlockIndex ( ) ;
delete pcoinsTip ;
delete pcoinsdbview ;
delete pblocktree ;
pblocktree = new CBlockTreeDB ( nBlockTreeDBCache , false , fReindex ) ;
pcoinsdbview = new CCoinsViewDB ( nCoinDBCache , false , fReindex ) ;
pcoinsTip = new CCoinsViewCache ( * pcoinsdbview ) ;
if ( fReindex )
pblocktree - > WriteReindexing ( true ) ;
if ( ! LoadBlockIndex ( ) ) {
strLoadError = _ ( " Error loading block database " ) ;
break ;
}
2013-05-12 12:03:32 +02:00
// If the loaded chain has a wrong genesis, bail out immediately
// (we're likely using a testnet datadir, or the other way around).
2013-10-10 23:07:44 +02:00
if ( ! mapBlockIndex . empty ( ) & & chainActive . Genesis ( ) = = NULL )
2013-05-12 12:03:32 +02:00
return InitError ( _ ( " Incorrect or no genesis block found. Wrong datadir for network? " ) ) ;
2013-02-16 17:58:45 +01:00
// Initialize the block index (no-op if non-empty database was already loaded)
if ( ! InitBlockIndex ( ) ) {
strLoadError = _ ( " Error initializing block database " ) ;
break ;
}
2013-06-22 16:03:11 +02:00
// Check for changed -txindex state
if ( fTxIndex ! = GetBoolArg ( " -txindex " , false ) ) {
strLoadError = _ ( " You need to rebuild the database using -reindex to change -txindex " ) ;
break ;
}
2013-02-23 23:48:02 +01:00
uiInterface . InitMessage ( _ ( " Verifying blocks... " ) ) ;
2014-05-23 18:04:09 +02:00
if ( ! CVerifyDB ( ) . VerifyDB ( GetArg ( " -checklevel " , 3 ) ,
2013-08-31 01:11:12 +02:00
GetArg ( " -checkblocks " , 288 ) ) ) {
2013-02-16 17:58:45 +01:00
strLoadError = _ ( " Corrupted block database detected " ) ;
break ;
}
} catch ( std : : exception & e ) {
2013-09-18 12:38:08 +02:00
if ( fDebug ) LogPrintf ( " %s \n " , e . what ( ) ) ;
2013-02-16 17:58:45 +01:00
strLoadError = _ ( " Error opening block database " ) ;
break ;
}
2013-01-03 15:29:07 +01:00
2013-02-16 17:58:45 +01:00
fLoaded = true ;
} while ( false ) ;
if ( ! fLoaded ) {
// first suggest a reindex
if ( ! fReset ) {
bool fRet = uiInterface . ThreadSafeMessageBox (
2013-05-13 08:26:29 +02:00
strLoadError + " . \n \n " + _ ( " Do you want to rebuild the block database now? " ) ,
2013-02-16 17:58:45 +01:00
" " , CClientUIInterface : : MSG_ERROR | CClientUIInterface : : BTN_ABORT ) ;
if ( fRet ) {
fReindex = true ;
fRequestShutdown = false ;
} else {
2013-09-18 12:38:08 +02:00
LogPrintf ( " Aborted block database rebuild. Exiting. \n " ) ;
2013-02-16 17:58:45 +01:00
return false ;
}
} else {
return InitError ( strLoadError ) ;
}
}
}
2012-04-18 13:30:24 +02:00
2013-12-16 23:36:22 +01:00
// As LoadBlockIndex can take several minutes, it's possible the user
// requested to kill the GUI during the last operation. If so, exit.
2012-04-18 13:30:24 +02:00
// As the program has not fully started yet, Shutdown() is possibly overkill.
if ( fRequestShutdown )
{
2013-09-18 12:38:08 +02:00
LogPrintf ( " Shutdown requested. Exiting. \n " ) ;
2012-04-18 13:30:24 +02:00
return false ;
}
2014-02-24 09:08:56 +01:00
LogPrintf ( " block index %15dms \n " , GetTimeMillis ( ) - nStart ) ;
2011-05-14 20:10:21 +02:00
2013-04-28 17:37:50 +02:00
if ( GetBoolArg ( " -printblockindex " , false ) | | GetBoolArg ( " -printblocktree " , false ) )
2012-02-20 20:50:26 +01:00
{
2012-05-21 16:47:29 +02:00
PrintBlockTree ( ) ;
return false ;
}
if ( mapArgs . count ( " -printblock " ) )
{
string strMatch = mapArgs [ " -printblock " ] ;
int nFound = 0 ;
for ( map < uint256 , CBlockIndex * > : : iterator mi = mapBlockIndex . begin ( ) ; mi ! = mapBlockIndex . end ( ) ; + + mi )
2012-02-20 20:50:26 +01:00
{
2012-05-21 16:47:29 +02:00
uint256 hash = ( * mi ) . first ;
2014-05-21 12:50:46 +02:00
if ( boost : : algorithm : : starts_with ( hash . ToString ( ) , strMatch ) )
2012-05-21 16:47:29 +02:00
{
CBlockIndex * pindex = ( * mi ) . second ;
CBlock block ;
2013-06-24 03:10:02 +02:00
ReadBlockFromDisk ( block , pindex ) ;
2012-05-21 16:47:29 +02:00
block . BuildMerkleTree ( ) ;
block . print ( ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " \n " ) ;
2012-05-21 16:47:29 +02:00
nFound + + ;
}
2012-02-20 20:50:26 +01:00
}
2012-05-21 16:47:29 +02:00
if ( nFound = = 0 )
2014-01-16 16:15:27 +01:00
LogPrintf ( " No blocks matching %s were found \n " , strMatch ) ;
2012-05-21 16:47:29 +02:00
return false ;
2012-02-20 20:50:26 +01:00
}
2014-03-17 13:19:54 +01:00
boost : : filesystem : : path est_path = GetDataDir ( ) / FEE_ESTIMATES_FILENAME ;
CAutoFile est_filein = CAutoFile ( fopen ( est_path . string ( ) . c_str ( ) , " rb " ) , SER_DISK , CLIENT_VERSION ) ;
if ( est_filein )
mempool . ReadFeeEstimates ( est_filein ) ;
2012-09-18 20:30:47 +02:00
// ********************************************************* Step 8: load wallet
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2013-10-02 17:19:10 +02:00
if ( fDisableWallet ) {
pwalletMain = NULL ;
LogPrintf ( " Wallet disabled! \n " ) ;
} else {
2014-02-14 18:27:15 +01:00
// needed to restore wallet transaction meta data after -zapwallettxes
std : : vector < CWalletTx > vWtx ;
2014-02-14 17:33:07 +01:00
if ( GetBoolArg ( " -zapwallettxes " , false ) ) {
uiInterface . InitMessage ( _ ( " Zapping all transactions from wallet... " ) ) ;
pwalletMain = new CWallet ( strWalletFile ) ;
2014-02-14 18:27:15 +01:00
DBErrors nZapWalletRet = pwalletMain - > ZapWalletTx ( vWtx ) ;
2014-02-14 17:33:07 +01:00
if ( nZapWalletRet ! = DB_LOAD_OK ) {
uiInterface . InitMessage ( _ ( " Error loading wallet.dat: Wallet corrupted " ) ) ;
return false ;
}
delete pwalletMain ;
pwalletMain = NULL ;
}
2013-10-02 17:15:51 +02:00
uiInterface . InitMessage ( _ ( " Loading wallet... " ) ) ;
2013-01-11 22:57:22 +01:00
2013-10-02 17:15:51 +02:00
nStart = GetTimeMillis ( ) ;
bool fFirstRun = true ;
pwalletMain = new CWallet ( strWalletFile ) ;
DBErrors nLoadWalletRet = pwalletMain - > LoadWallet ( fFirstRun ) ;
if ( nLoadWalletRet ! = DB_LOAD_OK )
2012-09-18 20:30:47 +02:00
{
2013-10-02 17:15:51 +02:00
if ( nLoadWalletRet = = DB_CORRUPT )
strErrors < < _ ( " Error loading wallet.dat: Wallet corrupted " ) < < " \n " ;
else if ( nLoadWalletRet = = DB_NONCRITICAL_ERROR )
{
string msg ( _ ( " Warning: error reading wallet.dat! All keys read correctly, but transaction data "
" or address book entries might be missing or incorrect. " ) ) ;
InitWarning ( msg ) ;
}
else if ( nLoadWalletRet = = DB_TOO_NEW )
strErrors < < _ ( " Error loading wallet.dat: Wallet requires newer version of Bitcoin " ) < < " \n " ;
else if ( nLoadWalletRet = = DB_NEED_REWRITE )
{
strErrors < < _ ( " Wallet needed to be rewritten: restart Bitcoin to complete " ) < < " \n " ;
2014-01-16 16:15:27 +01:00
LogPrintf ( " %s " , strErrors . str ( ) ) ;
2013-10-02 17:15:51 +02:00
return InitError ( strErrors . str ( ) ) ;
}
else
strErrors < < _ ( " Error loading wallet.dat " ) < < " \n " ;
2012-09-18 20:30:47 +02:00
}
2013-10-02 17:15:51 +02:00
if ( GetBoolArg ( " -upgradewallet " , fFirstRun ) )
2011-11-11 03:12:46 +01:00
{
2013-10-02 17:15:51 +02:00
int nMaxVersion = GetArg ( " -upgradewallet " , 0 ) ;
if ( nMaxVersion = = 0 ) // the -upgradewallet without argument case
{
LogPrintf ( " Performing wallet upgrade to %i \n " , FEATURE_LATEST ) ;
nMaxVersion = CLIENT_VERSION ;
pwalletMain - > SetMinVersion ( FEATURE_LATEST ) ; // permanently upgrade the wallet immediately
}
else
LogPrintf ( " Allowing wallet upgrade up to %i \n " , nMaxVersion ) ;
if ( nMaxVersion < pwalletMain - > GetVersion ( ) )
strErrors < < _ ( " Cannot downgrade wallet " ) < < " \n " ;
pwalletMain - > SetMaxVersion ( nMaxVersion ) ;
2011-11-11 03:12:46 +01:00
}
2012-03-22 03:56:31 +01:00
2013-10-02 17:15:51 +02:00
if ( fFirstRun )
2012-03-22 03:56:31 +01:00
{
2013-10-02 17:15:51 +02:00
// Create new keyUser and set as default key
RandAddSeedPerfmon ( ) ;
CPubKey newDefaultKey ;
if ( pwalletMain - > GetKeyFromPool ( newDefaultKey ) ) {
pwalletMain - > SetDefaultKey ( newDefaultKey ) ;
if ( ! pwalletMain - > SetAddressBook ( pwalletMain - > vchDefaultKey . GetID ( ) , " " , " receive " ) )
strErrors < < _ ( " Cannot write default address " ) < < " \n " ;
}
2012-03-22 03:56:31 +01:00
2013-10-02 17:15:51 +02:00
pwalletMain - > SetBestChain ( chainActive . GetLocator ( ) ) ;
2013-04-25 19:30:28 +02:00
}
2013-05-22 20:58:53 +02:00
2014-01-16 16:15:27 +01:00
LogPrintf ( " %s " , strErrors . str ( ) ) ;
2014-02-24 09:08:56 +01:00
LogPrintf ( " wallet %15dms \n " , GetTimeMillis ( ) - nStart ) ;
2011-05-14 20:10:21 +02:00
2013-10-02 17:15:51 +02:00
RegisterWallet ( pwalletMain ) ;
2011-06-26 19:23:24 +02:00
2013-10-02 17:15:51 +02:00
CBlockIndex * pindexRescan = chainActive . Tip ( ) ;
if ( GetBoolArg ( " -rescan " , false ) )
2013-10-10 23:07:44 +02:00
pindexRescan = chainActive . Genesis ( ) ;
2013-10-02 17:15:51 +02:00
else
{
CWalletDB walletdb ( strWalletFile ) ;
CBlockLocator locator ;
if ( walletdb . ReadBestBlock ( locator ) )
pindexRescan = chainActive . FindFork ( locator ) ;
else
pindexRescan = chainActive . Genesis ( ) ;
}
if ( chainActive . Tip ( ) & & chainActive . Tip ( ) ! = pindexRescan )
{
uiInterface . InitMessage ( _ ( " Rescanning... " ) ) ;
LogPrintf ( " Rescanning last %i blocks (from block %i)... \n " , chainActive . Height ( ) - pindexRescan - > nHeight , pindexRescan - > nHeight ) ;
nStart = GetTimeMillis ( ) ;
pwalletMain - > ScanForWalletTransactions ( pindexRescan , true ) ;
2014-02-24 09:08:56 +01:00
LogPrintf ( " rescan %15dms \n " , GetTimeMillis ( ) - nStart ) ;
2013-10-02 17:15:51 +02:00
pwalletMain - > SetBestChain ( chainActive . GetLocator ( ) ) ;
nWalletDBUpdated + + ;
2014-02-14 18:27:15 +01:00
// Restore wallet transaction metadata after -zapwallettxes=1
if ( GetBoolArg ( " -zapwallettxes " , false ) & & GetArg ( " -zapwallettxes " , " 1 " ) ! = " 2 " )
{
BOOST_FOREACH ( const CWalletTx & wtxOld , vWtx )
{
uint256 hash = wtxOld . GetHash ( ) ;
std : : map < uint256 , CWalletTx > : : iterator mi = pwalletMain - > mapWallet . find ( hash ) ;
if ( mi ! = pwalletMain - > mapWallet . end ( ) )
{
const CWalletTx * copyFrom = & wtxOld ;
CWalletTx * copyTo = & mi - > second ;
copyTo - > mapValue = copyFrom - > mapValue ;
copyTo - > vOrderForm = copyFrom - > vOrderForm ;
copyTo - > nTimeReceived = copyFrom - > nTimeReceived ;
copyTo - > nTimeSmart = copyFrom - > nTimeSmart ;
copyTo - > fFromMe = copyFrom - > fFromMe ;
copyTo - > strFromAccount = copyFrom - > strFromAccount ;
copyTo - > nOrderPos = copyFrom - > nOrderPos ;
copyTo - > WriteToDisk ( ) ;
}
}
}
2013-10-02 17:15:51 +02:00
}
2013-10-02 17:19:10 +02:00
} // (!fDisableWallet)
2013-11-29 16:04:29 +01:00
# else // ENABLE_WALLET
LogPrintf ( " No wallet compiled in! \n " ) ;
# endif // !ENABLE_WALLET
2012-09-18 20:30:47 +02:00
// ********************************************************* Step 9: import blocks
2012-01-03 16:14:22 +01:00
2012-08-10 15:13:57 +02:00
// scan for better chains in the block chain database, that are not yet connected in the active best chain
2013-01-27 00:14:11 +01:00
CValidationState state ;
2013-11-16 19:28:24 +01:00
if ( ! ActivateBestChain ( state ) )
2012-08-19 00:33:01 +02:00
strErrors < < " Failed to connect best block " ;
2012-08-10 15:13:57 +02:00
2013-03-07 04:31:26 +01:00
std : : vector < boost : : filesystem : : path > vImportFiles ;
2012-05-21 16:47:29 +02:00
if ( mapArgs . count ( " -loadblock " ) )
2011-05-14 20:10:21 +02:00
{
2012-05-21 16:47:29 +02:00
BOOST_FOREACH ( string strFile , mapMultiArgs [ " -loadblock " ] )
2013-03-07 04:31:26 +01:00
vImportFiles . push_back ( strFile ) ;
2012-09-24 19:37:03 +02:00
}
2013-03-07 04:31:26 +01:00
threadGroup . create_thread ( boost : : bind ( & ThreadImport , vImportFiles ) ) ;
2012-09-24 19:37:03 +02:00
2012-09-18 20:30:47 +02:00
// ********************************************************* Step 10: load peers
2012-01-03 16:14:22 +01:00
2012-05-21 16:47:29 +02:00
uiInterface . InitMessage ( _ ( " Loading addresses... " ) ) ;
2013-01-11 22:57:22 +01:00
2012-05-21 16:47:29 +02:00
nStart = GetTimeMillis ( ) ;
2012-02-06 21:48:00 +01:00
2012-01-03 16:14:22 +01:00
{
2012-05-21 16:47:29 +02:00
CAddrDB adb ;
if ( ! adb . Read ( addrman ) )
2013-09-18 12:38:08 +02:00
LogPrintf ( " Invalid or missing peers.dat; recreating \n " ) ;
2012-01-03 16:14:22 +01:00
}
2014-02-24 09:08:56 +01:00
LogPrintf ( " Loaded %i addresses from peers.dat %dms \n " ,
2012-05-21 16:47:29 +02:00
addrman . size ( ) , GetTimeMillis ( ) - nStart ) ;
2011-05-14 20:10:21 +02:00
2012-09-18 20:30:47 +02:00
// ********************************************************* Step 11: start node
2011-05-14 20:10:21 +02:00
if ( ! CheckDiskSpace ( ) )
return false ;
2013-05-02 18:26:33 +02:00
if ( ! strErrors . str ( ) . empty ( ) )
return InitError ( strErrors . str ( ) ) ;
2011-05-14 20:10:21 +02:00
RandAddSeedPerfmon ( ) ;
2012-05-21 16:47:29 +02:00
//// debug print
2014-05-06 15:25:01 +02:00
LogPrintf ( " mapBlockIndex.size() = %u \n " , mapBlockIndex . size ( ) ) ;
2013-10-10 23:07:44 +02:00
LogPrintf ( " nBestHeight = %d \n " , chainActive . Height ( ) ) ;
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2014-05-06 15:25:01 +02:00
LogPrintf ( " setKeyPool.size() = %u \n " , pwalletMain ? pwalletMain - > setKeyPool . size ( ) : 0 ) ;
LogPrintf ( " mapWallet.size() = %u \n " , pwalletMain ? pwalletMain - > mapWallet . size ( ) : 0 ) ;
LogPrintf ( " mapAddressBook.size() = %u \n " , pwalletMain ? pwalletMain - > mapAddressBook . size ( ) : 0 ) ;
2013-11-29 16:04:29 +01:00
# endif
2012-05-21 16:47:29 +02:00
2013-03-09 18:02:57 +01:00
StartNode ( threadGroup ) ;
2011-05-14 20:10:21 +02:00
if ( fServer )
2013-03-07 04:31:26 +01:00
StartRPCThreads ( ) ;
2011-05-14 20:10:21 +02:00
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2013-03-31 07:54:27 +02:00
// Generate coins in the background
2013-08-25 06:00:02 +02:00
if ( pwalletMain )
2013-11-21 05:07:55 +01:00
GenerateBitcoins ( GetBoolArg ( " -gen " , false ) , pwalletMain , GetArg ( " -genproclimit " , - 1 ) ) ;
2013-11-29 16:04:29 +01:00
# endif
2013-03-31 07:54:27 +02:00
2012-09-18 20:30:47 +02:00
// ********************************************************* Step 12: finished
2012-05-21 16:47:29 +02:00
uiInterface . InitMessage ( _ ( " Done loading " ) ) ;
2013-11-29 16:04:29 +01:00
# ifdef ENABLE_WALLET
2013-08-25 06:00:02 +02:00
if ( pwalletMain ) {
// Add wallet transactions that aren't already in a block to mapTransactions
pwalletMain - > ReacceptWalletTransactions ( ) ;
2012-05-21 16:47:29 +02:00
2013-08-25 06:00:02 +02:00
// Run a thread to flush wallet periodically
threadGroup . create_thread ( boost : : bind ( & ThreadFlushWalletDB , boost : : ref ( pwalletMain - > strWalletFile ) ) ) ;
}
2013-11-29 16:04:29 +01:00
# endif
2011-05-14 20:10:21 +02:00
2013-03-09 18:02:57 +01:00
return ! fRequestShutdown ;
2011-05-14 20:10:21 +02:00
}