Projects : bitcoin : bitcoin_dumpblock_no_losers
1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | // Copyright (c) 2009-2012 The Bitcoin developers |
3 | // Distributed under the MIT/X11 software license, see the accompanying |
4 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. |
5 | #include "headers.h" |
6 | #include "db.h" |
7 | #include "bitcoinrpc.h" |
8 | #include "net.h" |
9 | #include "init.h" |
10 | #include "strlcpy.h" |
11 | #include <boost/filesystem.hpp> |
12 | #include <boost/filesystem/fstream.hpp> |
13 | #include <boost/interprocess/sync/file_lock.hpp> |
14 | |
15 | // v0.5.4 RELEASE (keccak) |
16 | |
17 | using namespace std; |
18 | using namespace boost; |
19 | |
20 | CWallet* pwalletMain; |
21 | |
22 | ////////////////////////////////////////////////////////////////////////////// |
23 | // |
24 | // Shutdown |
25 | // |
26 | |
27 | void ExitTimeout(void* parg) |
28 | { |
29 | } |
30 | |
31 | void Shutdown(void* parg) |
32 | { |
33 | static CCriticalSection cs_Shutdown; |
34 | static bool fTaken; |
35 | bool fFirstThread = false; |
36 | TRY_CRITICAL_BLOCK(cs_Shutdown) |
37 | { |
38 | fFirstThread = !fTaken; |
39 | fTaken = true; |
40 | } |
41 | static bool fExit; |
42 | if (fFirstThread) |
43 | { |
44 | fShutdown = true; |
45 | nTransactionsUpdated++; |
46 | DBFlush(false); |
47 | StopNode(); |
48 | DBFlush(true); |
49 | boost::filesystem::remove(GetPidFile()); |
50 | UnregisterWallet(pwalletMain); |
51 | delete pwalletMain; |
52 | CreateThread(ExitTimeout, NULL); |
53 | Sleep(50); |
54 | printf("Bitcoin exiting\n\n"); |
55 | fExit = true; |
56 | exit(0); |
57 | } |
58 | else |
59 | { |
60 | while (!fExit) |
61 | Sleep(500); |
62 | Sleep(100); |
63 | ExitThread(0); |
64 | } |
65 | } |
66 | |
67 | void HandleSIGTERM(int) |
68 | { |
69 | fRequestShutdown = true; |
70 | } |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | ////////////////////////////////////////////////////////////////////////////// |
78 | // |
79 | // Start |
80 | // |
81 | |
82 | int main(int argc, char* argv[]) |
83 | { |
84 | bool fRet = false; |
85 | fRet = AppInit(argc, argv); |
86 | |
87 | if (fRet && fDaemon) |
88 | return 0; |
89 | |
90 | return 1; |
91 | } |
92 | |
93 | |
94 | bool AppInit(int argc, char* argv[]) |
95 | { |
96 | bool fRet = false; |
97 | try |
98 | { |
99 | fRet = AppInit2(argc, argv); |
100 | } |
101 | catch (std::exception& e) { |
102 | PrintException(&e, "AppInit()"); |
103 | } catch (...) { |
104 | PrintException(NULL, "AppInit()"); |
105 | } |
106 | if (!fRet) |
107 | Shutdown(NULL); |
108 | return fRet; |
109 | } |
110 | |
111 | bool AppInit2(int argc, char* argv[]) |
112 | { |
113 | umask(077); |
114 | |
115 | // Clean shutdown on SIGTERM |
116 | struct sigaction sa; |
117 | sa.sa_handler = HandleSIGTERM; |
118 | sigemptyset(&sa.sa_mask); |
119 | sa.sa_flags = 0; |
120 | sigaction(SIGTERM, &sa, NULL); |
121 | sigaction(SIGINT, &sa, NULL); |
122 | sigaction(SIGHUP, &sa, NULL); |
123 | |
124 | // |
125 | // Parameters |
126 | // |
127 | ParseParameters(argc, argv); |
128 | |
129 | if (mapArgs.count("-datadir")) |
130 | { |
131 | if (filesystem::is_directory(filesystem::system_complete(mapArgs["-datadir"]))) |
132 | { |
133 | filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]); |
134 | strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir)); |
135 | } |
136 | else |
137 | { |
138 | fprintf(stderr, "Error: Specified directory does not exist\n"); |
139 | Shutdown(NULL); |
140 | } |
141 | } |
142 | |
143 | |
144 | ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir |
145 | |
146 | if (mapArgs.count("-?") || mapArgs.count("--help")) |
147 | { |
148 | string strUsage = string() + |
149 | _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" + |
150 | _("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" + |
151 | " bitcoind [options] \t " + "\n" + |
152 | " bitcoind [options] <command> [params]\t " + _("Send command to -server or bitcoind\n") + |
153 | " bitcoind [options] help \t\t " + _("List commands\n") + |
154 | " bitcoind [options] help <command> \t\t " + _("Get help for a command\n") + |
155 | _("Options:\n") + |
156 | " -conf=<file> \t\t " + _("Specify configuration file (default: bitcoin.conf)\n") + |
157 | " -pid=<file> \t\t " + _("Specify pid file (default: bitcoind.pid)\n") + |
158 | " -gen \t\t " + _("Generate coins\n") + |
159 | " -gen=0 \t\t " + _("Don't generate coins\n") + |
160 | " -min \t\t " + _("Start minimized\n") + |
161 | " -datadir=<dir> \t\t " + _("Specify data directory\n") + |
162 | " -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)\n") + |
163 | " -proxy=<ip:port> \t " + _("Connect through socks4 proxy\n") + |
164 | " -port=<port> \t\t " + _("Listen for connections on <port> (default: 8333)\n") + |
165 | " -maxconnections=<n>\t " + _("Maintain at most <n> connections to peers (default: 125)\n") + |
166 | " -myip=<ip> \t " + _("Set this node's external IP address.\n") + |
167 | " -addnode=<ip> \t " + _("Add a node to connect to\n") + |
168 | " -connect=<ip> \t\t " + _("Connect only to the specified node\n") + |
169 | " -nolisten \t " + _("Don't accept connections from outside\n") + |
170 | " -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)\n") + |
171 | " -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)\n") + |
172 | " -maxreceivebuffer=<n>\t " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)\n") + |
173 | " -maxsendbuffer=<n>\t " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)\n") + |
174 | " -paytxfee=<amt> \t " + _("Fee per kB to add to transactions you send\n") + |
175 | " -daemon \t\t " + _("Run in the background as a daemon and accept commands\n") + |
176 | " -debug \t\t " + _("Output extra debugging information\n") + |
177 | " -caneat \t\t " + _("Permit the use of 'eatblock'\n") + |
178 | " -verifyall \t\t " + _("Forbid the skipping of ECDSA signature verification between checkpoints.\n") + |
179 | " -setverstring \t\t " + _("Set a custom version string.\n") + |
180 | " -setvernum \t\t " + _("Set a custom version number.\n") + |
181 | " -highs \t\t " + _("Set all transactions to have DER 'S' Value set to 'high'.\n") + |
182 | " -lows \t\t " + _("Set all transactions to have DER 'S' Value set to 'low'.\n") + |
183 | " -logtimestamps \t " + _("Prepend debug output with timestamp\n") + |
184 | " -printtoconsole \t " + _("Send trace/debug info to console instead of debug.log file\n") + |
185 | " -rpcuser=<user> \t " + _("Username for JSON-RPC connections\n") + |
186 | " -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections\n") + |
187 | " -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)\n") + |
188 | " -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address\n") + |
189 | " -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)\n") + |
190 | " -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)\n") + |
191 | " -rescan \t " + _("Rescan the block chain for missing wallet transactions\n"); |
192 | |
193 | strUsage += string() + |
194 | " -? \t\t " + _("This help message\n"); |
195 | |
196 | // Remove tabs |
197 | strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end()); |
198 | fprintf(stderr, "%s", strUsage.c_str()); |
199 | return false; |
200 | } |
201 | |
202 | fDebug = GetBoolArg("-debug"); |
203 | fDaemon = GetBoolArg("-daemon"); |
204 | fCanEat = GetBoolArg("-caneat"); |
205 | fVerifyAll = GetBoolArg("-verifyall"); |
206 | fHighS = GetBoolArg("-highs"); |
207 | fLowS = GetBoolArg("-lows"); |
208 | |
209 | if (fHighS && fLowS) |
210 | { |
211 | printf("Error: '-highs' and '-lows' can not be set at the same time.\n"); |
212 | return false; |
213 | } |
214 | |
215 | if (mapArgs.count("-setverstring")) |
216 | { |
217 | CLIENT_NAME = mapArgs["-setverstring"]; |
218 | } |
219 | |
220 | if (mapArgs.count("-setvernum")) |
221 | { |
222 | VERSION = atoi(mapArgs["-setvernum"]); |
223 | } |
224 | |
225 | if (fDaemon) |
226 | fServer = true; |
227 | else |
228 | fServer = GetBoolArg("-server"); |
229 | |
230 | /* force fServer when running without GUI */ |
231 | fServer = true; |
232 | fPrintToConsole = GetBoolArg("-printtoconsole"); |
233 | fPrintToDebugger = GetBoolArg("-printtodebugger"); |
234 | fLogTimestamps = GetBoolArg("-logtimestamps"); |
235 | |
236 | for (int i = 1; i < argc; i++) |
237 | if (!IsSwitchChar(argv[i][0])) |
238 | fCommandLine = true; |
239 | |
240 | if (fCommandLine) |
241 | { |
242 | int ret = CommandLineRPC(argc, argv); |
243 | exit(ret); |
244 | } |
245 | |
246 | if (fDaemon) |
247 | { |
248 | // Daemonize |
249 | pid_t pid = fork(); |
250 | if (pid < 0) |
251 | { |
252 | fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno); |
253 | return false; |
254 | } |
255 | if (pid > 0) |
256 | { |
257 | CreatePidFile(GetPidFile(), pid); |
258 | return true; |
259 | } |
260 | |
261 | pid_t sid = setsid(); |
262 | if (sid < 0) |
263 | fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); |
264 | } |
265 | |
266 | if (!fDebug && !pszSetDataDir[0]) |
267 | ShrinkDebugFile(); |
268 | printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); |
269 | printf("Bitcoin version %s\n", FormatFullVersion().c_str()); |
270 | printf("Default data directory %s\n", GetDefaultDataDir().c_str()); |
271 | |
272 | if (GetBoolArg("-loadblockindextest")) |
273 | { |
274 | CTxDB txdb("r"); |
275 | txdb.LoadBlockIndex(); |
276 | PrintBlockTree(); |
277 | return false; |
278 | } |
279 | |
280 | // Make sure only a single bitcoin process is using the data directory. |
281 | string strLockFile = GetDataDir() + "/.lock"; |
282 | FILE* file = fopen(strLockFile.c_str(), "a"); // empty lock file; created if it doesn't exist. |
283 | if (file) fclose(file); |
284 | static boost::interprocess::file_lock lock(strLockFile.c_str()); |
285 | if (!lock.try_lock()) |
286 | { |
287 | wxMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), "Bitcoin"); |
288 | return false; |
289 | } |
290 | |
291 | string strErrors; |
292 | |
293 | // |
294 | // Load data files |
295 | // |
296 | if (fDaemon) |
297 | fprintf(stdout, "bitcoin server starting\n"); |
298 | strErrors = ""; |
299 | int64 nStart; |
300 | |
301 | InitMessage(_("Loading addresses...")); |
302 | printf("Loading addresses...\n"); |
303 | nStart = GetTimeMillis(); |
304 | if (!LoadAddresses()) |
305 | strErrors += _("Error loading addr.dat \n"); |
306 | printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
307 | |
308 | InitMessage(_("Loading block index...")); |
309 | printf("Loading block index...\n"); |
310 | nStart = GetTimeMillis(); |
311 | if (!LoadBlockIndex()) |
312 | strErrors += _("Error loading blkindex.dat \n"); |
313 | printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
314 | |
315 | InitMessage(_("Loading wallet...")); |
316 | printf("Loading wallet...\n"); |
317 | nStart = GetTimeMillis(); |
318 | bool fFirstRun; |
319 | pwalletMain = new CWallet("wallet.dat"); |
320 | int nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun); |
321 | if (nLoadWalletRet != DB_LOAD_OK) |
322 | { |
323 | if (nLoadWalletRet == DB_CORRUPT) |
324 | strErrors += _("Error loading wallet.dat: Wallet corrupted \n"); |
325 | else if (nLoadWalletRet == DB_TOO_NEW) |
326 | strErrors += _("Error loading wallet.dat: Wallet requires newer version of Bitcoin \n"); |
327 | else if (nLoadWalletRet == DB_NEED_REWRITE) |
328 | { |
329 | strErrors += _("Wallet needed to be rewritten: restart Bitcoin to complete \n"); |
330 | wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR); |
331 | return false; |
332 | } |
333 | else |
334 | strErrors += _("Error loading wallet.dat \n"); |
335 | } |
336 | printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
337 | |
338 | RegisterWallet(pwalletMain); |
339 | |
340 | CBlockIndex *pindexRescan = pindexBest; |
341 | if (GetBoolArg("-rescan")) |
342 | pindexRescan = pindexGenesisBlock; |
343 | else |
344 | { |
345 | CWalletDB walletdb("wallet.dat"); |
346 | CBlockLocator locator; |
347 | if (walletdb.ReadBestBlock(locator)) |
348 | pindexRescan = locator.GetBlockIndex(); |
349 | } |
350 | if (pindexBest != pindexRescan) |
351 | { |
352 | InitMessage(_("Rescanning...")); |
353 | printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight); |
354 | nStart = GetTimeMillis(); |
355 | pwalletMain->ScanForWalletTransactions(pindexRescan, true); |
356 | printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
357 | } |
358 | |
359 | InitMessage(_("Done loading")); |
360 | printf("Done loading\n"); |
361 | |
362 | //// debug print |
363 | printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size()); |
364 | printf("nBestHeight = %d\n", nBestHeight); |
365 | printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size()); |
366 | printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size()); |
367 | printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size()); |
368 | |
369 | if (!strErrors.empty()) |
370 | { |
371 | wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR); |
372 | return false; |
373 | } |
374 | |
375 | // Add wallet transactions that aren't already in a block to mapTransactions |
376 | pwalletMain->ReacceptWalletTransactions(); |
377 | |
378 | // Note: Bitcoin-QT stores several settings in the wallet, so we want |
379 | // to load the wallet BEFORE parsing command-line arguments, so |
380 | // the command-line/bitcoin.conf settings override GUI setting. |
381 | |
382 | // |
383 | // Parameters |
384 | // |
385 | if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree")) |
386 | { |
387 | PrintBlockTree(); |
388 | return false; |
389 | } |
390 | |
391 | if (mapArgs.count("-timeout")) |
392 | { |
393 | int nNewTimeout = GetArg("-timeout", 5000); |
394 | if (nNewTimeout > 0 && nNewTimeout < 600000) |
395 | nConnectTimeout = nNewTimeout; |
396 | } |
397 | |
398 | if (mapArgs.count("-printblock")) |
399 | { |
400 | string strMatch = mapArgs["-printblock"]; |
401 | int nFound = 0; |
402 | for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) |
403 | { |
404 | uint256 hash = (*mi).first; |
405 | if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0) |
406 | { |
407 | CBlockIndex* pindex = (*mi).second; |
408 | CBlock block; |
409 | block.ReadFromDisk(pindex); |
410 | block.BuildMerkleTree(); |
411 | block.print(); |
412 | printf("\n"); |
413 | nFound++; |
414 | } |
415 | } |
416 | if (nFound == 0) |
417 | printf("No blocks matching %s were found\n", strMatch.c_str()); |
418 | return false; |
419 | } |
420 | |
421 | fGenerateBitcoins = GetBoolArg("-gen"); |
422 | |
423 | if (mapArgs.count("-proxy")) |
424 | { |
425 | fUseProxy = true; |
426 | addrProxy = CAddress(mapArgs["-proxy"]); |
427 | if (!addrProxy.IsValid()) |
428 | { |
429 | wxMessageBox(_("Invalid -proxy address"), "Bitcoin"); |
430 | return false; |
431 | } |
432 | } |
433 | |
434 | bool fTor = (fUseProxy && addrProxy.port == htons(9050)); |
435 | if (fTor) |
436 | { |
437 | // Use SoftSetArg here so user can override any of these if they wish. |
438 | // Note: the GetBoolArg() calls for all of these must happen later. |
439 | SoftSetArg("-nolisten", true); |
440 | } |
441 | |
442 | fNoListen = GetBoolArg("-nolisten"); |
443 | |
444 | // Command-line args override in-wallet settings: |
445 | |
446 | if (!fNoListen) |
447 | { |
448 | if (!BindListenPort(strErrors)) |
449 | { |
450 | wxMessageBox(strErrors, "Bitcoin"); |
451 | return false; |
452 | } |
453 | } |
454 | |
455 | if (mapArgs.count("-addnode")) |
456 | { |
457 | BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"]) |
458 | { |
459 | CAddress addr(strAddr); |
460 | addr.nTime = 0; // so it won't relay unless successfully connected |
461 | if (addr.IsValid()) |
462 | AddAddress(addr); |
463 | } |
464 | } |
465 | |
466 | if (mapArgs.count("-paytxfee")) |
467 | { |
468 | if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee)) |
469 | { |
470 | wxMessageBox(_("Invalid amount for -paytxfee=<amount>"), "Bitcoin"); |
471 | return false; |
472 | } |
473 | if (nTransactionFee > 0.25 * COIN) |
474 | wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION); |
475 | } |
476 | |
477 | // |
478 | // Start the node |
479 | // |
480 | if (!CheckDiskSpace()) |
481 | return false; |
482 | |
483 | RandAddSeedPerfmon(); |
484 | |
485 | if (!CreateThread(StartNode, NULL)) |
486 | wxMessageBox(_("Error: CreateThread(StartNode) failed"), "Bitcoin"); |
487 | |
488 | if (fServer) |
489 | CreateThread(ThreadRPCServer, NULL); |
490 | |
491 | while (1) |
492 | Sleep(5000); |
493 | |
494 | return true; |
495 | } |