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