File indexing completed on 2020-06-25 15:50:41
0001
0002
0003
0004
0005 #include "headers.h"
0006 #include "db.h"
0007 #include "bitcoinrpc.h"
0008 #include "net.h"
0009 #include "init.h"
0010 #include "strlcpy.h"
0011 #include <boost/filesystem.hpp>
0012 #include <boost/filesystem/fstream.hpp>
0013 #include <boost/interprocess/sync/file_lock.hpp>
0014
0015
0016
0017 using namespace std;
0018 using namespace boost;
0019
0020 CWallet* pwalletMain;
0021
0022
0023
0024
0025
0026
0027 void ExitTimeout(void* parg)
0028 {
0029 }
0030
0031 void Shutdown(void* parg)
0032 {
0033 static CCriticalSection cs_Shutdown;
0034 static bool fTaken;
0035 bool fFirstThread = false;
0036 TRY_CRITICAL_BLOCK(cs_Shutdown)
0037 {
0038 fFirstThread = !fTaken;
0039 fTaken = true;
0040 }
0041 static bool fExit;
0042 if (fFirstThread)
0043 {
0044 fShutdown = true;
0045 nTransactionsUpdated++;
0046 DBFlush(false);
0047 StopNode();
0048 DBFlush(true);
0049 boost::filesystem::remove(GetPidFile());
0050 UnregisterWallet(pwalletMain);
0051 delete pwalletMain;
0052 CreateThread(ExitTimeout, NULL);
0053 Sleep(50);
0054 printf("Bitcoin exiting\n\n");
0055 fExit = true;
0056 exit(0);
0057 }
0058 else
0059 {
0060 while (!fExit)
0061 Sleep(500);
0062 Sleep(100);
0063 ExitThread(0);
0064 }
0065 }
0066
0067 void HandleSIGTERM(int)
0068 {
0069 fRequestShutdown = true;
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 int main(int argc, char* argv[])
0083 {
0084 bool fRet = false;
0085 fRet = AppInit(argc, argv);
0086
0087 if (fRet && fDaemon)
0088 return 0;
0089
0090 return 1;
0091 }
0092
0093
0094 bool AppInit(int argc, char* argv[])
0095 {
0096 bool fRet = false;
0097 try
0098 {
0099 fRet = AppInit2(argc, argv);
0100 }
0101 catch (std::exception& e) {
0102 PrintException(&e, "AppInit()");
0103 } catch (...) {
0104 PrintException(NULL, "AppInit()");
0105 }
0106 if (!fRet)
0107 Shutdown(NULL);
0108 return fRet;
0109 }
0110
0111 bool AppInit2(int argc, char* argv[])
0112 {
0113 umask(077);
0114
0115
0116 struct sigaction sa;
0117 sa.sa_handler = HandleSIGTERM;
0118 sigemptyset(&sa.sa_mask);
0119 sa.sa_flags = 0;
0120 sigaction(SIGTERM, &sa, NULL);
0121 sigaction(SIGINT, &sa, NULL);
0122 sigaction(SIGHUP, &sa, NULL);
0123
0124
0125
0126
0127 ParseParameters(argc, argv);
0128
0129 if (mapArgs.count("-datadir"))
0130 {
0131 if (filesystem::is_directory(filesystem::system_complete(mapArgs["-datadir"])))
0132 {
0133 filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]);
0134 strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
0135 }
0136 else
0137 {
0138 fprintf(stderr, "Error: Specified directory does not exist\n");
0139 Shutdown(NULL);
0140 }
0141 }
0142
0143
0144 ReadConfigFile(mapArgs, mapMultiArgs);
0145
0146 if (mapArgs.count("-?") || mapArgs.count("--help"))
0147 {
0148 string strUsage = string() +
0149 _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
0150 _("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" +
0151 " bitcoind [options] \t " + "\n" +
0152 " bitcoind [options] <command> [params]\t " + _("Send command to -server or bitcoind\n") +
0153 " bitcoind [options] help \t\t " + _("List commands\n") +
0154 " bitcoind [options] help <command> \t\t " + _("Get help for a command\n") +
0155 _("Options:\n") +
0156 " -conf=<file> \t\t " + _("Specify configuration file (default: bitcoin.conf)\n") +
0157 " -pid=<file> \t\t " + _("Specify pid file (default: bitcoind.pid)\n") +
0158 " -gen \t\t " + _("Generate coins\n") +
0159 " -gen=0 \t\t " + _("Don't generate coins\n") +
0160 " -min \t\t " + _("Start minimized\n") +
0161 " -datadir=<dir> \t\t " + _("Specify data directory\n") +
0162 " -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)\n") +
0163 " -proxy=<ip:port> \t " + _("Connect through socks4 proxy\n") +
0164 " -port=<port> \t\t " + _("Listen for connections on <port> (default: 8333)\n") +
0165 " -maxconnections=<n>\t " + _("Maintain at most <n> connections to peers (default: 125)\n") +
0166 " -myip=<ip> \t " + _("Set this node's external IP address.\n") +
0167 " -addnode=<ip> \t " + _("Add a node to connect to\n") +
0168 " -connect=<ip> \t\t " + _("Connect only to the specified node\n") +
0169 " -nolisten \t " + _("Don't accept connections from outside\n") +
0170 " -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)\n") +
0171 " -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)\n") +
0172 " -maxreceivebuffer=<n>\t " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)\n") +
0173 " -maxsendbuffer=<n>\t " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)\n") +
0174 " -paytxfee=<amt> \t " + _("Fee per kB to add to transactions you send\n") +
0175 " -daemon \t\t " + _("Run in the background as a daemon and accept commands\n") +
0176 " -debug \t\t " + _("Output extra debugging information\n") +
0177 " -caneat \t\t " + _("Permit the use of 'eatblock'\n") +
0178 " -verifyall \t\t " + _("Forbid the skipping of ECDSA signature verification between checkpoints.\n") +
0179 " -setverstring \t\t " + _("Set a custom version string.\n") +
0180 " -setvernum \t\t " + _("Set a custom version number.\n") +
0181 " -highs \t\t " + _("Set all transactions to have DER 'S' Value set to 'high'.\n") +
0182 " -lows \t\t " + _("Set all transactions to have DER 'S' Value set to 'low'.\n") +
0183 " -logtimestamps \t " + _("Prepend debug output with timestamp\n") +
0184 " -printtoconsole \t " + _("Send trace/debug info to console instead of debug.log file\n") +
0185 " -rpcuser=<user> \t " + _("Username for JSON-RPC connections\n") +
0186 " -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections\n") +
0187 " -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)\n") +
0188 " -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address\n") +
0189 " -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)\n") +
0190 " -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)\n") +
0191 " -rescan \t " + _("Rescan the block chain for missing wallet transactions\n");
0192
0193 strUsage += string() +
0194 " -? \t\t " + _("This help message\n");
0195
0196
0197 strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end());
0198 fprintf(stderr, "%s", strUsage.c_str());
0199 return false;
0200 }
0201
0202 fDebug = GetBoolArg("-debug");
0203 fDaemon = GetBoolArg("-daemon");
0204 fCanEat = GetBoolArg("-caneat");
0205 fVerifyAll = GetBoolArg("-verifyall");
0206 fHighS = GetBoolArg("-highs");
0207 fLowS = GetBoolArg("-lows");
0208
0209 if (fHighS && fLowS)
0210 {
0211 printf("Error: '-highs' and '-lows' can not be set at the same time.\n");
0212 return false;
0213 }
0214
0215 if (mapArgs.count("-setverstring"))
0216 {
0217 CLIENT_NAME = mapArgs["-setverstring"];
0218 }
0219
0220 if (mapArgs.count("-setvernum"))
0221 {
0222 VERSION = atoi(mapArgs["-setvernum"]);
0223 }
0224
0225 if (fDaemon)
0226 fServer = true;
0227 else
0228 fServer = GetBoolArg("-server");
0229
0230
0231 fServer = true;
0232 fPrintToConsole = GetBoolArg("-printtoconsole");
0233 fPrintToDebugger = GetBoolArg("-printtodebugger");
0234 fLogTimestamps = GetBoolArg("-logtimestamps");
0235
0236 for (int i = 1; i < argc; i++)
0237 if (!IsSwitchChar(argv[i][0]))
0238 fCommandLine = true;
0239
0240 if (fCommandLine)
0241 {
0242 int ret = CommandLineRPC(argc, argv);
0243 exit(ret);
0244 }
0245
0246 if (fDaemon)
0247 {
0248
0249 pid_t pid = fork();
0250 if (pid < 0)
0251 {
0252 fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
0253 return false;
0254 }
0255 if (pid > 0)
0256 {
0257 CreatePidFile(GetPidFile(), pid);
0258 return true;
0259 }
0260
0261 pid_t sid = setsid();
0262 if (sid < 0)
0263 fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
0264 }
0265
0266 if (!fDebug && !pszSetDataDir[0])
0267 ShrinkDebugFile();
0268 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
0269 printf("Bitcoin version %s\n", FormatFullVersion().c_str());
0270 printf("Default data directory %s\n", GetDefaultDataDir().c_str());
0271
0272 if (GetBoolArg("-loadblockindextest"))
0273 {
0274 CTxDB txdb("r");
0275 txdb.LoadBlockIndex();
0276 PrintBlockTree();
0277 return false;
0278 }
0279
0280
0281 string strLockFile = GetDataDir() + "/.lock";
0282 FILE* file = fopen(strLockFile.c_str(), "a");
0283 if (file) fclose(file);
0284 static boost::interprocess::file_lock lock(strLockFile.c_str());
0285 if (!lock.try_lock())
0286 {
0287 wxMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), "Bitcoin");
0288 return false;
0289 }
0290
0291 string strErrors;
0292
0293
0294
0295
0296 if (fDaemon)
0297 fprintf(stdout, "bitcoin server starting\n");
0298 strErrors = "";
0299 int64 nStart;
0300
0301 InitMessage(_("Loading addresses..."));
0302 printf("Loading addresses...\n");
0303 nStart = GetTimeMillis();
0304 if (!LoadAddresses())
0305 strErrors += _("Error loading addr.dat \n");
0306 printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
0307
0308 InitMessage(_("Loading block index..."));
0309 printf("Loading block index...\n");
0310 nStart = GetTimeMillis();
0311 if (!LoadBlockIndex())
0312 strErrors += _("Error loading blkindex.dat \n");
0313 printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
0314
0315 InitMessage(_("Loading wallet..."));
0316 printf("Loading wallet...\n");
0317 nStart = GetTimeMillis();
0318 bool fFirstRun;
0319 pwalletMain = new CWallet("wallet.dat");
0320 int nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun);
0321 if (nLoadWalletRet != DB_LOAD_OK)
0322 {
0323 if (nLoadWalletRet == DB_CORRUPT)
0324 strErrors += _("Error loading wallet.dat: Wallet corrupted \n");
0325 else if (nLoadWalletRet == DB_TOO_NEW)
0326 strErrors += _("Error loading wallet.dat: Wallet requires newer version of Bitcoin \n");
0327 else if (nLoadWalletRet == DB_NEED_REWRITE)
0328 {
0329 strErrors += _("Wallet needed to be rewritten: restart Bitcoin to complete \n");
0330 wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
0331 return false;
0332 }
0333 else
0334 strErrors += _("Error loading wallet.dat \n");
0335 }
0336 printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
0337
0338 RegisterWallet(pwalletMain);
0339
0340 CBlockIndex *pindexRescan = pindexBest;
0341 if (GetBoolArg("-rescan"))
0342 pindexRescan = pindexGenesisBlock;
0343 else
0344 {
0345 CWalletDB walletdb("wallet.dat");
0346 CBlockLocator locator;
0347 if (walletdb.ReadBestBlock(locator))
0348 pindexRescan = locator.GetBlockIndex();
0349 }
0350 if (pindexBest != pindexRescan)
0351 {
0352 InitMessage(_("Rescanning..."));
0353 printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
0354 nStart = GetTimeMillis();
0355 pwalletMain->ScanForWalletTransactions(pindexRescan, true);
0356 printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
0357 }
0358
0359 InitMessage(_("Done loading"));
0360 printf("Done loading\n");
0361
0362
0363 printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
0364 printf("nBestHeight = %d\n", nBestHeight);
0365 printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
0366 printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
0367 printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());
0368
0369 if (!strErrors.empty())
0370 {
0371 wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
0372 return false;
0373 }
0374
0375
0376 pwalletMain->ReacceptWalletTransactions();
0377
0378
0379
0380
0381
0382
0383
0384
0385 if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree"))
0386 {
0387 PrintBlockTree();
0388 return false;
0389 }
0390
0391 if (mapArgs.count("-timeout"))
0392 {
0393 int nNewTimeout = GetArg("-timeout", 5000);
0394 if (nNewTimeout > 0 && nNewTimeout < 600000)
0395 nConnectTimeout = nNewTimeout;
0396 }
0397
0398 if (mapArgs.count("-printblock"))
0399 {
0400 string strMatch = mapArgs["-printblock"];
0401 int nFound = 0;
0402 for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
0403 {
0404 uint256 hash = (*mi).first;
0405 if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
0406 {
0407 CBlockIndex* pindex = (*mi).second;
0408 CBlock block;
0409 block.ReadFromDisk(pindex);
0410 block.BuildMerkleTree();
0411 block.print();
0412 printf("\n");
0413 nFound++;
0414 }
0415 }
0416 if (nFound == 0)
0417 printf("No blocks matching %s were found\n", strMatch.c_str());
0418 return false;
0419 }
0420
0421 fGenerateBitcoins = GetBoolArg("-gen");
0422
0423 if (mapArgs.count("-proxy"))
0424 {
0425 fUseProxy = true;
0426 addrProxy = CAddress(mapArgs["-proxy"]);
0427 if (!addrProxy.IsValid())
0428 {
0429 wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
0430 return false;
0431 }
0432 }
0433
0434 bool fTor = (fUseProxy && addrProxy.port == htons(9050));
0435 if (fTor)
0436 {
0437
0438
0439 SoftSetArg("-nolisten", true);
0440 }
0441
0442 fNoListen = GetBoolArg("-nolisten");
0443
0444
0445
0446 if (!fNoListen)
0447 {
0448 if (!BindListenPort(strErrors))
0449 {
0450 wxMessageBox(strErrors, "Bitcoin");
0451 return false;
0452 }
0453 }
0454
0455 if (mapArgs.count("-addnode"))
0456 {
0457 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
0458 {
0459 CAddress addr(strAddr);
0460 addr.nTime = 0;
0461 if (addr.IsValid())
0462 AddAddress(addr);
0463 }
0464 }
0465
0466 if (mapArgs.count("-paytxfee"))
0467 {
0468 if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
0469 {
0470 wxMessageBox(_("Invalid amount for -paytxfee=<amount>"), "Bitcoin");
0471 return false;
0472 }
0473 if (nTransactionFee > 0.25 * COIN)
0474 wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION);
0475 }
0476
0477
0478
0479
0480 if (!CheckDiskSpace())
0481 return false;
0482
0483 RandAddSeedPerfmon();
0484
0485 if (!CreateThread(StartNode, NULL))
0486 wxMessageBox(_("Error: CreateThread(StartNode) failed"), "Bitcoin");
0487
0488 if (fServer)
0489 CreateThread(ThreadRPCServer, NULL);
0490
0491 while (1)
0492 Sleep(5000);
0493
0494 return true;
0495 }