]>
Commit | Line | Data |
---|---|---|
69d605f4 | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
88216419 | 2 | // Copyright (c) 2009-2012 The Bitcoin developers |
69d605f4 WL |
3 | // Distributed under the MIT/X11 software license, see the accompanying |
4 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. | |
0eeb4f5d | 5 | #include "db.h" |
9eace6b1 | 6 | #include "walletdb.h" |
8fe2308b | 7 | #include "bitcoinrpc.h" |
0eeb4f5d WL |
8 | #include "net.h" |
9 | #include "init.h" | |
ed6d0b5f PW |
10 | #include "util.h" |
11 | #include "ui_interface.h" | |
e8ef3da7 | 12 | #include <boost/filesystem.hpp> |
0eeb4f5d | 13 | #include <boost/filesystem/fstream.hpp> |
f18a119a | 14 | #include <boost/filesystem/convenience.hpp> |
0eeb4f5d | 15 | #include <boost/interprocess/sync/file_lock.hpp> |
69d605f4 | 16 | |
ed6d0b5f PW |
17 | #ifndef WIN32 |
18 | #include <signal.h> | |
52d3a481 | 19 | #endif |
5f2e76b8 | 20 | |
69d605f4 WL |
21 | using namespace std; |
22 | using namespace boost; | |
23 | ||
e8ef3da7 WL |
24 | CWallet* pwalletMain; |
25 | ||
69d605f4 WL |
26 | ////////////////////////////////////////////////////////////////////////////// |
27 | // | |
28 | // Shutdown | |
29 | // | |
30 | ||
31 | void ExitTimeout(void* parg) | |
32 | { | |
6853e627 | 33 | #ifdef WIN32 |
69d605f4 WL |
34 | Sleep(5000); |
35 | ExitProcess(0); | |
36 | #endif | |
37 | } | |
38 | ||
39 | void Shutdown(void* parg) | |
40 | { | |
41 | static CCriticalSection cs_Shutdown; | |
42 | static bool fTaken; | |
d764d916 | 43 | bool fFirstThread = false; |
69d605f4 | 44 | { |
f8dcd5ca PW |
45 | TRY_LOCK(cs_Shutdown, lockShutdown); |
46 | if (lockShutdown) | |
47 | { | |
48 | fFirstThread = !fTaken; | |
49 | fTaken = true; | |
50 | } | |
69d605f4 WL |
51 | } |
52 | static bool fExit; | |
53 | if (fFirstThread) | |
54 | { | |
55 | fShutdown = true; | |
56 | nTransactionsUpdated++; | |
1c15f886 | 57 | DBFlush(false); |
69d605f4 | 58 | StopNode(); |
1c15f886 | 59 | DBFlush(true); |
69d605f4 | 60 | boost::filesystem::remove(GetPidFile()); |
e8ef3da7 WL |
61 | UnregisterWallet(pwalletMain); |
62 | delete pwalletMain; | |
69d605f4 WL |
63 | CreateThread(ExitTimeout, NULL); |
64 | Sleep(50); | |
65 | printf("Bitcoin exiting\n\n"); | |
66 | fExit = true; | |
67 | exit(0); | |
68 | } | |
69 | else | |
70 | { | |
71 | while (!fExit) | |
72 | Sleep(500); | |
73 | Sleep(100); | |
74 | ExitThread(0); | |
75 | } | |
76 | } | |
77 | ||
78 | void HandleSIGTERM(int) | |
79 | { | |
80 | fRequestShutdown = true; | |
81 | } | |
82 | ||
83 | ||
84 | ||
85 | ||
86 | ||
87 | ||
88 | ////////////////////////////////////////////////////////////////////////////// | |
89 | // | |
90 | // Start | |
91 | // | |
565c4771 | 92 | #if !defined(QT_GUI) |
69d605f4 WL |
93 | int main(int argc, char* argv[]) |
94 | { | |
95 | bool fRet = false; | |
96 | fRet = AppInit(argc, argv); | |
97 | ||
98 | if (fRet && fDaemon) | |
99 | return 0; | |
100 | ||
101 | return 1; | |
102 | } | |
69d605f4 WL |
103 | |
104 | bool AppInit(int argc, char* argv[]) | |
105 | { | |
106 | bool fRet = false; | |
107 | try | |
108 | { | |
9f5b11e6 WL |
109 | // |
110 | // Parameters | |
111 | // | |
112 | // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main() | |
113 | ParseParameters(argc, argv); | |
114 | if (!boost::filesystem::is_directory(GetDataDir(false))) | |
115 | { | |
116 | fprintf(stderr, "Error: Specified directory does not exist\n"); | |
117 | Shutdown(NULL); | |
118 | } | |
119 | ReadConfigFile(mapArgs, mapMultiArgs); | |
120 | ||
121 | if (mapArgs.count("-?") || mapArgs.count("--help")) | |
122 | { | |
123 | // First part of help message is specific to bitcoind / RPC client | |
124 | std::string strUsage = _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" + | |
125 | _("Usage:") + "\n" + | |
126 | " bitcoind [options] " + "\n" + | |
127 | " bitcoind [options] <command> [params] " + _("Send command to -server or bitcoind") + "\n" + | |
128 | " bitcoind [options] help " + _("List commands") + "\n" + | |
129 | " bitcoind [options] help <command> " + _("Get help for a command") + "\n"; | |
130 | ||
131 | strUsage += "\n" + HelpMessage(); | |
132 | ||
133 | fprintf(stderr, "%s", strUsage.c_str()); | |
134 | return false; | |
135 | } | |
136 | ||
137 | // Command-line RPC | |
138 | for (int i = 1; i < argc; i++) | |
139 | if (!IsSwitchChar(argv[i][0]) && !(strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)) | |
140 | fCommandLine = true; | |
141 | ||
142 | if (fCommandLine) | |
143 | { | |
144 | int ret = CommandLineRPC(argc, argv); | |
145 | exit(ret); | |
146 | } | |
147 | ||
148 | fRet = AppInit2(); | |
69d605f4 WL |
149 | } |
150 | catch (std::exception& e) { | |
151 | PrintException(&e, "AppInit()"); | |
152 | } catch (...) { | |
153 | PrintException(NULL, "AppInit()"); | |
154 | } | |
155 | if (!fRet) | |
156 | Shutdown(NULL); | |
157 | return fRet; | |
158 | } | |
9f5b11e6 | 159 | #endif |
69d605f4 | 160 | |
ac7c7ab9 PW |
161 | bool static InitError(const std::string &str) |
162 | { | |
163 | ThreadSafeMessageBox(str, _("Bitcoin"), wxOK | wxMODAL); | |
164 | return false; | |
165 | ||
166 | } | |
167 | ||
168 | bool static InitWarning(const std::string &str) | |
169 | { | |
170 | ThreadSafeMessageBox(str, _("Bitcoin"), wxOK | wxICON_EXCLAMATION | wxMODAL); | |
171 | return true; | |
172 | } | |
173 | ||
174 | ||
8f10a288 PW |
175 | bool static Bind(const CService &addr) { |
176 | if (IsLimited(addr)) | |
177 | return false; | |
178 | std::string strError; | |
179 | if (!BindListenPort(addr, strError)) | |
ac7c7ab9 | 180 | return InitError(strError); |
8f10a288 PW |
181 | return true; |
182 | } | |
183 | ||
9f5b11e6 WL |
184 | // Core-specific options shared between UI and daemon |
185 | std::string HelpMessage() | |
186 | { | |
187 | string strUsage = _("Options:") + "\n" + | |
188 | " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n" + | |
189 | " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n" + | |
190 | " -gen " + _("Generate coins") + "\n" + | |
191 | " -gen=0 " + _("Don't generate coins") + "\n" + | |
192 | " -datadir=<dir> " + _("Specify data directory") + "\n" + | |
193 | " -dbcache=<n> " + _("Set database cache size in megabytes (default: 25)") + "\n" + | |
194 | " -dblogsize=<n> " + _("Set database disk log size in megabytes (default: 100)") + "\n" + | |
195 | " -timeout=<n> " + _("Specify connection timeout (in milliseconds)") + "\n" + | |
196 | " -proxy=<ip:port> " + _("Connect through socks proxy") + "\n" + | |
197 | " -socks=<n> " + _("Select the version of socks proxy to use (4 or 5, 5 is default)") + "\n" + | |
198 | " -noproxy=<net> " + _("Do not use proxy for connections to network <net> (IPv4 or IPv6)") + "\n" + | |
199 | " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" + | |
200 | " -proxydns " + _("Pass DNS requests to (SOCKS5) proxy") + "\n" + | |
201 | " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" + | |
202 | " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" + | |
203 | " -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n" + | |
204 | " -connect=<ip> " + _("Connect only to the specified node") + "\n" + | |
205 | " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" + | |
206 | " -externalip=<ip> " + _("Specify your own public address") + "\n" + | |
0f1707de | 207 | " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4 or IPv6)") + "\n" + |
9f5b11e6 WL |
208 | " -discover " + _("Try to discover public IP address (default: 1)") + "\n" + |
209 | " -irc " + _("Find peers using internet relay chat (default: 0)") + "\n" + | |
210 | " -listen " + _("Accept connections from outside (default: 1)") + "\n" + | |
211 | " -bind=<addr> " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" + | |
212 | " -dnsseed " + _("Find peers using DNS lookup (default: 1)") + "\n" + | |
213 | " -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" + | |
214 | " -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" + | |
215 | " -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)") + "\n" + | |
216 | " -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)") + "\n" + | |
217 | #ifdef USE_UPNP | |
218 | #if USE_UPNP | |
219 | " -upnp " + _("Use Universal Plug and Play to map the listening port (default: 1)") + "\n" + | |
220 | #else | |
221 | " -upnp " + _("Use Universal Plug and Play to map the listening port (default: 0)") + "\n" + | |
222 | #endif | |
223 | #endif | |
224 | " -detachdb " + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" + | |
225 | " -paytxfee=<amt> " + _("Fee per KB to add to transactions you send") + "\n" + | |
226 | #ifdef QT_GUI | |
227 | " -server " + _("Accept command line and JSON-RPC commands") + "\n" + | |
228 | #endif | |
229 | #if !defined(WIN32) && !defined(QT_GUI) | |
230 | " -daemon " + _("Run in the background as a daemon and accept commands") + "\n" + | |
231 | #endif | |
232 | " -testnet " + _("Use the test network") + "\n" + | |
233 | " -debug " + _("Output extra debugging information") + "\n" + | |
234 | " -logtimestamps " + _("Prepend debug output with timestamp") + "\n" + | |
235 | " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n" + | |
236 | #ifdef WIN32 | |
237 | " -printtodebugger " + _("Send trace/debug info to debugger") + "\n" + | |
238 | #endif | |
239 | " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n" + | |
240 | " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n" + | |
241 | " -rpcport=<port> " + _("Listen for JSON-RPC connections on <port> (default: 8332)") + "\n" + | |
242 | " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified IP address") + "\n" + | |
243 | " -rpcconnect=<ip> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" + | |
244 | " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" + | |
245 | " -upgradewallet " + _("Upgrade wallet to latest format") + "\n" + | |
246 | " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n" + | |
247 | " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n" + | |
248 | " -checkblocks=<n> " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" + | |
249 | " -checklevel=<n> " + _("How thorough the block verification is (0-6, default: 1)") + "\n" + | |
250 | " -loadblock=<file> " + _("Imports blocks from external blk000?.dat file") + "\n" + | |
251 | " -? " + _("This help message") + "\n"; | |
252 | ||
253 | strUsage += string() + | |
254 | _("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" + | |
255 | " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" + | |
256 | " -rpcsslcertificatechainfile=<file.cert> " + _("Server certificate file (default: server.cert)") + "\n" + | |
257 | " -rpcsslprivatekeyfile=<file.pem> " + _("Server private key (default: server.pem)") + "\n" + | |
258 | " -rpcsslciphers=<ciphers> " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n"; | |
259 | ||
260 | return strUsage; | |
261 | } | |
262 | ||
263 | /** Initialize bitcoin. | |
264 | * @pre Parameters should be parsed and config file should be read. | |
265 | */ | |
266 | bool AppInit2() | |
69d605f4 WL |
267 | { |
268 | #ifdef _MSC_VER | |
269 | // Turn off microsoft heap dump noise | |
270 | _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); | |
271 | _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0)); | |
272 | #endif | |
273 | #if _MSC_VER >= 1400 | |
274 | // Disable confusing "helpful" text message on abort, ctrl-c | |
275 | _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); | |
276 | #endif | |
6853e627 | 277 | #ifndef WIN32 |
69d605f4 WL |
278 | umask(077); |
279 | #endif | |
6853e627 | 280 | #ifndef WIN32 |
69d605f4 WL |
281 | // Clean shutdown on SIGTERM |
282 | struct sigaction sa; | |
283 | sa.sa_handler = HandleSIGTERM; | |
284 | sigemptyset(&sa.sa_mask); | |
285 | sa.sa_flags = 0; | |
286 | sigaction(SIGTERM, &sa, NULL); | |
287 | sigaction(SIGINT, &sa, NULL); | |
288 | sigaction(SIGHUP, &sa, NULL); | |
289 | #endif | |
290 | ||
8677f9c7 | 291 | fTestNet = GetBoolArg("-testnet"); |
92d5864b PW |
292 | if (fTestNet) |
293 | { | |
294 | SoftSetBoolArg("-irc", true); | |
295 | } | |
296 | ||
69d605f4 | 297 | fDebug = GetBoolArg("-debug"); |
83743ed6 | 298 | fDetachDB = GetBoolArg("-detachdb", false); |
69d605f4 | 299 | |
a3f3e54e | 300 | #if !defined(WIN32) && !defined(QT_GUI) |
69d605f4 WL |
301 | fDaemon = GetBoolArg("-daemon"); |
302 | #else | |
303 | fDaemon = false; | |
304 | #endif | |
305 | ||
306 | if (fDaemon) | |
307 | fServer = true; | |
308 | else | |
309 | fServer = GetBoolArg("-server"); | |
310 | ||
311 | /* force fServer when running without GUI */ | |
565c4771 | 312 | #if !defined(QT_GUI) |
69d605f4 | 313 | fServer = true; |
858ff187 | 314 | #endif |
69d605f4 WL |
315 | fPrintToConsole = GetBoolArg("-printtoconsole"); |
316 | fPrintToDebugger = GetBoolArg("-printtodebugger"); | |
69d605f4 WL |
317 | fLogTimestamps = GetBoolArg("-logtimestamps"); |
318 | ||
a3f3e54e | 319 | #if !defined(WIN32) && !defined(QT_GUI) |
69d605f4 WL |
320 | if (fDaemon) |
321 | { | |
322 | // Daemonize | |
323 | pid_t pid = fork(); | |
324 | if (pid < 0) | |
325 | { | |
326 | fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno); | |
327 | return false; | |
328 | } | |
329 | if (pid > 0) | |
330 | { | |
331 | CreatePidFile(GetPidFile(), pid); | |
332 | return true; | |
333 | } | |
334 | ||
335 | pid_t sid = setsid(); | |
336 | if (sid < 0) | |
337 | fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); | |
338 | } | |
339 | #endif | |
340 | ||
ee12c3d6 | 341 | if (!fDebug) |
69d605f4 WL |
342 | ShrinkDebugFile(); |
343 | printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); | |
a20c0d0f | 344 | printf("Bitcoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str()); |
ee12c3d6 | 345 | printf("Default data directory %s\n", GetDefaultDataDir().string().c_str()); |
69d605f4 WL |
346 | |
347 | if (GetBoolArg("-loadblockindextest")) | |
348 | { | |
349 | CTxDB txdb("r"); | |
350 | txdb.LoadBlockIndex(); | |
351 | PrintBlockTree(); | |
352 | return false; | |
353 | } | |
354 | ||
69d605f4 | 355 | // Make sure only a single bitcoin process is using the data directory. |
ee12c3d6 PW |
356 | boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; |
357 | FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. | |
69d605f4 | 358 | if (file) fclose(file); |
ee12c3d6 | 359 | static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); |
69d605f4 | 360 | if (!lock.try_lock()) |
ac7c7ab9 | 361 | return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().string().c_str())); |
69d605f4 | 362 | |
6e39e7c9 | 363 | std::ostringstream strErrors; |
69d605f4 WL |
364 | // |
365 | // Load data files | |
366 | // | |
367 | if (fDaemon) | |
368 | fprintf(stdout, "bitcoin server starting\n"); | |
bde280b9 | 369 | int64 nStart; |
69d605f4 | 370 | |
3f0816e3 | 371 | InitMessage(_("Loading addresses...")); |
69d605f4 WL |
372 | printf("Loading addresses...\n"); |
373 | nStart = GetTimeMillis(); | |
374 | if (!LoadAddresses()) | |
6e39e7c9 | 375 | strErrors << _("Error loading addr.dat") << "\n"; |
69d605f4 WL |
376 | printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
377 | ||
3f0816e3 | 378 | InitMessage(_("Loading block index...")); |
69d605f4 WL |
379 | printf("Loading block index...\n"); |
380 | nStart = GetTimeMillis(); | |
381 | if (!LoadBlockIndex()) | |
6e39e7c9 | 382 | strErrors << _("Error loading blkindex.dat") << "\n"; |
871c3557 B |
383 | |
384 | // as LoadBlockIndex can take several minutes, it's possible the user | |
385 | // requested to kill bitcoin-qt during the last operation. If so, exit. | |
386 | // As the program has not fully started yet, Shutdown() is possibly overkill. | |
387 | if (fRequestShutdown) | |
388 | { | |
389 | printf("Shutdown requested. Exiting.\n"); | |
390 | return false; | |
391 | } | |
69d605f4 WL |
392 | printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
393 | ||
1d740055 PW |
394 | if (mapArgs.count("-loadblock")) |
395 | { | |
396 | BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"]) | |
397 | { | |
398 | FILE *file = fopen(strFile.c_str(), "rb"); | |
399 | if (file) | |
400 | LoadExternalBlockFile(file); | |
401 | } | |
402 | } | |
403 | ||
3f0816e3 | 404 | InitMessage(_("Loading wallet...")); |
69d605f4 WL |
405 | printf("Loading wallet...\n"); |
406 | nStart = GetTimeMillis(); | |
407 | bool fFirstRun; | |
e8ef3da7 | 408 | pwalletMain = new CWallet("wallet.dat"); |
7ec55267 MC |
409 | int nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun); |
410 | if (nLoadWalletRet != DB_LOAD_OK) | |
411 | { | |
412 | if (nLoadWalletRet == DB_CORRUPT) | |
6e39e7c9 | 413 | strErrors << _("Error loading wallet.dat: Wallet corrupted") << "\n"; |
7ec55267 | 414 | else if (nLoadWalletRet == DB_TOO_NEW) |
6e39e7c9 | 415 | strErrors << _("Error loading wallet.dat: Wallet requires newer version of Bitcoin") << "\n"; |
d764d916 GA |
416 | else if (nLoadWalletRet == DB_NEED_REWRITE) |
417 | { | |
6e39e7c9 | 418 | strErrors << _("Wallet needed to be rewritten: restart Bitcoin to complete") << "\n"; |
21e875c9 | 419 | printf("%s", strErrors.str().c_str()); |
ac7c7ab9 | 420 | return InitError(strErrors.str()); |
d764d916 | 421 | } |
7ec55267 | 422 | else |
6e39e7c9 | 423 | strErrors << _("Error loading wallet.dat") << "\n"; |
7ec55267 | 424 | } |
439e1497 PW |
425 | |
426 | if (GetBoolArg("-upgradewallet", fFirstRun)) | |
427 | { | |
428 | int nMaxVersion = GetArg("-upgradewallet", 0); | |
429 | if (nMaxVersion == 0) // the -walletupgrade without argument case | |
430 | { | |
431 | printf("Performing wallet upgrade to %i\n", FEATURE_LATEST); | |
432 | nMaxVersion = CLIENT_VERSION; | |
433 | pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately | |
434 | } | |
435 | else | |
436 | printf("Allowing wallet upgrade up to %i\n", nMaxVersion); | |
437 | if (nMaxVersion < pwalletMain->GetVersion()) | |
438 | strErrors << _("Cannot downgrade wallet") << "\n"; | |
439 | pwalletMain->SetMaxVersion(nMaxVersion); | |
440 | } | |
441 | ||
442 | if (fFirstRun) | |
443 | { | |
444 | // Create new keyUser and set as default key | |
445 | RandAddSeedPerfmon(); | |
446 | ||
447 | std::vector<unsigned char> newDefaultKey; | |
448 | if (!pwalletMain->GetKeyFromPool(newDefaultKey, false)) | |
449 | strErrors << _("Cannot initialize keypool") << "\n"; | |
450 | pwalletMain->SetDefaultKey(newDefaultKey); | |
451 | if (!pwalletMain->SetAddressBookName(CBitcoinAddress(pwalletMain->vchDefaultKey), "")) | |
452 | strErrors << _("Cannot write default address") << "\n"; | |
453 | } | |
454 | ||
21e875c9 | 455 | printf("%s", strErrors.str().c_str()); |
69d605f4 WL |
456 | printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
457 | ||
e8ef3da7 WL |
458 | RegisterWallet(pwalletMain); |
459 | ||
69d605f4 WL |
460 | CBlockIndex *pindexRescan = pindexBest; |
461 | if (GetBoolArg("-rescan")) | |
462 | pindexRescan = pindexGenesisBlock; | |
463 | else | |
464 | { | |
e8ef3da7 | 465 | CWalletDB walletdb("wallet.dat"); |
69d605f4 WL |
466 | CBlockLocator locator; |
467 | if (walletdb.ReadBestBlock(locator)) | |
468 | pindexRescan = locator.GetBlockIndex(); | |
469 | } | |
470 | if (pindexBest != pindexRescan) | |
471 | { | |
3f0816e3 | 472 | InitMessage(_("Rescanning...")); |
69d605f4 WL |
473 | printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight); |
474 | nStart = GetTimeMillis(); | |
e8ef3da7 | 475 | pwalletMain->ScanForWalletTransactions(pindexRescan, true); |
69d605f4 WL |
476 | printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
477 | } | |
478 | ||
3f0816e3 | 479 | InitMessage(_("Done loading")); |
69d605f4 WL |
480 | printf("Done loading\n"); |
481 | ||
6e39e7c9 GA |
482 | //// debug print |
483 | printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size()); | |
484 | printf("nBestHeight = %d\n", nBestHeight); | |
485 | printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size()); | |
486 | printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size()); | |
487 | printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size()); | |
69d605f4 | 488 | |
6e39e7c9 | 489 | if (!strErrors.str().empty()) |
ac7c7ab9 | 490 | return InitError(strErrors.str()); |
69d605f4 WL |
491 | |
492 | // Add wallet transactions that aren't already in a block to mapTransactions | |
e8ef3da7 | 493 | pwalletMain->ReacceptWalletTransactions(); |
69d605f4 | 494 | |
0fcf91ea GA |
495 | // Note: Bitcoin-QT stores several settings in the wallet, so we want |
496 | // to load the wallet BEFORE parsing command-line arguments, so | |
497 | // the command-line/bitcoin.conf settings override GUI setting. | |
498 | ||
69d605f4 WL |
499 | // |
500 | // Parameters | |
501 | // | |
502 | if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree")) | |
503 | { | |
504 | PrintBlockTree(); | |
505 | return false; | |
506 | } | |
507 | ||
18cf2145 WL |
508 | if (mapArgs.count("-timeout")) |
509 | { | |
510 | int nNewTimeout = GetArg("-timeout", 5000); | |
511 | if (nNewTimeout > 0 && nNewTimeout < 600000) | |
512 | nConnectTimeout = nNewTimeout; | |
513 | } | |
514 | ||
69d605f4 WL |
515 | if (mapArgs.count("-printblock")) |
516 | { | |
517 | string strMatch = mapArgs["-printblock"]; | |
518 | int nFound = 0; | |
519 | for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) | |
520 | { | |
521 | uint256 hash = (*mi).first; | |
522 | if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0) | |
523 | { | |
524 | CBlockIndex* pindex = (*mi).second; | |
525 | CBlock block; | |
526 | block.ReadFromDisk(pindex); | |
527 | block.BuildMerkleTree(); | |
528 | block.print(); | |
529 | printf("\n"); | |
530 | nFound++; | |
531 | } | |
532 | } | |
533 | if (nFound == 0) | |
534 | printf("No blocks matching %s were found\n", strMatch.c_str()); | |
535 | return false; | |
536 | } | |
537 | ||
69d605f4 WL |
538 | if (mapArgs.count("-proxy")) |
539 | { | |
540 | fUseProxy = true; | |
c981d768 | 541 | addrProxy = CService(mapArgs["-proxy"], 9050); |
69d605f4 | 542 | if (!addrProxy.IsValid()) |
ac7c7ab9 | 543 | return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"].c_str())); |
69d605f4 WL |
544 | } |
545 | ||
623b9878 PW |
546 | if (mapArgs.count("-noproxy")) |
547 | { | |
548 | BOOST_FOREACH(std::string snet, mapMultiArgs["-noproxy"]) { | |
549 | enum Network net = ParseNetwork(snet); | |
ac7c7ab9 PW |
550 | if (net == NET_UNROUTABLE) |
551 | return InitError(strprintf(_("Unknown network specified in -noproxy: '%s'"), snet.c_str())); | |
623b9878 PW |
552 | SetNoProxy(net); |
553 | } | |
554 | } | |
555 | ||
19b6958c PW |
556 | if (mapArgs.count("-connect")) |
557 | SoftSetBoolArg("-dnsseed", false); | |
8f10a288 PW |
558 | |
559 | // even in Tor mode, if -bind is specified, you really want -listen | |
560 | if (mapArgs.count("-bind")) | |
561 | SoftSetBoolArg("-listen", true); | |
562 | ||
67a42f92 | 563 | bool fTor = (fUseProxy && addrProxy.GetPort() == 9050); |
0fcf91ea GA |
564 | if (fTor) |
565 | { | |
7bf8b7c2 | 566 | // Use SoftSetBoolArg here so user can override any of these if they wish. |
0fcf91ea | 567 | // Note: the GetBoolArg() calls for all of these must happen later. |
9d952d17 GA |
568 | SoftSetBoolArg("-listen", false); |
569 | SoftSetBoolArg("-irc", false); | |
9bab521d | 570 | SoftSetBoolArg("-proxydns", true); |
7bf8b7c2 | 571 | SoftSetBoolArg("-upnp", false); |
19b6958c | 572 | SoftSetBoolArg("-discover", false); |
0fcf91ea GA |
573 | } |
574 | ||
0f1707de PW |
575 | if (mapArgs.count("-onlynet")) { |
576 | std::set<enum Network> nets; | |
577 | BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) { | |
457754d2 | 578 | enum Network net = ParseNetwork(snet); |
ac7c7ab9 | 579 | if (net == NET_UNROUTABLE) |
0f1707de PW |
580 | return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet.c_str())); |
581 | nets.insert(net); | |
582 | } | |
583 | for (int n = 0; n < NET_MAX; n++) { | |
584 | enum Network net = (enum Network)n; | |
585 | if (!nets.count(net)) | |
586 | SetLimited(net); | |
457754d2 PW |
587 | } |
588 | } | |
589 | ||
9bab521d PW |
590 | fNameLookup = GetBoolArg("-dns"); |
591 | fProxyNameLookup = GetBoolArg("-proxydns"); | |
592 | if (fProxyNameLookup) | |
593 | fNameLookup = true; | |
9d952d17 | 594 | fNoListen = !GetBoolArg("-listen", true); |
9bab521d | 595 | nSocksVersion = GetArg("-socks", 5); |
ac7c7ab9 PW |
596 | if (nSocksVersion != 4 && nSocksVersion != 5) |
597 | return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion)); | |
0fcf91ea | 598 | |
478b01d9 PW |
599 | BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"]) |
600 | AddOneShot(strDest); | |
0fcf91ea | 601 | |
8f188ece GA |
602 | // Continue to put "/P2SH/" in the coinbase to monitor |
603 | // BIP16 support. | |
604 | // This can be removed eventually... | |
605 | const char* pszP2SH = "/P2SH/"; | |
606 | COINBASE_FLAGS << std::vector<unsigned char>(pszP2SH, pszP2SH+strlen(pszP2SH)); | |
7bf8b7c2 | 607 | |
8f10a288 | 608 | bool fBound = false; |
0fcf91ea GA |
609 | if (!fNoListen) |
610 | { | |
611 | std::string strError; | |
8f10a288 PW |
612 | if (mapArgs.count("-bind")) { |
613 | BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) { | |
55bb0cfb PW |
614 | CService addrBind; |
615 | if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) | |
ac7c7ab9 PW |
616 | return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind.c_str())); |
617 | fBound |= Bind(addrBind); | |
8f10a288 PW |
618 | } |
619 | } else { | |
839c4e79 PW |
620 | struct in_addr inaddr_any; |
621 | inaddr_any.s_addr = INADDR_ANY; | |
5a3cb32e | 622 | fBound |= Bind(CService(inaddr_any, GetListenPort())); |
8f10a288 | 623 | #ifdef USE_IPV6 |
5a3cb32e | 624 | fBound |= Bind(CService(in6addr_any, GetListenPort())); |
8f10a288 | 625 | #endif |
0fcf91ea | 626 | } |
8f10a288 | 627 | if (!fBound) |
55bb0cfb | 628 | return InitError(_("Not listening on any port")); |
0fcf91ea GA |
629 | } |
630 | ||
19b6958c | 631 | if (mapArgs.count("-externalip")) |
69d605f4 | 632 | { |
ac7c7ab9 PW |
633 | BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"]) { |
634 | CService addrLocal(strAddr, GetListenPort(), fNameLookup); | |
635 | if (!addrLocal.IsValid()) | |
636 | return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr.c_str())); | |
5a3cb32e | 637 | AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL); |
ac7c7ab9 | 638 | } |
69d605f4 WL |
639 | } |
640 | ||
69d605f4 WL |
641 | if (mapArgs.count("-paytxfee")) |
642 | { | |
643 | if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee)) | |
ac7c7ab9 | 644 | return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"].c_str())); |
69d605f4 | 645 | if (nTransactionFee > 0.25 * COIN) |
ac7c7ab9 | 646 | InitWarning(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction.")); |
69d605f4 | 647 | } |
69d605f4 WL |
648 | |
649 | // | |
565c4771 | 650 | // Start the node |
69d605f4 | 651 | // |
69d605f4 WL |
652 | if (!CheckDiskSpace()) |
653 | return false; | |
654 | ||
655 | RandAddSeedPerfmon(); | |
656 | ||
657 | if (!CreateThread(StartNode, NULL)) | |
ac7c7ab9 | 658 | InitError(_("Error: could not start node")); |
69d605f4 WL |
659 | |
660 | if (fServer) | |
661 | CreateThread(ThreadRPCServer, NULL); | |
662 | ||
565c4771 | 663 | #if !defined(QT_GUI) |
9f5b11e6 WL |
664 | // Loop until process is exit()ed from shutdown() function, |
665 | // called from ThreadRPCServer thread when a "stop" command is received. | |
69d605f4 WL |
666 | while (1) |
667 | Sleep(5000); | |
668 | #endif | |
669 | ||
670 | return true; | |
671 | } | |
f18a119a | 672 |