1 // Copyright (c) 2009 Satoshi Nakamoto
\r
2 // Distributed under the MIT/X11 software license, see the accompanying
\r
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
\r
8 map<string, string> mapArgs;
\r
9 map<string, vector<string> > mapMultiArgs;
\r
10 bool fDebug = false;
\r
11 bool fPrintToDebugger = false;
\r
12 bool fPrintToConsole = false;
\r
13 char pszSetDataDir[MAX_PATH] = "";
\r
19 // Init openssl library multithreading support
\r
20 static wxMutex** ppmutexOpenSSL;
\r
21 void locking_callback(int mode, int i, const char* file, int line)
\r
23 if (mode & CRYPTO_LOCK)
\r
24 ppmutexOpenSSL[i]->Lock();
\r
26 ppmutexOpenSSL[i]->Unlock();
\r
35 // Init openssl library multithreading support
\r
36 ppmutexOpenSSL = (wxMutex**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(wxMutex*));
\r
37 for (int i = 0; i < CRYPTO_num_locks(); i++)
\r
38 ppmutexOpenSSL[i] = new wxMutex();
\r
39 CRYPTO_set_locking_callback(locking_callback);
\r
42 // Seed random number generator with screen scrape and other hardware sources
\r
46 // Seed random number generator with performance counter
\r
51 // Shutdown openssl library multithreading support
\r
52 CRYPTO_set_locking_callback(NULL);
\r
53 for (int i = 0; i < CRYPTO_num_locks(); i++)
\r
54 delete ppmutexOpenSSL[i];
\r
55 OPENSSL_free(ppmutexOpenSSL);
\r
58 foreach(CNode* pnode, vNodes)
\r
59 if (pnode->hSocket != INVALID_SOCKET)
\r
60 closesocket(pnode->hSocket);
\r
61 if (hListenSocket != INVALID_SOCKET)
\r
62 if (closesocket(hListenSocket) == SOCKET_ERROR)
\r
63 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
\r
66 // Shutdown Windows Sockets
\r
82 // Seed with CPU performance counter
\r
83 int64 nCounter = PerformanceCounter();
\r
84 RAND_add(&nCounter, sizeof(nCounter), 1.5);
\r
85 memset(&nCounter, 0, sizeof(nCounter));
\r
88 void RandAddSeedPerfmon()
\r
90 // This can take up to 2 seconds, so only do it every 10 minutes
\r
91 static int64 nLastPerfmon;
\r
92 if (GetTime() < nLastPerfmon + 10 * 60)
\r
94 nLastPerfmon = GetTime();
\r
97 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
\r
98 // Seed with the entire set of perfmon data
\r
99 unsigned char pdata[250000];
\r
100 memset(pdata, 0, sizeof(pdata));
\r
101 unsigned long nSize = sizeof(pdata);
\r
102 long ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
\r
103 RegCloseKey(HKEY_PERFORMANCE_DATA);
\r
104 if (ret == ERROR_SUCCESS)
\r
107 SHA256(pdata, nSize, (unsigned char*)&hash);
\r
108 RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash)));
\r
110 memset(pdata, 0, nSize);
\r
112 printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str(), nSize);
\r
115 printf("%s RandAddSeed()\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
\r
119 uint64 GetRand(uint64 nMax)
\r
124 // The range of the random source must be a multiple of the modulus
\r
125 // to give every possible output value an equal possibility
\r
126 uint64 nRange = (UINT64_MAX / nMax) * nMax;
\r
129 RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
\r
130 while (nRand >= nRange);
\r
131 return (nRand % nMax);
\r
147 // - prints up to limit-1 characters
\r
148 // - output string is always null terminated even if limit reached
\r
149 // - return value is the number of characters actually printed
\r
150 int my_snprintf(char* buffer, size_t limit, const char* format, ...)
\r
155 va_start(arg_ptr, format);
\r
156 int ret = _vsnprintf(buffer, limit, format, arg_ptr);
\r
158 if (ret < 0 || ret >= limit)
\r
161 buffer[limit-1] = 0;
\r
167 string strprintf(const char* format, ...)
\r
169 char buffer[50000];
\r
171 int limit = sizeof(buffer);
\r
176 va_start(arg_ptr, format);
\r
177 ret = _vsnprintf(p, limit, format, arg_ptr);
\r
179 if (ret >= 0 && ret < limit)
\r
184 p = new char[limit];
\r
186 throw std::bad_alloc();
\r
189 // msvc optimisation
\r
191 return string(p, p+ret);
\r
193 string str(p, p+ret);
\r
200 bool error(const char* format, ...)
\r
202 char buffer[50000];
\r
203 int limit = sizeof(buffer);
\r
205 va_start(arg_ptr, format);
\r
206 int ret = _vsnprintf(buffer, limit, format, arg_ptr);
\r
208 if (ret < 0 || ret >= limit)
\r
211 buffer[limit-1] = 0;
\r
213 printf("ERROR: %s\n", buffer);
\r
218 void ParseString(const string& str, char c, vector<string>& v)
\r
220 unsigned int i1 = 0;
\r
224 i2 = str.find(c, i1);
\r
225 v.push_back(str.substr(i1, i2-i1));
\r
228 while (i2 != str.npos);
\r
232 string FormatMoney(int64 n, bool fPlus)
\r
235 string str = strprintf("%"PRI64d".%02"PRI64d, (n > 0 ? n : -n)/100, (n > 0 ? n : -n)%100);
\r
236 for (int i = 6; i < str.size(); i += 4)
\r
237 if (isdigit(str[str.size() - i - 1]))
\r
238 str.insert(str.size() - i, 1, ',');
\r
240 str.insert((unsigned int)0, 1, '-');
\r
241 else if (fPlus && n > 0)
\r
242 str.insert((unsigned int)0, 1, '+');
\r
246 bool ParseMoney(const char* pszIn, int64& nRet)
\r
250 const char* p = pszIn;
\r
251 while (isspace(*p))
\r
255 if (*p == ',' && p > pszIn && isdigit(p[-1]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]) && !isdigit(p[4]))
\r
262 nCents = 10 * (*p++ - '0');
\r
264 nCents += (*p++ - '0');
\r
272 strWhole.insert(strWhole.end(), *p);
\r
277 if (strWhole.size() > 14)
\r
279 if (nCents < 0 || nCents > 99)
\r
281 int64 nWhole = atoi64(strWhole);
\r
282 int64 nPreValue = nWhole * 100 + nCents;
\r
283 int64 nValue = nPreValue * CENT;
\r
284 if (nValue / CENT != nPreValue)
\r
286 if (nValue / COIN != nWhole)
\r
293 vector<unsigned char> ParseHex(const char* psz)
\r
295 vector<unsigned char> vch;
\r
296 while (isspace(*psz))
\r
298 vch.reserve((strlen(psz)+1)/3);
\r
300 static char phexdigit[256] =
\r
301 { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
302 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
303 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
304 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
\r
305 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
306 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
307 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1
\r
308 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
309 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
310 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
311 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
312 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
313 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
314 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
315 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
\r
316 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
\r
320 char c = phexdigit[(unsigned char)*psz++];
\r
323 unsigned char n = (c << 4);
\r
326 char c = phexdigit[(unsigned char)*psz++];
\r
332 while (isspace(*psz))
\r
339 vector<unsigned char> ParseHex(const std::string& str)
\r
341 return ParseHex(str.c_str());
\r
345 void ParseParameters(int argc, char* argv[])
\r
348 mapMultiArgs.clear();
\r
349 for (int i = 0; i < argc; i++)
\r
352 strlcpy(psz, argv[i], sizeof(psz));
\r
353 char* pszValue = (char*)"";
\r
354 if (strchr(psz, '='))
\r
356 pszValue = strchr(psz, '=');
\r
357 *pszValue++ = '\0';
\r
364 mapArgs[psz] = pszValue;
\r
365 mapMultiArgs[psz].push_back(pszValue);
\r
375 void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
\r
378 char pszModule[MAX_PATH];
\r
379 pszModule[0] = '\0';
\r
380 GetModuleFileName(NULL, pszModule, sizeof(pszModule));
\r
382 // might not be thread safe, uses wxString
\r
383 //const char* pszModule = wxStandardPaths::Get().GetExecutablePath().mb_str();
\r
384 const char* pszModule = "bitcoin";
\r
387 snprintf(pszMessage, 1000,
\r
388 "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
\r
390 snprintf(pszMessage, 1000,
\r
391 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
\r
394 void LogException(std::exception* pex, const char* pszThread)
\r
396 char pszMessage[1000];
\r
397 FormatException(pszMessage, pex, pszThread);
\r
398 printf("\n%s", pszMessage);
\r
401 void PrintException(std::exception* pex, const char* pszThread)
\r
403 char pszMessage[1000];
\r
404 FormatException(pszMessage, pex, pszThread);
\r
405 printf("\n\n************************\n%s\n", pszMessage);
\r
407 wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
\r
419 int GetFilesize(FILE* file)
\r
421 int nSavePos = ftell(file);
\r
422 int nFilesize = -1;
\r
423 if (fseek(file, 0, SEEK_END) == 0)
\r
424 nFilesize = ftell(file);
\r
425 fseek(file, nSavePos, SEEK_SET);
\r
429 void GetDataDir(char* pszDir)
\r
431 // pszDir must be at least MAX_PATH length.
\r
432 if (pszSetDataDir[0] != 0)
\r
434 strlcpy(pszDir, pszSetDataDir, MAX_PATH);
\r
435 static bool fMkdirDone;
\r
444 // This can be called during exceptions by printf, so we cache the
\r
445 // value so we don't have to do memory allocations after that.
\r
446 // wxStandardPaths::GetUserDataDir
\r
447 // Return the directory for the user-dependent application data files:
\r
448 // Unix: ~/.appname
\r
449 // Windows: C:\Documents and Settings\username\Application Data\appname
\r
450 // Mac: ~/Library/Application Support/appname
\r
451 static char pszCachedDir[MAX_PATH];
\r
452 if (pszCachedDir[0] == 0)
\r
454 strlcpy(pszCachedDir, wxStandardPaths::Get().GetUserDataDir().c_str(), sizeof(pszCachedDir));
\r
455 _mkdir(pszCachedDir);
\r
457 strlcpy(pszDir, pszCachedDir, MAX_PATH);
\r
461 string GetDataDir()
\r
463 char pszDir[MAX_PATH];
\r
464 GetDataDir(pszDir);
\r
478 // "Never go to sea with two chronometers; take one or three."
\r
479 // Our three chronometers are:
\r
481 // - Median of other server's clocks
\r
484 // note: NTP isn't implemented yet, so until then we just use the median
\r
485 // of other nodes clocks to correct ours.
\r
492 static int64 nTimeOffset = 0;
\r
494 int64 GetAdjustedTime()
\r
496 return GetTime() + nTimeOffset;
\r
499 void AddTimeData(unsigned int ip, int64 nTime)
\r
501 int64 nOffsetSample = nTime - GetTime();
\r
503 // Ignore duplicates
\r
504 static set<unsigned int> setKnown;
\r
505 if (!setKnown.insert(ip).second)
\r
509 static vector<int64> vTimeOffsets;
\r
510 if (vTimeOffsets.empty())
\r
511 vTimeOffsets.push_back(0);
\r
512 vTimeOffsets.push_back(nOffsetSample);
\r
513 printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60);
\r
514 if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
\r
516 sort(vTimeOffsets.begin(), vTimeOffsets.end());
\r
517 int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2];
\r
518 nTimeOffset = nMedian;
\r
519 if ((nMedian > 0 ? nMedian : -nMedian) > 5 * 60)
\r
521 // Only let other nodes change our clock so far before we
\r
522 // go to the NTP servers
\r
523 /// todo: Get time from NTP servers, then set a flag
\r
524 /// to make sure it doesn't get changed again
\r
526 foreach(int64 n, vTimeOffsets)
\r
527 printf("%+"PRI64d" ", n);
\r
528 printf("| nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
\r