X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.cpp;h=d4d4520b66bd7b7298574eefeac0d4504128a9d9;hb=21d9f36781604e4ca9fc35dc65265593423b73e9;hp=80095fe771361ecbc4e474238e5bf134d4df7b34;hpb=17e2c24645a10354849dec917b31f364e9056d58;p=novacoin.git diff --git a/src/util.cpp b/src/util.cpp index 80095fe..d4d4520 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -2,8 +2,12 @@ // Copyright (c) 2011 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. + +#include + #include "headers.h" #include "strlcpy.h" +#include #include #include #include @@ -30,7 +34,7 @@ string strMiscWarning; bool fTestNet = false; bool fNoListen = false; bool fLogTimestamps = false; - +CMedianFilter vTimeOffsets(200,0); @@ -64,7 +68,7 @@ public: ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex(); CRYPTO_set_locking_callback(locking_callback); -#ifdef __WXMSW__ +#ifdef WIN32 // Seed random number generator with screen scrape and other hardware sources RAND_screen(); #endif @@ -93,7 +97,7 @@ instance_of_cinit; void RandAddSeed() { // Seed with CPU performance counter - int64 nCounter = GetPerformanceCounter(); + int64_t nCounter = GetPerformanceCounter(); RAND_add(&nCounter, sizeof(nCounter), 1.5); memset(&nCounter, 0, sizeof(nCounter)); } @@ -103,12 +107,12 @@ void RandAddSeedPerfmon() RandAddSeed(); // This can take up to 2 seconds, so only do it every 10 minutes - static int64 nLastPerfmon; + static int64_t nLastPerfmon; if (GetTime() < nLastPerfmon + 10 * 60) return; nLastPerfmon = GetTime(); -#ifdef __WXMSW__ +#ifdef WIN32 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom // Seed with the entire set of perfmon data unsigned char pdata[250000]; @@ -125,15 +129,15 @@ void RandAddSeedPerfmon() #endif } -uint64 GetRand(uint64 nMax) +uint64_t GetRand(uint64_t nMax) { if (nMax == 0) return 0; // The range of the random source must be a multiple of the modulus // to give every possible output value an equal possibility - uint64 nRange = (UINT64_MAX / nMax) * nMax; - uint64 nRand = 0; + uint64_t nRange = (std::numeric_limits::max() / nMax) * nMax; + uint64_t nRand = 0; do RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); while (nRand >= nRange); @@ -198,7 +202,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...) } } -#ifdef __WXMSW__ +#ifdef WIN32 if (fPrintToDebugger) { static CCriticalSection cs_OutputDebugStringF; @@ -329,13 +333,13 @@ void ParseString(const string& str, char c, vector& v) } -string FormatMoney(int64 n, bool fPlus) +string FormatMoney(int64_t n, bool fPlus) { // Note: not using straight sprintf here because we do NOT want // localized number formatting. - int64 n_abs = (n > 0 ? n : -n); - int64 quotient = n_abs/COIN; - int64 remainder = n_abs%COIN; + int64_t n_abs = (n > 0 ? n : -n); + int64_t quotient = n_abs/COIN; + int64_t remainder = n_abs%COIN; string str = strprintf("%"PRI64d".%08"PRI64d, quotient, remainder); // Right-trim excess 0's before the decimal point: @@ -353,15 +357,15 @@ string FormatMoney(int64 n, bool fPlus) } -bool ParseMoney(const string& str, int64& nRet) +bool ParseMoney(const string& str, int64_t& nRet) { return ParseMoney(str.c_str(), nRet); } -bool ParseMoney(const char* pszIn, int64& nRet) +bool ParseMoney(const char* pszIn, int64_t& nRet) { string strWhole; - int64 nUnits = 0; + int64_t nUnits = 0; const char* p = pszIn; while (isspace(*p)) p++; @@ -370,7 +374,7 @@ bool ParseMoney(const char* pszIn, int64& nRet) if (*p == '.') { p++; - int64 nMult = CENT*10; + int64_t nMult = CENT*10; while (isdigit(*p) && (nMult > 0)) { nUnits += nMult * (*p++ - '0'); @@ -387,12 +391,12 @@ bool ParseMoney(const char* pszIn, int64& nRet) for (; *p; p++) if (!isspace(*p)) return false; - if (strWhole.size() > 14) + if (strWhole.size() > 10) // guard against 63 bit overflow return false; if (nUnits < 0 || nUnits > COIN) return false; - int64 nWhole = atoi64(strWhole); - int64 nValue = nWhole*COIN + nUnits; + int64_t nWhole = atoi64(strWhole); + int64_t nValue = nWhole*COIN + nUnits; nRet = nValue; return true; @@ -443,7 +447,6 @@ vector ParseHex(const string& str) return ParseHex(str.c_str()); } - void ParseParameters(int argc, char* argv[]) { mapArgs.clear(); @@ -458,7 +461,7 @@ void ParseParameters(int argc, char* argv[]) pszValue = strchr(psz, '='); *pszValue++ = '\0'; } - #ifdef __WXMSW__ + #ifdef WIN32 _strlwr(psz); if (psz[0] == '/') psz[0] = '-'; @@ -470,39 +473,144 @@ void ParseParameters(int argc, char* argv[]) } } +string EncodeBase64(const unsigned char* pch, size_t len) +{ + static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + string strRet=""; + strRet.reserve((len+2)/3*4); + + int mode=0, left=0; + const unsigned char *pchEnd = pch+len; + + while (pch> 2]; + left = (enc & 3) << 4; + mode = 1; + break; + + case 1: // we have two bits + strRet += pbase64[left | (enc >> 4)]; + left = (enc & 15) << 2; + mode = 2; + break; + + case 2: // we have four bits + strRet += pbase64[left | (enc >> 6)]; + strRet += pbase64[enc & 63]; + mode = 0; + break; + } + } + + if (mode) + { + strRet += pbase64[left]; + strRet += '='; + if (mode == 1) + strRet += '='; + } + + return strRet; +} -const char* wxGetTranslation(const char* pszEnglish) +string EncodeBase64(const string& str) { -#ifdef GUI - // Wrapper of wxGetTranslation returning the same const char* type as was passed in - static CCriticalSection cs; - CRITICAL_BLOCK(cs) + return EncodeBase64((const unsigned char*)str.c_str(), str.size()); +} + +vector DecodeBase64(const char* p, bool* pfInvalid) +{ + static const int decode64_table[256] = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, + -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + if (pfInvalid) + *pfInvalid = false; + + vector vchRet; + vchRet.reserve(strlen(p)*3/4); + + int mode = 0; + int left = 0; + + while (1) { - // Look in cache - static map mapCache; - map::iterator mi = mapCache.find(pszEnglish); - if (mi != mapCache.end()) - return (*mi).second; - - // wxWidgets translation - wxString strTranslated = wxGetTranslation(wxString(pszEnglish, wxConvUTF8)); - - // We don't cache unknown strings because caller might be passing in a - // dynamic string and we would keep allocating memory for each variation. - if (strcmp(pszEnglish, strTranslated.utf8_str()) == 0) - return pszEnglish; - - // Add to cache, memory doesn't need to be freed. We only cache because - // we must pass back a pointer to permanently allocated memory. - char* pszCached = new char[strlen(strTranslated.utf8_str())+1]; - strcpy(pszCached, strTranslated.utf8_str()); - mapCache[pszEnglish] = pszCached; - return pszCached; + int dec = decode64_table[*p]; + if (dec == -1) break; + p++; + switch (mode) + { + case 0: // we have no bits and get 6 + left = dec; + mode = 1; + break; + + case 1: // we have 6 bits and keep 4 + vchRet.push_back((left<<2) | (dec>>4)); + left = dec & 15; + mode = 2; + break; + + case 2: // we have 4 bits and get 6, we keep 2 + vchRet.push_back((left<<4) | (dec>>2)); + left = dec & 3; + mode = 3; + break; + + case 3: // we have 2 bits and get 6 + vchRet.push_back((left<<6) | dec); + mode = 0; + break; + } } - return NULL; -#else - return pszEnglish; -#endif + + if (pfInvalid) + switch (mode) + { + case 0: // 4n base64 characters processed: ok + break; + + case 1: // 4n+1 base64 character processed: impossible + *pfInvalid = true; + break; + + case 2: // 4n+2 base64 characters processed: require '==' + if (left || p[0] != '=' || p[1] != '=' || decode64_table[p[2]] != -1) + *pfInvalid = true; + break; + + case 3: // 4n+3 base64 characters processed: require '=' + if (left || p[0] != '=' || decode64_table[p[1]] != -1) + *pfInvalid = true; + break; + } + + return vchRet; +} + +string DecodeBase64(const string& str) +{ + vector vchRet = DecodeBase64(str.c_str()); + return string((const char*)&vchRet[0], vchRet.size()); } @@ -544,7 +652,7 @@ bool WildcardMatch(const string& str, const string& mask) void FormatException(char* pszMessage, std::exception* pex, const char* pszThread) { -#ifdef __WXMSW__ +#ifdef WIN32 char pszModule[MAX_PATH]; pszModule[0] = '\0'; GetModuleFileNameA(NULL, pszModule, sizeof(pszModule)); @@ -573,10 +681,6 @@ void PrintException(std::exception* pex, const char* pszThread) printf("\n\n************************\n%s\n", pszMessage); fprintf(stderr, "\n\n************************\n%s\n", pszMessage); strMiscWarning = pszMessage; -#ifdef GUI - if (wxTheApp && !fDaemon) - MyMessageBox(pszMessage, "Bitcoin", wxOK | wxICON_ERROR); -#endif throw; } @@ -598,10 +702,6 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread) printf("\n\n************************\n%s\n", pszMessage); fprintf(stderr, "\n\n************************\n%s\n", pszMessage); strMiscWarning = pszMessage; -#ifdef GUI - if (wxTheApp && !fDaemon) - boost::thread(boost::bind(ThreadOneMessageBox, string(pszMessage))); -#endif } @@ -611,7 +711,7 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread) -#ifdef __WXMSW__ +#ifdef WIN32 typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate); string MyGetSpecialFolderPath(int nFolder, bool fCreate) @@ -652,7 +752,7 @@ string GetDefaultDataDir() // Windows: C:\Documents and Settings\username\Application Data\Bitcoin // Mac: ~/Library/Application Support/Bitcoin // Unix: ~/.bitcoin -#ifdef __WXMSW__ +#ifdef WIN32 // Windows return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\Bitcoin"; #else @@ -662,7 +762,7 @@ string GetDefaultDataDir() string strHome = pszHome; if (strHome[strHome.size()-1] != '/') strHome += '/'; -#ifdef __WXMAC_OSX__ +#ifdef MAC_OSX // Mac strHome += "Library/Application Support/"; filesystem::create_directory(strHome.c_str()); @@ -813,30 +913,30 @@ void ShrinkDebugFile() // - Median of other nodes's clocks // - The user (asking the user to fix the system clock if the first two disagree) // -static int64 nMockTime = 0; // For unit testing +static int64_t nMockTime = 0; // For unit testing -int64 GetTime() +int64_t GetTime() { if (nMockTime) return nMockTime; return time(NULL); } -void SetMockTime(int64 nMockTimeIn) +void SetMockTime(int64_t nMockTimeIn) { nMockTime = nMockTimeIn; } -static int64 nTimeOffset = 0; +static int64_t nTimeOffset = 0; -int64 GetAdjustedTime() +int64_t GetAdjustedTime() { return GetTime() + nTimeOffset; } -void AddTimeData(unsigned int ip, int64 nTime) +void AddTimeData(unsigned int ip, int64_t nTime) { - int64 nOffsetSample = nTime - GetTime(); + int64_t nOffsetSample = nTime - GetTime(); // Ignore duplicates static set setKnown; @@ -844,15 +944,12 @@ void AddTimeData(unsigned int ip, int64 nTime) return; // Add data - static vector vTimeOffsets; - if (vTimeOffsets.empty()) - vTimeOffsets.push_back(0); - vTimeOffsets.push_back(nOffsetSample); - printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60); + vTimeOffsets.input(nOffsetSample); + printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) { - sort(vTimeOffsets.begin(), vTimeOffsets.end()); - int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2]; + int64_t nMedian = vTimeOffsets.median(); + std::vector vSorted = vTimeOffsets.sorted(); // Only let other nodes change our time by so much if (abs64(nMedian) < 70 * 60) { @@ -867,7 +964,7 @@ void AddTimeData(unsigned int ip, int64 nTime) { // If nobody has a time different than ours but within 5 minutes of ours, give a warning bool fMatch = false; - BOOST_FOREACH(int64 nOffset, vTimeOffsets) + BOOST_FOREACH(int64_t nOffset, vSorted) if (nOffset != 0 && abs64(nOffset) < 5 * 60) fMatch = true; @@ -881,9 +978,12 @@ void AddTimeData(unsigned int ip, int64 nTime) } } } - BOOST_FOREACH(int64 n, vTimeOffsets) - printf("%+"PRI64d" ", n); - printf("| nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60); + if (fDebug) { + BOOST_FOREACH(int64_t n, vSorted) + printf("%+"PRI64d" ", n); + printf("| "); + } + printf("nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60); } } @@ -905,7 +1005,7 @@ string FormatVersion(int nVersion) string FormatFullVersion() { - string s = FormatVersion(VERSION) + pszSubVer; + string s = FormatVersion(CLIENT_VERSION); if (VERSION_IS_BETA) { s += "-"; s += _("beta"); @@ -913,6 +1013,17 @@ string FormatFullVersion() return s; } +// Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014) +std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments) +{ + std::ostringstream ss; + ss << "/"; + ss << name << ":" << FormatVersion(nClientVersion); + if (!comments.empty()) + ss << "(" << boost::algorithm::join(comments, "; ") << ")"; + ss << "/"; + return ss.str(); +}