Projects : bitcoin : bitcoin_tx_fee_cleanup
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 "knobs.h" |
6 | #include "headers.h" |
7 | #include "strlcpy.h" |
8 | #include <boost/program_options/detail/config_file.hpp> |
9 | #include <boost/program_options/parsers.hpp> |
10 | #include <boost/filesystem.hpp> |
11 | #include <boost/filesystem/fstream.hpp> |
12 | #include <boost/interprocess/sync/interprocess_mutex.hpp> |
13 | #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp> |
14 | #include <boost/foreach.hpp> |
15 | |
16 | using namespace std; |
17 | using namespace boost; |
18 | |
19 | map<string, string> mapArgs; |
20 | map<string, vector<string> > mapMultiArgs; |
21 | bool fDebug = false; |
22 | bool fPrintToConsole = false; |
23 | bool fPrintToDebugger = false; |
24 | bool fVerifyAll = false; |
25 | char pszSetDataDir[MAX_PATH] = ""; |
26 | bool fRequestShutdown = false; |
27 | bool fShutdown = false; |
28 | bool fDaemon = false; |
29 | bool fServer = false; |
30 | bool fCommandLine = false; |
31 | string strMiscWarning; |
32 | bool fNoListen = false; |
33 | bool fLogTimestamps = false; |
34 | bool fLowS = false; |
35 | bool fHighS = false; |
36 | bool fTestSafeMode = false; |
37 | bool fDisableSafeMode = false; |
38 | bool fPermissive = false; |
39 | |
40 | std::string CLIENT_NAME(DEFAULT_CLIENT_NAME); |
41 | |
42 | |
43 | // Workaround for "multiple definition of `_tls_used'" |
44 | // http://svn.boost.org/trac/boost/ticket/4258 |
45 | extern "C" void tss_cleanup_implemented() { } |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | // Init openssl library multithreading support |
52 | static boost::interprocess::interprocess_mutex** ppmutexOpenSSL; |
53 | void locking_callback(int mode, int i, const char* file, int line) |
54 | { |
55 | if (mode & CRYPTO_LOCK) |
56 | ppmutexOpenSSL[i]->lock(); |
57 | else |
58 | ppmutexOpenSSL[i]->unlock(); |
59 | } |
60 | |
61 | // Init |
62 | class CInit |
63 | { |
64 | public: |
65 | CInit() |
66 | { |
67 | // Init openssl library multithreading support |
68 | ppmutexOpenSSL = (boost::interprocess::interprocess_mutex**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(boost::interprocess::interprocess_mutex*)); |
69 | for (int i = 0; i < CRYPTO_num_locks(); i++) |
70 | ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex(); |
71 | CRYPTO_set_locking_callback(locking_callback); |
72 | |
73 | // Seed random number generator with performance counter |
74 | RandAddSeed(); |
75 | } |
76 | ~CInit() |
77 | { |
78 | // Shutdown openssl library multithreading support |
79 | CRYPTO_set_locking_callback(NULL); |
80 | for (int i = 0; i < CRYPTO_num_locks(); i++) |
81 | delete ppmutexOpenSSL[i]; |
82 | OPENSSL_free(ppmutexOpenSSL); |
83 | } |
84 | } |
85 | instance_of_cinit; |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | void RandAddSeed() |
95 | { |
96 | // Seed with CPU performance counter |
97 | int64 nCounter = GetPerformanceCounter(); |
98 | RAND_add(&nCounter, sizeof(nCounter), 1.5); |
99 | memset(&nCounter, 0, sizeof(nCounter)); |
100 | } |
101 | |
102 | void RandAddSeedPerfmon() |
103 | { |
104 | RandAddSeed(); |
105 | |
106 | // This can take up to 2 seconds, so only do it every 10 minutes |
107 | static int64 nLastPerfmon; |
108 | if (GetTime() < nLastPerfmon + 10 * 60) |
109 | return; |
110 | nLastPerfmon = GetTime(); |
111 | |
112 | } |
113 | |
114 | uint64 GetRand(uint64 nMax) |
115 | { |
116 | if (nMax == 0) |
117 | return 0; |
118 | |
119 | // The range of the random source must be a multiple of the modulus |
120 | // to give every possible output value an equal possibility |
121 | uint64 nRange = (UINT64_MAX / nMax) * nMax; |
122 | uint64 nRand = 0; |
123 | do |
124 | RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); |
125 | while (nRand >= nRange); |
126 | return (nRand % nMax); |
127 | } |
128 | |
129 | int GetRandInt(int nMax) |
130 | { |
131 | return GetRand(nMax); |
132 | } |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | inline int OutputDebugStringF(const char* pszFormat, ...) |
145 | { |
146 | int ret = 0; |
147 | if (fPrintToConsole) |
148 | { |
149 | // print to console |
150 | va_list arg_ptr; |
151 | va_start(arg_ptr, pszFormat); |
152 | ret = vprintf(pszFormat, arg_ptr); |
153 | va_end(arg_ptr); |
154 | } |
155 | else |
156 | { |
157 | // print to debug.log |
158 | static FILE* fileout = NULL; |
159 | |
160 | if (!fileout) |
161 | { |
162 | char pszFile[MAX_PATH+100]; |
163 | GetDataDir(pszFile); |
164 | strlcat(pszFile, "/debug.log", sizeof(pszFile)); |
165 | fileout = fopen(pszFile, "a"); |
166 | if (fileout) setbuf(fileout, NULL); // unbuffered |
167 | } |
168 | if (fileout) |
169 | { |
170 | static bool fStartedNewLine = true; |
171 | |
172 | // Debug print useful for profiling |
173 | if (fLogTimestamps && fStartedNewLine) |
174 | fprintf(fileout, "%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); |
175 | if (pszFormat[strlen(pszFormat) - 1] == '\n') |
176 | fStartedNewLine = true; |
177 | else |
178 | fStartedNewLine = false; |
179 | |
180 | va_list arg_ptr; |
181 | va_start(arg_ptr, pszFormat); |
182 | ret = vfprintf(fileout, pszFormat, arg_ptr); |
183 | va_end(arg_ptr); |
184 | } |
185 | } |
186 | |
187 | return ret; |
188 | } |
189 | |
190 | |
191 | // Safer snprintf |
192 | // - prints up to limit-1 characters |
193 | // - output string is always null terminated even if limit reached |
194 | // - return value is the number of characters actually printed |
195 | int my_snprintf(char* buffer, size_t limit, const char* format, ...) |
196 | { |
197 | if (limit == 0) |
198 | return 0; |
199 | va_list arg_ptr; |
200 | va_start(arg_ptr, format); |
201 | int ret = _vsnprintf(buffer, limit, format, arg_ptr); |
202 | va_end(arg_ptr); |
203 | if (ret < 0 || ret >= limit) |
204 | { |
205 | ret = limit - 1; |
206 | buffer[limit-1] = 0; |
207 | } |
208 | return ret; |
209 | } |
210 | |
211 | string strprintf(const std::string &format, ...) |
212 | { |
213 | char buffer[50000]; |
214 | char* p = buffer; |
215 | int limit = sizeof(buffer); |
216 | int ret; |
217 | loop |
218 | { |
219 | va_list arg_ptr; |
220 | va_start(arg_ptr, format); |
221 | ret = _vsnprintf(p, limit, format.c_str(), arg_ptr); |
222 | va_end(arg_ptr); |
223 | if (ret >= 0 && ret < limit) |
224 | break; |
225 | if (p != buffer) |
226 | delete[] p; |
227 | limit *= 2; |
228 | p = new char[limit]; |
229 | if (p == NULL) |
230 | throw std::bad_alloc(); |
231 | } |
232 | string str(p, p+ret); |
233 | if (p != buffer) |
234 | delete[] p; |
235 | return str; |
236 | } |
237 | |
238 | bool error(const std::string &format, ...) |
239 | { |
240 | char buffer[50000]; |
241 | int limit = sizeof(buffer); |
242 | va_list arg_ptr; |
243 | va_start(arg_ptr, format); |
244 | int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr); |
245 | va_end(arg_ptr); |
246 | if (ret < 0 || ret >= limit) |
247 | { |
248 | ret = limit - 1; |
249 | buffer[limit-1] = 0; |
250 | } |
251 | printf("ERROR: %s\n", buffer); |
252 | return false; |
253 | } |
254 | |
255 | |
256 | void ParseString(const string& str, char c, vector<string>& v) |
257 | { |
258 | if (str.empty()) |
259 | return; |
260 | string::size_type i1 = 0; |
261 | string::size_type i2; |
262 | loop |
263 | { |
264 | i2 = str.find(c, i1); |
265 | if (i2 == str.npos) |
266 | { |
267 | v.push_back(str.substr(i1)); |
268 | return; |
269 | } |
270 | v.push_back(str.substr(i1, i2-i1)); |
271 | i1 = i2+1; |
272 | } |
273 | } |
274 | |
275 | |
276 | string FormatMoney(int64 n, bool fPlus) |
277 | { |
278 | // Note: not using straight sprintf here because we do NOT want |
279 | // localized number formatting. |
280 | int64 n_abs = (n > 0 ? n : -n); |
281 | int64 quotient = n_abs/COIN; |
282 | int64 remainder = n_abs%COIN; |
283 | string str = strprintf("%"PRI64d".%08"PRI64d, quotient, remainder); |
284 | |
285 | // Right-trim excess 0's before the decimal point: |
286 | int nTrim = 0; |
287 | for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i) |
288 | ++nTrim; |
289 | if (nTrim) |
290 | str.erase(str.size()-nTrim, nTrim); |
291 | |
292 | if (n < 0) |
293 | str.insert((unsigned int)0, 1, '-'); |
294 | else if (fPlus && n > 0) |
295 | str.insert((unsigned int)0, 1, '+'); |
296 | return str; |
297 | } |
298 | |
299 | |
300 | bool ParseMoney(const string& str, int64& nRet) |
301 | { |
302 | return ParseMoney(str.c_str(), nRet); |
303 | } |
304 | |
305 | bool ParseMoney(const char* pszIn, int64& nRet) |
306 | { |
307 | string strWhole; |
308 | int64 nUnits = 0; |
309 | const char* p = pszIn; |
310 | while (isspace(*p)) |
311 | p++; |
312 | for (; *p; p++) |
313 | { |
314 | if (*p == '.') |
315 | { |
316 | p++; |
317 | int64 nMult = CENT*10; |
318 | while (isdigit(*p) && (nMult > 0)) |
319 | { |
320 | nUnits += nMult * (*p++ - '0'); |
321 | nMult /= 10; |
322 | } |
323 | break; |
324 | } |
325 | if (isspace(*p)) |
326 | break; |
327 | if (!isdigit(*p)) |
328 | return false; |
329 | strWhole.insert(strWhole.end(), *p); |
330 | } |
331 | for (; *p; p++) |
332 | if (!isspace(*p)) |
333 | return false; |
334 | if (strWhole.size() > 10) // guard against 63 bit overflow |
335 | return false; |
336 | if (nUnits < 0 || nUnits > COIN) |
337 | return false; |
338 | int64 nWhole = atoi64(strWhole); |
339 | int64 nValue = nWhole*COIN + nUnits; |
340 | |
341 | nRet = nValue; |
342 | return true; |
343 | } |
344 | |
345 | |
346 | vector<unsigned char> ParseHex(const char* psz) |
347 | { |
348 | static char phexdigit[256] = |
349 | { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
350 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
351 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
352 | 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, |
353 | -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
354 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
355 | -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
356 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
357 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
358 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
359 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
360 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
361 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
362 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
363 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
364 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; |
365 | |
366 | // convert hex dump to vector |
367 | vector<unsigned char> vch; |
368 | loop |
369 | { |
370 | while (isspace(*psz)) |
371 | psz++; |
372 | char c = phexdigit[(unsigned char)*psz++]; |
373 | if (c == (char)-1) |
374 | break; |
375 | unsigned char n = (c << 4); |
376 | c = phexdigit[(unsigned char)*psz++]; |
377 | if (c == (char)-1) |
378 | break; |
379 | n |= c; |
380 | vch.push_back(n); |
381 | } |
382 | return vch; |
383 | } |
384 | |
385 | vector<unsigned char> ParseHex(const string& str) |
386 | { |
387 | return ParseHex(str.c_str()); |
388 | } |
389 | |
390 | void ParseParameters(int argc, char* argv[]) |
391 | { |
392 | mapArgs.clear(); |
393 | mapMultiArgs.clear(); |
394 | for (int i = 1; i < argc; i++) |
395 | { |
396 | char psz[10000]; |
397 | strlcpy(psz, argv[i], sizeof(psz)); |
398 | char* pszValue = (char*)""; |
399 | if (strchr(psz, '=')) |
400 | { |
401 | pszValue = strchr(psz, '='); |
402 | *pszValue++ = '\0'; |
403 | } |
404 | if (psz[0] != '-') |
405 | break; |
406 | mapArgs[psz] = pszValue; |
407 | mapMultiArgs[psz].push_back(pszValue); |
408 | } |
409 | } |
410 | |
411 | bool SoftSetArg(const std::string& strArg, const std::string& strValue) |
412 | { |
413 | if (mapArgs.count(strArg)) |
414 | return false; |
415 | mapArgs[strArg] = strValue; |
416 | return true; |
417 | } |
418 | |
419 | bool SoftSetArg(const std::string& strArg, bool fValue) |
420 | { |
421 | if (fValue) |
422 | return SoftSetArg(strArg, std::string("1")); |
423 | else |
424 | return SoftSetArg(strArg, std::string("0")); |
425 | } |
426 | |
427 | |
428 | string EncodeBase64(const unsigned char* pch, size_t len) |
429 | { |
430 | static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
431 | |
432 | string strRet=""; |
433 | strRet.reserve((len+2)/3*4); |
434 | |
435 | int mode=0, left=0; |
436 | const unsigned char *pchEnd = pch+len; |
437 | |
438 | while (pch<pchEnd) |
439 | { |
440 | int enc = *(pch++); |
441 | switch (mode) |
442 | { |
443 | case 0: // we have no bits |
444 | strRet += pbase64[enc >> 2]; |
445 | left = (enc & 3) << 4; |
446 | mode = 1; |
447 | break; |
448 | |
449 | case 1: // we have two bits |
450 | strRet += pbase64[left | (enc >> 4)]; |
451 | left = (enc & 15) << 2; |
452 | mode = 2; |
453 | break; |
454 | |
455 | case 2: // we have four bits |
456 | strRet += pbase64[left | (enc >> 6)]; |
457 | strRet += pbase64[enc & 63]; |
458 | mode = 0; |
459 | break; |
460 | } |
461 | } |
462 | |
463 | if (mode) |
464 | { |
465 | strRet += pbase64[left]; |
466 | strRet += '='; |
467 | if (mode == 1) |
468 | strRet += '='; |
469 | } |
470 | |
471 | return strRet; |
472 | } |
473 | |
474 | string EncodeBase64(const string& str) |
475 | { |
476 | return EncodeBase64((const unsigned char*)str.c_str(), str.size()); |
477 | } |
478 | |
479 | vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid) |
480 | { |
481 | static const int decode64_table[256] = |
482 | { |
483 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
484 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
485 | -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, |
486 | -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
487 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, |
488 | 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, |
489 | 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
490 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
491 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
492 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
493 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
494 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
495 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 |
496 | }; |
497 | |
498 | if (pfInvalid) |
499 | *pfInvalid = false; |
500 | |
501 | vector<unsigned char> vchRet; |
502 | vchRet.reserve(strlen(p)*3/4); |
503 | |
504 | int mode = 0; |
505 | int left = 0; |
506 | |
507 | while (1) |
508 | { |
509 | int dec = decode64_table[*p]; |
510 | if (dec == -1) break; |
511 | p++; |
512 | switch (mode) |
513 | { |
514 | case 0: // we have no bits and get 6 |
515 | left = dec; |
516 | mode = 1; |
517 | break; |
518 | |
519 | case 1: // we have 6 bits and keep 4 |
520 | vchRet.push_back((left<<2) | (dec>>4)); |
521 | left = dec & 15; |
522 | mode = 2; |
523 | break; |
524 | |
525 | case 2: // we have 4 bits and get 6, we keep 2 |
526 | vchRet.push_back((left<<4) | (dec>>2)); |
527 | left = dec & 3; |
528 | mode = 3; |
529 | break; |
530 | |
531 | case 3: // we have 2 bits and get 6 |
532 | vchRet.push_back((left<<6) | dec); |
533 | mode = 0; |
534 | break; |
535 | } |
536 | } |
537 | |
538 | if (pfInvalid) |
539 | switch (mode) |
540 | { |
541 | case 0: // 4n base64 characters processed: ok |
542 | break; |
543 | |
544 | case 1: // 4n+1 base64 character processed: impossible |
545 | *pfInvalid = true; |
546 | break; |
547 | |
548 | case 2: // 4n+2 base64 characters processed: require '==' |
549 | if (left || p[0] != '=' || p[1] != '=' || decode64_table[p[2]] != -1) |
550 | *pfInvalid = true; |
551 | break; |
552 | |
553 | case 3: // 4n+3 base64 characters processed: require '=' |
554 | if (left || p[0] != '=' || decode64_table[p[1]] != -1) |
555 | *pfInvalid = true; |
556 | break; |
557 | } |
558 | |
559 | return vchRet; |
560 | } |
561 | |
562 | string DecodeBase64(const string& str) |
563 | { |
564 | vector<unsigned char> vchRet = DecodeBase64(str.c_str()); |
565 | return string((const char*)&vchRet[0], vchRet.size()); |
566 | } |
567 | |
568 | |
569 | bool WildcardMatch(const char* psz, const char* mask) |
570 | { |
571 | loop |
572 | { |
573 | switch (*mask) |
574 | { |
575 | case '\0': |
576 | return (*psz == '\0'); |
577 | case '*': |
578 | return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask)); |
579 | case '?': |
580 | if (*psz == '\0') |
581 | return false; |
582 | break; |
583 | default: |
584 | if (*psz != *mask) |
585 | return false; |
586 | break; |
587 | } |
588 | psz++; |
589 | mask++; |
590 | } |
591 | } |
592 | |
593 | bool WildcardMatch(const string& str, const string& mask) |
594 | { |
595 | return WildcardMatch(str.c_str(), mask.c_str()); |
596 | } |
597 | |
598 | |
599 | |
600 | |
601 | |
602 | |
603 | |
604 | |
605 | void FormatException(char* pszMessage, std::exception* pex, const char* pszThread) |
606 | { |
607 | const char* pszModule = "bitcoin"; |
608 | if (pex) |
609 | snprintf(pszMessage, 1000, |
610 | "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread); |
611 | else |
612 | snprintf(pszMessage, 1000, |
613 | "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread); |
614 | } |
615 | |
616 | void LogException(std::exception* pex, const char* pszThread) |
617 | { |
618 | char pszMessage[10000]; |
619 | FormatException(pszMessage, pex, pszThread); |
620 | printf("\n%s", pszMessage); |
621 | } |
622 | |
623 | void PrintException(std::exception* pex, const char* pszThread) |
624 | { |
625 | char pszMessage[10000]; |
626 | FormatException(pszMessage, pex, pszThread); |
627 | printf("\n\n************************\n%s\n", pszMessage); |
628 | fprintf(stderr, "\n\n************************\n%s\n", pszMessage); |
629 | strMiscWarning = pszMessage; |
630 | throw; |
631 | } |
632 | |
633 | void ThreadOneMessageBox(string strMessage) |
634 | { |
635 | // Skip message boxes if one is already open |
636 | static bool fMessageBoxOpen; |
637 | if (fMessageBoxOpen) |
638 | return; |
639 | fMessageBoxOpen = true; |
640 | ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION); |
641 | fMessageBoxOpen = false; |
642 | } |
643 | |
644 | void PrintExceptionContinue(std::exception* pex, const char* pszThread) |
645 | { |
646 | char pszMessage[10000]; |
647 | FormatException(pszMessage, pex, pszThread); |
648 | printf("\n\n************************\n%s\n", pszMessage); |
649 | fprintf(stderr, "\n\n************************\n%s\n", pszMessage); |
650 | strMiscWarning = pszMessage; |
651 | } |
652 | |
653 | string GetDefaultDataDir() |
654 | { |
655 | // Mac: ~/Library/Application Support/Bitcoin |
656 | // Unix: ~/.bitcoin |
657 | char* pszHome = getenv("HOME"); |
658 | if (pszHome == NULL || strlen(pszHome) == 0) |
659 | pszHome = (char*)"/"; |
660 | string strHome = pszHome; |
661 | if (strHome[strHome.size()-1] != '/') |
662 | strHome += '/'; |
663 | #ifdef MAC_OSX |
664 | // Mac |
665 | strHome += "Library/Application Support/"; |
666 | filesystem::create_directory(strHome.c_str()); |
667 | return strHome + "Bitcoin"; |
668 | #else |
669 | // Unix |
670 | return strHome + ".bitcoin"; |
671 | #endif |
672 | } |
673 | |
674 | void GetDataDir(char* pszDir) |
675 | { |
676 | // pszDir must be at least MAX_PATH length. |
677 | int nVariation; |
678 | if (pszSetDataDir[0] != 0) |
679 | { |
680 | strlcpy(pszDir, pszSetDataDir, MAX_PATH); |
681 | nVariation = 0; |
682 | } |
683 | else |
684 | { |
685 | // This can be called during exceptions by printf, so we cache the |
686 | // value so we don't have to do memory allocations after that. |
687 | static char pszCachedDir[MAX_PATH]; |
688 | if (pszCachedDir[0] == 0) |
689 | strlcpy(pszCachedDir, GetDefaultDataDir().c_str(), sizeof(pszCachedDir)); |
690 | strlcpy(pszDir, pszCachedDir, MAX_PATH); |
691 | nVariation = 1; |
692 | } |
693 | static bool pfMkdir[4]; |
694 | if (!pfMkdir[nVariation]) |
695 | { |
696 | pfMkdir[nVariation] = true; |
697 | boost::filesystem::create_directory(pszDir); |
698 | } |
699 | } |
700 | |
701 | string GetDataDir() |
702 | { |
703 | char pszDir[MAX_PATH]; |
704 | GetDataDir(pszDir); |
705 | return pszDir; |
706 | } |
707 | |
708 | string GetConfigFile() |
709 | { |
710 | namespace fs = boost::filesystem; |
711 | fs::path pathConfig(GetArg("-conf", "bitcoin.conf")); |
712 | if (!pathConfig.is_complete()) |
713 | pathConfig = fs::path(GetDataDir()) / pathConfig; |
714 | return pathConfig.string(); |
715 | } |
716 | |
717 | void ReadConfigFile(map<string, string>& mapSettingsRet, |
718 | map<string, vector<string> >& mapMultiSettingsRet) |
719 | { |
720 | namespace fs = boost::filesystem; |
721 | namespace pod = boost::program_options::detail; |
722 | |
723 | fs::ifstream streamConfig(GetConfigFile()); |
724 | if (!streamConfig.good()) |
725 | return; |
726 | |
727 | set<string> setOptions; |
728 | setOptions.insert("*"); |
729 | |
730 | for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it) |
731 | { |
732 | // Don't overwrite existing settings so command line settings override bitcoin.conf |
733 | string strKey = string("-") + it->string_key; |
734 | if (mapSettingsRet.count(strKey) == 0) |
735 | mapSettingsRet[strKey] = it->value[0]; |
736 | mapMultiSettingsRet[strKey].push_back(it->value[0]); |
737 | } |
738 | } |
739 | |
740 | string GetPidFile() |
741 | { |
742 | namespace fs = boost::filesystem; |
743 | fs::path pathConfig(GetArg("-pid", "bitcoind.pid")); |
744 | if (!pathConfig.is_complete()) |
745 | pathConfig = fs::path(GetDataDir()) / pathConfig; |
746 | return pathConfig.string(); |
747 | } |
748 | |
749 | void CreatePidFile(string pidFile, pid_t pid) |
750 | { |
751 | FILE* file = fopen(pidFile.c_str(), "w"); |
752 | if (file) |
753 | { |
754 | fprintf(file, "%d\n", pid); |
755 | fclose(file); |
756 | } |
757 | } |
758 | |
759 | int GetFilesize(FILE* file) |
760 | { |
761 | int nSavePos = ftell(file); |
762 | int nFilesize = -1; |
763 | if (fseek(file, 0, SEEK_END) == 0) |
764 | nFilesize = ftell(file); |
765 | fseek(file, nSavePos, SEEK_SET); |
766 | return nFilesize; |
767 | } |
768 | |
769 | void ShrinkDebugFile() |
770 | { |
771 | // Scroll debug.log if it's getting too big |
772 | string strFile = GetDataDir() + "/debug.log"; |
773 | FILE* file = fopen(strFile.c_str(), "r"); |
774 | if (file && GetFilesize(file) > 10 * 1000000) |
775 | { |
776 | // Restart the file with some of the end |
777 | char pch[200000]; |
778 | fseek(file, -sizeof(pch), SEEK_END); |
779 | int nBytes = fread(pch, 1, sizeof(pch), file); |
780 | fclose(file); |
781 | |
782 | file = fopen(strFile.c_str(), "w"); |
783 | if (file) |
784 | { |
785 | fwrite(pch, 1, nBytes, file); |
786 | fclose(file); |
787 | } |
788 | } |
789 | } |
790 | |
791 | |
792 | |
793 | |
794 | |
795 | |
796 | |
797 | |
798 | // |
799 | // "Never go to sea with two chronometers; take one or three." |
800 | // Our three time sources are: |
801 | // - System clock |
802 | // - Median of other nodes's clocks |
803 | // - The user (asking the user to fix the system clock if the first two disagree) |
804 | // |
805 | static int64 nMockTime = 0; // For unit testing |
806 | |
807 | int64 GetTime() |
808 | { |
809 | if (nMockTime) return nMockTime; |
810 | |
811 | return time(NULL); |
812 | } |
813 | |
814 | void SetMockTime(int64 nMockTimeIn) |
815 | { |
816 | nMockTime = nMockTimeIn; |
817 | } |
818 | |
819 | static int64 nTimeOffset = 0; |
820 | |
821 | int64 GetAdjustedTime() |
822 | { |
823 | return GetTime() + nTimeOffset; |
824 | } |
825 | |
826 | void AddTimeData(unsigned int ip, int64 nTime) |
827 | { |
828 | int64 nOffsetSample = nTime - GetTime(); |
829 | |
830 | // Ignore duplicates |
831 | static set<unsigned int> setKnown; |
832 | if (!setKnown.insert(ip).second) |
833 | return; |
834 | |
835 | // Add data |
836 | static vector<int64> vTimeOffsets; |
837 | if (vTimeOffsets.empty()) |
838 | vTimeOffsets.push_back(0); |
839 | vTimeOffsets.push_back(nOffsetSample); |
840 | printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60); |
841 | if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) |
842 | { |
843 | sort(vTimeOffsets.begin(), vTimeOffsets.end()); |
844 | int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2]; |
845 | // Only let other nodes change our time by so much |
846 | if (abs64(nMedian) < 70 * 60) |
847 | { |
848 | nTimeOffset = nMedian; |
849 | } |
850 | else |
851 | { |
852 | nTimeOffset = 0; |
853 | |
854 | static bool fDone; |
855 | if (!fDone) |
856 | { |
857 | // If nobody has a time different than ours but within 5 minutes of ours, give a warning |
858 | bool fMatch = false; |
859 | BOOST_FOREACH(int64 nOffset, vTimeOffsets) |
860 | if (nOffset != 0 && abs64(nOffset) < 5 * 60) |
861 | fMatch = true; |
862 | |
863 | if (!fMatch) |
864 | { |
865 | fDone = true; |
866 | string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly."); |
867 | strMiscWarning = strMessage; |
868 | printf("*** %s\n", strMessage.c_str()); |
869 | boost::thread(boost::bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1)); |
870 | } |
871 | } |
872 | } |
873 | BOOST_FOREACH(int64 n, vTimeOffsets) |
874 | printf("%+"PRI64d" ", n); |
875 | printf("| nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60); |
876 | } |
877 | } |
878 | |
879 | |
880 | |
881 | |
882 | |
883 | |
884 | |
885 | |
886 | |
887 | string FormatVersion(int nVersion) |
888 | { |
889 | if (nVersion%100 == 0) |
890 | return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100); |
891 | else |
892 | return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100); |
893 | } |
894 | |
895 | string FormatFullVersion() |
896 | { |
897 | string s = FormatVersion(VERSION); |
898 | return s; |
899 | } |
900 | |
901 | std::string FormatSubVersion(const std::string& name, int nClientVersion) |
902 | { |
903 | std::ostringstream ss; |
904 | ss << "/"; |
905 | ss << name << ":" << FormatVersion(nClientVersion); |
906 | ss << "/"; |
907 | return ss.str(); |
908 | } |
909 | |
910 | |
911 | |
912 | #ifdef DEBUG_LOCKORDER |
913 | // |
914 | // Early deadlock detection. |
915 | // Problem being solved: |
916 | // Thread 1 locks A, then B, then C |
917 | // Thread 2 locks D, then C, then A |
918 | // --> may result in deadlock between the two threads, depending on when they run. |
919 | // Solution implemented here: |
920 | // Keep track of pairs of locks: (A before B), (A before C), etc. |
921 | // Complain if any thread trys to lock in a different order. |
922 | // |
923 | |
924 | struct CLockLocation |
925 | { |
926 | CLockLocation(const char* pszName, const char* pszFile, int nLine) |
927 | { |
928 | mutexName = pszName; |
929 | sourceFile = pszFile; |
930 | sourceLine = nLine; |
931 | } |
932 | |
933 | std::string ToString() const |
934 | { |
935 | return mutexName+" "+sourceFile+":"+itostr(sourceLine); |
936 | } |
937 | |
938 | private: |
939 | std::string mutexName; |
940 | std::string sourceFile; |
941 | int sourceLine; |
942 | }; |
943 | |
944 | typedef std::vector< std::pair<CCriticalSection*, CLockLocation> > LockStack; |
945 | |
946 | static boost::interprocess::interprocess_mutex dd_mutex; |
947 | static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lockorders; |
948 | static boost::thread_specific_ptr<LockStack> lockstack; |
949 | |
950 | |
951 | static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCriticalSection*>& mismatch, const LockStack& s1, const LockStack& s2) |
952 | { |
953 | printf("POTENTIAL DEADLOCK DETECTED\n"); |
954 | printf("Previous lock order was:\n"); |
955 | BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2) |
956 | { |
957 | if (i.first == mismatch.first) printf(" (1)"); |
958 | if (i.first == mismatch.second) printf(" (2)"); |
959 | printf(" %s\n", i.second.ToString().c_str()); |
960 | } |
961 | printf("Current lock order is:\n"); |
962 | BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1) |
963 | { |
964 | if (i.first == mismatch.first) printf(" (1)"); |
965 | if (i.first == mismatch.second) printf(" (2)"); |
966 | printf(" %s\n", i.second.ToString().c_str()); |
967 | } |
968 | } |
969 | |
970 | static void push_lock(CCriticalSection* c, const CLockLocation& locklocation) |
971 | { |
972 | bool fOrderOK = true; |
973 | if (lockstack.get() == NULL) |
974 | lockstack.reset(new LockStack); |
975 | |
976 | if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str()); |
977 | dd_mutex.lock(); |
978 | |
979 | (*lockstack).push_back(std::make_pair(c, locklocation)); |
980 | |
981 | BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, (*lockstack)) |
982 | { |
983 | if (i.first == c) break; |
984 | |
985 | std::pair<CCriticalSection*, CCriticalSection*> p1 = std::make_pair(i.first, c); |
986 | if (lockorders.count(p1)) |
987 | continue; |
988 | lockorders[p1] = (*lockstack); |
989 | |
990 | std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first); |
991 | if (lockorders.count(p2)) |
992 | { |
993 | potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); |
994 | break; |
995 | } |
996 | } |
997 | dd_mutex.unlock(); |
998 | } |
999 | |
1000 | static void pop_lock() |
1001 | { |
1002 | if (fDebug) |
1003 | { |
1004 | const CLockLocation& locklocation = (*lockstack).rbegin()->second; |
1005 | printf("Unlocked: %s\n", locklocation.ToString().c_str()); |
1006 | } |
1007 | dd_mutex.lock(); |
1008 | (*lockstack).pop_back(); |
1009 | dd_mutex.unlock(); |
1010 | } |
1011 | |
1012 | void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine) |
1013 | { |
1014 | push_lock(this, CLockLocation(pszName, pszFile, nLine)); |
1015 | mutex.lock(); |
1016 | } |
1017 | void CCriticalSection::Leave() |
1018 | { |
1019 | mutex.unlock(); |
1020 | pop_lock(); |
1021 | } |
1022 | bool CCriticalSection::TryEnter(const char* pszName, const char* pszFile, int nLine) |
1023 | { |
1024 | push_lock(this, CLockLocation(pszName, pszFile, nLine)); |
1025 | bool result = mutex.try_lock(); |
1026 | if (!result) pop_lock(); |
1027 | return result; |
1028 | } |
1029 | |
1030 | #else |
1031 | |
1032 | void CCriticalSection::Enter(const char*, const char*, int) |
1033 | { |
1034 | mutex.lock(); |
1035 | } |
1036 | |
1037 | void CCriticalSection::Leave() |
1038 | { |
1039 | mutex.unlock(); |
1040 | } |
1041 | |
1042 | bool CCriticalSection::TryEnter(const char*, const char*, int) |
1043 | { |
1044 | bool result = mutex.try_lock(); |
1045 | return result; |
1046 | } |
1047 | |
1048 | #endif /* DEBUG_LOCKORDER */ |