-
+ CD2140CB3B788CB22C819B659F7BAB62C23275D2F7528787E3DDE7519CF425169C8A3B42539ACFB947BB35B5406DBE415910FF352379CAB15ED4B22D8B1F3F22
bitcoin/src/init.cpp
(0 . 0)(1 . 581)
5913 // /****************************\
5914 // * EXPERIMENTAL BRANCH. *
5915 // * FOR LABORATORY USE ONLY. *
5916 // ********************************
5917 // ************
5918 // **************
5919 // ****************
5920 // **** **** ****
5921 // *** *** ***
5922 // *** *** ***
5923 // *** * * **
5924 // ******** ********
5925 // ******* ******
5926 // *** **
5927 // * ******* **
5928 // ** * * * * *
5929 // ** * * ***
5930 // **** * * * * ****
5931 // **** *** * * ** ***
5932 // **** ********* ******
5933 // ******* ***** *******
5934 // ********* ****** **
5935 // ** ****** ******
5936 // ** ******* **
5937 // ** ******* ***
5938 // **** ******** ************
5939 // ************ ************
5940 // ******** *******
5941 // ****** ****
5942 // *** ***
5943 // ********************************
5944 // Copyright (c) 2009-2010 Satoshi Nakamoto
5945 // Copyright (c) 2009-2012 The Bitcoin developers
5946 // Distributed under the MIT/X11 software license, see the accompanying
5947 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
5948 #include "headers.h"
5949 #include "db.h"
5950 #include "bitcoinrpc.h"
5951 #include "net.h"
5952 #include "init.h"
5953 #include "strlcpy.h"
5954 #include <boost/filesystem.hpp>
5955 #include <boost/filesystem/fstream.hpp>
5956 #include <boost/interprocess/sync/file_lock.hpp>
5957
5958 #if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
5959 #define _BITCOIN_QT_PLUGINS_INCLUDED
5960 #define __INSURE__
5961 #include <QtPlugin>
5962 Q_IMPORT_PLUGIN(qcncodecs)
5963 Q_IMPORT_PLUGIN(qjpcodecs)
5964 Q_IMPORT_PLUGIN(qtwcodecs)
5965 Q_IMPORT_PLUGIN(qkrcodecs)
5966 Q_IMPORT_PLUGIN(qtaccessiblewidgets)
5967 #endif
5968
5969 using namespace std;
5970 using namespace boost;
5971
5972 CWallet* pwalletMain;
5973
5974 //////////////////////////////////////////////////////////////////////////////
5975 //
5976 // Shutdown
5977 //
5978
5979 void ExitTimeout(void* parg)
5980 {
5981 #ifdef WIN32
5982 Sleep(5000);
5983 ExitProcess(0);
5984 #endif
5985 }
5986
5987 void Shutdown(void* parg)
5988 {
5989 static CCriticalSection cs_Shutdown;
5990 static bool fTaken;
5991 bool fFirstThread = false;
5992 TRY_CRITICAL_BLOCK(cs_Shutdown)
5993 {
5994 fFirstThread = !fTaken;
5995 fTaken = true;
5996 }
5997 static bool fExit;
5998 if (fFirstThread)
5999 {
6000 fShutdown = true;
6001 nTransactionsUpdated++;
6002 DBFlush(false);
6003 StopNode();
6004 DBFlush(true);
6005 boost::filesystem::remove(GetPidFile());
6006 UnregisterWallet(pwalletMain);
6007 delete pwalletMain;
6008 CreateThread(ExitTimeout, NULL);
6009 Sleep(50);
6010 printf("Bitcoin exiting\n\n");
6011 fExit = true;
6012 exit(0);
6013 }
6014 else
6015 {
6016 while (!fExit)
6017 Sleep(500);
6018 Sleep(100);
6019 ExitThread(0);
6020 }
6021 }
6022
6023 void HandleSIGTERM(int)
6024 {
6025 fRequestShutdown = true;
6026 }
6027
6028
6029
6030
6031
6032
6033 //////////////////////////////////////////////////////////////////////////////
6034 //
6035 // Start
6036 //
6037 #if !defined(QT_GUI)
6038 int main(int argc, char* argv[])
6039 {
6040 bool fRet = false;
6041 fRet = AppInit(argc, argv);
6042
6043 if (fRet && fDaemon)
6044 return 0;
6045
6046 return 1;
6047 }
6048 #endif
6049
6050 bool AppInit(int argc, char* argv[])
6051 {
6052 bool fRet = false;
6053 try
6054 {
6055 fRet = AppInit2(argc, argv);
6056 }
6057 catch (std::exception& e) {
6058 PrintException(&e, "AppInit()");
6059 } catch (...) {
6060 PrintException(NULL, "AppInit()");
6061 }
6062 if (!fRet)
6063 Shutdown(NULL);
6064 return fRet;
6065 }
6066
6067 bool AppInit2(int argc, char* argv[])
6068 {
6069 #ifdef _MSC_VER
6070 // Turn off microsoft heap dump noise
6071 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
6072 _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
6073 #endif
6074 #if _MSC_VER >= 1400
6075 // Disable confusing "helpful" text message on abort, ctrl-c
6076 _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
6077 #endif
6078 #ifndef WIN32
6079 umask(077);
6080 #endif
6081 #ifndef WIN32
6082 // Clean shutdown on SIGTERM
6083 struct sigaction sa;
6084 sa.sa_handler = HandleSIGTERM;
6085 sigemptyset(&sa.sa_mask);
6086 sa.sa_flags = 0;
6087 sigaction(SIGTERM, &sa, NULL);
6088 sigaction(SIGINT, &sa, NULL);
6089 sigaction(SIGHUP, &sa, NULL);
6090 #endif
6091
6092 //
6093 // Parameters
6094 //
6095 ParseParameters(argc, argv);
6096
6097 if (mapArgs.count("-datadir"))
6098 {
6099 if (filesystem::is_directory(filesystem::system_complete(mapArgs["-datadir"])))
6100 {
6101 filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]);
6102 strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
6103 }
6104 else
6105 {
6106 fprintf(stderr, "Error: Specified directory does not exist\n");
6107 Shutdown(NULL);
6108 }
6109 }
6110
6111
6112 ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir
6113
6114 if (mapArgs.count("-?") || mapArgs.count("--help"))
6115 {
6116 string strUsage = string() +
6117 _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
6118 _("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" +
6119 " bitcoind [options] \t " + "\n" +
6120 " bitcoind [options] <command> [params]\t " + _("Send command to -server or bitcoind\n") +
6121 " bitcoind [options] help \t\t " + _("List commands\n") +
6122 " bitcoind [options] help <command> \t\t " + _("Get help for a command\n") +
6123 _("Options:\n") +
6124 " -conf=<file> \t\t " + _("Specify configuration file (default: bitcoin.conf)\n") +
6125 " -pid=<file> \t\t " + _("Specify pid file (default: bitcoind.pid)\n") +
6126 " -gen \t\t " + _("Generate coins\n") +
6127 " -gen=0 \t\t " + _("Don't generate coins\n") +
6128 " -min \t\t " + _("Start minimized\n") +
6129 " -datadir=<dir> \t\t " + _("Specify data directory\n") +
6130 " -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)\n") +
6131 " -proxy=<ip:port> \t " + _("Connect through socks4 proxy\n") +
6132 " -dns \t " + _("Allow DNS lookups for addnode and connect\n") +
6133 " -port=<port> \t\t " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)\n") +
6134 " -maxconnections=<n>\t " + _("Maintain at most <n> connections to peers (default: 125)\n") +
6135 " -addnode=<ip> \t " + _("Add a node to connect to\n") +
6136 " -connect=<ip> \t\t " + _("Connect only to the specified node\n") +
6137 " -noirc \t " + _("Don't find peers using internet relay chat\n") +
6138 " -nolisten \t " + _("Don't accept connections from outside\n") +
6139 " -nodnsseed \t " + _("Don't bootstrap list of peers using DNS\n") +
6140 " -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)\n") +
6141 " -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)\n") +
6142 " -maxreceivebuffer=<n>\t " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)\n") +
6143 " -maxsendbuffer=<n>\t " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)\n") +
6144 #ifdef USE_UPNP
6145 #if USE_UPNP
6146 " -noupnp \t " + _("Don't attempt to use UPnP to map the listening port\n") +
6147 #else
6148 " -upnp \t " + _("Attempt to use UPnP to map the listening port\n") +
6149 #endif
6150 #endif
6151 " -paytxfee=<amt> \t " + _("Fee per kB to add to transactions you send\n") +
6152 #ifdef QT_GUI
6153 " -server \t\t " + _("Accept command line and JSON-RPC commands\n") +
6154 #endif
6155 #if !defined(WIN32) && !defined(QT_GUI)
6156 " -daemon \t\t " + _("Run in the background as a daemon and accept commands\n") +
6157 #endif
6158 " -testnet \t\t " + _("Use the test network\n") +
6159 " -debug \t\t " + _("Output extra debugging information\n") +
6160 " -logtimestamps \t " + _("Prepend debug output with timestamp\n") +
6161 " -printtoconsole \t " + _("Send trace/debug info to console instead of debug.log file\n") +
6162 #ifdef WIN32
6163 " -printtodebugger \t " + _("Send trace/debug info to debugger\n") +
6164 #endif
6165 " -rpcuser=<user> \t " + _("Username for JSON-RPC connections\n") +
6166 " -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections\n") +
6167 " -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)\n") +
6168 " -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address\n") +
6169 " -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)\n") +
6170 " -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)\n") +
6171 " -rescan \t " + _("Rescan the block chain for missing wallet transactions\n");
6172
6173 #ifdef USE_SSL
6174 strUsage += string() +
6175 _("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)\n") +
6176 " -rpcssl \t " + _("Use OpenSSL (https) for JSON-RPC connections\n") +
6177 " -rpcsslcertificatechainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)\n") +
6178 " -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)\n") +
6179 " -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)\n");
6180 #endif
6181
6182 strUsage += string() +
6183 " -? \t\t " + _("This help message\n");
6184
6185 // Remove tabs
6186 strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end());
6187 #if defined(QT_GUI) && defined(WIN32)
6188 // On windows, show a message box, as there is no stderr
6189 wxMessageBox(strUsage, "Usage");
6190 #else
6191 fprintf(stderr, "%s", strUsage.c_str());
6192 #endif
6193 return false;
6194 }
6195
6196 fTestNet = GetBoolArg("-testnet");
6197 fDebug = GetBoolArg("-debug");
6198
6199 #if !defined(WIN32) && !defined(QT_GUI)
6200 fDaemon = GetBoolArg("-daemon");
6201 #else
6202 fDaemon = false;
6203 #endif
6204
6205 if (fDaemon)
6206 fServer = true;
6207 else
6208 fServer = GetBoolArg("-server");
6209
6210 /* force fServer when running without GUI */
6211 #if !defined(QT_GUI)
6212 fServer = true;
6213 #endif
6214 fPrintToConsole = GetBoolArg("-printtoconsole");
6215 fPrintToDebugger = GetBoolArg("-printtodebugger");
6216 fLogTimestamps = GetBoolArg("-logtimestamps");
6217
6218 #ifndef QT_GUI
6219 for (int i = 1; i < argc; i++)
6220 if (!IsSwitchChar(argv[i][0]))
6221 fCommandLine = true;
6222
6223 if (fCommandLine)
6224 {
6225 int ret = CommandLineRPC(argc, argv);
6226 exit(ret);
6227 }
6228 #endif
6229
6230 #if !defined(WIN32) && !defined(QT_GUI)
6231 if (fDaemon)
6232 {
6233 // Daemonize
6234 pid_t pid = fork();
6235 if (pid < 0)
6236 {
6237 fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
6238 return false;
6239 }
6240 if (pid > 0)
6241 {
6242 CreatePidFile(GetPidFile(), pid);
6243 return true;
6244 }
6245
6246 pid_t sid = setsid();
6247 if (sid < 0)
6248 fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
6249 }
6250 #endif
6251
6252 if (!fDebug && !pszSetDataDir[0])
6253 ShrinkDebugFile();
6254 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
6255 printf("Bitcoin version %s\n", FormatFullVersion().c_str());
6256 printf("Default data directory %s\n", GetDefaultDataDir().c_str());
6257
6258 if (GetBoolArg("-loadblockindextest"))
6259 {
6260 CTxDB txdb("r");
6261 txdb.LoadBlockIndex();
6262 PrintBlockTree();
6263 return false;
6264 }
6265
6266 // Make sure only a single bitcoin process is using the data directory.
6267 string strLockFile = GetDataDir() + "/.lock";
6268 FILE* file = fopen(strLockFile.c_str(), "a"); // empty lock file; created if it doesn't exist.
6269 if (file) fclose(file);
6270 static boost::interprocess::file_lock lock(strLockFile.c_str());
6271 if (!lock.try_lock())
6272 {
6273 wxMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), "Bitcoin");
6274 return false;
6275 }
6276
6277 string strErrors;
6278
6279 //
6280 // Load data files
6281 //
6282 if (fDaemon)
6283 fprintf(stdout, "bitcoin server starting\n");
6284 strErrors = "";
6285 int64 nStart;
6286
6287 InitMessage(_("Loading addresses..."));
6288 printf("Loading addresses...\n");
6289 nStart = GetTimeMillis();
6290 if (!LoadAddresses())
6291 strErrors += _("Error loading addr.dat \n");
6292 printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
6293
6294 InitMessage(_("Loading block index..."));
6295 printf("Loading block index...\n");
6296 nStart = GetTimeMillis();
6297 if (!LoadBlockIndex())
6298 strErrors += _("Error loading blkindex.dat \n");
6299 printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
6300
6301 InitMessage(_("Loading wallet..."));
6302 printf("Loading wallet...\n");
6303 nStart = GetTimeMillis();
6304 bool fFirstRun;
6305 pwalletMain = new CWallet("wallet.dat");
6306 int nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun);
6307 if (nLoadWalletRet != DB_LOAD_OK)
6308 {
6309 if (nLoadWalletRet == DB_CORRUPT)
6310 strErrors += _("Error loading wallet.dat: Wallet corrupted \n");
6311 else if (nLoadWalletRet == DB_TOO_NEW)
6312 strErrors += _("Error loading wallet.dat: Wallet requires newer version of Bitcoin \n");
6313 else if (nLoadWalletRet == DB_NEED_REWRITE)
6314 {
6315 strErrors += _("Wallet needed to be rewritten: restart Bitcoin to complete \n");
6316 wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
6317 return false;
6318 }
6319 else
6320 strErrors += _("Error loading wallet.dat \n");
6321 }
6322 printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
6323
6324 RegisterWallet(pwalletMain);
6325
6326 CBlockIndex *pindexRescan = pindexBest;
6327 if (GetBoolArg("-rescan"))
6328 pindexRescan = pindexGenesisBlock;
6329 else
6330 {
6331 CWalletDB walletdb("wallet.dat");
6332 CBlockLocator locator;
6333 if (walletdb.ReadBestBlock(locator))
6334 pindexRescan = locator.GetBlockIndex();
6335 }
6336 if (pindexBest != pindexRescan)
6337 {
6338 InitMessage(_("Rescanning..."));
6339 printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
6340 nStart = GetTimeMillis();
6341 pwalletMain->ScanForWalletTransactions(pindexRescan, true);
6342 printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
6343 }
6344
6345 InitMessage(_("Done loading"));
6346 printf("Done loading\n");
6347
6348 //// debug print
6349 printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
6350 printf("nBestHeight = %d\n", nBestHeight);
6351 printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
6352 printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
6353 printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());
6354
6355 if (!strErrors.empty())
6356 {
6357 wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
6358 return false;
6359 }
6360
6361 // Add wallet transactions that aren't already in a block to mapTransactions
6362 pwalletMain->ReacceptWalletTransactions();
6363
6364 // Note: Bitcoin-QT stores several settings in the wallet, so we want
6365 // to load the wallet BEFORE parsing command-line arguments, so
6366 // the command-line/bitcoin.conf settings override GUI setting.
6367
6368 //
6369 // Parameters
6370 //
6371 if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree"))
6372 {
6373 PrintBlockTree();
6374 return false;
6375 }
6376
6377 if (mapArgs.count("-timeout"))
6378 {
6379 int nNewTimeout = GetArg("-timeout", 5000);
6380 if (nNewTimeout > 0 && nNewTimeout < 600000)
6381 nConnectTimeout = nNewTimeout;
6382 }
6383
6384 if (mapArgs.count("-printblock"))
6385 {
6386 string strMatch = mapArgs["-printblock"];
6387 int nFound = 0;
6388 for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
6389 {
6390 uint256 hash = (*mi).first;
6391 if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
6392 {
6393 CBlockIndex* pindex = (*mi).second;
6394 CBlock block;
6395 block.ReadFromDisk(pindex);
6396 block.BuildMerkleTree();
6397 block.print();
6398 printf("\n");
6399 nFound++;
6400 }
6401 }
6402 if (nFound == 0)
6403 printf("No blocks matching %s were found\n", strMatch.c_str());
6404 return false;
6405 }
6406
6407 fGenerateBitcoins = GetBoolArg("-gen");
6408
6409 if (mapArgs.count("-proxy"))
6410 {
6411 fUseProxy = true;
6412 addrProxy = CAddress(mapArgs["-proxy"]);
6413 if (!addrProxy.IsValid())
6414 {
6415 wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
6416 return false;
6417 }
6418 }
6419
6420 bool fTor = (fUseProxy && addrProxy.port == htons(9050));
6421 if (fTor)
6422 {
6423 // Use SoftSetArg here so user can override any of these if they wish.
6424 // Note: the GetBoolArg() calls for all of these must happen later.
6425 SoftSetArg("-nolisten", true);
6426 SoftSetArg("-noirc", true);
6427 SoftSetArg("-nodnsseed", true);
6428 SoftSetArg("-noupnp", true);
6429 SoftSetArg("-upnp", false);
6430 SoftSetArg("-dns", false);
6431 }
6432
6433 fAllowDNS = GetBoolArg("-dns");
6434 fNoListen = GetBoolArg("-nolisten");
6435
6436 // Command-line args override in-wallet settings:
6437 if (mapArgs.count("-upnp"))
6438 fUseUPnP = GetBoolArg("-upnp");
6439 else if (mapArgs.count("-noupnp"))
6440 fUseUPnP = !GetBoolArg("-noupnp");
6441
6442 if (!fNoListen)
6443 {
6444 if (!BindListenPort(strErrors))
6445 {
6446 wxMessageBox(strErrors, "Bitcoin");
6447 return false;
6448 }
6449 }
6450
6451 if (mapArgs.count("-addnode"))
6452 {
6453 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
6454 {
6455 CAddress addr(strAddr, fAllowDNS);
6456 addr.nTime = 0; // so it won't relay unless successfully connected
6457 if (addr.IsValid())
6458 AddAddress(addr);
6459 }
6460 }
6461
6462 if (mapArgs.count("-paytxfee"))
6463 {
6464 if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
6465 {
6466 wxMessageBox(_("Invalid amount for -paytxfee=<amount>"), "Bitcoin");
6467 return false;
6468 }
6469 if (nTransactionFee > 0.25 * COIN)
6470 wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION);
6471 }
6472
6473 //
6474 // Start the node
6475 //
6476 if (!CheckDiskSpace())
6477 return false;
6478
6479 RandAddSeedPerfmon();
6480
6481 if (!CreateThread(StartNode, NULL))
6482 wxMessageBox(_("Error: CreateThread(StartNode) failed"), "Bitcoin");
6483
6484 if (fServer)
6485 CreateThread(ThreadRPCServer, NULL);
6486
6487 #if !defined(QT_GUI)
6488 while (1)
6489 Sleep(5000);
6490 #endif
6491
6492 return true;
6493 }