-
+ 9EA336B2061C743C7F9FD590A02546616D8E3FD0DEE8C9A15BB9A24E8E6138FB48F9B9BE4B7452CE1E0EB4E69E8882D2B5F03EF2D6D0B50FDB9E0A869719ECFCbitcoin/src/init.cpp(0 . 0)(1 . 550)
5510 // Copyright (c) 2009-2010 Satoshi Nakamoto
5511 // Copyright (c) 2009-2012 The Bitcoin developers
5512 // Distributed under the MIT/X11 software license, see the accompanying
5513 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
5514 #include "headers.h"
5515 #include "db.h"
5516 #include "bitcoinrpc.h"
5517 #include "net.h"
5518 #include "init.h"
5519 #include "strlcpy.h"
5520 #include <boost/filesystem.hpp>
5521 #include <boost/filesystem/fstream.hpp>
5522 #include <boost/interprocess/sync/file_lock.hpp>
5523
5524 #if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
5525 #define _BITCOIN_QT_PLUGINS_INCLUDED
5526 #define __INSURE__
5527 #include <QtPlugin>
5528 Q_IMPORT_PLUGIN(qcncodecs)
5529 Q_IMPORT_PLUGIN(qjpcodecs)
5530 Q_IMPORT_PLUGIN(qtwcodecs)
5531 Q_IMPORT_PLUGIN(qkrcodecs)
5532 Q_IMPORT_PLUGIN(qtaccessiblewidgets)
5533 #endif
5534
5535 using namespace std;
5536 using namespace boost;
5537
5538 CWallet* pwalletMain;
5539
5540 //////////////////////////////////////////////////////////////////////////////
5541 //
5542 // Shutdown
5543 //
5544
5545 void ExitTimeout(void* parg)
5546 {
5547 #ifdef WIN32
5548 Sleep(5000);
5549 ExitProcess(0);
5550 #endif
5551 }
5552
5553 void Shutdown(void* parg)
5554 {
5555 static CCriticalSection cs_Shutdown;
5556 static bool fTaken;
5557 bool fFirstThread = false;
5558 TRY_CRITICAL_BLOCK(cs_Shutdown)
5559 {
5560 fFirstThread = !fTaken;
5561 fTaken = true;
5562 }
5563 static bool fExit;
5564 if (fFirstThread)
5565 {
5566 fShutdown = true;
5567 nTransactionsUpdated++;
5568 DBFlush(false);
5569 StopNode();
5570 DBFlush(true);
5571 boost::filesystem::remove(GetPidFile());
5572 UnregisterWallet(pwalletMain);
5573 delete pwalletMain;
5574 CreateThread(ExitTimeout, NULL);
5575 Sleep(50);
5576 printf("Bitcoin exiting\n\n");
5577 fExit = true;
5578 exit(0);
5579 }
5580 else
5581 {
5582 while (!fExit)
5583 Sleep(500);
5584 Sleep(100);
5585 ExitThread(0);
5586 }
5587 }
5588
5589 void HandleSIGTERM(int)
5590 {
5591 fRequestShutdown = true;
5592 }
5593
5594
5595
5596
5597
5598
5599 //////////////////////////////////////////////////////////////////////////////
5600 //
5601 // Start
5602 //
5603 #if !defined(QT_GUI)
5604 int main(int argc, char* argv[])
5605 {
5606 bool fRet = false;
5607 fRet = AppInit(argc, argv);
5608
5609 if (fRet && fDaemon)
5610 return 0;
5611
5612 return 1;
5613 }
5614 #endif
5615
5616 bool AppInit(int argc, char* argv[])
5617 {
5618 bool fRet = false;
5619 try
5620 {
5621 fRet = AppInit2(argc, argv);
5622 }
5623 catch (std::exception& e) {
5624 PrintException(&e, "AppInit()");
5625 } catch (...) {
5626 PrintException(NULL, "AppInit()");
5627 }
5628 if (!fRet)
5629 Shutdown(NULL);
5630 return fRet;
5631 }
5632
5633 bool AppInit2(int argc, char* argv[])
5634 {
5635 #ifdef _MSC_VER
5636 // Turn off microsoft heap dump noise
5637 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
5638 _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
5639 #endif
5640 #if _MSC_VER >= 1400
5641 // Disable confusing "helpful" text message on abort, ctrl-c
5642 _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
5643 #endif
5644 #ifndef WIN32
5645 umask(077);
5646 #endif
5647 #ifndef WIN32
5648 // Clean shutdown on SIGTERM
5649 struct sigaction sa;
5650 sa.sa_handler = HandleSIGTERM;
5651 sigemptyset(&sa.sa_mask);
5652 sa.sa_flags = 0;
5653 sigaction(SIGTERM, &sa, NULL);
5654 sigaction(SIGINT, &sa, NULL);
5655 sigaction(SIGHUP, &sa, NULL);
5656 #endif
5657
5658 //
5659 // Parameters
5660 //
5661 ParseParameters(argc, argv);
5662
5663 if (mapArgs.count("-datadir"))
5664 {
5665 if (filesystem::is_directory(filesystem::system_complete(mapArgs["-datadir"])))
5666 {
5667 filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]);
5668 strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
5669 }
5670 else
5671 {
5672 fprintf(stderr, "Error: Specified directory does not exist\n");
5673 Shutdown(NULL);
5674 }
5675 }
5676
5677
5678 ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir
5679
5680 if (mapArgs.count("-?") || mapArgs.count("--help"))
5681 {
5682 string strUsage = string() +
5683 _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
5684 _("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" +
5685 " bitcoind [options] \t " + "\n" +
5686 " bitcoind [options] <command> [params]\t " + _("Send command to -server or bitcoind\n") +
5687 " bitcoind [options] help \t\t " + _("List commands\n") +
5688 " bitcoind [options] help <command> \t\t " + _("Get help for a command\n") +
5689 _("Options:\n") +
5690 " -conf=<file> \t\t " + _("Specify configuration file (default: bitcoin.conf)\n") +
5691 " -pid=<file> \t\t " + _("Specify pid file (default: bitcoind.pid)\n") +
5692 " -gen \t\t " + _("Generate coins\n") +
5693 " -gen=0 \t\t " + _("Don't generate coins\n") +
5694 " -min \t\t " + _("Start minimized\n") +
5695 " -datadir=<dir> \t\t " + _("Specify data directory\n") +
5696 " -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)\n") +
5697 " -proxy=<ip:port> \t " + _("Connect through socks4 proxy\n") +
5698 " -dns \t " + _("Allow DNS lookups for addnode and connect\n") +
5699 " -port=<port> \t\t " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)\n") +
5700 " -maxconnections=<n>\t " + _("Maintain at most <n> connections to peers (default: 125)\n") +
5701 " -addnode=<ip> \t " + _("Add a node to connect to\n") +
5702 " -connect=<ip> \t\t " + _("Connect only to the specified node\n") +
5703 " -noirc \t " + _("Don't find peers using internet relay chat\n") +
5704 " -nolisten \t " + _("Don't accept connections from outside\n") +
5705 " -nodnsseed \t " + _("Don't bootstrap list of peers using DNS\n") +
5706 " -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)\n") +
5707 " -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)\n") +
5708 " -maxreceivebuffer=<n>\t " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)\n") +
5709 " -maxsendbuffer=<n>\t " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)\n") +
5710 #ifdef USE_UPNP
5711 #if USE_UPNP
5712 " -noupnp \t " + _("Don't attempt to use UPnP to map the listening port\n") +
5713 #else
5714 " -upnp \t " + _("Attempt to use UPnP to map the listening port\n") +
5715 #endif
5716 #endif
5717 " -paytxfee=<amt> \t " + _("Fee per kB to add to transactions you send\n") +
5718 #ifdef QT_GUI
5719 " -server \t\t " + _("Accept command line and JSON-RPC commands\n") +
5720 #endif
5721 #if !defined(WIN32) && !defined(QT_GUI)
5722 " -daemon \t\t " + _("Run in the background as a daemon and accept commands\n") +
5723 #endif
5724 " -testnet \t\t " + _("Use the test network\n") +
5725 " -debug \t\t " + _("Output extra debugging information\n") +
5726 " -logtimestamps \t " + _("Prepend debug output with timestamp\n") +
5727 " -printtoconsole \t " + _("Send trace/debug info to console instead of debug.log file\n") +
5728 #ifdef WIN32
5729 " -printtodebugger \t " + _("Send trace/debug info to debugger\n") +
5730 #endif
5731 " -rpcuser=<user> \t " + _("Username for JSON-RPC connections\n") +
5732 " -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections\n") +
5733 " -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)\n") +
5734 " -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address\n") +
5735 " -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)\n") +
5736 " -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)\n") +
5737 " -rescan \t " + _("Rescan the block chain for missing wallet transactions\n");
5738
5739 #ifdef USE_SSL
5740 strUsage += string() +
5741 _("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)\n") +
5742 " -rpcssl \t " + _("Use OpenSSL (https) for JSON-RPC connections\n") +
5743 " -rpcsslcertificatechainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)\n") +
5744 " -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)\n") +
5745 " -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)\n");
5746 #endif
5747
5748 strUsage += string() +
5749 " -? \t\t " + _("This help message\n");
5750
5751 // Remove tabs
5752 strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end());
5753 #if defined(QT_GUI) && defined(WIN32)
5754 // On windows, show a message box, as there is no stderr
5755 wxMessageBox(strUsage, "Usage");
5756 #else
5757 fprintf(stderr, "%s", strUsage.c_str());
5758 #endif
5759 return false;
5760 }
5761
5762 fTestNet = GetBoolArg("-testnet");
5763 fDebug = GetBoolArg("-debug");
5764
5765 #if !defined(WIN32) && !defined(QT_GUI)
5766 fDaemon = GetBoolArg("-daemon");
5767 #else
5768 fDaemon = false;
5769 #endif
5770
5771 if (fDaemon)
5772 fServer = true;
5773 else
5774 fServer = GetBoolArg("-server");
5775
5776 /* force fServer when running without GUI */
5777 #if !defined(QT_GUI)
5778 fServer = true;
5779 #endif
5780 fPrintToConsole = GetBoolArg("-printtoconsole");
5781 fPrintToDebugger = GetBoolArg("-printtodebugger");
5782 fLogTimestamps = GetBoolArg("-logtimestamps");
5783
5784 #ifndef QT_GUI
5785 for (int i = 1; i < argc; i++)
5786 if (!IsSwitchChar(argv[i][0]))
5787 fCommandLine = true;
5788
5789 if (fCommandLine)
5790 {
5791 int ret = CommandLineRPC(argc, argv);
5792 exit(ret);
5793 }
5794 #endif
5795
5796 #if !defined(WIN32) && !defined(QT_GUI)
5797 if (fDaemon)
5798 {
5799 // Daemonize
5800 pid_t pid = fork();
5801 if (pid < 0)
5802 {
5803 fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
5804 return false;
5805 }
5806 if (pid > 0)
5807 {
5808 CreatePidFile(GetPidFile(), pid);
5809 return true;
5810 }
5811
5812 pid_t sid = setsid();
5813 if (sid < 0)
5814 fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
5815 }
5816 #endif
5817
5818 if (!fDebug && !pszSetDataDir[0])
5819 ShrinkDebugFile();
5820 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
5821 printf("Bitcoin version %s\n", FormatFullVersion().c_str());
5822 printf("Default data directory %s\n", GetDefaultDataDir().c_str());
5823
5824 if (GetBoolArg("-loadblockindextest"))
5825 {
5826 CTxDB txdb("r");
5827 txdb.LoadBlockIndex();
5828 PrintBlockTree();
5829 return false;
5830 }
5831
5832 // Make sure only a single bitcoin process is using the data directory.
5833 string strLockFile = GetDataDir() + "/.lock";
5834 FILE* file = fopen(strLockFile.c_str(), "a"); // empty lock file; created if it doesn't exist.
5835 if (file) fclose(file);
5836 static boost::interprocess::file_lock lock(strLockFile.c_str());
5837 if (!lock.try_lock())
5838 {
5839 wxMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), "Bitcoin");
5840 return false;
5841 }
5842
5843 string strErrors;
5844
5845 //
5846 // Load data files
5847 //
5848 if (fDaemon)
5849 fprintf(stdout, "bitcoin server starting\n");
5850 strErrors = "";
5851 int64 nStart;
5852
5853 InitMessage(_("Loading addresses..."));
5854 printf("Loading addresses...\n");
5855 nStart = GetTimeMillis();
5856 if (!LoadAddresses())
5857 strErrors += _("Error loading addr.dat \n");
5858 printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
5859
5860 InitMessage(_("Loading block index..."));
5861 printf("Loading block index...\n");
5862 nStart = GetTimeMillis();
5863 if (!LoadBlockIndex())
5864 strErrors += _("Error loading blkindex.dat \n");
5865 printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
5866
5867 InitMessage(_("Loading wallet..."));
5868 printf("Loading wallet...\n");
5869 nStart = GetTimeMillis();
5870 bool fFirstRun;
5871 pwalletMain = new CWallet("wallet.dat");
5872 int nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun);
5873 if (nLoadWalletRet != DB_LOAD_OK)
5874 {
5875 if (nLoadWalletRet == DB_CORRUPT)
5876 strErrors += _("Error loading wallet.dat: Wallet corrupted \n");
5877 else if (nLoadWalletRet == DB_TOO_NEW)
5878 strErrors += _("Error loading wallet.dat: Wallet requires newer version of Bitcoin \n");
5879 else if (nLoadWalletRet == DB_NEED_REWRITE)
5880 {
5881 strErrors += _("Wallet needed to be rewritten: restart Bitcoin to complete \n");
5882 wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
5883 return false;
5884 }
5885 else
5886 strErrors += _("Error loading wallet.dat \n");
5887 }
5888 printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
5889
5890 RegisterWallet(pwalletMain);
5891
5892 CBlockIndex *pindexRescan = pindexBest;
5893 if (GetBoolArg("-rescan"))
5894 pindexRescan = pindexGenesisBlock;
5895 else
5896 {
5897 CWalletDB walletdb("wallet.dat");
5898 CBlockLocator locator;
5899 if (walletdb.ReadBestBlock(locator))
5900 pindexRescan = locator.GetBlockIndex();
5901 }
5902 if (pindexBest != pindexRescan)
5903 {
5904 InitMessage(_("Rescanning..."));
5905 printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
5906 nStart = GetTimeMillis();
5907 pwalletMain->ScanForWalletTransactions(pindexRescan, true);
5908 printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
5909 }
5910
5911 InitMessage(_("Done loading"));
5912 printf("Done loading\n");
5913
5914 //// debug print
5915 printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
5916 printf("nBestHeight = %d\n", nBestHeight);
5917 printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
5918 printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
5919 printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());
5920
5921 if (!strErrors.empty())
5922 {
5923 wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
5924 return false;
5925 }
5926
5927 // Add wallet transactions that aren't already in a block to mapTransactions
5928 pwalletMain->ReacceptWalletTransactions();
5929
5930 // Note: Bitcoin-QT stores several settings in the wallet, so we want
5931 // to load the wallet BEFORE parsing command-line arguments, so
5932 // the command-line/bitcoin.conf settings override GUI setting.
5933
5934 //
5935 // Parameters
5936 //
5937 if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree"))
5938 {
5939 PrintBlockTree();
5940 return false;
5941 }
5942
5943 if (mapArgs.count("-timeout"))
5944 {
5945 int nNewTimeout = GetArg("-timeout", 5000);
5946 if (nNewTimeout > 0 && nNewTimeout < 600000)
5947 nConnectTimeout = nNewTimeout;
5948 }
5949
5950 if (mapArgs.count("-printblock"))
5951 {
5952 string strMatch = mapArgs["-printblock"];
5953 int nFound = 0;
5954 for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
5955 {
5956 uint256 hash = (*mi).first;
5957 if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
5958 {
5959 CBlockIndex* pindex = (*mi).second;
5960 CBlock block;
5961 block.ReadFromDisk(pindex);
5962 block.BuildMerkleTree();
5963 block.print();
5964 printf("\n");
5965 nFound++;
5966 }
5967 }
5968 if (nFound == 0)
5969 printf("No blocks matching %s were found\n", strMatch.c_str());
5970 return false;
5971 }
5972
5973 fGenerateBitcoins = GetBoolArg("-gen");
5974
5975 if (mapArgs.count("-proxy"))
5976 {
5977 fUseProxy = true;
5978 addrProxy = CAddress(mapArgs["-proxy"]);
5979 if (!addrProxy.IsValid())
5980 {
5981 wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
5982 return false;
5983 }
5984 }
5985
5986 bool fTor = (fUseProxy && addrProxy.port == htons(9050));
5987 if (fTor)
5988 {
5989 // Use SoftSetArg here so user can override any of these if they wish.
5990 // Note: the GetBoolArg() calls for all of these must happen later.
5991 SoftSetArg("-nolisten", true);
5992 SoftSetArg("-noirc", true);
5993 SoftSetArg("-nodnsseed", true);
5994 SoftSetArg("-noupnp", true);
5995 SoftSetArg("-upnp", false);
5996 SoftSetArg("-dns", false);
5997 }
5998
5999 fAllowDNS = GetBoolArg("-dns");
6000 fNoListen = GetBoolArg("-nolisten");
6001
6002 // Command-line args override in-wallet settings:
6003 if (mapArgs.count("-upnp"))
6004 fUseUPnP = GetBoolArg("-upnp");
6005 else if (mapArgs.count("-noupnp"))
6006 fUseUPnP = !GetBoolArg("-noupnp");
6007
6008 if (!fNoListen)
6009 {
6010 if (!BindListenPort(strErrors))
6011 {
6012 wxMessageBox(strErrors, "Bitcoin");
6013 return false;
6014 }
6015 }
6016
6017 if (mapArgs.count("-addnode"))
6018 {
6019 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
6020 {
6021 CAddress addr(strAddr, fAllowDNS);
6022 addr.nTime = 0; // so it won't relay unless successfully connected
6023 if (addr.IsValid())
6024 AddAddress(addr);
6025 }
6026 }
6027
6028 if (mapArgs.count("-paytxfee"))
6029 {
6030 if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
6031 {
6032 wxMessageBox(_("Invalid amount for -paytxfee=<amount>"), "Bitcoin");
6033 return false;
6034 }
6035 if (nTransactionFee > 0.25 * COIN)
6036 wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION);
6037 }
6038
6039 //
6040 // Start the node
6041 //
6042 if (!CheckDiskSpace())
6043 return false;
6044
6045 RandAddSeedPerfmon();
6046
6047 if (!CreateThread(StartNode, NULL))
6048 wxMessageBox(_("Error: CreateThread(StartNode) failed"), "Bitcoin");
6049
6050 if (fServer)
6051 CreateThread(ThreadRPCServer, NULL);
6052
6053 #if !defined(QT_GUI)
6054 while (1)
6055 Sleep(5000);
6056 #endif
6057
6058 return true;
6059 }