// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "util.h" #include "chainparamsbase.h" #include "sync.h" #include "ui_interface.h" #include "uint256.h" #include "version.h" #include #include #ifndef WIN32 // for posix_fallocate #ifdef __linux_ #ifdef _POSIX_C_SOURCE #undef _POSIX_C_SOURCE #endif #define _POSIX_C_SOURCE 200112L #include #endif #include #include #include #include #else #ifdef _MSC_VER #pragma warning(disable:4786) #pragma warning(disable:4804) #pragma warning(disable:4805) #pragma warning(disable:4717) #endif #ifdef _WIN32_WINNT #undef _WIN32_WINNT #endif #define _WIN32_WINNT 0x0501 #ifdef _WIN32_IE #undef _WIN32_IE #endif #define _WIN32_IE 0x0501 #define WIN32_LEAN_AND_MEAN 1 #ifndef NOMINMAX #define NOMINMAX #endif #include /* for _commit */ #include #endif #include // for to_lower() #include #include // for startswith() and endswith() #include #include #include #include #include #include #include // Work around clang compilation problem in Boost 1.46: // /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup // See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options // http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION namespace boost { namespace program_options { std::string to_internal(const std::string&); } } using namespace std; map mapArgs; map > mapMultiArgs; bool fDebug = false; bool fPrintToConsole = false; bool fPrintToDebugLog = true; bool fDaemon = false; bool fServer = false; string strMiscWarning; bool fLogTimestamps = false; volatile bool fReopenDebugLog = false; CClientUIInterface uiInterface; // Init OpenSSL library multithreading support static CCriticalSection** ppmutexOpenSSL; void locking_callback(int mode, int i, const char* file, int line) { if (mode & CRYPTO_LOCK) { ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]); } else { LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]); } } // Init class CInit { public: CInit() { // Init OpenSSL library multithreading support ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*)); for (int i = 0; i < CRYPTO_num_locks(); i++) ppmutexOpenSSL[i] = new CCriticalSection(); CRYPTO_set_locking_callback(locking_callback); #ifdef WIN32 // Seed OpenSSL PRNG with current contents of the screen RAND_screen(); #endif // Seed OpenSSL PRNG with performance counter RandAddSeed(); } ~CInit() { // Securely erase the memory used by the PRNG RAND_cleanup(); // Shutdown OpenSSL library multithreading support CRYPTO_set_locking_callback(NULL); for (int i = 0; i < CRYPTO_num_locks(); i++) delete ppmutexOpenSSL[i]; OPENSSL_free(ppmutexOpenSSL); } } instance_of_cinit; void RandAddSeed() { // Seed with CPU performance counter int64_t nCounter = GetPerformanceCounter(); RAND_add(&nCounter, sizeof(nCounter), 1.5); memset(&nCounter, 0, sizeof(nCounter)); } void RandAddSeedPerfmon() { RandAddSeed(); // This can take up to 2 seconds, so only do it every 10 minutes static int64_t nLastPerfmon; if (GetTime() < nLastPerfmon + 10 * 60) return; nLastPerfmon = GetTime(); #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]; memset(pdata, 0, sizeof(pdata)); unsigned long nSize = sizeof(pdata); long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize); RegCloseKey(HKEY_PERFORMANCE_DATA); if (ret == ERROR_SUCCESS) { RAND_add(pdata, nSize, nSize/100.0); OPENSSL_cleanse(pdata, nSize); LogPrint("rand", "RandAddSeed() %lu bytes\n", nSize); } #endif } 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_t nRange = (std::numeric_limits::max() / nMax) * nMax; uint64_t nRand = 0; do RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); while (nRand >= nRange); return (nRand % nMax); } int GetRandInt(int nMax) { return GetRand(nMax); } uint256 GetRandHash() { uint256 hash; RAND_bytes((unsigned char*)&hash, sizeof(hash)); return hash; } // LogPrintf() has been broken a couple of times now // by well-meaning people adding mutexes in the most straightforward way. // It breaks because it may be called by global destructors during shutdown. // Since the order of destruction of static/global objects is undefined, // defining a mutex as a global object doesn't work (the mutex gets // destroyed, and then some later destructor calls OutputDebugStringF, // maybe indirectly, and you get a core dump at shutdown trying to lock // the mutex). static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT; // We use boost::call_once() to make sure these are initialized in // in a thread-safe manner the first time it is called: static FILE* fileout = NULL; static boost::mutex* mutexDebugLog = NULL; static void DebugPrintInit() { assert(fileout == NULL); assert(mutexDebugLog == NULL); boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; fileout = fopen(pathDebug.string().c_str(), "a"); if (fileout) setbuf(fileout, NULL); // unbuffered mutexDebugLog = new boost::mutex(); } bool LogAcceptCategory(const char* category) { if (category != NULL) { if (!fDebug) return false; // Give each thread quick access to -debug settings. // This helps prevent issues debugging global destructors, // where mapMultiArgs might be deleted before another // global destructor calls LogPrint() static boost::thread_specific_ptr > ptrCategory; if (ptrCategory.get() == NULL) { const vector& categories = mapMultiArgs["-debug"]; ptrCategory.reset(new set(categories.begin(), categories.end())); // thread_specific_ptr automatically deletes the set when the thread ends. } const set& setCategories = *ptrCategory.get(); // if not debugging everything and not debugging specific category, LogPrint does nothing. if (setCategories.count(string("")) == 0 && setCategories.count(string(category)) == 0) return false; } return true; } int LogPrintStr(const std::string &str) { int ret = 0; // Returns total number of characters written if (fPrintToConsole) { // print to console ret = fwrite(str.data(), 1, str.size(), stdout); } else if (fPrintToDebugLog) { static bool fStartedNewLine = true; boost::call_once(&DebugPrintInit, debugPrintInitFlag); if (fileout == NULL) return ret; boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); // reopen the log file, if requested if (fReopenDebugLog) { fReopenDebugLog = false; boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) setbuf(fileout, NULL); // unbuffered } // Debug print useful for profiling if (fLogTimestamps && fStartedNewLine) ret += fprintf(fileout, "%s ", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str()); if (!str.empty() && str[str.size()-1] == '\n') fStartedNewLine = true; else fStartedNewLine = false; ret = fwrite(str.data(), 1, str.size(), fileout); } return ret; } string FormatMoney(int64_t n, bool fPlus) { // Note: not using straight sprintf here because we do NOT want // localized number formatting. int64_t n_abs = (n > 0 ? n : -n); int64_t quotient = n_abs/COIN; int64_t remainder = n_abs%COIN; string str = strprintf("%d.%08d", quotient, remainder); // Right-trim excess zeros before the decimal point: int nTrim = 0; for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i) ++nTrim; if (nTrim) str.erase(str.size()-nTrim, nTrim); if (n < 0) str.insert((unsigned int)0, 1, '-'); else if (fPlus && n > 0) str.insert((unsigned int)0, 1, '+'); return str; } bool ParseMoney(const string& str, int64_t& nRet) { return ParseMoney(str.c_str(), nRet); } bool ParseMoney(const char* pszIn, int64_t& nRet) { string strWhole; int64_t nUnits = 0; const char* p = pszIn; while (isspace(*p)) p++; for (; *p; p++) { if (*p == '.') { p++; int64_t nMult = CENT*10; while (isdigit(*p) && (nMult > 0)) { nUnits += nMult * (*p++ - '0'); nMult /= 10; } break; } if (isspace(*p)) break; if (!isdigit(*p)) return false; strWhole.insert(strWhole.end(), *p); } for (; *p; p++) if (!isspace(*p)) return false; if (strWhole.size() > 10) // guard against 63 bit overflow return false; if (nUnits < 0 || nUnits > COIN) return false; int64_t nWhole = atoi64(strWhole); int64_t nValue = nWhole*COIN + nUnits; nRet = nValue; return true; } // safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything // even possibly remotely dangerous like & or > static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@"); string SanitizeString(const string& str) { string strResult; for (std::string::size_type i = 0; i < str.size(); i++) { if (safeChars.find(str[i]) != std::string::npos) strResult.push_back(str[i]); } return strResult; } const signed char p_util_hexdigit[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,-1,-1,-1,-1,-1, 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, -1,0xa,0xb,0xc,0xd,0xe,0xf,-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,0xa,0xb,0xc,0xd,0xe,0xf,-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,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; bool IsHex(const string& str) { BOOST_FOREACH(char c, str) { if (HexDigit(c) < 0) return false; } return (str.size() > 0) && (str.size()%2 == 0); } vector ParseHex(const char* psz) { // convert hex dump to vector vector vch; while (true) { while (isspace(*psz)) psz++; signed char c = HexDigit(*psz++); if (c == (signed char)-1) break; unsigned char n = (c << 4); c = HexDigit(*psz++); if (c == (signed char)-1) break; n |= c; vch.push_back(n); } return vch; } vector ParseHex(const string& str) { return ParseHex(str.c_str()); } static void InterpretNegativeSetting(string name, map& mapSettingsRet) { // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set if (name.find("-no") == 0) { std::string positive("-"); positive.append(name.begin()+3, name.end()); if (mapSettingsRet.count(positive) == 0) { bool value = !GetBoolArg(name, false); mapSettingsRet[positive] = (value ? "1" : "0"); } } } void ParseParameters(int argc, const char* const argv[]) { mapArgs.clear(); mapMultiArgs.clear(); for (int i = 1; i < argc; i++) { std::string str(argv[i]); std::string strValue; size_t is_index = str.find('='); if (is_index != std::string::npos) { strValue = str.substr(is_index+1); str = str.substr(0, is_index); } #ifdef WIN32 boost::to_lower(str); if (boost::algorithm::starts_with(str, "/")) str = "-" + str.substr(1); #endif if (str[0] != '-') break; // Interpret --foo as -foo. // If both --foo and -foo are set, the last takes effect. if (str.length() > 1 && str[1] == '-') str = str.substr(1); mapArgs[str] = strValue; mapMultiArgs[str].push_back(strValue); } // New 0.6 features: BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs) { // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set InterpretNegativeSetting(entry.first, mapArgs); } } std::string GetArg(const std::string& strArg, const std::string& strDefault) { if (mapArgs.count(strArg)) return mapArgs[strArg]; return strDefault; } int64_t GetArg(const std::string& strArg, int64_t nDefault) { if (mapArgs.count(strArg)) return atoi64(mapArgs[strArg]); return nDefault; } bool GetBoolArg(const std::string& strArg, bool fDefault) { if (mapArgs.count(strArg)) { if (mapArgs[strArg].empty()) return true; return (atoi(mapArgs[strArg]) != 0); } return fDefault; } bool SoftSetArg(const std::string& strArg, const std::string& strValue) { if (mapArgs.count(strArg)) return false; mapArgs[strArg] = strValue; return true; } bool SoftSetBoolArg(const std::string& strArg, bool fValue) { if (fValue) return SoftSetArg(strArg, std::string("1")); else return SoftSetArg(strArg, std::string("0")); } 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; } string EncodeBase64(const string& str) { 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) { int dec = decode64_table[(unsigned char)*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; } } 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[(unsigned char)p[2]] != -1) *pfInvalid = true; break; case 3: // 4n+3 base64 characters processed: require '=' if (left || p[0] != '=' || decode64_table[(unsigned char)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()); } string EncodeBase32(const unsigned char* pch, size_t len) { static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567"; string strRet=""; strRet.reserve((len+4)/5*8); int mode=0, left=0; const unsigned char *pchEnd = pch+len; while (pch> 3]; left = (enc & 7) << 2; mode = 1; break; case 1: // we have three bits strRet += pbase32[left | (enc >> 6)]; strRet += pbase32[(enc >> 1) & 31]; left = (enc & 1) << 4; mode = 2; break; case 2: // we have one bit strRet += pbase32[left | (enc >> 4)]; left = (enc & 15) << 1; mode = 3; break; case 3: // we have four bits strRet += pbase32[left | (enc >> 7)]; strRet += pbase32[(enc >> 2) & 31]; left = (enc & 3) << 3; mode = 4; break; case 4: // we have two bits strRet += pbase32[left | (enc >> 5)]; strRet += pbase32[enc & 31]; mode = 0; } } static const int nPadding[5] = {0, 6, 4, 3, 1}; if (mode) { strRet += pbase32[left]; for (int n=0; n DecodeBase32(const char* p, bool* pfInvalid) { static const int decode32_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, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -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, 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, -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))*5/8); int mode = 0; int left = 0; while (1) { int dec = decode32_table[(unsigned char)*p]; if (dec == -1) break; p++; switch (mode) { case 0: // we have no bits and get 5 left = dec; mode = 1; break; case 1: // we have 5 bits and keep 2 vchRet.push_back((left<<3) | (dec>>2)); left = dec & 3; mode = 2; break; case 2: // we have 2 bits and keep 7 left = left << 5 | dec; mode = 3; break; case 3: // we have 7 bits and keep 4 vchRet.push_back((left<<1) | (dec>>4)); left = dec & 15; mode = 4; break; case 4: // we have 4 bits, and keep 1 vchRet.push_back((left<<4) | (dec>>1)); left = dec & 1; mode = 5; break; case 5: // we have 1 bit, and keep 6 left = left << 5 | dec; mode = 6; break; case 6: // we have 6 bits, and keep 3 vchRet.push_back((left<<2) | (dec>>3)); left = dec & 7; mode = 7; break; case 7: // we have 3 bits, and keep 0 vchRet.push_back((left<<5) | dec); mode = 0; break; } } if (pfInvalid) switch (mode) { case 0: // 8n base32 characters processed: ok break; case 1: // 8n+1 base32 characters processed: impossible case 3: // +3 case 6: // +6 *pfInvalid = true; break; case 2: // 8n+2 base32 characters processed: require '======' if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(unsigned char)p[6]] != -1) *pfInvalid = true; break; case 4: // 8n+4 base32 characters processed: require '====' if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(unsigned char)p[4]] != -1) *pfInvalid = true; break; case 5: // 8n+5 base32 characters processed: require '===' if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(unsigned char)p[3]] != -1) *pfInvalid = true; break; case 7: // 8n+7 base32 characters processed: require '=' if (left || p[0] != '=' || decode32_table[(unsigned char)p[1]] != -1) *pfInvalid = true; break; } return vchRet; } string DecodeBase32(const string& str) { vector vchRet = DecodeBase32(str.c_str()); return string((const char*)&vchRet[0], vchRet.size()); } static std::string FormatException(std::exception* pex, const char* pszThread) { #ifdef WIN32 char pszModule[MAX_PATH] = ""; GetModuleFileNameA(NULL, pszModule, sizeof(pszModule)); #else const char* pszModule = "bitcoin"; #endif if (pex) return strprintf( "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread); else return strprintf( "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread); } void PrintExceptionContinue(std::exception* pex, const char* pszThread) { std::string message = FormatException(pex, pszThread); LogPrintf("\n\n************************\n%s\n", message); fprintf(stderr, "\n\n************************\n%s\n", message.c_str()); strMiscWarning = message; } boost::filesystem::path GetDefaultDataDir() { namespace fs = boost::filesystem; // Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin // Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin // Mac: ~/Library/Application Support/Bitcoin // Unix: ~/.bitcoin #ifdef WIN32 // Windows return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin"; #else fs::path pathRet; char* pszHome = getenv("HOME"); if (pszHome == NULL || strlen(pszHome) == 0) pathRet = fs::path("/"); else pathRet = fs::path(pszHome); #ifdef MAC_OSX // Mac pathRet /= "Library/Application Support"; TryCreateDirectory(pathRet); return pathRet / "Bitcoin"; #else // Unix return pathRet / ".bitcoin"; #endif #endif } static boost::filesystem::path pathCached[CBaseChainParams::MAX_NETWORK_TYPES+1]; static CCriticalSection csPathCached; const boost::filesystem::path &GetDataDir(bool fNetSpecific) { namespace fs = boost::filesystem; LOCK(csPathCached); int nNet = CBaseChainParams::MAX_NETWORK_TYPES; if (fNetSpecific) nNet = BaseParams().NetworkID(); fs::path &path = pathCached[nNet]; // This can be called during exceptions by LogPrintf(), so we cache the // value so we don't have to do memory allocations after that. if (!path.empty()) return path; if (mapArgs.count("-datadir")) { path = fs::system_complete(mapArgs["-datadir"]); if (!fs::is_directory(path)) { path = ""; return path; } } else { path = GetDefaultDataDir(); } if (fNetSpecific) path /= BaseParams().DataDir(); fs::create_directories(path); return path; } void ClearDatadirCache() { std::fill(&pathCached[0], &pathCached[CBaseChainParams::MAX_NETWORK_TYPES+1], boost::filesystem::path()); } boost::filesystem::path GetConfigFile() { boost::filesystem::path pathConfigFile(GetArg("-conf", "bitcoin.conf")); if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; return pathConfigFile; } void ReadConfigFile(map& mapSettingsRet, map >& mapMultiSettingsRet) { boost::filesystem::ifstream streamConfig(GetConfigFile()); if (!streamConfig.good()) return; // No bitcoin.conf file is OK set setOptions; setOptions.insert("*"); for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it) { // Don't overwrite existing settings so command line settings override bitcoin.conf string strKey = string("-") + it->string_key; if (mapSettingsRet.count(strKey) == 0) { mapSettingsRet[strKey] = it->value[0]; // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set) InterpretNegativeSetting(strKey, mapSettingsRet); } mapMultiSettingsRet[strKey].push_back(it->value[0]); } // If datadir is changed in .conf file: ClearDatadirCache(); } boost::filesystem::path GetPidFile() { boost::filesystem::path pathPidFile(GetArg("-pid", "bitcoind.pid")); if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile; return pathPidFile; } #ifndef WIN32 void CreatePidFile(const boost::filesystem::path &path, pid_t pid) { FILE* file = fopen(path.string().c_str(), "w"); if (file) { fprintf(file, "%d\n", pid); fclose(file); } } #endif bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) { #ifdef WIN32 return MoveFileExA(src.string().c_str(), dest.string().c_str(), MOVEFILE_REPLACE_EXISTING); #else int rc = std::rename(src.string().c_str(), dest.string().c_str()); return (rc == 0); #endif /* WIN32 */ } // Ignores exceptions thrown by Boost's create_directory if the requested directory exists. // Specifically handles case where path p exists, but it wasn't possible for the user to // write to the parent directory. bool TryCreateDirectory(const boost::filesystem::path& p) { try { return boost::filesystem::create_directory(p); } catch (boost::filesystem::filesystem_error) { if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p)) throw; } // create_directory didn't create the directory, it had to have existed already return false; } void FileCommit(FILE *fileout) { fflush(fileout); // harmless if redundantly called #ifdef WIN32 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout)); FlushFileBuffers(hFile); #else #if defined(__linux__) || defined(__NetBSD__) fdatasync(fileno(fileout)); #elif defined(__APPLE__) && defined(F_FULLFSYNC) fcntl(fileno(fileout), F_FULLFSYNC, 0); #else fsync(fileno(fileout)); #endif #endif } bool TruncateFile(FILE *file, unsigned int length) { #if defined(WIN32) return _chsize(_fileno(file), length) == 0; #else return ftruncate(fileno(file), length) == 0; #endif } // this function tries to raise the file descriptor limit to the requested number. // It returns the actual file descriptor limit (which may be more or less than nMinFD) int RaiseFileDescriptorLimit(int nMinFD) { #if defined(WIN32) return 2048; #else struct rlimit limitFD; if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) { if (limitFD.rlim_cur < (rlim_t)nMinFD) { limitFD.rlim_cur = nMinFD; if (limitFD.rlim_cur > limitFD.rlim_max) limitFD.rlim_cur = limitFD.rlim_max; setrlimit(RLIMIT_NOFILE, &limitFD); getrlimit(RLIMIT_NOFILE, &limitFD); } return limitFD.rlim_cur; } return nMinFD; // getrlimit failed, assume it's fine #endif } // this function tries to make a particular range of a file allocated (corresponding to disk space) // it is advisory, and the range specified in the arguments will never contain live data void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) { #if defined(WIN32) // Windows-specific version HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file)); LARGE_INTEGER nFileSize; int64_t nEndPos = (int64_t)offset + length; nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF; nFileSize.u.HighPart = nEndPos >> 32; SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN); SetEndOfFile(hFile); #elif defined(MAC_OSX) // OSX specific version fstore_t fst; fst.fst_flags = F_ALLOCATECONTIG; fst.fst_posmode = F_PEOFPOSMODE; fst.fst_offset = 0; fst.fst_length = (off_t)offset + length; fst.fst_bytesalloc = 0; if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) { fst.fst_flags = F_ALLOCATEALL; fcntl(fileno(file), F_PREALLOCATE, &fst); } ftruncate(fileno(file), fst.fst_length); #elif defined(__linux__) // Version using posix_fallocate off_t nEndPos = (off_t)offset + length; posix_fallocate(fileno(file), 0, nEndPos); #else // Fallback version // TODO: just write one byte per block static const char buf[65536] = {}; fseek(file, offset, SEEK_SET); while (length > 0) { unsigned int now = 65536; if (length < now) now = length; fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway length -= now; } #endif } void ShrinkDebugFile() { // Scroll debug.log if it's getting too big boost::filesystem::path pathLog = GetDataDir() / "debug.log"; FILE* file = fopen(pathLog.string().c_str(), "r"); if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000) { // Restart the file with some of the end char pch[200000]; fseek(file, -sizeof(pch), SEEK_END); int nBytes = fread(pch, 1, sizeof(pch), file); fclose(file); file = fopen(pathLog.string().c_str(), "w"); if (file) { fwrite(pch, 1, nBytes, file); fclose(file); } } else if (file != NULL) fclose(file); } static int64_t nMockTime = 0; // For unit testing int64_t GetTime() { if (nMockTime) return nMockTime; return time(NULL); } void SetMockTime(int64_t nMockTimeIn) { nMockTime = nMockTimeIn; } uint32_t insecure_rand_Rz = 11; uint32_t insecure_rand_Rw = 11; void seed_insecure_rand(bool fDeterministic) { //The seed values have some unlikely fixed points which we avoid. if(fDeterministic) { insecure_rand_Rz = insecure_rand_Rw = 11; } else { uint32_t tmp; do { RAND_bytes((unsigned char*)&tmp, 4); } while(tmp == 0 || tmp == 0x9068ffffU); insecure_rand_Rz = tmp; do { RAND_bytes((unsigned char*)&tmp, 4); } while(tmp == 0 || tmp == 0x464fffffU); insecure_rand_Rw = tmp; } } string FormatVersion(int nVersion) { if (nVersion%100 == 0) return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100); else return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100); } string FormatFullVersion() { return CLIENT_BUILD; } // 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(); } #ifdef WIN32 boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate) { namespace fs = boost::filesystem; char pszPath[MAX_PATH] = ""; if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate)) { return fs::path(pszPath); } LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n"); return fs::path(""); } #endif boost::filesystem::path GetTempPath() { #if BOOST_FILESYSTEM_VERSION == 3 return boost::filesystem::temp_directory_path(); #else // TODO: remove when we don't support filesystem v2 anymore boost::filesystem::path path; #ifdef WIN32 char pszPath[MAX_PATH] = ""; if (GetTempPathA(MAX_PATH, pszPath)) path = boost::filesystem::path(pszPath); #else path = boost::filesystem::path("/tmp"); #endif if (path.empty() || !boost::filesystem::is_directory(path)) { LogPrintf("GetTempPath(): failed to find temp path\n"); return boost::filesystem::path(""); } return path; #endif } void runCommand(std::string strCommand) { int nErr = ::system(strCommand.c_str()); if (nErr) LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr); } void RenameThread(const char* name) { #if defined(PR_SET_NAME) // Only the first 15 characters are used (16 - NUL terminator) ::prctl(PR_SET_NAME, name, 0, 0, 0); #elif 0 && (defined(__FreeBSD__) || defined(__OpenBSD__)) // TODO: This is currently disabled because it needs to be verified to work // on FreeBSD or OpenBSD first. When verified the '0 &&' part can be // removed. pthread_set_name_np(pthread_self(), name); #elif defined(MAC_OSX) && defined(__MAC_OS_X_VERSION_MAX_ALLOWED) // pthread_setname_np is XCode 10.6-and-later #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 pthread_setname_np(name); #endif #else // Prevent warnings for unused parameters... (void)name; #endif } bool ParseInt32(const std::string& str, int32_t *out) { char *endp = NULL; errno = 0; // strtol will not set errno if valid long int n = strtol(str.c_str(), &endp, 10); if(out) *out = (int)n; // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit // platforms the size of these types may be different. return endp && *endp == 0 && !errno && n >= std::numeric_limits::min() && n <= std::numeric_limits::max(); } void SetupEnvironment() { #ifndef WIN32 try { #if BOOST_FILESYSTEM_VERSION == 3 boost::filesystem::path::codecvt(); // Raises runtime error if current locale is invalid #else // boost filesystem v2 std::locale(); // Raises runtime error if current locale is invalid #endif } catch(std::runtime_error &e) { setenv("LC_ALL", "C", 1); // Force C locale } #endif } std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) { // std::locale takes ownership of the pointer std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat)); std::stringstream ss; ss.imbue(loc); ss << boost::posix_time::from_time_t(nTime); return ss.str(); } std::string FormatParagraph(const std::string in, size_t width, size_t indent) { std::stringstream out; size_t col = 0; size_t ptr = 0; while(ptr < in.size()) { // Find beginning of next word ptr = in.find_first_not_of(' ', ptr); if (ptr == std::string::npos) break; // Find end of next word size_t endword = in.find_first_of(' ', ptr); if (endword == std::string::npos) endword = in.size(); // Add newline and indentation if this wraps over the allowed width if (col > 0) { if ((col + endword - ptr) > width) { out << '\n'; for(size_t i=0; i