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
14 // Init openssl library multithreading support
\r
15 static HANDLE* lock_cs;
\r
17 void win32_locking_callback(int mode, int type, const char* file, int line)
\r
19 if (mode & CRYPTO_LOCK)
\r
20 WaitForSingleObject(lock_cs[type], INFINITE);
\r
22 ReleaseMutex(lock_cs[type]);
\r
31 // Init openssl library multithreading support
\r
32 lock_cs = (HANDLE*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
\r
33 for (int i = 0; i < CRYPTO_num_locks(); i++)
\r
34 lock_cs[i] = CreateMutex(NULL,FALSE,NULL);
\r
35 CRYPTO_set_locking_callback(win32_locking_callback);
\r
37 // Seed random number generator with screen scrape and other hardware sources
\r
40 // Seed random number generator with perfmon data
\r
45 // Shutdown openssl library multithreading support
\r
46 CRYPTO_set_locking_callback(NULL);
\r
47 for (int i =0 ; i < CRYPTO_num_locks(); i++)
\r
48 CloseHandle(lock_cs[i]);
\r
49 OPENSSL_free(lock_cs);
\r
57 void RandAddSeed(bool fPerfmon)
\r
59 // Seed with CPU performance counter
\r
60 LARGE_INTEGER PerformanceCount;
\r
61 QueryPerformanceCounter(&PerformanceCount);
\r
62 RAND_add(&PerformanceCount, sizeof(PerformanceCount), 1.5);
\r
63 memset(&PerformanceCount, 0, sizeof(PerformanceCount));
\r
65 static int64 nLastPerfmon;
\r
66 if (fPerfmon || GetTime() > nLastPerfmon + 5 * 60)
\r
68 nLastPerfmon = GetTime();
\r
70 // Seed with the entire set of perfmon data
\r
71 unsigned char pdata[250000];
\r
72 memset(pdata, 0, sizeof(pdata));
\r
73 unsigned long nSize = sizeof(pdata);
\r
74 long ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
\r
75 RegCloseKey(HKEY_PERFORMANCE_DATA);
\r
76 if (ret == ERROR_SUCCESS)
\r
79 SHA256(pdata, nSize, (unsigned char*)&hash);
\r
80 RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash)));
\r
82 memset(pdata, 0, nSize);
\r
86 struct tm* ptmTime = gmtime(&nTime);
\r
88 strftime(pszTime, sizeof(pszTime), "%x %H:%M:%S", ptmTime);
\r
89 printf("%s RandAddSeed() %d bytes\n", pszTime, nSize);
\r
104 // - prints up to limit-1 characters
\r
105 // - output string is always null terminated even if limit reached
\r
106 // - return value is the number of characters actually printed
\r
107 int my_snprintf(char* buffer, size_t limit, const char* format, ...)
\r
112 va_start(arg_ptr, format);
\r
113 int ret = _vsnprintf(buffer, limit, format, arg_ptr);
\r
115 if (ret < 0 || ret >= limit)
\r
118 buffer[limit-1] = 0;
\r
124 string strprintf(const char* format, ...)
\r
126 char buffer[50000];
\r
128 int limit = sizeof(buffer);
\r
133 va_start(arg_ptr, format);
\r
134 ret = _vsnprintf(p, limit, format, arg_ptr);
\r
136 if (ret >= 0 && ret < limit)
\r
141 p = new char[limit];
\r
143 throw std::bad_alloc();
\r
146 // msvc optimisation
\r
148 return string(p, p+ret);
\r
150 string str(p, p+ret);
\r
157 bool error(const char* format, ...)
\r
159 char buffer[50000];
\r
160 int limit = sizeof(buffer);
\r
162 va_start(arg_ptr, format);
\r
163 int ret = _vsnprintf(buffer, limit, format, arg_ptr);
\r
165 if (ret < 0 || ret >= limit)
\r
168 buffer[limit-1] = 0;
\r
170 printf("ERROR: %s\n", buffer);
\r
175 void PrintException(std::exception* pex, const char* pszThread)
\r
177 char pszModule[MAX_PATH];
\r
178 pszModule[0] = '\0';
\r
179 GetModuleFileName(NULL, pszModule, sizeof(pszModule));
\r
180 _strlwr(pszModule);
\r
181 char pszMessage[1000];
\r
183 snprintf(pszMessage, sizeof(pszMessage),
\r
184 "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
\r
186 snprintf(pszMessage, sizeof(pszMessage),
\r
187 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
\r
188 printf("\n\n************************\n%s", pszMessage);
\r
190 wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
\r
196 void ParseString(const string& str, char c, vector<string>& v)
\r
198 unsigned int i1 = 0;
\r
202 i2 = str.find(c, i1);
\r
203 v.push_back(str.substr(i1, i2-i1));
\r
206 while (i2 != str.npos);
\r
210 string FormatMoney(int64 n, bool fPlus)
\r
213 string str = strprintf("%I64d.%02I64d", (n > 0 ? n : -n)/100, (n > 0 ? n : -n)%100);
\r
214 for (int i = 6; i < str.size(); i += 4)
\r
215 if (isdigit(str[str.size() - i - 1]))
\r
216 str.insert(str.size() - i, 1, ',');
\r
218 str.insert((unsigned int)0, 1, '-');
\r
219 else if (fPlus && n > 0)
\r
220 str.insert((unsigned int)0, 1, '+');
\r
224 bool ParseMoney(const char* pszIn, int64& nRet)
\r
228 const char* p = pszIn;
\r
229 while (isspace(*p))
\r
233 if (*p == ',' && p > pszIn && isdigit(p[-1]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]) && !isdigit(p[4]))
\r
240 nCents = 10 * (*p++ - '0');
\r
242 nCents += (*p++ - '0');
\r
250 strWhole.insert(strWhole.end(), *p);
\r
255 if (strWhole.size() > 14)
\r
257 if (nCents < 0 || nCents > 99)
\r
259 int64 nWhole = atoi64(strWhole);
\r
260 int64 nPreValue = nWhole * 100 + nCents;
\r
261 int64 nValue = nPreValue * CENT;
\r
262 if (nValue / CENT != nPreValue)
\r
264 if (nValue / COIN != nWhole)
\r
279 bool FileExists(const char* psz)
\r
282 return GetFileAttributes(psz) != -1;
\r
284 return access(psz, 0) != -1;
\r
288 int GetFilesize(FILE* file)
\r
290 int nSavePos = ftell(file);
\r
291 int nFilesize = -1;
\r
292 if (fseek(file, 0, SEEK_END) == 0)
\r
293 nFilesize = ftell(file);
\r
294 fseek(file, nSavePos, SEEK_SET);
\r
305 uint64 GetRand(uint64 nMax)
\r
310 // The range of the random source must be a multiple of the modulus
\r
311 // to give every possible output value an equal possibility
\r
312 uint64 nRange = (_UI64_MAX / nMax) * nMax;
\r
315 RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
\r
316 while (nRand >= nRange);
\r
317 return (nRand % nMax);
\r
330 // "Never go to sea with two chronometers; take one or three."
\r
331 // Our three chronometers are:
\r
333 // - Median of other server's clocks
\r
336 // note: NTP isn't implemented yet, so until then we just use the median
\r
337 // of other nodes clocks to correct ours.
\r
345 static int64 nTimeOffset = 0;
\r
347 int64 GetAdjustedTime()
\r
349 return GetTime() + nTimeOffset;
\r
352 void AddTimeData(unsigned int ip, int64 nTime)
\r
354 int64 nOffsetSample = nTime - GetTime();
\r
356 // Ignore duplicates
\r
357 static set<unsigned int> setKnown;
\r
358 if (!setKnown.insert(ip).second)
\r
362 static vector<int64> vTimeOffsets;
\r
363 if (vTimeOffsets.empty())
\r
364 vTimeOffsets.push_back(0);
\r
365 vTimeOffsets.push_back(nOffsetSample);
\r
366 printf("Added time data, samples %d, ip %08x, offset %+I64d (%+I64d minutes)\n", vTimeOffsets.size(), ip, vTimeOffsets.back(), vTimeOffsets.back()/60);
\r
367 if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
\r
369 sort(vTimeOffsets.begin(), vTimeOffsets.end());
\r
370 int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2];
\r
371 nTimeOffset = nMedian;
\r
372 if ((nMedian > 0 ? nMedian : -nMedian) > 5 * 60)
\r
374 // Only let other nodes change our clock so far before we
\r
375 // go to the NTP servers
\r
376 /// todo: Get time from NTP servers, then set a flag
\r
377 /// to make sure it doesn't get changed again
\r
379 foreach(int64 n, vTimeOffsets)
\r
380 printf("%+I64d ", n);
\r
381 printf("| nTimeOffset = %+I64d (%+I64d minutes)\n", nTimeOffset, nTimeOffset/60);
\r