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