X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.h;h=df1a3b1293f71098ad0efc8c1113f1d5df618b09;hb=21c897e170c14da4754fb699d701b9980f092959;hp=752bb4d64a56a690b0a16cda5950edfb2f846e96;hpb=1e3f8efde20dd2244de1b888195b876fc2cec560;p=novacoin.git diff --git a/src/util.h b/src/util.h index 752bb4d..df1a3b1 100644 --- a/src/util.h +++ b/src/util.h @@ -1,6 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2012 The Bitcoin developers -// Copyright (c) 2012 The PPCoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_UTIL_H @@ -13,7 +12,7 @@ #include #include #else -typedef int pid_t; /* define for windows compatiblity */ +typedef int pid_t; /* define for Windows compatibility */ #endif #include #include @@ -22,10 +21,6 @@ typedef int pid_t; /* define for windows compatiblity */ #include #include #include -#include -#include -#include -#include #include #include @@ -40,18 +35,16 @@ typedef unsigned long long uint64; static const int64 COIN = 1000000; static const int64 CENT = 10000; -#define loop for (;;) #define BEGIN(a) ((char*)&(a)) #define END(a) ((char*)&((&(a))[1])) #define UBEGIN(a) ((unsigned char*)&(a)) #define UEND(a) ((unsigned char*)&((&(a))[1])) #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) -#define printf OutputDebugStringF -#ifdef snprintf -#undef snprintf -#endif -#define snprintf my_snprintf +#define UVOIDBEGIN(a) ((void*)&(a)) +#define CVOIDBEGIN(a) ((const void*)&(a)) +#define UINTBEGIN(a) ((uint32_t*)&(a)) +#define CUINTBEGIN(a) ((const uint32_t*)&(a)) #ifndef PRI64d #if defined(_MSC_VER) || defined(__MSVCRT__) @@ -65,6 +58,36 @@ static const int64 CENT = 10000; #endif #endif +#ifndef THROW_WITH_STACKTRACE +#define THROW_WITH_STACKTRACE(exception) \ +{ \ + LogStackTrace(); \ + throw (exception); \ +} +void LogStackTrace(); +#endif + + +/* Format characters for (s)size_t and ptrdiff_t */ +#if defined(_MSC_VER) || defined(__MSVCRT__) + /* (s)size_t and ptrdiff_t have the same size specifier in MSVC: + http://msdn.microsoft.com/en-us/library/tcxf1dw6%28v=vs.100%29.aspx + */ + #define PRIszx "Ix" + #define PRIszu "Iu" + #define PRIszd "Id" + #define PRIpdx "Ix" + #define PRIpdu "Iu" + #define PRIpdd "Id" +#else /* C99 standard */ + #define PRIszx "zx" + #define PRIszu "zu" + #define PRIszd "zd" + #define PRIpdx "tx" + #define PRIpdu "tu" + #define PRIpdd "td" +#endif + // This is needed because the foreach macro can't get over the comma in pair #define PAIRTYPE(t1, t2) std::pair @@ -90,11 +113,7 @@ T* alignup(T* p) #define S_IRUSR 0400 #define S_IWUSR 0200 #endif -#define unlink _unlink #else -#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) -#define strlwr(psz) to_lower(psz) -#define _strlwr(psz) to_lower(psz) #define MAX_PATH 1024 inline void Sleep(int64 n) { @@ -104,13 +123,14 @@ inline void Sleep(int64 n) } #endif -#ifndef THROW_WITH_STACKTRACE -#define THROW_WITH_STACKTRACE(exception) \ -{ \ - LogStackTrace(); \ - throw (exception); \ -} -void LogStackTrace(); +/* This GNU C extension enables the compiler to check the format string against the parameters provided. + * X is the number of the "format string" parameter, and Y is the number of the first variadic parameter. + * Parameters count from 1. + */ +#ifdef __GNUC__ +#define ATTR_WARN_PRINTF(X,Y) __attribute__((format(printf,X,Y))) +#else +#define ATTR_WARN_PRINTF(X,Y) #endif @@ -118,9 +138,12 @@ void LogStackTrace(); + + extern std::map mapArgs; extern std::map > mapMultiArgs; extern bool fDebug; +extern bool fDebugNet; extern bool fPrintToConsole; extern bool fPrintToDebugger; extern bool fRequestShutdown; @@ -132,20 +155,38 @@ extern std::string strMiscWarning; extern bool fTestNet; extern bool fNoListen; extern bool fLogTimestamps; +extern bool fReopenDebugLog; void RandAddSeed(); void RandAddSeedPerfmon(); -int OutputDebugStringF(const char* pszFormat, ...); -int my_snprintf(char* buffer, size_t limit, const char* format, ...); +int ATTR_WARN_PRINTF(1,2) OutputDebugStringF(const char* pszFormat, ...); -/* It is not allowed to use va_start with a pass-by-reference argument. - (C++ standard, 18.7, paragraph 3). Use a dummy argument to work around this, and use a - macro to keep similar semantics. +/* + Rationale for the real_strprintf / strprintf construction: + It is not allowed to use va_start with a pass-by-reference argument. + (C++ standard, 18.7, paragraph 3). Use a dummy argument to work around this, and use a + macro to keep similar semantics. */ + +/** Overload strprintf for char*, so that GCC format type warnings can be given */ +std::string ATTR_WARN_PRINTF(1,3) real_strprintf(const char *format, int dummy, ...); +/** Overload strprintf for std::string, to be able to use it with _ (translation). + * This will not support GCC format type warnings (-Wformat) so be careful. + */ std::string real_strprintf(const std::string &format, int dummy, ...); #define strprintf(format, ...) real_strprintf(format, 0, __VA_ARGS__) +std::string vstrprintf(const char *format, va_list ap); + +bool ATTR_WARN_PRINTF(1,2) error(const char *format, ...); + +/* Redefine printf so that it directs output to debug.log + * + * Do this *after* defining the other printf-like functions, because otherwise the + * __attribute__((format(printf,X,Y))) gets expanded to __attribute__((format(OutputDebugStringF,X,Y))) + * which confuses gcc. + */ +#define printf OutputDebugStringF -bool error(const char *format, ...); void LogException(std::exception* pex, const char* pszThread); void PrintException(std::exception* pex, const char* pszThread); void PrintExceptionContinue(std::exception* pex, const char* pszThread); @@ -160,18 +201,25 @@ std::vector DecodeBase64(const char* p, bool* pfInvalid = NULL); std::string DecodeBase64(const std::string& str); std::string EncodeBase64(const unsigned char* pch, size_t len); std::string EncodeBase64(const std::string& str); +std::vector DecodeBase32(const char* p, bool* pfInvalid = NULL); +std::string DecodeBase32(const std::string& str); +std::string EncodeBase32(const unsigned char* pch, size_t len); +std::string EncodeBase32(const std::string& str); void ParseParameters(int argc, const char*const argv[]); bool WildcardMatch(const char* psz, const char* mask); bool WildcardMatch(const std::string& str, const std::string& mask); +void FileCommit(FILE *fileout); int GetFilesize(FILE* file); +bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); boost::filesystem::path GetDefaultDataDir(); const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); boost::filesystem::path GetConfigFile(); boost::filesystem::path GetPidFile(); void CreatePidFile(const boost::filesystem::path &path, pid_t pid); void ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); -bool GetStartOnSystemStartup(); -bool SetStartOnSystemStartup(bool fAutoStart); +#ifdef WIN32 +boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); +#endif void ShrinkDebugFile(); int GetRandInt(int nMax); uint64 GetRand(uint64 nMax); @@ -179,9 +227,11 @@ uint256 GetRandHash(); int64 GetTime(); void SetMockTime(int64 nMockTimeIn); int64 GetAdjustedTime(); +int64 GetTimeOffset(); std::string FormatFullVersion(); std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments); void AddTimeData(const CNetAddr& ip, int64 nTime); +void runCommand(std::string strCommand); @@ -191,154 +241,6 @@ void AddTimeData(const CNetAddr& ip, int64 nTime); - - -/** Wrapped boost mutex: supports recursive locking, but no waiting */ -typedef boost::interprocess::interprocess_recursive_mutex CCriticalSection; - -/** Wrapped boost mutex: supports waiting but not recursive locking */ -typedef boost::interprocess::interprocess_mutex CWaitableCriticalSection; - -#ifdef DEBUG_LOCKORDER -void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false); -void LeaveCritical(); -#else -void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {} -void static inline LeaveCritical() {} -#endif - -/** Wrapper around boost::interprocess::scoped_lock */ -template -class CMutexLock -{ -private: - boost::interprocess::scoped_lock lock; -public: - - void Enter(const char* pszName, const char* pszFile, int nLine) - { - if (!lock.owns()) - { - EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex())); -#ifdef DEBUG_LOCKCONTENTION - if (!lock.try_lock()) - { - printf("LOCKCONTENTION: %s\n", pszName); - printf("Locker: %s:%d\n", pszFile, nLine); -#endif - lock.lock(); -#ifdef DEBUG_LOCKCONTENTION - } -#endif - } - } - - void Leave() - { - if (lock.owns()) - { - lock.unlock(); - LeaveCritical(); - } - } - - bool TryEnter(const char* pszName, const char* pszFile, int nLine) - { - if (!lock.owns()) - { - EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true); - lock.try_lock(); - if (!lock.owns()) - LeaveCritical(); - } - return lock.owns(); - } - - CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::interprocess::defer_lock) - { - if (fTry) - TryEnter(pszName, pszFile, nLine); - else - Enter(pszName, pszFile, nLine); - } - - ~CMutexLock() - { - if (lock.owns()) - LeaveCritical(); - } - - operator bool() - { - return lock.owns(); - } - - boost::interprocess::scoped_lock &GetLock() - { - return lock; - } -}; - -typedef CMutexLock CCriticalBlock; - -#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__) -#define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__) -#define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true) - -#define ENTER_CRITICAL_SECTION(cs) \ - { \ - EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \ - (cs).lock(); \ - } - -#define LEAVE_CRITICAL_SECTION(cs) \ - { \ - (cs).unlock(); \ - LeaveCritical(); \ - } - -#ifdef MAC_OSX -// boost::interprocess::interprocess_semaphore seems to spinlock on OSX; prefer polling instead -class CSemaphore -{ -private: - CCriticalSection cs; - int val; - -public: - CSemaphore(int init) : val(init) {} - - void wait() { - do { - { - LOCK(cs); - if (val>0) { - val--; - return; - } - } - Sleep(100); - } while(1); - } - - bool try_wait() { - LOCK(cs); - if (val>0) { - val--; - return true; - } - return false; - } - - void post() { - LOCK(cs); - val++; - } -}; -#else -typedef boost::interprocess::interprocess_semaphore CSemaphore; -#endif - inline std::string i64tostr(int64 n) { return strprintf("%"PRI64d, n); @@ -390,9 +292,9 @@ inline int64 abs64(int64 n) template std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) { - std::vector rv; - static char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + std::string rv; + static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; rv.reserve((itend-itbegin)*3); for(T it = itbegin; it < itend; ++it) { @@ -403,7 +305,7 @@ std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) rv.push_back(hexmap[val&15]); } - return std::string(rv.begin(), rv.end()); + return rv; } inline std::string HexStr(const std::vector& vch, bool fSpaces=false) @@ -430,7 +332,7 @@ inline int64 GetPerformanceCounter() #else timeval t; gettimeofday(&t, NULL); - nCounter = t.tv_sec * 1000000 + t.tv_usec; + nCounter = (int64) t.tv_sec * 1000000 + t.tv_usec; #endif return nCounter; } @@ -456,6 +358,7 @@ inline std::string DateTimeStrFormat(int64 nTime) return DateTimeStrFormat(strTimestampFormat.c_str(), nTime); } + template void skipspaces(T& it) { @@ -525,20 +428,6 @@ bool SoftSetBoolArg(const std::string& strArg, bool fValue); -// Randomize the stack to help protect against buffer overrun exploits -#define IMPLEMENT_RANDOMIZE_STACK(ThreadFn) \ - { \ - static char nLoops; \ - if (nLoops <= 0) \ - nLoops = GetRand(20) + 1; \ - if (nLoops-- > 1) \ - { \ - ThreadFn; \ - return; \ - } \ - } - - template inline uint256 Hash(const T1 pbegin, const T1 pend) { @@ -550,6 +439,46 @@ inline uint256 Hash(const T1 pbegin, const T1 pend) return hash2; } +class CHashWriter +{ +private: + SHA256_CTX ctx; + +public: + int nType; + int nVersion; + + void Init() { + SHA256_Init(&ctx); + } + + CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) { + Init(); + } + + CHashWriter& write(const char *pch, size_t size) { + SHA256_Update(&ctx, pch, size); + return (*this); + } + + // invalidates the object + uint256 GetHash() { + uint256 hash1; + SHA256_Final((unsigned char*)&hash1, &ctx); + uint256 hash2; + SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); + return hash2; + } + + template + CHashWriter& operator<<(const T& obj) { + // Serialize to this stream + ::Serialize(*this, obj, nType, nVersion); + return (*this); + } +}; + + template inline uint256 Hash(const T1 p1begin, const T1 p1end, const T2 p2begin, const T2 p2end) @@ -587,13 +516,9 @@ inline uint256 Hash(const T1 p1begin, const T1 p1end, template uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) { - // Most of the time is spent allocating and deallocating CDataStream's - // buffer. If this ever needs to be optimized further, make a CStaticStream - // class with its buffer on the stack. - CDataStream ss(nType, nVersion); - ss.reserve(10000); + CHashWriter ss(nType, nVersion); ss << obj; - return Hash(ss.begin(), ss.end()); + return ss.GetHash(); } inline uint160 Hash160(const std::vector& vch) @@ -605,8 +530,22 @@ inline uint160 Hash160(const std::vector& vch) return hash2; } +/** + * Timing-attack-resistant comparison. + * Takes time proportional to length + * of first argument. + */ +template +bool TimingResistantEqual(const T& a, const T& b) +{ + if (b.size() == 0) return a.size() == 0; + size_t accumulator = a.size() ^ b.size(); + for (size_t i = 0; i < a.size(); i++) + accumulator |= a[i] ^ b[i%b.size()]; + return accumulator == 0; +} -/** Median filter over a stream of values. +/** Median filter over a stream of values. * Returns the median of the last N numbers */ template class CMedianFilter @@ -623,7 +562,7 @@ public: vValues.push_back(initial_value); vSorted = vValues; } - + void input(T value) { if(vValues.size() == nSize) @@ -662,65 +601,14 @@ public: } }; +bool NewThread(void(*pfn)(void*), void* parg); - - - - - - - - -// Note: It turns out we might have been able to use boost::thread -// by using TerminateThread(boost::thread.native_handle(), 0); #ifdef WIN32 -typedef HANDLE bitcoin_pthread_t; - -inline bitcoin_pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false) -{ - DWORD nUnused = 0; - HANDLE hthread = - CreateThread( - NULL, // default security - 0, // inherit stack size from parent - (LPTHREAD_START_ROUTINE)pfn, // function pointer - parg, // argument - 0, // creation option, start immediately - &nUnused); // thread identifier - if (hthread == NULL) - { - printf("Error: CreateThread() returned %d\n", GetLastError()); - return (bitcoin_pthread_t)0; - } - if (!fWantHandle) - { - CloseHandle(hthread); - return (bitcoin_pthread_t)-1; - } - return hthread; -} - inline void SetThreadPriority(int nPriority) { SetThreadPriority(GetCurrentThread(), nPriority); } #else -inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false) -{ - pthread_t hthread = 0; - int ret = pthread_create(&hthread, NULL, (void*(*)(void*))pfn, parg); - if (ret != 0) - { - printf("Error: pthread_create() returned %d\n", ret); - return (pthread_t)0; - } - if (!fWantHandle) - { - pthread_detach(hthread); - return (pthread_t)-1; - } - return hthread; -} #define THREAD_PRIORITY_LOWEST PRIO_MAX #define THREAD_PRIORITY_BELOW_NORMAL 2 @@ -744,9 +632,7 @@ inline void ExitThread(size_t nExitCode) } #endif - - - +void RenameThread(const char* name); inline uint32_t ByteReverse(uint32_t value) {