diff options
Diffstat (limited to 'src')
158 files changed, 3794 insertions, 2753 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 94a582dfac..155adfef7d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,8 +65,10 @@ BITCOIN_CORE_H = \ addrman.h \ alert.h \ allocators.h \ + amount.h \ base58.h \ bloom.h \ + chain.h \ chainparams.h \ chainparamsbase.h \ chainparamsseeds.h \ @@ -101,6 +103,7 @@ BITCOIN_CORE_H = \ script/compressor.h \ script/interpreter.h \ script/script.h \ + script/sigcache.h \ script/sign.h \ script/standard.h \ serialize.h \ @@ -145,6 +148,7 @@ libbitcoin_server_a_SOURCES = \ addrman.cpp \ alert.cpp \ bloom.cpp \ + chain.cpp \ checkpoints.cpp \ init.cpp \ leveldbwrapper.cpp \ @@ -215,6 +219,7 @@ libbitcoin_common_a_SOURCES = \ script/compressor.cpp \ script/interpreter.cpp \ script/script.cpp \ + script/sigcache.cpp \ script/sign.cpp \ script/standard.cpp \ $(BITCOIN_CORE_H) diff --git a/src/addrman.cpp b/src/addrman.cpp index 68948ac7ff..7b674a66e7 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -9,7 +9,7 @@ using namespace std; -int CAddrInfo::GetTriedBucket(const std::vector<unsigned char> &nKey) const +int CAddrInfo::GetTriedBucket(const std::vector<unsigned char>& nKey) const { CDataStream ss1(SER_GETHASH, 0); std::vector<unsigned char> vchKey = GetKey(); @@ -23,7 +23,7 @@ int CAddrInfo::GetTriedBucket(const std::vector<unsigned char> &nKey) const return hash2 % ADDRMAN_TRIED_BUCKET_COUNT; } -int CAddrInfo::GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const +int CAddrInfo::GetNewBucket(const std::vector<unsigned char>& nKey, const CNetAddr& src) const { CDataStream ss1(SER_GETHASH, 0); std::vector<unsigned char> vchGroupKey = GetGroup(); @@ -39,19 +39,19 @@ int CAddrInfo::GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAd bool CAddrInfo::IsTerrible(int64_t nNow) const { - if (nLastTry && nLastTry >= nNow-60) // never remove things tried the last minute + if (nLastTry && nLastTry >= nNow - 60) // never remove things tried the last minute return false; - if (nTime > nNow + 10*60) // came in a flying DeLorean + if (nTime > nNow + 10 * 60) // came in a flying DeLorean return true; - if (nTime==0 || nNow-nTime > ADDRMAN_HORIZON_DAYS*24*60*60) // not seen in recent history + if (nTime == 0 || nNow - nTime > ADDRMAN_HORIZON_DAYS * 24 * 60 * 60) // not seen in recent history return true; - if (nLastSuccess==0 && nAttempts>=ADDRMAN_RETRIES) // tried N times and never a success + if (nLastSuccess == 0 && nAttempts >= ADDRMAN_RETRIES) // tried N times and never a success return true; - if (nNow-nLastSuccess > ADDRMAN_MIN_FAIL_DAYS*24*60*60 && nAttempts>=ADDRMAN_MAX_FAILURES) // N successive failures in the last week + if (nNow - nLastSuccess > ADDRMAN_MIN_FAIL_DAYS * 24 * 60 * 60 && nAttempts >= ADDRMAN_MAX_FAILURES) // N successive failures in the last week return true; return false; @@ -64,23 +64,25 @@ double CAddrInfo::GetChance(int64_t nNow) const int64_t nSinceLastSeen = nNow - nTime; int64_t nSinceLastTry = nNow - nLastTry; - if (nSinceLastSeen < 0) nSinceLastSeen = 0; - if (nSinceLastTry < 0) nSinceLastTry = 0; + if (nSinceLastSeen < 0) + nSinceLastSeen = 0; + if (nSinceLastTry < 0) + nSinceLastTry = 0; fChance *= 600.0 / (600.0 + nSinceLastSeen); // deprioritize very recent attempts away - if (nSinceLastTry < 60*10) + if (nSinceLastTry < 60 * 10) fChance *= 0.01; // deprioritize 50% after each failed attempt - for (int n=0; n<nAttempts; n++) + for (int n = 0; n < nAttempts; n++) fChance /= 1.5; return fChance; } -CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int *pnId) +CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId) { std::map<CNetAddr, int>::iterator it = mapAddr.find(addr); if (it == mapAddr.end()) @@ -93,7 +95,7 @@ CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int *pnId) return NULL; } -CAddrInfo* CAddrMan::Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId) +CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId) { int nId = nIdCount++; mapInfo[nId] = CAddrInfo(addr, addrSource); @@ -127,22 +129,21 @@ void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) int CAddrMan::SelectTried(int nKBucket) { - std::vector<int> &vTried = vvTried[nKBucket]; + std::vector<int>& vTried = vvTried[nKBucket]; // random shuffle the first few elements (using the entire list) // find the least recently tried among them int64_t nOldest = -1; int nOldestPos = -1; - for (unsigned int i = 0; i < ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i < vTried.size(); i++) - { + for (unsigned int i = 0; i < ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i < vTried.size(); i++) { int nPos = GetRandInt(vTried.size() - i) + i; int nTemp = vTried[nPos]; vTried[nPos] = vTried[i]; vTried[i] = nTemp; assert(nOldest == -1 || mapInfo.count(nTemp) == 1); if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess) { - nOldest = nTemp; - nOldestPos = nPos; + nOldest = nTemp; + nOldestPos = nPos; } } @@ -152,18 +153,15 @@ int CAddrMan::SelectTried(int nKBucket) int CAddrMan::ShrinkNew(int nUBucket) { assert(nUBucket >= 0 && (unsigned int)nUBucket < vvNew.size()); - std::set<int> &vNew = vvNew[nUBucket]; + std::set<int>& vNew = vvNew[nUBucket]; // first look for deletable items - for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++) - { + for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++) { assert(mapInfo.count(*it)); - CAddrInfo &info = mapInfo[*it]; - if (info.IsTerrible()) - { - if (--info.nRefCount == 0) - { - SwapRandom(info.nRandomPos, vRandom.size()-1); + CAddrInfo& info = mapInfo[*it]; + if (info.IsTerrible()) { + if (--info.nRefCount == 0) { + SwapRandom(info.nRandomPos, vRandom.size() - 1); vRandom.pop_back(); mapAddr.erase(info); mapInfo.erase(*it); @@ -178,10 +176,8 @@ int CAddrMan::ShrinkNew(int nUBucket) int n[4] = {GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size())}; int nI = 0; int nOldest = -1; - for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++) - { - if (nI == n[0] || nI == n[1] || nI == n[2] || nI == n[3]) - { + for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++) { + if (nI == n[0] || nI == n[1] || nI == n[2] || nI == n[3]) { assert(nOldest == -1 || mapInfo.count(*it) == 1); if (nOldest == -1 || mapInfo[*it].nTime < mapInfo[nOldest].nTime) nOldest = *it; @@ -189,10 +185,9 @@ int CAddrMan::ShrinkNew(int nUBucket) nI++; } assert(mapInfo.count(nOldest) == 1); - CAddrInfo &info = mapInfo[nOldest]; - if (--info.nRefCount == 0) - { - SwapRandom(info.nRandomPos, vRandom.size()-1); + CAddrInfo& info = mapInfo[nOldest]; + if (--info.nRefCount == 0) { + SwapRandom(info.nRandomPos, vRandom.size() - 1); vRandom.pop_back(); mapAddr.erase(info); mapInfo.erase(nOldest); @@ -208,8 +203,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin) assert(vvNew[nOrigin].count(nId) == 1); // remove the entry from all new buckets - for (std::vector<std::set<int> >::iterator it = vvNew.begin(); it != vvNew.end(); it++) - { + for (std::vector<std::set<int> >::iterator it = vvNew.begin(); it != vvNew.end(); it++) { if ((*it).erase(nId)) info.nRefCount--; } @@ -219,11 +213,10 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin) // what tried bucket to move the entry to int nKBucket = info.GetTriedBucket(nKey); - std::vector<int> &vTried = vvTried[nKBucket]; + std::vector<int>& vTried = vvTried[nKBucket]; // first check whether there is place to just add it - if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE) - { + if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE) { vTried.push_back(nId); nTried++; info.fInTried = true; @@ -236,7 +229,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin) // find which new bucket it belongs to assert(mapInfo.count(vTried[nPos]) == 1); int nUBucket = mapInfo[vTried[nPos]].GetNewBucket(nKey); - std::set<int> &vNew = vvNew[nUBucket]; + std::set<int>& vNew = vvNew[nUBucket]; // remove the to-be-replaced tried entry from the tried set CAddrInfo& infoOld = mapInfo[vTried[nPos]]; @@ -245,8 +238,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin) // do not update nTried, as we are going to move something else there immediately // check whether there is place in that one, - if (vNew.size() < ADDRMAN_NEW_BUCKET_SIZE) - { + if (vNew.size() < ADDRMAN_NEW_BUCKET_SIZE) { // if so, move it back there vNew.insert(vTried[nPos]); } else { @@ -261,16 +253,16 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin) return; } -void CAddrMan::Good_(const CService &addr, int64_t nTime) +void CAddrMan::Good_(const CService& addr, int64_t nTime) { int nId; - CAddrInfo *pinfo = Find(addr, &nId); + CAddrInfo* pinfo = Find(addr, &nId); // if not found, bail out if (!pinfo) return; - CAddrInfo &info = *pinfo; + CAddrInfo& info = *pinfo; // check whether we are talking about the exact same CService (including same port) if (info != addr) @@ -289,12 +281,10 @@ void CAddrMan::Good_(const CService &addr, int64_t nTime) // find a bucket it is in now int nRnd = GetRandInt(vvNew.size()); int nUBucket = -1; - for (unsigned int n = 0; n < vvNew.size(); n++) - { - int nB = (n+nRnd) % vvNew.size(); - std::set<int> &vNew = vvNew[nB]; - if (vNew.count(nId)) - { + for (unsigned int n = 0; n < vvNew.size(); n++) { + int nB = (n + nRnd) % vvNew.size(); + std::set<int>& vNew = vvNew[nB]; + if (vNew.count(nId)) { nUBucket = nB; break; } @@ -302,7 +292,8 @@ void CAddrMan::Good_(const CService &addr, int64_t nTime) // if no bucket is found, something bad happened; // TODO: maybe re-add the node, but for now, just bail out - if (nUBucket == -1) return; + if (nUBucket == -1) + return; LogPrint("addrman", "Moving %s to tried\n", addr.ToString()); @@ -310,17 +301,16 @@ void CAddrMan::Good_(const CService &addr, int64_t nTime) MakeTried(info, nId, nUBucket); } -bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty) +bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty) { if (!addr.IsRoutable()) return false; bool fNew = false; int nId; - CAddrInfo *pinfo = Find(addr, &nId); + CAddrInfo* pinfo = Find(addr, &nId); - if (pinfo) - { + if (pinfo) { // periodically update nTime bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60); int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60); @@ -344,7 +334,7 @@ bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimeP // stochastic test: previous nRefCount == N: 2^N times harder to increase it int nFactor = 1; - for (int n=0; n<pinfo->nRefCount; n++) + for (int n = 0; n < pinfo->nRefCount; n++) nFactor *= 2; if (nFactor > 1 && (GetRandInt(nFactor) != 0)) return false; @@ -356,9 +346,8 @@ bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimeP } int nUBucket = pinfo->GetNewBucket(nKey, source); - std::set<int> &vNew = vvNew[nUBucket]; - if (!vNew.count(nId)) - { + std::set<int>& vNew = vvNew[nUBucket]; + if (!vNew.count(nId)) { pinfo->nRefCount++; if (vNew.size() == ADDRMAN_NEW_BUCKET_SIZE) ShrinkNew(nUBucket); @@ -367,15 +356,15 @@ bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimeP return fNew; } -void CAddrMan::Attempt_(const CService &addr, int64_t nTime) +void CAddrMan::Attempt_(const CService& addr, int64_t nTime) { - CAddrInfo *pinfo = Find(addr); + CAddrInfo* pinfo = Find(addr); // if not found, bail out if (!pinfo) return; - CAddrInfo &info = *pinfo; + CAddrInfo& info = *pinfo; // check whether we are talking about the exact same CService (including same port) if (info != addr) @@ -393,37 +382,36 @@ CAddress CAddrMan::Select_(int nUnkBias) double nCorTried = sqrt(nTried) * (100.0 - nUnkBias); double nCorNew = sqrt(nNew) * nUnkBias; - if ((nCorTried + nCorNew)*GetRandInt(1<<30)/(1<<30) < nCorTried) - { + if ((nCorTried + nCorNew) * GetRandInt(1 << 30) / (1 << 30) < nCorTried) { // use a tried node double fChanceFactor = 1.0; - while(1) - { + while (1) { int nKBucket = GetRandInt(vvTried.size()); - std::vector<int> &vTried = vvTried[nKBucket]; - if (vTried.size() == 0) continue; + std::vector<int>& vTried = vvTried[nKBucket]; + if (vTried.size() == 0) + continue; int nPos = GetRandInt(vTried.size()); assert(mapInfo.count(vTried[nPos]) == 1); - CAddrInfo &info = mapInfo[vTried[nPos]]; - if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30)) + CAddrInfo& info = mapInfo[vTried[nPos]]; + if (GetRandInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30)) return info; fChanceFactor *= 1.2; } } else { // use a new node double fChanceFactor = 1.0; - while(1) - { + while (1) { int nUBucket = GetRandInt(vvNew.size()); - std::set<int> &vNew = vvNew[nUBucket]; - if (vNew.size() == 0) continue; + std::set<int>& vNew = vvNew[nUBucket]; + if (vNew.size() == 0) + continue; int nPos = GetRandInt(vNew.size()); std::set<int>::iterator it = vNew.begin(); while (nPos--) it++; assert(mapInfo.count(*it) == 1); - CAddrInfo &info = mapInfo[*it]; - if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30)) + CAddrInfo& info = mapInfo[*it]; + if (GetRandInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30)) return info; fChanceFactor *= 1.2; } @@ -436,69 +424,76 @@ int CAddrMan::Check_() std::set<int> setTried; std::map<int, int> mapNew; - if (vRandom.size() != nTried + nNew) return -7; + if (vRandom.size() != nTried + nNew) + return -7; - for (std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++) - { + for (std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++) { int n = (*it).first; - CAddrInfo &info = (*it).second; - if (info.fInTried) - { - - if (!info.nLastSuccess) return -1; - if (info.nRefCount) return -2; + CAddrInfo& info = (*it).second; + if (info.fInTried) { + if (!info.nLastSuccess) + return -1; + if (info.nRefCount) + return -2; setTried.insert(n); } else { - if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS) return -3; - if (!info.nRefCount) return -4; + if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS) + return -3; + if (!info.nRefCount) + return -4; mapNew[n] = info.nRefCount; } - if (mapAddr[info] != n) return -5; - if (info.nRandomPos<0 || info.nRandomPos>=vRandom.size() || vRandom[info.nRandomPos] != n) return -14; - if (info.nLastTry < 0) return -6; - if (info.nLastSuccess < 0) return -8; + if (mapAddr[info] != n) + return -5; + if (info.nRandomPos < 0 || info.nRandomPos >= vRandom.size() || vRandom[info.nRandomPos] != n) + return -14; + if (info.nLastTry < 0) + return -6; + if (info.nLastSuccess < 0) + return -8; } - if (setTried.size() != nTried) return -9; - if (mapNew.size() != nNew) return -10; + if (setTried.size() != nTried) + return -9; + if (mapNew.size() != nNew) + return -10; - for (int n=0; n<vvTried.size(); n++) - { - std::vector<int> &vTried = vvTried[n]; - for (std::vector<int>::iterator it = vTried.begin(); it != vTried.end(); it++) - { - if (!setTried.count(*it)) return -11; + for (int n = 0; n < vvTried.size(); n++) { + std::vector<int>& vTried = vvTried[n]; + for (std::vector<int>::iterator it = vTried.begin(); it != vTried.end(); it++) { + if (!setTried.count(*it)) + return -11; setTried.erase(*it); } } - for (int n=0; n<vvNew.size(); n++) - { - std::set<int> &vNew = vvNew[n]; - for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++) - { - if (!mapNew.count(*it)) return -12; + for (int n = 0; n < vvNew.size(); n++) { + std::set<int>& vNew = vvNew[n]; + for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++) { + if (!mapNew.count(*it)) + return -12; if (--mapNew[*it] == 0) mapNew.erase(*it); } } - if (setTried.size()) return -13; - if (mapNew.size()) return -15; + if (setTried.size()) + return -13; + if (mapNew.size()) + return -15; return 0; } #endif -void CAddrMan::GetAddr_(std::vector<CAddress> &vAddr) +void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr) { unsigned int nNodes = ADDRMAN_GETADDR_MAX_PCT * vRandom.size() / 100; if (nNodes > ADDRMAN_GETADDR_MAX) nNodes = ADDRMAN_GETADDR_MAX; // gather a list of random nodes, skipping those of low quality - for (unsigned int n = 0; n < vRandom.size(); n++) - { + for (unsigned int n = 0; n < vRandom.size(); n++) { if (vAddr.size() >= nNodes) break; @@ -512,15 +507,15 @@ void CAddrMan::GetAddr_(std::vector<CAddress> &vAddr) } } -void CAddrMan::Connected_(const CService &addr, int64_t nTime) +void CAddrMan::Connected_(const CService& addr, int64_t nTime) { - CAddrInfo *pinfo = Find(addr); + CAddrInfo* pinfo = Find(addr); // if not found, bail out if (!pinfo) return; - CAddrInfo &info = *pinfo; + CAddrInfo& info = *pinfo; // check whether we are talking about the exact same CService (including same port) if (info != addr) diff --git a/src/allocators.cpp b/src/allocators.cpp index 8ecd7206cd..dfe26f1b1e 100644 --- a/src/allocators.cpp +++ b/src/allocators.cpp @@ -37,13 +37,13 @@ static inline size_t GetSystemPageSize() page_size = sSysInfo.dwPageSize; #elif defined(PAGESIZE) // defined in limits.h page_size = PAGESIZE; -#else // assume some POSIX OS +#else // assume some POSIX OS page_size = sysconf(_SC_PAGESIZE); #endif return page_size; } -bool MemoryPageLocker::Lock(const void *addr, size_t len) +bool MemoryPageLocker::Lock(const void* addr, size_t len) { #ifdef WIN32 return VirtualLock(const_cast<void*>(addr), len) != 0; @@ -52,7 +52,7 @@ bool MemoryPageLocker::Lock(const void *addr, size_t len) #endif } -bool MemoryPageLocker::Unlock(const void *addr, size_t len) +bool MemoryPageLocker::Unlock(const void* addr, size_t len) { #ifdef WIN32 return VirtualUnlock(const_cast<void*>(addr), len) != 0; @@ -64,4 +64,3 @@ bool MemoryPageLocker::Unlock(const void *addr, size_t len) LockedPageManager::LockedPageManager() : LockedPageManagerBase<MemoryPageLocker>(GetSystemPageSize()) { } - diff --git a/src/allocators.h b/src/allocators.h index 65a7d08987..6b69e7ae69 100644 --- a/src/allocators.h +++ b/src/allocators.h @@ -26,14 +26,14 @@ * small objects that span up to a few pages, mostly smaller than a page. To support large allocations, * something like an interval tree would be the preferred data structure. */ -template <class Locker> class LockedPageManagerBase +template <class Locker> +class LockedPageManagerBase { public: - LockedPageManagerBase(size_t page_size): - page_size(page_size) + LockedPageManagerBase(size_t page_size) : page_size(page_size) { // Determine bitmask for extracting page from address - assert(!(page_size & (page_size-1))); // size must be power of two + assert(!(page_size & (page_size - 1))); // size must be power of two page_mask = ~(page_size - 1); } @@ -44,22 +44,21 @@ public: // For all pages in affected range, increase lock count - void LockRange(void *p, size_t size) + void LockRange(void* p, size_t size) { boost::mutex::scoped_lock lock(mutex); - if(!size) return; + if (!size) + return; const size_t base_addr = reinterpret_cast<size_t>(p); const size_t start_page = base_addr & page_mask; const size_t end_page = (base_addr + size - 1) & page_mask; - for(size_t page = start_page; page <= end_page; page += page_size) - { + for (size_t page = start_page; page <= end_page; page += page_size) { Histogram::iterator it = histogram.find(page); - if(it == histogram.end()) // Newly locked page + if (it == histogram.end()) // Newly locked page { locker.Lock(reinterpret_cast<void*>(page), page_size); histogram.insert(std::make_pair(page, 1)); - } - else // Page was already locked; increase counter + } else // Page was already locked; increase counter { it->second += 1; } @@ -67,20 +66,20 @@ public: } // For all pages in affected range, decrease lock count - void UnlockRange(void *p, size_t size) + void UnlockRange(void* p, size_t size) { boost::mutex::scoped_lock lock(mutex); - if(!size) return; + if (!size) + return; const size_t base_addr = reinterpret_cast<size_t>(p); const size_t start_page = base_addr & page_mask; const size_t end_page = (base_addr + size - 1) & page_mask; - for(size_t page = start_page; page <= end_page; page += page_size) - { + for (size_t page = start_page; page <= end_page; page += page_size) { Histogram::iterator it = histogram.find(page); assert(it != histogram.end()); // Cannot unlock an area that was not locked // Decrease counter for page, when it is zero, the page will be unlocked it->second -= 1; - if(it->second == 0) // Nothing on the page anymore that keeps it locked + if (it->second == 0) // Nothing on the page anymore that keeps it locked { // Unlock page and remove the count from histogram locker.Unlock(reinterpret_cast<void*>(page), page_size); @@ -101,7 +100,7 @@ private: boost::mutex mutex; size_t page_size, page_mask; // map of page base address to lock count - typedef std::map<size_t,int> Histogram; + typedef std::map<size_t, int> Histogram; Histogram histogram; }; @@ -116,11 +115,11 @@ public: /** Lock memory pages. * addr and len must be a multiple of the system page size */ - bool Lock(const void *addr, size_t len); + bool Lock(const void* addr, size_t len); /** Unlock memory pages. * addr and len must be a multiple of the system page size */ - bool Unlock(const void *addr, size_t len); + bool Unlock(const void* addr, size_t len); }; /** @@ -134,10 +133,10 @@ public: * secure_allocator are created. So instead of having LockedPageManager also be * static-initialized, it is created on demand. */ -class LockedPageManager: public LockedPageManagerBase<MemoryPageLocker> +class LockedPageManager : public LockedPageManagerBase<MemoryPageLocker> { public: - static LockedPageManager& Instance() + static LockedPageManager& Instance() { boost::call_once(LockedPageManager::CreateInstance, LockedPageManager::init_flag); return *LockedPageManager::_instance; @@ -165,11 +164,15 @@ private: // Functions for directly locking/unlocking memory objects. // Intended for non-dynamically allocated structures. // -template<typename T> void LockObject(const T &t) { +template <typename T> +void LockObject(const T& t) +{ LockedPageManager::Instance().LockRange((void*)(&t), sizeof(T)); } -template<typename T> void UnlockObject(const T &t) { +template <typename T> +void UnlockObject(const T& t) +{ OPENSSL_cleanse((void*)(&t), sizeof(T)); LockedPageManager::Instance().UnlockRange((void*)(&t), sizeof(T)); } @@ -178,13 +181,12 @@ template<typename T> void UnlockObject(const T &t) { // Allocator that locks its contents from being paged // out of memory and clears its contents before deletion. // -template<typename T> -struct secure_allocator : public std::allocator<T> -{ +template <typename T> +struct secure_allocator : public std::allocator<T> { // MSVC8 default copy constructor is broken typedef std::allocator<T> base; typedef typename base::size_type size_type; - typedef typename base::difference_type difference_type; + typedef typename base::difference_type difference_type; typedef typename base::pointer pointer; typedef typename base::const_pointer const_pointer; typedef typename base::reference reference; @@ -193,14 +195,18 @@ struct secure_allocator : public std::allocator<T> secure_allocator() throw() {} secure_allocator(const secure_allocator& a) throw() : base(a) {} template <typename U> - secure_allocator(const secure_allocator<U>& a) throw() : base(a) {} + secure_allocator(const secure_allocator<U>& a) throw() : base(a) + { + } ~secure_allocator() throw() {} - template<typename _Other> struct rebind - { typedef secure_allocator<_Other> other; }; + template <typename _Other> + struct rebind { + typedef secure_allocator<_Other> other; + }; - T* allocate(std::size_t n, const void *hint = 0) + T* allocate(std::size_t n, const void* hint = 0) { - T *p; + T* p; p = std::allocator<T>::allocate(n, hint); if (p != NULL) LockedPageManager::Instance().LockRange(p, sizeof(T) * n); @@ -209,8 +215,7 @@ struct secure_allocator : public std::allocator<T> void deallocate(T* p, std::size_t n) { - if (p != NULL) - { + if (p != NULL) { OPENSSL_cleanse(p, sizeof(T) * n); LockedPageManager::Instance().UnlockRange(p, sizeof(T) * n); } @@ -222,13 +227,12 @@ struct secure_allocator : public std::allocator<T> // // Allocator that clears its contents before deletion. // -template<typename T> -struct zero_after_free_allocator : public std::allocator<T> -{ +template <typename T> +struct zero_after_free_allocator : public std::allocator<T> { // MSVC8 default copy constructor is broken typedef std::allocator<T> base; typedef typename base::size_type size_type; - typedef typename base::difference_type difference_type; + typedef typename base::difference_type difference_type; typedef typename base::pointer pointer; typedef typename base::const_pointer const_pointer; typedef typename base::reference reference; @@ -237,10 +241,14 @@ struct zero_after_free_allocator : public std::allocator<T> zero_after_free_allocator() throw() {} zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {} template <typename U> - zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a) {} + zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a) + { + } ~zero_after_free_allocator() throw() {} - template<typename _Other> struct rebind - { typedef zero_after_free_allocator<_Other> other; }; + template <typename _Other> + struct rebind { + typedef zero_after_free_allocator<_Other> other; + }; void deallocate(T* p, std::size_t n) { diff --git a/src/amount.h b/src/amount.h new file mode 100644 index 0000000000..831fa1f6ca --- /dev/null +++ b/src/amount.h @@ -0,0 +1,13 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_AMOUNT_H +#define BITCOIN_AMOUNT_H + +#include <stdint.h> + +typedef int64_t CAmount; + +#endif // BITCOIN_AMOUNT_H diff --git a/src/base58.cpp b/src/base58.cpp index 76f0404a18..d94db2c51b 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -18,7 +18,8 @@ /* All alphanumeric characters except for "0", "I", "O", and "l" */ static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; -bool DecodeBase58(const char *psz, std::vector<unsigned char>& vch) { +bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch) +{ // Skip leading spaces. while (*psz && isspace(*psz)) psz++; @@ -33,7 +34,7 @@ bool DecodeBase58(const char *psz, std::vector<unsigned char>& vch) { // Process the characters. while (*psz && !isspace(*psz)) { // Decode base58 character - const char *ch = strchr(pszBase58, *psz); + const char* ch = strchr(pszBase58, *psz); if (ch == NULL) return false; // Apply "b256 = b256 * 58 + ch". @@ -59,11 +60,12 @@ bool DecodeBase58(const char *psz, std::vector<unsigned char>& vch) { vch.reserve(zeroes + (b256.end() - it)); vch.assign(zeroes, 0x00); while (it != b256.end()) - vch.push_back(*(it++)); + vch.push_back(*(it++)); return true; } -std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) { +std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) +{ // Skip & count leading zeroes. int zeroes = 0; while (pbegin != pend && *pbegin == 0) { @@ -97,15 +99,18 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) return str; } -std::string EncodeBase58(const std::vector<unsigned char>& vch) { +std::string EncodeBase58(const std::vector<unsigned char>& vch) +{ return EncodeBase58(&vch[0], &vch[0] + vch.size()); } -bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet) { +bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet) +{ return DecodeBase58(str.c_str(), vchRet); } -std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn) { +std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn) +{ // add 4-byte hash check to the end std::vector<unsigned char> vch(vchIn); uint256 hash = Hash(vch.begin(), vch.end()); @@ -113,45 +118,49 @@ std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn) { return EncodeBase58(vch); } -bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet) { +bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet) +{ if (!DecodeBase58(psz, vchRet) || - (vchRet.size() < 4)) - { + (vchRet.size() < 4)) { vchRet.clear(); return false; } // re-calculate the checksum, insure it matches the included 4-byte checksum - uint256 hash = Hash(vchRet.begin(), vchRet.end()-4); - if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) - { + uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4); + if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) { vchRet.clear(); return false; } - vchRet.resize(vchRet.size()-4); + vchRet.resize(vchRet.size() - 4); return true; } -bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet) { +bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet) +{ return DecodeBase58Check(str.c_str(), vchRet); } -CBase58Data::CBase58Data() { +CBase58Data::CBase58Data() +{ vchVersion.clear(); vchData.clear(); } -void CBase58Data::SetData(const std::vector<unsigned char> &vchVersionIn, const void* pdata, size_t nSize) { +void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize) +{ vchVersion = vchVersionIn; vchData.resize(nSize); if (!vchData.empty()) memcpy(&vchData[0], pdata, nSize); } -void CBase58Data::SetData(const std::vector<unsigned char> &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend) { +void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend) +{ SetData(vchVersionIn, (void*)pbegin, pend - pbegin); } -bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) { +bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) +{ std::vector<unsigned char> vchTemp; bool rc58 = DecodeBase58Check(psz, vchTemp); if ((!rc58) || (vchTemp.size() < nVersionBytes)) { @@ -167,65 +176,80 @@ bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) { return true; } -bool CBase58Data::SetString(const std::string& str) { +bool CBase58Data::SetString(const std::string& str) +{ return SetString(str.c_str()); } -std::string CBase58Data::ToString() const { +std::string CBase58Data::ToString() const +{ std::vector<unsigned char> vch = vchVersion; vch.insert(vch.end(), vchData.begin(), vchData.end()); return EncodeBase58Check(vch); } -int CBase58Data::CompareTo(const CBase58Data& b58) const { - if (vchVersion < b58.vchVersion) return -1; - if (vchVersion > b58.vchVersion) return 1; - if (vchData < b58.vchData) return -1; - if (vchData > b58.vchData) return 1; +int CBase58Data::CompareTo(const CBase58Data& b58) const +{ + if (vchVersion < b58.vchVersion) + return -1; + if (vchVersion > b58.vchVersion) + return 1; + if (vchData < b58.vchData) + return -1; + if (vchData > b58.vchData) + return 1; return 0; } -namespace { +namespace +{ +class CBitcoinAddressVisitor : public boost::static_visitor<bool> +{ +private: + CBitcoinAddress* addr; - class CBitcoinAddressVisitor : public boost::static_visitor<bool> { - private: - CBitcoinAddress *addr; - public: - CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { } +public: + CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {} - bool operator()(const CKeyID &id) const { return addr->Set(id); } - bool operator()(const CScriptID &id) const { return addr->Set(id); } - bool operator()(const CNoDestination &no) const { return false; } - }; + bool operator()(const CKeyID& id) const { return addr->Set(id); } + bool operator()(const CScriptID& id) const { return addr->Set(id); } + bool operator()(const CNoDestination& no) const { return false; } +}; } // anon namespace -bool CBitcoinAddress::Set(const CKeyID &id) { +bool CBitcoinAddress::Set(const CKeyID& id) +{ SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20); return true; } -bool CBitcoinAddress::Set(const CScriptID &id) { +bool CBitcoinAddress::Set(const CScriptID& id) +{ SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20); return true; } -bool CBitcoinAddress::Set(const CTxDestination &dest) { +bool CBitcoinAddress::Set(const CTxDestination& dest) +{ return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); } -bool CBitcoinAddress::IsValid() const { +bool CBitcoinAddress::IsValid() const +{ return IsValid(Params()); } -bool CBitcoinAddress::IsValid(const CChainParams ¶ms) const { +bool CBitcoinAddress::IsValid(const CChainParams& params) const +{ bool fCorrectSize = vchData.size() == 20; bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) || vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); return fCorrectSize && fKnownVersion; } -CTxDestination CBitcoinAddress::Get() const { +CTxDestination CBitcoinAddress::Get() const +{ if (!IsValid()) return CNoDestination(); uint160 id; @@ -238,7 +262,8 @@ CTxDestination CBitcoinAddress::Get() const { return CNoDestination(); } -bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const { +bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const +{ if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) return false; uint160 id; @@ -247,33 +272,40 @@ bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const { return true; } -bool CBitcoinAddress::IsScript() const { +bool CBitcoinAddress::IsScript() const +{ return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS); } -void CBitcoinSecret::SetKey(const CKey& vchSecret) { +void CBitcoinSecret::SetKey(const CKey& vchSecret) +{ assert(vchSecret.IsValid()); SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size()); if (vchSecret.IsCompressed()) vchData.push_back(1); } -CKey CBitcoinSecret::GetKey() { +CKey CBitcoinSecret::GetKey() +{ CKey ret; - ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1); + assert(vchData.size() >= 32); + ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1); return ret; } -bool CBitcoinSecret::IsValid() const { +bool CBitcoinSecret::IsValid() const +{ bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1); bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY); return fExpectedFormat && fCorrectVersion; } -bool CBitcoinSecret::SetString(const char* pszSecret) { +bool CBitcoinSecret::SetString(const char* pszSecret) +{ return CBase58Data::SetString(pszSecret) && IsValid(); } -bool CBitcoinSecret::SetString(const std::string& strSecret) { +bool CBitcoinSecret::SetString(const std::string& strSecret) +{ return SetString(strSecret.c_str()); } diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index b6e7a6c540..a198eb586e 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -214,7 +214,7 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput) // extract and validate VALUE string strValue = strInput.substr(0, pos); - int64_t value; + CAmount value; if (!ParseMoney(strValue, value)) throw runtime_error("invalid TX output value"); @@ -242,7 +242,7 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput // extract and validate VALUE string strValue = strInput.substr(0, pos); - int64_t value; + CAmount value; if (!ParseMoney(strValue, value)) throw runtime_error("invalid TX output value"); @@ -435,7 +435,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) BOOST_FOREACH(const CTransaction& txv, txVariants) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); } - if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STANDARD_SCRIPT_VERIFY_FLAGS)) + if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, SignatureChecker(mergedTx, i))) fComplete = false; } diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 5be8708979..0737b5a83d 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -129,7 +129,6 @@ bool AppInit(int argc, char* argv[]) } if (pid > 0) // Parent process, pid is child process id { - CreatePidFile(GetPidFile(), pid); return true; } // Child process falls through to rest of initialization diff --git a/src/chain.cpp b/src/chain.cpp new file mode 100644 index 0000000000..05427a4569 --- /dev/null +++ b/src/chain.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "chain.h" + +using namespace std; + +// CChain implementation + +CBlockIndex *CChain::SetTip(CBlockIndex *pindex) { + if (pindex == NULL) { + vChain.clear(); + return NULL; + } + vChain.resize(pindex->nHeight + 1); + while (pindex && vChain[pindex->nHeight] != pindex) { + vChain[pindex->nHeight] = pindex; + pindex = pindex->pprev; + } + return pindex; +} + +CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const { + int nStep = 1; + std::vector<uint256> vHave; + vHave.reserve(32); + + if (!pindex) + pindex = Tip(); + while (pindex) { + vHave.push_back(pindex->GetBlockHash()); + // Stop when we have added the genesis block. + if (pindex->nHeight == 0) + break; + // Exponentially larger steps back, plus the genesis block. + int nHeight = std::max(pindex->nHeight - nStep, 0); + if (Contains(pindex)) { + // Use O(1) CChain index if possible. + pindex = (*this)[nHeight]; + } else { + // Otherwise, use O(log n) skiplist. + pindex = pindex->GetAncestor(nHeight); + } + if (vHave.size() > 10) + nStep *= 2; + } + + return CBlockLocator(vHave); +} + +const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const { + if (pindex->nHeight > Height()) + pindex = pindex->GetAncestor(Height()); + while (pindex && !Contains(pindex)) + pindex = pindex->pprev; + return pindex; +} diff --git a/src/chain.h b/src/chain.h new file mode 100644 index 0000000000..0aafb40b98 --- /dev/null +++ b/src/chain.h @@ -0,0 +1,390 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef H_BITCOIN_CHAIN +#define H_BITCOIN_CHAIN + +#include "core.h" +#include "pow.h" +#include "uint256.h" + +#include <vector> + +#include <boost/foreach.hpp> + +struct CDiskBlockPos +{ + int nFile; + unsigned int nPos; + + ADD_SERIALIZE_METHODS; + + template <typename Stream, typename Operation> + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(VARINT(nFile)); + READWRITE(VARINT(nPos)); + } + + CDiskBlockPos() { + SetNull(); + } + + CDiskBlockPos(int nFileIn, unsigned int nPosIn) { + nFile = nFileIn; + nPos = nPosIn; + } + + friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) { + return (a.nFile == b.nFile && a.nPos == b.nPos); + } + + friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) { + return !(a == b); + } + + void SetNull() { nFile = -1; nPos = 0; } + bool IsNull() const { return (nFile == -1); } +}; + +enum BlockStatus { + BLOCK_VALID_UNKNOWN = 0, + BLOCK_VALID_HEADER = 1, // parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future + BLOCK_VALID_TREE = 2, // parent found, difficulty matches, timestamp >= median previous, checkpoint + BLOCK_VALID_TRANSACTIONS = 3, // only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids, sigops, size, merkle root + BLOCK_VALID_CHAIN = 4, // outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends, BIP30 + BLOCK_VALID_SCRIPTS = 5, // scripts/signatures ok + BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS | + BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS, + + BLOCK_HAVE_DATA = 8, // full block available in blk*.dat + BLOCK_HAVE_UNDO = 16, // undo data available in rev*.dat + BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO, + + BLOCK_FAILED_VALID = 32, // stage after last reached validness failed + BLOCK_FAILED_CHILD = 64, // descends from failed block + BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD, +}; + +/** The block chain is a tree shaped structure starting with the + * genesis block at the root, with each block potentially having multiple + * candidates to be the next block. A blockindex may have multiple pprev pointing + * to it, but at most one of them can be part of the currently active branch. + */ +class CBlockIndex +{ +public: + // pointer to the hash of the block, if any. memory is owned by this CBlockIndex + const uint256* phashBlock; + + // pointer to the index of the predecessor of this block + CBlockIndex* pprev; + + // pointer to the index of some further predecessor of this block + CBlockIndex* pskip; + + // height of the entry in the chain. The genesis block has height 0 + int nHeight; + + // Which # file this block is stored in (blk?????.dat) + int nFile; + + // Byte offset within blk?????.dat where this block's data is stored + unsigned int nDataPos; + + // Byte offset within rev?????.dat where this block's undo data is stored + unsigned int nUndoPos; + + // (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block + uint256 nChainWork; + + // Number of transactions in this block. + // Note: in a potential headers-first mode, this number cannot be relied upon + unsigned int nTx; + + // (memory only) Number of transactions in the chain up to and including this block + unsigned int nChainTx; // change to 64-bit type when necessary; won't happen before 2030 + + // Verification status of this block. See enum BlockStatus + unsigned int nStatus; + + // block header + int nVersion; + uint256 hashMerkleRoot; + unsigned int nTime; + unsigned int nBits; + unsigned int nNonce; + + // (memory only) Sequencial id assigned to distinguish order in which blocks are received. + uint32_t nSequenceId; + + void SetNull() + { + phashBlock = NULL; + pprev = NULL; + pskip = NULL; + nHeight = 0; + nFile = 0; + nDataPos = 0; + nUndoPos = 0; + nChainWork = 0; + nTx = 0; + nChainTx = 0; + nStatus = 0; + nSequenceId = 0; + + nVersion = 0; + hashMerkleRoot = 0; + nTime = 0; + nBits = 0; + nNonce = 0; + } + + CBlockIndex() + { + SetNull(); + } + + CBlockIndex(CBlockHeader& block) + { + SetNull(); + + nVersion = block.nVersion; + hashMerkleRoot = block.hashMerkleRoot; + nTime = block.nTime; + nBits = block.nBits; + nNonce = block.nNonce; + } + + CDiskBlockPos GetBlockPos() const { + CDiskBlockPos ret; + if (nStatus & BLOCK_HAVE_DATA) { + ret.nFile = nFile; + ret.nPos = nDataPos; + } + return ret; + } + + CDiskBlockPos GetUndoPos() const { + CDiskBlockPos ret; + if (nStatus & BLOCK_HAVE_UNDO) { + ret.nFile = nFile; + ret.nPos = nUndoPos; + } + return ret; + } + + CBlockHeader GetBlockHeader() const + { + CBlockHeader block; + block.nVersion = nVersion; + if (pprev) + block.hashPrevBlock = pprev->GetBlockHash(); + block.hashMerkleRoot = hashMerkleRoot; + block.nTime = nTime; + block.nBits = nBits; + block.nNonce = nNonce; + return block; + } + + uint256 GetBlockHash() const + { + return *phashBlock; + } + + int64_t GetBlockTime() const + { + return (int64_t)nTime; + } + + uint256 GetBlockWork() const + { + return GetProofIncrement(nBits); + } + + enum { nMedianTimeSpan=11 }; + + int64_t GetMedianTimePast() const + { + int64_t pmedian[nMedianTimeSpan]; + int64_t* pbegin = &pmedian[nMedianTimeSpan]; + int64_t* pend = &pmedian[nMedianTimeSpan]; + + const CBlockIndex* pindex = this; + for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev) + *(--pbegin) = pindex->GetBlockTime(); + + std::sort(pbegin, pend); + return pbegin[(pend - pbegin)/2]; + } + + /** + * Returns true if there are nRequired or more blocks of minVersion or above + * in the last Params().ToCheckBlockUpgradeMajority() blocks, starting at pstart + * and going backwards. + */ + static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, + unsigned int nRequired); + + std::string ToString() const + { + return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", + pprev, nHeight, + hashMerkleRoot.ToString(), + GetBlockHash().ToString()); + } + + // Check whether this block index entry is valid up to the passed validity level. + bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const + { + assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. + if (nStatus & BLOCK_FAILED_MASK) + return false; + return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); + } + + // Raise the validity level of this block index entry. + // Returns true if the validity was changed. + bool RaiseValidity(enum BlockStatus nUpTo) + { + assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. + if (nStatus & BLOCK_FAILED_MASK) + return false; + if ((nStatus & BLOCK_VALID_MASK) < nUpTo) { + nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo; + return true; + } + return false; + } + + // Build the skiplist pointer for this entry. + void BuildSkip(); + + // Efficiently find an ancestor of this block. + CBlockIndex* GetAncestor(int height); + const CBlockIndex* GetAncestor(int height) const; +}; + +/** Used to marshal pointers into hashes for db storage. */ +class CDiskBlockIndex : public CBlockIndex +{ +public: + uint256 hashPrev; + + CDiskBlockIndex() { + hashPrev = 0; + } + + explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex) { + hashPrev = (pprev ? pprev->GetBlockHash() : 0); + } + + ADD_SERIALIZE_METHODS; + + template <typename Stream, typename Operation> + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + if (!(nType & SER_GETHASH)) + READWRITE(VARINT(nVersion)); + + READWRITE(VARINT(nHeight)); + READWRITE(VARINT(nStatus)); + READWRITE(VARINT(nTx)); + if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) + READWRITE(VARINT(nFile)); + if (nStatus & BLOCK_HAVE_DATA) + READWRITE(VARINT(nDataPos)); + if (nStatus & BLOCK_HAVE_UNDO) + READWRITE(VARINT(nUndoPos)); + + // block header + READWRITE(this->nVersion); + READWRITE(hashPrev); + READWRITE(hashMerkleRoot); + READWRITE(nTime); + READWRITE(nBits); + READWRITE(nNonce); + } + + uint256 GetBlockHash() const + { + CBlockHeader block; + block.nVersion = nVersion; + block.hashPrevBlock = hashPrev; + block.hashMerkleRoot = hashMerkleRoot; + block.nTime = nTime; + block.nBits = nBits; + block.nNonce = nNonce; + return block.GetHash(); + } + + + std::string ToString() const + { + std::string str = "CDiskBlockIndex("; + str += CBlockIndex::ToString(); + str += strprintf("\n hashBlock=%s, hashPrev=%s)", + GetBlockHash().ToString(), + hashPrev.ToString()); + return str; + } +}; + +/** An in-memory indexed chain of blocks. */ +class CChain { +private: + std::vector<CBlockIndex*> vChain; + +public: + /** Returns the index entry for the genesis block of this chain, or NULL if none. */ + CBlockIndex *Genesis() const { + return vChain.size() > 0 ? vChain[0] : NULL; + } + + /** Returns the index entry for the tip of this chain, or NULL if none. */ + CBlockIndex *Tip() const { + return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL; + } + + /** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */ + CBlockIndex *operator[](int nHeight) const { + if (nHeight < 0 || nHeight >= (int)vChain.size()) + return NULL; + return vChain[nHeight]; + } + + /** Compare two chains efficiently. */ + friend bool operator==(const CChain &a, const CChain &b) { + return a.vChain.size() == b.vChain.size() && + a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1]; + } + + /** Efficiently check whether a block is present in this chain. */ + bool Contains(const CBlockIndex *pindex) const { + return (*this)[pindex->nHeight] == pindex; + } + + /** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */ + CBlockIndex *Next(const CBlockIndex *pindex) const { + if (Contains(pindex)) + return (*this)[pindex->nHeight + 1]; + else + return NULL; + } + + /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */ + int Height() const { + return vChain.size() - 1; + } + + /** Set/initialize a chain with a given tip. Returns the forking point. */ + CBlockIndex *SetTip(CBlockIndex *pindex); + + /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */ + CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const; + + /** Find the last common block between this chain and a block index entry. */ + const CBlockIndex *FindFork(const CBlockIndex *pindex) const; +}; + +#endif // H_BITCOIN_CHAIN diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 179db5a818..31c67715c8 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -115,6 +115,7 @@ public: fAllowMinDifficultyBlocks = false; fRequireStandard = true; fMineBlocksOnDemand = false; + fSkipProofOfWorkCheck = false; } }; static CMainParams mainParams; @@ -214,8 +215,46 @@ public: }; static CRegTestParams regTestParams; +// +// Unit test +// +class CUnitTestParams : public CMainParams, public CModifiableParams { +public: + CUnitTestParams() { + networkID = CBaseChainParams::UNITTEST; + strNetworkID = "unittest"; + nDefaultPort = 18445; + vFixedSeeds.clear(); + vSeeds.clear(); // Regtest mode doesn't have any DNS seeds. + + fRequireRPCPassword = false; + fMiningRequiresPeers = false; + fDefaultCheckMemPool = true; + fAllowMinDifficultyBlocks = false; + fMineBlocksOnDemand = true; + } +public: + // Published setters to allow changing values in unit test cases + virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) { nSubsidyHalvingInterval=anSubsidyHalvingInterval; } + virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority) { nEnforceBlockUpgradeMajority=anEnforceBlockUpgradeMajority; } + virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority) { nRejectBlockOutdatedMajority=anRejectBlockOutdatedMajority; } + virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority) { nToCheckBlockUpgradeMajority=anToCheckBlockUpgradeMajority; } + virtual void setDefaultCheckMemPool(bool afDefaultCheckMemPool) { fDefaultCheckMemPool=afDefaultCheckMemPool; } + virtual void setAllowMinDifficultyBlocks(bool afAllowMinDifficultyBlocks) { fAllowMinDifficultyBlocks=afAllowMinDifficultyBlocks; } + virtual void setSkipProofOfWorkCheck(bool afSkipProofOfWorkCheck) { fSkipProofOfWorkCheck = afSkipProofOfWorkCheck; } +}; +static CUnitTestParams unitTestParams; + + static CChainParams *pCurrentParams = 0; +CModifiableParams *ModifiableParams() +{ + assert(pCurrentParams); + assert(pCurrentParams==&unitTestParams); + return (CModifiableParams*)&unitTestParams; +} + const CChainParams &Params() { assert(pCurrentParams); return *pCurrentParams; @@ -229,6 +268,8 @@ CChainParams &Params(CBaseChainParams::Network network) { return testNetParams; case CBaseChainParams::REGTEST: return regTestParams; + case CBaseChainParams::UNITTEST: + return unitTestParams; default: assert(false && "Unimplemented network"); return mainParams; diff --git a/src/chainparams.h b/src/chainparams.h index e5dfc87c6d..50441a89f3 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -61,6 +61,8 @@ public: bool DefaultCheckMemPool() const { return fDefaultCheckMemPool; } /* Allow mining of a min-difficulty block */ bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; } + /* Skip proof-of-work check: allow mining of any difficulty block */ + bool SkipProofOfWorkCheck() const { return fSkipProofOfWorkCheck; } /* Make standard checks */ bool RequireStandard() const { return fRequireStandard; } int64_t TargetTimespan() const { return nTargetTimespan; } @@ -103,8 +105,27 @@ protected: bool fAllowMinDifficultyBlocks; bool fRequireStandard; bool fMineBlocksOnDemand; + bool fSkipProofOfWorkCheck; }; +/** Modifiable parameters interface is used by test cases to adapt the parameters in order +*** to test specific features more easily. Test cases should always restore the previous +*** values after finalization. +**/ + +class CModifiableParams { +public: + // Published setters to allow changing values in unit test cases + virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) =0; + virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority)=0; + virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority)=0; + virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority)=0; + virtual void setDefaultCheckMemPool(bool aDefaultCheckMemPool)=0; + virtual void setAllowMinDifficultyBlocks(bool aAllowMinDifficultyBlocks)=0; + virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck)=0; +}; + + /** * Return the currently selected parameters. This won't change after app startup * outside of the unit tests. @@ -114,6 +135,9 @@ const CChainParams &Params(); /** Return parameters for the given network. */ CChainParams &Params(CBaseChainParams::Network network); +/** Get modifyable network parameters (UNITTEST only) */ +CModifiableParams *ModifiableParams(); + /** Sets the params returned by Params() to those for the given network. */ void SelectParams(CBaseChainParams::Network network); diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index d1e19871c3..e9d63197bd 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -17,9 +17,11 @@ using namespace boost::assign; // Main network // -class CBaseMainParams : public CBaseChainParams { +class CBaseMainParams : public CBaseChainParams +{ public: - CBaseMainParams() { + CBaseMainParams() + { networkID = CBaseChainParams::MAIN; nRPCPort = 8332; } @@ -29,9 +31,11 @@ static CBaseMainParams mainParams; // // Testnet (v3) // -class CBaseTestNetParams : public CBaseMainParams { +class CBaseTestNetParams : public CBaseMainParams +{ public: - CBaseTestNetParams() { + CBaseTestNetParams() + { networkID = CBaseChainParams::TESTNET; nRPCPort = 18332; strDataDir = "testnet3"; @@ -42,40 +46,62 @@ static CBaseTestNetParams testNetParams; // // Regression test // -class CBaseRegTestParams : public CBaseTestNetParams { +class CBaseRegTestParams : public CBaseTestNetParams +{ public: - CBaseRegTestParams() { + CBaseRegTestParams() + { networkID = CBaseChainParams::REGTEST; strDataDir = "regtest"; } }; static CBaseRegTestParams regTestParams; -static CBaseChainParams *pCurrentBaseParams = 0; +// +// Unit test +// +class CBaseUnitTestParams : public CBaseMainParams +{ +public: + CBaseUnitTestParams() + { + networkID = CBaseChainParams::UNITTEST; + strDataDir = "unittest"; + } +}; +static CBaseUnitTestParams unitTestParams; + +static CBaseChainParams* pCurrentBaseParams = 0; -const CBaseChainParams &BaseParams() { +const CBaseChainParams& BaseParams() +{ assert(pCurrentBaseParams); return *pCurrentBaseParams; } -void SelectBaseParams(CBaseChainParams::Network network) { +void SelectBaseParams(CBaseChainParams::Network network) +{ switch (network) { - case CBaseChainParams::MAIN: - pCurrentBaseParams = &mainParams; - break; - case CBaseChainParams::TESTNET: - pCurrentBaseParams = &testNetParams; - break; - case CBaseChainParams::REGTEST: - pCurrentBaseParams = ®TestParams; - break; - default: - assert(false && "Unimplemented network"); - return; + case CBaseChainParams::MAIN: + pCurrentBaseParams = &mainParams; + break; + case CBaseChainParams::TESTNET: + pCurrentBaseParams = &testNetParams; + break; + case CBaseChainParams::REGTEST: + pCurrentBaseParams = ®TestParams; + break; + case CBaseChainParams::UNITTEST: + pCurrentBaseParams = &unitTestParams; + break; + default: + assert(false && "Unimplemented network"); + return; } } -bool SelectBaseParamsFromCommandLine() { +bool SelectBaseParamsFromCommandLine() +{ bool fRegTest = GetBoolArg("-regtest", false); bool fTestNet = GetBoolArg("-testnet", false); @@ -93,6 +119,7 @@ bool SelectBaseParamsFromCommandLine() { return true; } -bool AreBaseParamsConfigured() { +bool AreBaseParamsConfigured() +{ return pCurrentBaseParams != NULL; } diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 743c8c541a..cc154cf501 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -19,6 +19,7 @@ public: MAIN, TESTNET, REGTEST, + UNITTEST, MAX_NETWORK_TYPES }; @@ -26,6 +27,7 @@ public: const std::string& DataDir() const { return strDataDir; } int RPCPort() const { return nRPCPort; } Network NetworkID() const { return networkID; } + protected: CBaseChainParams() {} @@ -38,7 +40,7 @@ protected: * Return the currently selected parameters. This won't change after app startup * outside of the unit tests. */ -const CBaseChainParams &BaseParams(); +const CBaseChainParams& BaseParams(); /** Sets the params returned by Params() to those for the given network. */ void SelectBaseParams(CBaseChainParams::Network network); diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index c41deea7ce..9a6bc05e63 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -88,6 +88,8 @@ namespace Checkpoints { return dataTestnet; else if (Params().NetworkID() == CBaseChainParams::MAIN) return data; + else if (Params().NetworkID() == CBaseChainParams::UNITTEST) // UnitTest share the same checkpoints as MAIN + return data; else return dataRegtest; } diff --git a/src/checkpoints.h b/src/checkpoints.h index 6d3f2d4935..fca046559a 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -13,20 +13,20 @@ class uint256; /** Block-chain checkpoints are compiled-in sanity checks. * They are updated every release or three. */ -namespace Checkpoints { +namespace Checkpoints +{ +// Returns true if block passes checkpoint checks +bool CheckBlock(int nHeight, const uint256& hash); - // Returns true if block passes checkpoint checks - bool CheckBlock(int nHeight, const uint256& hash); +// Return conservative estimate of total number of blocks, 0 if unknown +int GetTotalBlocksEstimate(); - // Return conservative estimate of total number of blocks, 0 if unknown - int GetTotalBlocksEstimate(); +// Returns last CBlockIndex* in mapBlockIndex that is a checkpoint +CBlockIndex* GetLastCheckpoint(); - // Returns last CBlockIndex* in mapBlockIndex that is a checkpoint - CBlockIndex* GetLastCheckpoint(); +double GuessVerificationProgress(CBlockIndex* pindex, bool fSigchecks = true); - double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks = true); - - extern bool fEnabled; +extern bool fEnabled; } //namespace Checkpoints diff --git a/src/checkqueue.h b/src/checkqueue.h index c2c7d8ca24..b2a713e646 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -13,7 +13,8 @@ #include <boost/thread/locks.hpp> #include <boost/thread/mutex.hpp> -template<typename T> class CCheckQueueControl; +template <typename T> +class CCheckQueueControl; /** Queue for verifications that have to be performed. * The verifications are represented by a type T, which must provide an @@ -24,7 +25,9 @@ template<typename T> class CCheckQueueControl; * the master is done adding work, it temporarily joins the worker pool * as an N'th worker, until all jobs are done. */ -template<typename T> class CCheckQueue { +template <typename T> +class CCheckQueue +{ private: // Mutex to protect the inner state boost::mutex mutex; @@ -60,8 +63,9 @@ private: unsigned int nBatchSize; // Internal function that does bulk of the verification work. - bool Loop(bool fMaster = false) { - boost::condition_variable &cond = fMaster ? condMaster : condWorker; + bool Loop(bool fMaster = false) + { + boost::condition_variable& cond = fMaster ? condMaster : condWorker; std::vector<T> vChecks; vChecks.reserve(nBatchSize); unsigned int nNow = 0; @@ -103,41 +107,43 @@ private: nNow = std::max(1U, std::min(nBatchSize, (unsigned int)queue.size() / (nTotal + nIdle + 1))); vChecks.resize(nNow); for (unsigned int i = 0; i < nNow; i++) { - // We want the lock on the mutex to be as short as possible, so swap jobs from the global - // queue to the local batch vector instead of copying. - vChecks[i].swap(queue.back()); - queue.pop_back(); + // We want the lock on the mutex to be as short as possible, so swap jobs from the global + // queue to the local batch vector instead of copying. + vChecks[i].swap(queue.back()); + queue.pop_back(); } // Check whether we need to do work at all fOk = fAllOk; } // execute work - BOOST_FOREACH(T &check, vChecks) + BOOST_FOREACH (T& check, vChecks) if (fOk) fOk = check(); vChecks.clear(); - } while(true); + } while (true); } public: // Create a new check queue - CCheckQueue(unsigned int nBatchSizeIn) : - nIdle(0), nTotal(0), fAllOk(true), nTodo(0), fQuit(false), nBatchSize(nBatchSizeIn) {} + CCheckQueue(unsigned int nBatchSizeIn) : nIdle(0), nTotal(0), fAllOk(true), nTodo(0), fQuit(false), nBatchSize(nBatchSizeIn) {} // Worker thread - void Thread() { + void Thread() + { Loop(); } // Wait until execution finishes, and return whether all evaluations where succesful. - bool Wait() { + bool Wait() + { return Loop(true); } // Add a batch of checks to the queue - void Add(std::vector<T> &vChecks) { + void Add(std::vector<T>& vChecks) + { boost::unique_lock<boost::mutex> lock(mutex); - BOOST_FOREACH(T &check, vChecks) { + BOOST_FOREACH (T& check, vChecks) { queue.push_back(T()); check.swap(queue.back()); } @@ -148,7 +154,8 @@ public: condWorker.notify_all(); } - ~CCheckQueue() { + ~CCheckQueue() + { } friend class CCheckQueueControl<T>; @@ -157,13 +164,16 @@ public: /** RAII-style controller object for a CCheckQueue that guarantees the passed * queue is finished before continuing. */ -template<typename T> class CCheckQueueControl { +template <typename T> +class CCheckQueueControl +{ private: - CCheckQueue<T> *pqueue; + CCheckQueue<T>* pqueue; bool fDone; public: - CCheckQueueControl(CCheckQueue<T> *pqueueIn) : pqueue(pqueueIn), fDone(false) { + CCheckQueueControl(CCheckQueue<T>* pqueueIn) : pqueue(pqueueIn), fDone(false) + { // passed queue is supposed to be unused, or NULL if (pqueue != NULL) { assert(pqueue->nTotal == pqueue->nIdle); @@ -172,7 +182,8 @@ public: } } - bool Wait() { + bool Wait() + { if (pqueue == NULL) return true; bool fRet = pqueue->Wait(); @@ -180,12 +191,14 @@ public: return fRet; } - void Add(std::vector<T> &vChecks) { + void Add(std::vector<T>& vChecks) + { if (pqueue != NULL) pqueue->Add(vChecks); } - ~CCheckQueueControl() { + ~CCheckQueueControl() + { if (!fDone) Wait(); } diff --git a/src/clientversion.h b/src/clientversion.h index 5634516ca4..cd7ceb78f0 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -13,13 +13,13 @@ // // These need to be macros, as version.cpp's and bitcoin*-res.rc's voodoo requires it -#define CLIENT_VERSION_MAJOR 0 -#define CLIENT_VERSION_MINOR 9 -#define CLIENT_VERSION_REVISION 99 -#define CLIENT_VERSION_BUILD 0 +#define CLIENT_VERSION_MAJOR 0 +#define CLIENT_VERSION_MINOR 9 +#define CLIENT_VERSION_REVISION 99 +#define CLIENT_VERSION_BUILD 0 // Set to true for release, false for prerelease or test build -#define CLIENT_VERSION_IS_RELEASE false +#define CLIENT_VERSION_IS_RELEASE false // Copyright year (2009-this) // Todo: update this when changing our copyright comments in the source @@ -33,6 +33,6 @@ #define DO_STRINGIZE(X) #X // Copyright string used in Windows .rc files -#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core Developers" +#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core Developers" #endif // CLIENTVERSION_H diff --git a/src/coincontrol.h b/src/coincontrol.h index 97c30c2713..033092c019 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -57,7 +57,6 @@ public: private: std::set<COutPoint> setSelected; - }; #endif // COINCONTROL_H diff --git a/src/coins.cpp b/src/coins.cpp index 34485db2bd..9b8d63d4e4 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -171,12 +171,12 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const return coins->vout[input.prevout.n]; } -int64_t CCoinsViewCache::GetValueIn(const CTransaction& tx) const +CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const { if (tx.IsCoinBase()) return 0; - int64_t nResult = 0; + CAmount nResult = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) nResult += GetOutputFor(tx.vin[i]).nValue; diff --git a/src/coins.h b/src/coins.h index bf61f55aac..2583475323 100644 --- a/src/coins.h +++ b/src/coins.h @@ -266,7 +266,7 @@ struct CCoinsStats uint64_t nTransactionOutputs; uint64_t nSerializedSize; uint256 hashSerialized; - int64_t nTotalAmount; + CAmount nTotalAmount; CCoinsStats() : nHeight(0), hashBlock(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), hashSerialized(0), nTotalAmount(0) {} }; @@ -367,7 +367,7 @@ public: @param[in] tx transaction for which we are checking input total @return Sum of value of all inputs (scriptSigs) */ - int64_t GetValueIn(const CTransaction& tx) const; + CAmount GetValueIn(const CTransaction& tx) const; // Check whether all prevouts of the transaction are present in the UTXO set represented by this view bool HaveInputs(const CTransaction& tx) const; diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp index 22f82e4259..f149a08cd5 100644 --- a/src/compat/glibc_compat.cpp +++ b/src/compat/glibc_compat.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) @@ -7,6 +7,7 @@ #endif #include <cstddef> + #if defined(HAVE_SYS_SELECT_H) #include <sys/select.h> #endif @@ -18,11 +19,11 @@ extern "C" void* memcpy(void* a, const void* b, size_t c) return memmove(a, b, c); } -extern "C" void __chk_fail (void) __attribute__((__noreturn__)); +extern "C" void __chk_fail(void) __attribute__((__noreturn__)); extern "C" FDELT_TYPE __fdelt_warn(FDELT_TYPE a) { if (a >= FD_SETSIZE) - __chk_fail (); + __chk_fail(); return a / __NFDBITS; } extern "C" FDELT_TYPE __fdelt_chk(FDELT_TYPE) __attribute__((weak, alias("__fdelt_warn"))); diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp index d93602e0fe..607e23b568 100644 --- a/src/compat/glibc_sanity.cpp +++ b/src/compat/glibc_sanity.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) @@ -7,6 +7,7 @@ #endif #include <cstddef> + #if defined(HAVE_SYS_SELECT_H) #include <sys/select.h> #endif @@ -14,10 +15,11 @@ extern "C" void* memcpy(void* a, const void* b, size_t c); void* memcpy_int(void* a, const void* b, size_t c) { - return memcpy(a,b,c); + return memcpy(a, b, c); } -namespace { +namespace +{ // trigger: Use the memcpy_int wrapper which calls our internal memcpy. // A direct call to memcpy may be optimized away by the compiler. // test: Fill an array with a sequence of integers. memcpy to a new empty array. @@ -31,11 +33,10 @@ bool sanity_test_memcpy() for (unsigned int i = 0; i != T; ++i) memcpy_test[i] = i; - memcpy_int(memcpy_verify,memcpy_test,sizeof(memcpy_test)); + memcpy_int(memcpy_verify, memcpy_test, sizeof(memcpy_test)); - for (unsigned int i = 0; i != T; ++i) - { - if(memcpy_verify[i] != i) + for (unsigned int i = 0; i != T; ++i) { + if (memcpy_verify[i] != i) return false; } return true; @@ -51,7 +52,7 @@ bool sanity_test_fdelt() fd_set fds; FD_ZERO(&fds); FD_SET(0, &fds); - return FD_ISSET(0,&fds); + return FD_ISSET(0, &fds); } #endif diff --git a/src/compat/glibcxx_compat.cpp b/src/compat/glibcxx_compat.cpp index cbe059735b..e0b4ac51f5 100644 --- a/src/compat/glibcxx_compat.cpp +++ b/src/compat/glibcxx_compat.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <cstddef> @@ -11,8 +11,8 @@ #define _GLIBCXX_USE_NOEXCEPT throw() #endif -namespace std { - +namespace std +{ const char* bad_exception::what() const throw() { return "std::bad_exception"; @@ -30,9 +30,8 @@ const char* bad_alloc::what() const throw() namespace __detail { -struct _List_node_base -{ - void _M_hook(std::__detail::_List_node_base* const __position) throw () __attribute__((used)) +struct _List_node_base { + void _M_hook(std::__detail::_List_node_base* const __position) throw() __attribute__((used)) { _M_next = __position; _M_prev = __position->_M_prev; @@ -62,9 +61,9 @@ template ostream& __ostream_insert(ostream&, const char*, streamsize); template istream& istream::_M_extract(long&); template istream& istream::_M_extract(unsigned short&); -out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT { } +out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT {} -length_error::~length_error() _GLIBCXX_USE_NOEXCEPT { } +length_error::~length_error() _GLIBCXX_USE_NOEXCEPT {} // Used with permission. // See: https://github.com/madlib/madlib/commit/c3db418c0d34d6813608f2137fef1012ce03043d @@ -85,11 +84,11 @@ void ctype<char>::_M_widen_init() const } } -void __throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__)); -void __throw_out_of_range_fmt(const char* err, ...) +void __throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__)); +void __throw_out_of_range_fmt(const char* err, ...) { // Safe and over-simplified version. Ignore the format and print it as-is. __throw_out_of_range(err); } -}// namespace std +} // namespace std diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp index cd8da4fd67..aafa4a6aef 100644 --- a/src/compat/glibcxx_sanity.cpp +++ b/src/compat/glibcxx_sanity.cpp @@ -1,20 +1,20 @@ // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <list> #include <locale> #include <stdexcept> -namespace{ - +namespace +{ // trigger: use ctype<char>::widen to trigger ctype<char>::_M_widen_init(). // test: convert a char from narrow to wide and back. Verify that the result // matches the original. bool sanity_test_widen(char testchar) { - const std::ctype<char>& test(std::use_facet< std::ctype<char> >(std::locale())); - return test.narrow(test.widen(testchar),'b') == testchar; + const std::ctype<char>& test(std::use_facet<std::ctype<char> >(std::locale())); + return test.narrow(test.widen(testchar), 'b') == testchar; } // trigger: use list::push_back and list::pop_back to trigger _M_hook and @@ -25,14 +25,13 @@ bool sanity_test_list(unsigned int size) { std::list<unsigned int> test; for (unsigned int i = 0; i != size; ++i) - test.push_back(i+1); + test.push_back(i + 1); if (test.size() != size) return false; - while (!test.empty()) - { - if(test.back() != test.size()) + while (!test.empty()) { + if (test.back() != test.size()) return false; test.pop_back(); } @@ -47,15 +46,12 @@ bool sanity_test_list(unsigned int size) bool sanity_test_range_fmt() { std::string test; - try - { + try { test.at(1); - } - catch (const std::out_of_range&) - { + } catch (const std::out_of_range&) { return true; + } catch (...) { } - catch (...){} return false; } diff --git a/src/compat/sanity.h b/src/compat/sanity.h index e7df44307a..7016ac0ab7 100644 --- a/src/compat/sanity.h +++ b/src/compat/sanity.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCON_COMPAT_SANITY_H diff --git a/src/core.cpp b/src/core.cpp index 491e4fa68b..380b1c38e0 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -43,7 +43,7 @@ std::string CTxIn::ToString() const return str; } -CTxOut::CTxOut(int64_t nValueIn, CScript scriptPubKeyIn) +CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn) { nValue = nValueIn; scriptPubKey = scriptPubKeyIn; @@ -59,7 +59,7 @@ std::string CTxOut::ToString() const return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30)); } -CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize) +CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize) { if (nSize > 0) nSatoshisPerK = nFeePaid*1000/nSize; @@ -67,9 +67,9 @@ CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize) nSatoshisPerK = 0; } -int64_t CFeeRate::GetFee(size_t nSize) const +CAmount CFeeRate::GetFee(size_t nSize) const { - int64_t nFee = nSatoshisPerK*nSize / 1000; + CAmount nFee = nSatoshisPerK*nSize / 1000; if (nFee == 0 && nSatoshisPerK > 0) nFee = nSatoshisPerK; @@ -110,9 +110,9 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) { return *this; } -int64_t CTransaction::GetValueOut() const +CAmount CTransaction::GetValueOut() const { - int64_t nValueOut = 0; + CAmount nValueOut = 0; BOOST_FOREACH(const CTxOut& txout, vout) { nValueOut += txout.nValue; @@ -224,22 +224,66 @@ uint256 CBlockHeader::GetHash() const return Hash(BEGIN(nVersion), END(nNonce)); } -uint256 CBlock::BuildMerkleTree() const +uint256 CBlock::BuildMerkleTree(bool* fMutated) const { + /* WARNING! If you're reading this because you're learning about crypto + and/or designing a new system that will use merkle trees, keep in mind + that the following merkle tree algorithm has a serious flaw related to + duplicate txids, resulting in a vulnerability (CVE-2012-2459). + + The reason is that if the number of hashes in the list at a given time + is odd, the last one is duplicated before computing the next level (which + is unusual in Merkle trees). This results in certain sequences of + transactions leading to the same merkle root. For example, these two + trees: + + A A + / \ / \ + B C B C + / \ | / \ / \ + D E F D E F F + / \ / \ / \ / \ / \ / \ / \ + 1 2 3 4 5 6 1 2 3 4 5 6 5 6 + + for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and + 6 are repeated) result in the same root hash A (because the hash of both + of (F) and (F,F) is C). + + The vulnerability results from being able to send a block with such a + transaction list, with the same merkle root, and the same block hash as + the original without duplication, resulting in failed validation. If the + receiving node proceeds to mark that block as permanently invalid + however, it will fail to accept further unmodified (and thus potentially + valid) versions of the same block. We defend against this by detecting + the case where we would hash two identical hashes at the end of the list + together, and treating that identically to the block having an invalid + merkle root. Assuming no double-SHA256 collisions, this will detect all + known ways of changing the transactions without affecting the merkle + root. + */ vMerkleTree.clear(); + vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. BOOST_FOREACH(const CTransaction& tx, vtx) vMerkleTree.push_back(tx.GetHash()); int j = 0; + bool mutated = false; for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) { for (int i = 0; i < nSize; i += 2) { int i2 = std::min(i+1, nSize-1); + if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) { + // Two identical hashes at the end of the list at a particular level. + mutated = true; + } vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]), BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2]))); } j += nSize; } + if (fMutated) { + *fMutated = mutated; + } return (vMerkleTree.empty() ? 0 : vMerkleTree.back()); } diff --git a/src/core.h b/src/core.h index 9a2ac47487..a348293578 100644 --- a/src/core.h +++ b/src/core.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_CORE_H #define BITCOIN_CORE_H +#include "amount.h" #include "script/compressor.h" #include "script/script.h" #include "serialize.h" @@ -19,8 +20,8 @@ static const int64_t COIN = 100000000; static const int64_t CENT = 1000000; /** No amount larger than this (in satoshi) is valid */ -static const int64_t MAX_MONEY = 21000000 * COIN; -inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } +static const CAmount MAX_MONEY = 21000000 * COIN; +inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } /** An outpoint - a combination of a transaction hash and an index n into its vout */ class COutPoint @@ -129,15 +130,15 @@ public: class CFeeRate { private: - int64_t nSatoshisPerK; // unit is satoshis-per-1,000-bytes + CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes public: CFeeRate() : nSatoshisPerK(0) { } - explicit CFeeRate(int64_t _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } - CFeeRate(int64_t nFeePaid, size_t nSize); + explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } + CFeeRate(const CAmount& nFeePaid, size_t nSize); CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; } - int64_t GetFee(size_t size) const; // unit returned is satoshis - int64_t GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes + CAmount GetFee(size_t size) const; // unit returned is satoshis + CAmount GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; } friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; } @@ -161,7 +162,7 @@ public: class CTxOut { public: - int64_t nValue; + CAmount nValue; CScript scriptPubKey; CTxOut() @@ -169,7 +170,7 @@ public: SetNull(); } - CTxOut(int64_t nValueIn, CScript scriptPubKeyIn); + CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn); ADD_SERIALIZE_METHODS; @@ -276,7 +277,7 @@ public: } // Return sum of txouts. - int64_t GetValueOut() const; + CAmount GetValueOut() const; // GetValueIn() is a method on CCoinsViewCache, because // inputs must be known to compute value in. @@ -528,7 +529,11 @@ public: return block; } - uint256 BuildMerkleTree() const; + // Build the in-memory merkle tree for this block and return the merkle root. + // If non-NULL, *mutated is set to whether mutation was detected in the merkle + // tree (a duplication of transactions in the block leading to an identical + // merkle root). + uint256 BuildMerkleTree(bool* mutated = NULL) const; std::vector<uint256> GetMerkleBranch(int nIndex) const; static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex); diff --git a/src/core_io.h b/src/core_io.h index 6268a3bf58..94848f1c3d 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -20,6 +20,7 @@ extern uint256 ParseHashUV(const UniValue& v, const std::string& strName); extern std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName); // core_write.cpp +extern std::string FormatScript(const CScript& script); extern std::string EncodeHexTx(const CTransaction& tx); extern void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); diff --git a/src/core_write.cpp b/src/core_write.cpp index cd64aabf63..40d547fb33 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -17,6 +17,41 @@ using namespace std; +string FormatScript(const CScript& script) +{ + string ret; + CScript::const_iterator it = script.begin(); + opcodetype op; + while (it != script.end()) { + CScript::const_iterator it2 = it; + vector<unsigned char> vch; + if (script.GetOp2(it, op, &vch)) { + if (op == OP_0) { + ret += "0 "; + continue; + } else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) { + ret += strprintf("%i ", op - OP_1NEGATE - 1); + continue; + } else if (op >= OP_NOP && op <= OP_CHECKMULTISIGVERIFY) { + string str(GetOpName(op)); + if (str.substr(0, 3) == string("OP_")) { + ret += str.substr(3, string::npos) + " "; + continue; + } + } + if (vch.size() > 0) { + ret += strprintf("0x%x 0x%x ", HexStr(it2, it - vch.size()), HexStr(it - vch.size(), it)); + } else { + ret += strprintf("0x%x", HexStr(it2, it)); + } + continue; + } + ret += strprintf("0x%x ", HexStr(it2, script.end())); + break; + } + return ret.substr(0, ret.size() - 1); +} + string EncodeHexTx(const CTransaction& tx) { CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/crypto/common.h b/src/crypto/common.h index 8f675a16c5..67c30023c3 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CRYPTO_COMMON_H @@ -8,12 +8,15 @@ #if defined(HAVE_CONFIG_H) #include "bitcoin-config.h" #endif + #include <stdint.h> + #if defined(HAVE_ENDIAN_H) #include <endian.h> #endif -uint32_t static inline ReadLE32(const unsigned char *ptr) { +uint32_t static inline ReadLE32(const unsigned char* ptr) +{ #if HAVE_DECL_LE32TOH == 1 return le32toh(*((uint32_t*)ptr)); #elif !defined(WORDS_BIGENDIAN) @@ -23,8 +26,8 @@ uint32_t static inline ReadLE32(const unsigned char *ptr) { #endif } -uint64_t static inline ReadLE64(const unsigned char *ptr) { - +uint64_t static inline ReadLE64(const unsigned char* ptr) +{ #if HAVE_DECL_LE64TOH == 1 return le64toh(*((uint64_t*)ptr)); #elif !defined(WORDS_BIGENDIAN) @@ -35,28 +38,40 @@ uint64_t static inline ReadLE64(const unsigned char *ptr) { #endif } -void static inline WriteLE32(unsigned char *ptr, uint32_t x) { +void static inline WriteLE32(unsigned char* ptr, uint32_t x) +{ #if HAVE_DECL_HTOLE32 == 1 *((uint32_t*)ptr) = htole32(x); #elif !defined(WORDS_BIGENDIAN) *((uint32_t*)ptr) = x; #else - ptr[3] = x >> 24; ptr[2] = x >> 16; ptr[1] = x >> 8; ptr[0] = x; + ptr[3] = x >> 24; + ptr[2] = x >> 16; + ptr[1] = x >> 8; + ptr[0] = x; #endif } -void static inline WriteLE64(unsigned char *ptr, uint64_t x) { +void static inline WriteLE64(unsigned char* ptr, uint64_t x) +{ #if HAVE_DECL_HTOLE64 == 1 *((uint64_t*)ptr) = htole64(x); #elif !defined(WORDS_BIGENDIAN) *((uint64_t*)ptr) = x; #else - ptr[7] = x >> 56; ptr[6] = x >> 48; ptr[5] = x >> 40; ptr[4] = x >> 32; - ptr[3] = x >> 24; ptr[2] = x >> 16; ptr[1] = x >> 8; ptr[0] = x; + ptr[7] = x >> 56; + ptr[6] = x >> 48; + ptr[5] = x >> 40; + ptr[4] = x >> 32; + ptr[3] = x >> 24; + ptr[2] = x >> 16; + ptr[1] = x >> 8; + ptr[0] = x; #endif } -uint32_t static inline ReadBE32(const unsigned char *ptr) { +uint32_t static inline ReadBE32(const unsigned char* ptr) +{ #if HAVE_DECL_BE32TOH == 1 return be32toh(*((uint32_t*)ptr)); #else @@ -64,7 +79,8 @@ uint32_t static inline ReadBE32(const unsigned char *ptr) { #endif } -uint64_t static inline ReadBE64(const unsigned char *ptr) { +uint64_t static inline ReadBE64(const unsigned char* ptr) +{ #if HAVE_DECL_BE64TOH == 1 return be64toh(*((uint64_t*)ptr)); #else @@ -73,21 +89,32 @@ uint64_t static inline ReadBE64(const unsigned char *ptr) { #endif } -void static inline WriteBE32(unsigned char *ptr, uint32_t x) { +void static inline WriteBE32(unsigned char* ptr, uint32_t x) +{ #if HAVE_DECL_HTOBE32 == 1 *((uint32_t*)ptr) = htobe32(x); #else - ptr[0] = x >> 24; ptr[1] = x >> 16; ptr[2] = x >> 8; ptr[3] = x; + ptr[0] = x >> 24; + ptr[1] = x >> 16; + ptr[2] = x >> 8; + ptr[3] = x; #endif } -void static inline WriteBE64(unsigned char *ptr, uint64_t x) { +void static inline WriteBE64(unsigned char* ptr, uint64_t x) +{ #if HAVE_DECL_HTOBE64 == 1 *((uint64_t*)ptr) = htobe64(x); #else - ptr[0] = x >> 56; ptr[1] = x >> 48; ptr[2] = x >> 40; ptr[3] = x >> 32; - ptr[4] = x >> 24; ptr[5] = x >> 16; ptr[6] = x >> 8; ptr[7] = x; + ptr[0] = x >> 56; + ptr[1] = x >> 48; + ptr[2] = x >> 40; + ptr[3] = x >> 32; + ptr[4] = x >> 24; + ptr[5] = x >> 16; + ptr[6] = x >> 8; + ptr[7] = x; #endif } -#endif +#endif // BITCOIN_CRYPTO_COMMON_H diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp index b5e9f0df49..cb4a94a44d 100644 --- a/src/crypto/ripemd160.cpp +++ b/src/crypto/ripemd160.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "crypto/ripemd160.h" @@ -9,11 +9,11 @@ #include <string.h> // Internal implementation code. -namespace { - +namespace +{ /// Internal RIPEMD-160 implementation. -namespace ripemd160 { - +namespace ripemd160 +{ uint32_t inline f1(uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; } uint32_t inline f2(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); } uint32_t inline f3(uint32_t x, uint32_t y, uint32_t z) { return (x | ~y) ^ z; } @@ -21,7 +21,8 @@ uint32_t inline f4(uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~ uint32_t inline f5(uint32_t x, uint32_t y, uint32_t z) { return x ^ (y | ~z); } /** Initialize RIPEMD-160 state. */ -void inline Initialize(uint32_t *s) { +void inline Initialize(uint32_t* s) +{ s[0] = 0x67452301ul; s[1] = 0xEFCDAB89ul; s[2] = 0x98BADCFEul; @@ -29,139 +30,223 @@ void inline Initialize(uint32_t *s) { s[4] = 0xC3D2E1F0ul; } -uint32_t inline rol(uint32_t x, int i) { return (x << i) | (x >> (32-i)); } +uint32_t inline rol(uint32_t x, int i) { return (x << i) | (x >> (32 - i)); } -void inline Round(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t f, uint32_t x, uint32_t k, int r) { +void inline Round(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t f, uint32_t x, uint32_t k, int r) +{ a = rol(a + f + x + k, r) + e; c = rol(c, 10); } -void inline R11(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); } -void inline R21(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x5A827999ul, r); } -void inline R31(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6ED9EBA1ul, r); } -void inline R41(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x8F1BBCDCul, r); } -void inline R51(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0xA953FD4Eul, r); } +void inline R11(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); } +void inline R21(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x5A827999ul, r); } +void inline R31(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6ED9EBA1ul, r); } +void inline R41(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x8F1BBCDCul, r); } +void inline R51(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0xA953FD4Eul, r); } -void inline R12(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0x50A28BE6ul, r); } -void inline R22(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x5C4DD124ul, r); } -void inline R32(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6D703EF3ul, r); } -void inline R42(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x7A6D76E9ul, r); } -void inline R52(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); } +void inline R12(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0x50A28BE6ul, r); } +void inline R22(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x5C4DD124ul, r); } +void inline R32(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6D703EF3ul, r); } +void inline R42(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x7A6D76E9ul, r); } +void inline R52(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); } /** Perform a RIPEMD-160 transformation, processing a 64-byte chunk. */ -void Transform(uint32_t *s, const unsigned char *chunk) { +void Transform(uint32_t* s, const unsigned char* chunk) +{ uint32_t a1 = s[0], b1 = s[1], c1 = s[2], d1 = s[3], e1 = s[4]; - uint32_t a2 = a1 , b2 = b1 , c2 = c1 , d2 = d1 , e2 = e1 ; - uint32_t w0 = ReadLE32(chunk + 0), w1 = ReadLE32(chunk + 4), w2 = ReadLE32(chunk + 8), w3 = ReadLE32(chunk + 12); - uint32_t w4 = ReadLE32(chunk + 16), w5 = ReadLE32(chunk + 20), w6 = ReadLE32(chunk + 24), w7 = ReadLE32(chunk + 28); - uint32_t w8 = ReadLE32(chunk + 32), w9 = ReadLE32(chunk + 36), w10 = ReadLE32(chunk + 40), w11 = ReadLE32(chunk + 44); + uint32_t a2 = a1, b2 = b1, c2 = c1, d2 = d1, e2 = e1; + uint32_t w0 = ReadLE32(chunk + 0), w1 = ReadLE32(chunk + 4), w2 = ReadLE32(chunk + 8), w3 = ReadLE32(chunk + 12); + uint32_t w4 = ReadLE32(chunk + 16), w5 = ReadLE32(chunk + 20), w6 = ReadLE32(chunk + 24), w7 = ReadLE32(chunk + 28); + uint32_t w8 = ReadLE32(chunk + 32), w9 = ReadLE32(chunk + 36), w10 = ReadLE32(chunk + 40), w11 = ReadLE32(chunk + 44); uint32_t w12 = ReadLE32(chunk + 48), w13 = ReadLE32(chunk + 52), w14 = ReadLE32(chunk + 56), w15 = ReadLE32(chunk + 60); - R11(a1, b1, c1, d1, e1, w0 , 11); R12(a2, b2, c2, d2, e2, w5 , 8); - R11(e1, a1, b1, c1, d1, w1 , 14); R12(e2, a2, b2, c2, d2, w14, 9); - R11(d1, e1, a1, b1, c1, w2 , 15); R12(d2, e2, a2, b2, c2, w7 , 9); - R11(c1, d1, e1, a1, b1, w3 , 12); R12(c2, d2, e2, a2, b2, w0 , 11); - R11(b1, c1, d1, e1, a1, w4 , 5); R12(b2, c2, d2, e2, a2, w9 , 13); - R11(a1, b1, c1, d1, e1, w5 , 8); R12(a2, b2, c2, d2, e2, w2 , 15); - R11(e1, a1, b1, c1, d1, w6 , 7); R12(e2, a2, b2, c2, d2, w11, 15); - R11(d1, e1, a1, b1, c1, w7 , 9); R12(d2, e2, a2, b2, c2, w4 , 5); - R11(c1, d1, e1, a1, b1, w8 , 11); R12(c2, d2, e2, a2, b2, w13, 7); - R11(b1, c1, d1, e1, a1, w9 , 13); R12(b2, c2, d2, e2, a2, w6 , 7); - R11(a1, b1, c1, d1, e1, w10, 14); R12(a2, b2, c2, d2, e2, w15, 8); - R11(e1, a1, b1, c1, d1, w11, 15); R12(e2, a2, b2, c2, d2, w8 , 11); - R11(d1, e1, a1, b1, c1, w12, 6); R12(d2, e2, a2, b2, c2, w1 , 14); - R11(c1, d1, e1, a1, b1, w13, 7); R12(c2, d2, e2, a2, b2, w10, 14); - R11(b1, c1, d1, e1, a1, w14, 9); R12(b2, c2, d2, e2, a2, w3 , 12); - R11(a1, b1, c1, d1, e1, w15, 8); R12(a2, b2, c2, d2, e2, w12, 6); - - R21(e1, a1, b1, c1, d1, w7 , 7); R22(e2, a2, b2, c2, d2, w6 , 9); - R21(d1, e1, a1, b1, c1, w4 , 6); R22(d2, e2, a2, b2, c2, w11, 13); - R21(c1, d1, e1, a1, b1, w13, 8); R22(c2, d2, e2, a2, b2, w3 , 15); - R21(b1, c1, d1, e1, a1, w1 , 13); R22(b2, c2, d2, e2, a2, w7 , 7); - R21(a1, b1, c1, d1, e1, w10, 11); R22(a2, b2, c2, d2, e2, w0 , 12); - R21(e1, a1, b1, c1, d1, w6 , 9); R22(e2, a2, b2, c2, d2, w13, 8); - R21(d1, e1, a1, b1, c1, w15, 7); R22(d2, e2, a2, b2, c2, w5 , 9); - R21(c1, d1, e1, a1, b1, w3 , 15); R22(c2, d2, e2, a2, b2, w10, 11); - R21(b1, c1, d1, e1, a1, w12, 7); R22(b2, c2, d2, e2, a2, w14, 7); - R21(a1, b1, c1, d1, e1, w0 , 12); R22(a2, b2, c2, d2, e2, w15, 7); - R21(e1, a1, b1, c1, d1, w9 , 15); R22(e2, a2, b2, c2, d2, w8 , 12); - R21(d1, e1, a1, b1, c1, w5 , 9); R22(d2, e2, a2, b2, c2, w12, 7); - R21(c1, d1, e1, a1, b1, w2 , 11); R22(c2, d2, e2, a2, b2, w4 , 6); - R21(b1, c1, d1, e1, a1, w14, 7); R22(b2, c2, d2, e2, a2, w9 , 15); - R21(a1, b1, c1, d1, e1, w11, 13); R22(a2, b2, c2, d2, e2, w1 , 13); - R21(e1, a1, b1, c1, d1, w8 , 12); R22(e2, a2, b2, c2, d2, w2 , 11); - - R31(d1, e1, a1, b1, c1, w3 , 11); R32(d2, e2, a2, b2, c2, w15, 9); - R31(c1, d1, e1, a1, b1, w10, 13); R32(c2, d2, e2, a2, b2, w5 , 7); - R31(b1, c1, d1, e1, a1, w14, 6); R32(b2, c2, d2, e2, a2, w1 , 15); - R31(a1, b1, c1, d1, e1, w4 , 7); R32(a2, b2, c2, d2, e2, w3 , 11); - R31(e1, a1, b1, c1, d1, w9 , 14); R32(e2, a2, b2, c2, d2, w7 , 8); - R31(d1, e1, a1, b1, c1, w15, 9); R32(d2, e2, a2, b2, c2, w14, 6); - R31(c1, d1, e1, a1, b1, w8 , 13); R32(c2, d2, e2, a2, b2, w6 , 6); - R31(b1, c1, d1, e1, a1, w1 , 15); R32(b2, c2, d2, e2, a2, w9 , 14); - R31(a1, b1, c1, d1, e1, w2 , 14); R32(a2, b2, c2, d2, e2, w11, 12); - R31(e1, a1, b1, c1, d1, w7 , 8); R32(e2, a2, b2, c2, d2, w8 , 13); - R31(d1, e1, a1, b1, c1, w0 , 13); R32(d2, e2, a2, b2, c2, w12, 5); - R31(c1, d1, e1, a1, b1, w6 , 6); R32(c2, d2, e2, a2, b2, w2 , 14); - R31(b1, c1, d1, e1, a1, w13, 5); R32(b2, c2, d2, e2, a2, w10, 13); - R31(a1, b1, c1, d1, e1, w11, 12); R32(a2, b2, c2, d2, e2, w0 , 13); - R31(e1, a1, b1, c1, d1, w5 , 7); R32(e2, a2, b2, c2, d2, w4 , 7); - R31(d1, e1, a1, b1, c1, w12, 5); R32(d2, e2, a2, b2, c2, w13, 5); - - R41(c1, d1, e1, a1, b1, w1 , 11); R42(c2, d2, e2, a2, b2, w8 , 15); - R41(b1, c1, d1, e1, a1, w9 , 12); R42(b2, c2, d2, e2, a2, w6 , 5); - R41(a1, b1, c1, d1, e1, w11, 14); R42(a2, b2, c2, d2, e2, w4 , 8); - R41(e1, a1, b1, c1, d1, w10, 15); R42(e2, a2, b2, c2, d2, w1 , 11); - R41(d1, e1, a1, b1, c1, w0 , 14); R42(d2, e2, a2, b2, c2, w3 , 14); - R41(c1, d1, e1, a1, b1, w8 , 15); R42(c2, d2, e2, a2, b2, w11, 14); - R41(b1, c1, d1, e1, a1, w12, 9); R42(b2, c2, d2, e2, a2, w15, 6); - R41(a1, b1, c1, d1, e1, w4 , 8); R42(a2, b2, c2, d2, e2, w0 , 14); - R41(e1, a1, b1, c1, d1, w13, 9); R42(e2, a2, b2, c2, d2, w5 , 6); - R41(d1, e1, a1, b1, c1, w3 , 14); R42(d2, e2, a2, b2, c2, w12, 9); - R41(c1, d1, e1, a1, b1, w7 , 5); R42(c2, d2, e2, a2, b2, w2 , 12); - R41(b1, c1, d1, e1, a1, w15, 6); R42(b2, c2, d2, e2, a2, w13, 9); - R41(a1, b1, c1, d1, e1, w14, 8); R42(a2, b2, c2, d2, e2, w9 , 12); - R41(e1, a1, b1, c1, d1, w5 , 6); R42(e2, a2, b2, c2, d2, w7 , 5); - R41(d1, e1, a1, b1, c1, w6 , 5); R42(d2, e2, a2, b2, c2, w10, 15); - R41(c1, d1, e1, a1, b1, w2 , 12); R42(c2, d2, e2, a2, b2, w14, 8); - - R51(b1, c1, d1, e1, a1, w4 , 9); R52(b2, c2, d2, e2, a2, w12, 8); - R51(a1, b1, c1, d1, e1, w0 , 15); R52(a2, b2, c2, d2, e2, w15, 5); - R51(e1, a1, b1, c1, d1, w5 , 5); R52(e2, a2, b2, c2, d2, w10, 12); - R51(d1, e1, a1, b1, c1, w9 , 11); R52(d2, e2, a2, b2, c2, w4 , 9); - R51(c1, d1, e1, a1, b1, w7 , 6); R52(c2, d2, e2, a2, b2, w1 , 12); - R51(b1, c1, d1, e1, a1, w12, 8); R52(b2, c2, d2, e2, a2, w5 , 5); - R51(a1, b1, c1, d1, e1, w2 , 13); R52(a2, b2, c2, d2, e2, w8 , 14); - R51(e1, a1, b1, c1, d1, w10, 12); R52(e2, a2, b2, c2, d2, w7 , 6); - R51(d1, e1, a1, b1, c1, w14, 5); R52(d2, e2, a2, b2, c2, w6 , 8); - R51(c1, d1, e1, a1, b1, w1 , 12); R52(c2, d2, e2, a2, b2, w2 , 13); - R51(b1, c1, d1, e1, a1, w3 , 13); R52(b2, c2, d2, e2, a2, w13, 6); - R51(a1, b1, c1, d1, e1, w8 , 14); R52(a2, b2, c2, d2, e2, w14, 5); - R51(e1, a1, b1, c1, d1, w11, 11); R52(e2, a2, b2, c2, d2, w0 , 15); - R51(d1, e1, a1, b1, c1, w6 , 8); R52(d2, e2, a2, b2, c2, w3 , 13); - R51(c1, d1, e1, a1, b1, w15, 5); R52(c2, d2, e2, a2, b2, w9 , 11); - R51(b1, c1, d1, e1, a1, w13, 6); R52(b2, c2, d2, e2, a2, w11, 11); + R11(a1, b1, c1, d1, e1, w0, 11); + R12(a2, b2, c2, d2, e2, w5, 8); + R11(e1, a1, b1, c1, d1, w1, 14); + R12(e2, a2, b2, c2, d2, w14, 9); + R11(d1, e1, a1, b1, c1, w2, 15); + R12(d2, e2, a2, b2, c2, w7, 9); + R11(c1, d1, e1, a1, b1, w3, 12); + R12(c2, d2, e2, a2, b2, w0, 11); + R11(b1, c1, d1, e1, a1, w4, 5); + R12(b2, c2, d2, e2, a2, w9, 13); + R11(a1, b1, c1, d1, e1, w5, 8); + R12(a2, b2, c2, d2, e2, w2, 15); + R11(e1, a1, b1, c1, d1, w6, 7); + R12(e2, a2, b2, c2, d2, w11, 15); + R11(d1, e1, a1, b1, c1, w7, 9); + R12(d2, e2, a2, b2, c2, w4, 5); + R11(c1, d1, e1, a1, b1, w8, 11); + R12(c2, d2, e2, a2, b2, w13, 7); + R11(b1, c1, d1, e1, a1, w9, 13); + R12(b2, c2, d2, e2, a2, w6, 7); + R11(a1, b1, c1, d1, e1, w10, 14); + R12(a2, b2, c2, d2, e2, w15, 8); + R11(e1, a1, b1, c1, d1, w11, 15); + R12(e2, a2, b2, c2, d2, w8, 11); + R11(d1, e1, a1, b1, c1, w12, 6); + R12(d2, e2, a2, b2, c2, w1, 14); + R11(c1, d1, e1, a1, b1, w13, 7); + R12(c2, d2, e2, a2, b2, w10, 14); + R11(b1, c1, d1, e1, a1, w14, 9); + R12(b2, c2, d2, e2, a2, w3, 12); + R11(a1, b1, c1, d1, e1, w15, 8); + R12(a2, b2, c2, d2, e2, w12, 6); + + R21(e1, a1, b1, c1, d1, w7, 7); + R22(e2, a2, b2, c2, d2, w6, 9); + R21(d1, e1, a1, b1, c1, w4, 6); + R22(d2, e2, a2, b2, c2, w11, 13); + R21(c1, d1, e1, a1, b1, w13, 8); + R22(c2, d2, e2, a2, b2, w3, 15); + R21(b1, c1, d1, e1, a1, w1, 13); + R22(b2, c2, d2, e2, a2, w7, 7); + R21(a1, b1, c1, d1, e1, w10, 11); + R22(a2, b2, c2, d2, e2, w0, 12); + R21(e1, a1, b1, c1, d1, w6, 9); + R22(e2, a2, b2, c2, d2, w13, 8); + R21(d1, e1, a1, b1, c1, w15, 7); + R22(d2, e2, a2, b2, c2, w5, 9); + R21(c1, d1, e1, a1, b1, w3, 15); + R22(c2, d2, e2, a2, b2, w10, 11); + R21(b1, c1, d1, e1, a1, w12, 7); + R22(b2, c2, d2, e2, a2, w14, 7); + R21(a1, b1, c1, d1, e1, w0, 12); + R22(a2, b2, c2, d2, e2, w15, 7); + R21(e1, a1, b1, c1, d1, w9, 15); + R22(e2, a2, b2, c2, d2, w8, 12); + R21(d1, e1, a1, b1, c1, w5, 9); + R22(d2, e2, a2, b2, c2, w12, 7); + R21(c1, d1, e1, a1, b1, w2, 11); + R22(c2, d2, e2, a2, b2, w4, 6); + R21(b1, c1, d1, e1, a1, w14, 7); + R22(b2, c2, d2, e2, a2, w9, 15); + R21(a1, b1, c1, d1, e1, w11, 13); + R22(a2, b2, c2, d2, e2, w1, 13); + R21(e1, a1, b1, c1, d1, w8, 12); + R22(e2, a2, b2, c2, d2, w2, 11); + + R31(d1, e1, a1, b1, c1, w3, 11); + R32(d2, e2, a2, b2, c2, w15, 9); + R31(c1, d1, e1, a1, b1, w10, 13); + R32(c2, d2, e2, a2, b2, w5, 7); + R31(b1, c1, d1, e1, a1, w14, 6); + R32(b2, c2, d2, e2, a2, w1, 15); + R31(a1, b1, c1, d1, e1, w4, 7); + R32(a2, b2, c2, d2, e2, w3, 11); + R31(e1, a1, b1, c1, d1, w9, 14); + R32(e2, a2, b2, c2, d2, w7, 8); + R31(d1, e1, a1, b1, c1, w15, 9); + R32(d2, e2, a2, b2, c2, w14, 6); + R31(c1, d1, e1, a1, b1, w8, 13); + R32(c2, d2, e2, a2, b2, w6, 6); + R31(b1, c1, d1, e1, a1, w1, 15); + R32(b2, c2, d2, e2, a2, w9, 14); + R31(a1, b1, c1, d1, e1, w2, 14); + R32(a2, b2, c2, d2, e2, w11, 12); + R31(e1, a1, b1, c1, d1, w7, 8); + R32(e2, a2, b2, c2, d2, w8, 13); + R31(d1, e1, a1, b1, c1, w0, 13); + R32(d2, e2, a2, b2, c2, w12, 5); + R31(c1, d1, e1, a1, b1, w6, 6); + R32(c2, d2, e2, a2, b2, w2, 14); + R31(b1, c1, d1, e1, a1, w13, 5); + R32(b2, c2, d2, e2, a2, w10, 13); + R31(a1, b1, c1, d1, e1, w11, 12); + R32(a2, b2, c2, d2, e2, w0, 13); + R31(e1, a1, b1, c1, d1, w5, 7); + R32(e2, a2, b2, c2, d2, w4, 7); + R31(d1, e1, a1, b1, c1, w12, 5); + R32(d2, e2, a2, b2, c2, w13, 5); + + R41(c1, d1, e1, a1, b1, w1, 11); + R42(c2, d2, e2, a2, b2, w8, 15); + R41(b1, c1, d1, e1, a1, w9, 12); + R42(b2, c2, d2, e2, a2, w6, 5); + R41(a1, b1, c1, d1, e1, w11, 14); + R42(a2, b2, c2, d2, e2, w4, 8); + R41(e1, a1, b1, c1, d1, w10, 15); + R42(e2, a2, b2, c2, d2, w1, 11); + R41(d1, e1, a1, b1, c1, w0, 14); + R42(d2, e2, a2, b2, c2, w3, 14); + R41(c1, d1, e1, a1, b1, w8, 15); + R42(c2, d2, e2, a2, b2, w11, 14); + R41(b1, c1, d1, e1, a1, w12, 9); + R42(b2, c2, d2, e2, a2, w15, 6); + R41(a1, b1, c1, d1, e1, w4, 8); + R42(a2, b2, c2, d2, e2, w0, 14); + R41(e1, a1, b1, c1, d1, w13, 9); + R42(e2, a2, b2, c2, d2, w5, 6); + R41(d1, e1, a1, b1, c1, w3, 14); + R42(d2, e2, a2, b2, c2, w12, 9); + R41(c1, d1, e1, a1, b1, w7, 5); + R42(c2, d2, e2, a2, b2, w2, 12); + R41(b1, c1, d1, e1, a1, w15, 6); + R42(b2, c2, d2, e2, a2, w13, 9); + R41(a1, b1, c1, d1, e1, w14, 8); + R42(a2, b2, c2, d2, e2, w9, 12); + R41(e1, a1, b1, c1, d1, w5, 6); + R42(e2, a2, b2, c2, d2, w7, 5); + R41(d1, e1, a1, b1, c1, w6, 5); + R42(d2, e2, a2, b2, c2, w10, 15); + R41(c1, d1, e1, a1, b1, w2, 12); + R42(c2, d2, e2, a2, b2, w14, 8); + + R51(b1, c1, d1, e1, a1, w4, 9); + R52(b2, c2, d2, e2, a2, w12, 8); + R51(a1, b1, c1, d1, e1, w0, 15); + R52(a2, b2, c2, d2, e2, w15, 5); + R51(e1, a1, b1, c1, d1, w5, 5); + R52(e2, a2, b2, c2, d2, w10, 12); + R51(d1, e1, a1, b1, c1, w9, 11); + R52(d2, e2, a2, b2, c2, w4, 9); + R51(c1, d1, e1, a1, b1, w7, 6); + R52(c2, d2, e2, a2, b2, w1, 12); + R51(b1, c1, d1, e1, a1, w12, 8); + R52(b2, c2, d2, e2, a2, w5, 5); + R51(a1, b1, c1, d1, e1, w2, 13); + R52(a2, b2, c2, d2, e2, w8, 14); + R51(e1, a1, b1, c1, d1, w10, 12); + R52(e2, a2, b2, c2, d2, w7, 6); + R51(d1, e1, a1, b1, c1, w14, 5); + R52(d2, e2, a2, b2, c2, w6, 8); + R51(c1, d1, e1, a1, b1, w1, 12); + R52(c2, d2, e2, a2, b2, w2, 13); + R51(b1, c1, d1, e1, a1, w3, 13); + R52(b2, c2, d2, e2, a2, w13, 6); + R51(a1, b1, c1, d1, e1, w8, 14); + R52(a2, b2, c2, d2, e2, w14, 5); + R51(e1, a1, b1, c1, d1, w11, 11); + R52(e2, a2, b2, c2, d2, w0, 15); + R51(d1, e1, a1, b1, c1, w6, 8); + R52(d2, e2, a2, b2, c2, w3, 13); + R51(c1, d1, e1, a1, b1, w15, 5); + R52(c2, d2, e2, a2, b2, w9, 11); + R51(b1, c1, d1, e1, a1, w13, 6); + R52(b2, c2, d2, e2, a2, w11, 11); uint32_t t = s[0]; s[0] = s[1] + c1 + d2; s[1] = s[2] + d1 + e2; s[2] = s[3] + e1 + a2; s[3] = s[4] + a1 + b2; - s[4] = t + b1 + c2; + s[4] = t + b1 + c2; } -} // namespace ripemd160 +} // namespace ripemd160 -} // namespace +} // namespace ////// RIPEMD160 -CRIPEMD160::CRIPEMD160() : bytes(0) { +CRIPEMD160::CRIPEMD160() : bytes(0) +{ ripemd160::Initialize(s); } -CRIPEMD160& CRIPEMD160::Write(const unsigned char *data, size_t len) { - const unsigned char *end = data + len; +CRIPEMD160& CRIPEMD160::Write(const unsigned char* data, size_t len) +{ + const unsigned char* end = data + len; size_t bufsize = bytes % 64; if (bufsize && bufsize + len >= 64) { // Fill the buffer, and process it. @@ -185,20 +270,22 @@ CRIPEMD160& CRIPEMD160::Write(const unsigned char *data, size_t len) { return *this; } -void CRIPEMD160::Finalize(unsigned char hash[OUTPUT_SIZE]) { +void CRIPEMD160::Finalize(unsigned char hash[OUTPUT_SIZE]) +{ static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; WriteLE64(sizedesc, bytes << 3); Write(pad, 1 + ((119 - (bytes % 64)) % 64)); Write(sizedesc, 8); WriteLE32(hash, s[0]); - WriteLE32(hash+4, s[1]); - WriteLE32(hash+8, s[2]); - WriteLE32(hash+12, s[3]); - WriteLE32(hash+16, s[4]); + WriteLE32(hash + 4, s[1]); + WriteLE32(hash + 8, s[2]); + WriteLE32(hash + 12, s[3]); + WriteLE32(hash + 16, s[4]); } -CRIPEMD160& CRIPEMD160::Reset() { +CRIPEMD160& CRIPEMD160::Reset() +{ bytes = 0; ripemd160::Initialize(s); return *this; diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h index 44bd4879a5..902e7ca83f 100644 --- a/src/crypto/ripemd160.h +++ b/src/crypto/ripemd160.h @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_RIPEMD160_H @@ -9,7 +9,8 @@ #include <stdlib.h> /** A hasher class for RIPEMD-160. */ -class CRIPEMD160 { +class CRIPEMD160 +{ private: uint32_t s[5]; unsigned char buf[64]; @@ -19,9 +20,9 @@ public: static const size_t OUTPUT_SIZE = 20; CRIPEMD160(); - CRIPEMD160& Write(const unsigned char *data, size_t len); + CRIPEMD160& Write(const unsigned char* data, size_t len); void Finalize(unsigned char hash[OUTPUT_SIZE]); CRIPEMD160& Reset(); }; -#endif +#endif // BITCOIN_RIPEMD160_H diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp index 819abab579..7f78fdfc6d 100644 --- a/src/crypto/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "crypto/sha1.h" @@ -9,14 +9,14 @@ #include <string.h> // Internal implementation code. -namespace { - +namespace +{ /// Internal SHA-1 implementation. -namespace sha1 { - +namespace sha1 +{ /** One round of SHA-1. */ -void inline Round(uint32_t a, uint32_t &b, uint32_t c, uint32_t d, uint32_t &e, - uint32_t f, uint32_t k, uint32_t w) { +void inline Round(uint32_t a, uint32_t& b, uint32_t c, uint32_t d, uint32_t& e, uint32_t f, uint32_t k, uint32_t w) +{ e += ((a << 5) | (a >> 27)) + f + k + w; b = (b << 30) | (b >> 2); } @@ -28,7 +28,8 @@ uint32_t inline f3(uint32_t b, uint32_t c, uint32_t d) { return (b & c) | (d & ( uint32_t inline left(uint32_t x) { return (x << 1) | (x >> 31); } /** Initialize SHA-1 state. */ -void inline Initialize(uint32_t *s) { +void inline Initialize(uint32_t* s) +{ s[0] = 0x67452301ul; s[1] = 0xEFCDAB89ul; s[2] = 0x98BADCFEul; @@ -42,20 +43,21 @@ const uint32_t k3 = 0x8F1BBCDCul; const uint32_t k4 = 0xCA62C1D6ul; /** Perform a SHA-1 transformation, processing a 64-byte chunk. */ -void Transform(uint32_t *s, const unsigned char *chunk) { +void Transform(uint32_t* s, const unsigned char* chunk) +{ uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4]; uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - Round(a, b, c, d, e, f1(b, c, d), k1, w0 = ReadBE32(chunk + 0)); - Round(e, a, b, c, d, f1(a, b, c), k1, w1 = ReadBE32(chunk + 4)); - Round(d, e, a, b, c, f1(e, a, b), k1, w2 = ReadBE32(chunk + 8)); - Round(c, d, e, a, b, f1(d, e, a), k1, w3 = ReadBE32(chunk + 12)); - Round(b, c, d, e, a, f1(c, d, e), k1, w4 = ReadBE32(chunk + 16)); - Round(a, b, c, d, e, f1(b, c, d), k1, w5 = ReadBE32(chunk + 20)); - Round(e, a, b, c, d, f1(a, b, c), k1, w6 = ReadBE32(chunk + 24)); - Round(d, e, a, b, c, f1(e, a, b), k1, w7 = ReadBE32(chunk + 28)); - Round(c, d, e, a, b, f1(d, e, a), k1, w8 = ReadBE32(chunk + 32)); - Round(b, c, d, e, a, f1(c, d, e), k1, w9 = ReadBE32(chunk + 36)); + Round(a, b, c, d, e, f1(b, c, d), k1, w0 = ReadBE32(chunk + 0)); + Round(e, a, b, c, d, f1(a, b, c), k1, w1 = ReadBE32(chunk + 4)); + Round(d, e, a, b, c, f1(e, a, b), k1, w2 = ReadBE32(chunk + 8)); + Round(c, d, e, a, b, f1(d, e, a), k1, w3 = ReadBE32(chunk + 12)); + Round(b, c, d, e, a, f1(c, d, e), k1, w4 = ReadBE32(chunk + 16)); + Round(a, b, c, d, e, f1(b, c, d), k1, w5 = ReadBE32(chunk + 20)); + Round(e, a, b, c, d, f1(a, b, c), k1, w6 = ReadBE32(chunk + 24)); + Round(d, e, a, b, c, f1(e, a, b), k1, w7 = ReadBE32(chunk + 28)); + Round(c, d, e, a, b, f1(d, e, a), k1, w8 = ReadBE32(chunk + 32)); + Round(b, c, d, e, a, f1(c, d, e), k1, w9 = ReadBE32(chunk + 36)); Round(a, b, c, d, e, f1(b, c, d), k1, w10 = ReadBE32(chunk + 40)); Round(e, a, b, c, d, f1(a, b, c), k1, w11 = ReadBE32(chunk + 44)); Round(d, e, a, b, c, f1(e, a, b), k1, w12 = ReadBE32(chunk + 48)); @@ -63,73 +65,73 @@ void Transform(uint32_t *s, const unsigned char *chunk) { Round(b, c, d, e, a, f1(c, d, e), k1, w14 = ReadBE32(chunk + 56)); Round(a, b, c, d, e, f1(b, c, d), k1, w15 = ReadBE32(chunk + 60)); - Round(e, a, b, c, d, f1(a, b, c), k1, w0 = left(w0 ^ w13 ^ w8 ^ w2 )); - Round(d, e, a, b, c, f1(e, a, b), k1, w1 = left(w1 ^ w14 ^ w9 ^ w3 )); - Round(c, d, e, a, b, f1(d, e, a), k1, w2 = left(w2 ^ w15 ^ w10 ^ w4 )); - Round(b, c, d, e, a, f1(c, d, e), k1, w3 = left(w3 ^ w0 ^ w11 ^ w5 )); - Round(a, b, c, d, e, f2(b, c, d), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6 )); - Round(e, a, b, c, d, f2(a, b, c), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7 )); - Round(d, e, a, b, c, f2(e, a, b), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8 )); - Round(c, d, e, a, b, f2(d, e, a), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9 )); - Round(b, c, d, e, a, f2(c, d, e), k2, w8 = left(w8 ^ w5 ^ w0 ^ w10)); - Round(a, b, c, d, e, f2(b, c, d), k2, w9 = left(w9 ^ w6 ^ w1 ^ w11)); - Round(e, a, b, c, d, f2(a, b, c), k2, w10 = left(w10 ^ w7 ^ w2 ^ w12)); - Round(d, e, a, b, c, f2(e, a, b), k2, w11 = left(w11 ^ w8 ^ w3 ^ w13)); - Round(c, d, e, a, b, f2(d, e, a), k2, w12 = left(w12 ^ w9 ^ w4 ^ w14)); - Round(b, c, d, e, a, f2(c, d, e), k2, w13 = left(w13 ^ w10 ^ w5 ^ w15)); - Round(a, b, c, d, e, f2(b, c, d), k2, w14 = left(w14 ^ w11 ^ w6 ^ w0 )); - Round(e, a, b, c, d, f2(a, b, c), k2, w15 = left(w15 ^ w12 ^ w7 ^ w1 )); - - Round(d, e, a, b, c, f2(e, a, b), k2, w0 = left(w0 ^ w13 ^ w8 ^ w2 )); - Round(c, d, e, a, b, f2(d, e, a), k2, w1 = left(w1 ^ w14 ^ w9 ^ w3 )); - Round(b, c, d, e, a, f2(c, d, e), k2, w2 = left(w2 ^ w15 ^ w10 ^ w4 )); - Round(a, b, c, d, e, f2(b, c, d), k2, w3 = left(w3 ^ w0 ^ w11 ^ w5 )); - Round(e, a, b, c, d, f2(a, b, c), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6 )); - Round(d, e, a, b, c, f2(e, a, b), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7 )); - Round(c, d, e, a, b, f2(d, e, a), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8 )); - Round(b, c, d, e, a, f2(c, d, e), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9 )); - Round(a, b, c, d, e, f3(b, c, d), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10)); - Round(e, a, b, c, d, f3(a, b, c), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11)); - Round(d, e, a, b, c, f3(e, a, b), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12)); - Round(c, d, e, a, b, f3(d, e, a), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13)); - Round(b, c, d, e, a, f3(c, d, e), k3, w12 = left(w12 ^ w9 ^ w4 ^ w14)); - Round(a, b, c, d, e, f3(b, c, d), k3, w13 = left(w13 ^ w10 ^ w5 ^ w15)); - Round(e, a, b, c, d, f3(a, b, c), k3, w14 = left(w14 ^ w11 ^ w6 ^ w0 )); - Round(d, e, a, b, c, f3(e, a, b), k3, w15 = left(w15 ^ w12 ^ w7 ^ w1 )); - - Round(c, d, e, a, b, f3(d, e, a), k3, w0 = left(w0 ^ w13 ^ w8 ^ w2 )); - Round(b, c, d, e, a, f3(c, d, e), k3, w1 = left(w1 ^ w14 ^ w9 ^ w3 )); - Round(a, b, c, d, e, f3(b, c, d), k3, w2 = left(w2 ^ w15 ^ w10 ^ w4 )); - Round(e, a, b, c, d, f3(a, b, c), k3, w3 = left(w3 ^ w0 ^ w11 ^ w5 )); - Round(d, e, a, b, c, f3(e, a, b), k3, w4 = left(w4 ^ w1 ^ w12 ^ w6 )); - Round(c, d, e, a, b, f3(d, e, a), k3, w5 = left(w5 ^ w2 ^ w13 ^ w7 )); - Round(b, c, d, e, a, f3(c, d, e), k3, w6 = left(w6 ^ w3 ^ w14 ^ w8 )); - Round(a, b, c, d, e, f3(b, c, d), k3, w7 = left(w7 ^ w4 ^ w15 ^ w9 )); - Round(e, a, b, c, d, f3(a, b, c), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10)); - Round(d, e, a, b, c, f3(e, a, b), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11)); - Round(c, d, e, a, b, f3(d, e, a), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12)); - Round(b, c, d, e, a, f3(c, d, e), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13)); - Round(a, b, c, d, e, f2(b, c, d), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14)); - Round(e, a, b, c, d, f2(a, b, c), k4, w13 = left(w13 ^ w10 ^ w5 ^ w15)); - Round(d, e, a, b, c, f2(e, a, b), k4, w14 = left(w14 ^ w11 ^ w6 ^ w0 )); - Round(c, d, e, a, b, f2(d, e, a), k4, w15 = left(w15 ^ w12 ^ w7 ^ w1 )); - - Round(b, c, d, e, a, f2(c, d, e), k4, w0 = left(w0 ^ w13 ^ w8 ^ w2 )); - Round(a, b, c, d, e, f2(b, c, d), k4, w1 = left(w1 ^ w14 ^ w9 ^ w3 )); - Round(e, a, b, c, d, f2(a, b, c), k4, w2 = left(w2 ^ w15 ^ w10 ^ w4 )); - Round(d, e, a, b, c, f2(e, a, b), k4, w3 = left(w3 ^ w0 ^ w11 ^ w5 )); - Round(c, d, e, a, b, f2(d, e, a), k4, w4 = left(w4 ^ w1 ^ w12 ^ w6 )); - Round(b, c, d, e, a, f2(c, d, e), k4, w5 = left(w5 ^ w2 ^ w13 ^ w7 )); - Round(a, b, c, d, e, f2(b, c, d), k4, w6 = left(w6 ^ w3 ^ w14 ^ w8 )); - Round(e, a, b, c, d, f2(a, b, c), k4, w7 = left(w7 ^ w4 ^ w15 ^ w9 )); - Round(d, e, a, b, c, f2(e, a, b), k4, w8 = left(w8 ^ w5 ^ w0 ^ w10)); - Round(c, d, e, a, b, f2(d, e, a), k4, w9 = left(w9 ^ w6 ^ w1 ^ w11)); - Round(b, c, d, e, a, f2(c, d, e), k4, w10 = left(w10 ^ w7 ^ w2 ^ w12)); - Round(a, b, c, d, e, f2(b, c, d), k4, w11 = left(w11 ^ w8 ^ w3 ^ w13)); - Round(e, a, b, c, d, f2(a, b, c), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14)); - Round(d, e, a, b, c, f2(e, a, b), k4, left(w13 ^ w10 ^ w5 ^ w15)); - Round(c, d, e, a, b, f2(d, e, a), k4, left(w14 ^ w11 ^ w6 ^ w0 )); - Round(b, c, d, e, a, f2(c, d, e), k4, left(w15 ^ w12 ^ w7 ^ w1 )); + Round(e, a, b, c, d, f1(a, b, c), k1, w0 = left(w0 ^ w13 ^ w8 ^ w2)); + Round(d, e, a, b, c, f1(e, a, b), k1, w1 = left(w1 ^ w14 ^ w9 ^ w3)); + Round(c, d, e, a, b, f1(d, e, a), k1, w2 = left(w2 ^ w15 ^ w10 ^ w4)); + Round(b, c, d, e, a, f1(c, d, e), k1, w3 = left(w3 ^ w0 ^ w11 ^ w5)); + Round(a, b, c, d, e, f2(b, c, d), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6)); + Round(e, a, b, c, d, f2(a, b, c), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7)); + Round(d, e, a, b, c, f2(e, a, b), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8)); + Round(c, d, e, a, b, f2(d, e, a), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9)); + Round(b, c, d, e, a, f2(c, d, e), k2, w8 = left(w8 ^ w5 ^ w0 ^ w10)); + Round(a, b, c, d, e, f2(b, c, d), k2, w9 = left(w9 ^ w6 ^ w1 ^ w11)); + Round(e, a, b, c, d, f2(a, b, c), k2, w10 = left(w10 ^ w7 ^ w2 ^ w12)); + Round(d, e, a, b, c, f2(e, a, b), k2, w11 = left(w11 ^ w8 ^ w3 ^ w13)); + Round(c, d, e, a, b, f2(d, e, a), k2, w12 = left(w12 ^ w9 ^ w4 ^ w14)); + Round(b, c, d, e, a, f2(c, d, e), k2, w13 = left(w13 ^ w10 ^ w5 ^ w15)); + Round(a, b, c, d, e, f2(b, c, d), k2, w14 = left(w14 ^ w11 ^ w6 ^ w0)); + Round(e, a, b, c, d, f2(a, b, c), k2, w15 = left(w15 ^ w12 ^ w7 ^ w1)); + + Round(d, e, a, b, c, f2(e, a, b), k2, w0 = left(w0 ^ w13 ^ w8 ^ w2)); + Round(c, d, e, a, b, f2(d, e, a), k2, w1 = left(w1 ^ w14 ^ w9 ^ w3)); + Round(b, c, d, e, a, f2(c, d, e), k2, w2 = left(w2 ^ w15 ^ w10 ^ w4)); + Round(a, b, c, d, e, f2(b, c, d), k2, w3 = left(w3 ^ w0 ^ w11 ^ w5)); + Round(e, a, b, c, d, f2(a, b, c), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6)); + Round(d, e, a, b, c, f2(e, a, b), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7)); + Round(c, d, e, a, b, f2(d, e, a), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8)); + Round(b, c, d, e, a, f2(c, d, e), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9)); + Round(a, b, c, d, e, f3(b, c, d), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10)); + Round(e, a, b, c, d, f3(a, b, c), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11)); + Round(d, e, a, b, c, f3(e, a, b), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12)); + Round(c, d, e, a, b, f3(d, e, a), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13)); + Round(b, c, d, e, a, f3(c, d, e), k3, w12 = left(w12 ^ w9 ^ w4 ^ w14)); + Round(a, b, c, d, e, f3(b, c, d), k3, w13 = left(w13 ^ w10 ^ w5 ^ w15)); + Round(e, a, b, c, d, f3(a, b, c), k3, w14 = left(w14 ^ w11 ^ w6 ^ w0)); + Round(d, e, a, b, c, f3(e, a, b), k3, w15 = left(w15 ^ w12 ^ w7 ^ w1)); + + Round(c, d, e, a, b, f3(d, e, a), k3, w0 = left(w0 ^ w13 ^ w8 ^ w2)); + Round(b, c, d, e, a, f3(c, d, e), k3, w1 = left(w1 ^ w14 ^ w9 ^ w3)); + Round(a, b, c, d, e, f3(b, c, d), k3, w2 = left(w2 ^ w15 ^ w10 ^ w4)); + Round(e, a, b, c, d, f3(a, b, c), k3, w3 = left(w3 ^ w0 ^ w11 ^ w5)); + Round(d, e, a, b, c, f3(e, a, b), k3, w4 = left(w4 ^ w1 ^ w12 ^ w6)); + Round(c, d, e, a, b, f3(d, e, a), k3, w5 = left(w5 ^ w2 ^ w13 ^ w7)); + Round(b, c, d, e, a, f3(c, d, e), k3, w6 = left(w6 ^ w3 ^ w14 ^ w8)); + Round(a, b, c, d, e, f3(b, c, d), k3, w7 = left(w7 ^ w4 ^ w15 ^ w9)); + Round(e, a, b, c, d, f3(a, b, c), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10)); + Round(d, e, a, b, c, f3(e, a, b), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11)); + Round(c, d, e, a, b, f3(d, e, a), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12)); + Round(b, c, d, e, a, f3(c, d, e), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13)); + Round(a, b, c, d, e, f2(b, c, d), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14)); + Round(e, a, b, c, d, f2(a, b, c), k4, w13 = left(w13 ^ w10 ^ w5 ^ w15)); + Round(d, e, a, b, c, f2(e, a, b), k4, w14 = left(w14 ^ w11 ^ w6 ^ w0)); + Round(c, d, e, a, b, f2(d, e, a), k4, w15 = left(w15 ^ w12 ^ w7 ^ w1)); + + Round(b, c, d, e, a, f2(c, d, e), k4, w0 = left(w0 ^ w13 ^ w8 ^ w2)); + Round(a, b, c, d, e, f2(b, c, d), k4, w1 = left(w1 ^ w14 ^ w9 ^ w3)); + Round(e, a, b, c, d, f2(a, b, c), k4, w2 = left(w2 ^ w15 ^ w10 ^ w4)); + Round(d, e, a, b, c, f2(e, a, b), k4, w3 = left(w3 ^ w0 ^ w11 ^ w5)); + Round(c, d, e, a, b, f2(d, e, a), k4, w4 = left(w4 ^ w1 ^ w12 ^ w6)); + Round(b, c, d, e, a, f2(c, d, e), k4, w5 = left(w5 ^ w2 ^ w13 ^ w7)); + Round(a, b, c, d, e, f2(b, c, d), k4, w6 = left(w6 ^ w3 ^ w14 ^ w8)); + Round(e, a, b, c, d, f2(a, b, c), k4, w7 = left(w7 ^ w4 ^ w15 ^ w9)); + Round(d, e, a, b, c, f2(e, a, b), k4, w8 = left(w8 ^ w5 ^ w0 ^ w10)); + Round(c, d, e, a, b, f2(d, e, a), k4, w9 = left(w9 ^ w6 ^ w1 ^ w11)); + Round(b, c, d, e, a, f2(c, d, e), k4, w10 = left(w10 ^ w7 ^ w2 ^ w12)); + Round(a, b, c, d, e, f2(b, c, d), k4, w11 = left(w11 ^ w8 ^ w3 ^ w13)); + Round(e, a, b, c, d, f2(a, b, c), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14)); + Round(d, e, a, b, c, f2(e, a, b), k4, left(w13 ^ w10 ^ w5 ^ w15)); + Round(c, d, e, a, b, f2(d, e, a), k4, left(w14 ^ w11 ^ w6 ^ w0)); + Round(b, c, d, e, a, f2(c, d, e), k4, left(w15 ^ w12 ^ w7 ^ w1)); s[0] += a; s[1] += b; @@ -138,18 +140,20 @@ void Transform(uint32_t *s, const unsigned char *chunk) { s[4] += e; } -} // namespace sha1 +} // namespace sha1 -} // namespace +} // namespace ////// SHA1 -CSHA1::CSHA1() : bytes(0) { +CSHA1::CSHA1() : bytes(0) +{ sha1::Initialize(s); } -CSHA1& CSHA1::Write(const unsigned char *data, size_t len) { - const unsigned char *end = data + len; +CSHA1& CSHA1::Write(const unsigned char* data, size_t len) +{ + const unsigned char* end = data + len; size_t bufsize = bytes % 64; if (bufsize && bufsize + len >= 64) { // Fill the buffer, and process it. @@ -173,20 +177,22 @@ CSHA1& CSHA1::Write(const unsigned char *data, size_t len) { return *this; } -void CSHA1::Finalize(unsigned char hash[OUTPUT_SIZE]) { +void CSHA1::Finalize(unsigned char hash[OUTPUT_SIZE]) +{ static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; WriteBE64(sizedesc, bytes << 3); Write(pad, 1 + ((119 - (bytes % 64)) % 64)); Write(sizedesc, 8); WriteBE32(hash, s[0]); - WriteBE32(hash+4, s[1]); - WriteBE32(hash+8, s[2]); - WriteBE32(hash+12, s[3]); - WriteBE32(hash+16, s[4]); + WriteBE32(hash + 4, s[1]); + WriteBE32(hash + 8, s[2]); + WriteBE32(hash + 12, s[3]); + WriteBE32(hash + 16, s[4]); } -CSHA1& CSHA1::Reset() { +CSHA1& CSHA1::Reset() +{ bytes = 0; sha1::Initialize(s); return *this; diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h index b16f2c88ce..68bd7ced9f 100644 --- a/src/crypto/sha1.h +++ b/src/crypto/sha1.h @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_SHA1_H @@ -9,7 +9,8 @@ #include <stdlib.h> /** A hasher class for SHA1. */ -class CSHA1 { +class CSHA1 +{ private: uint32_t s[5]; unsigned char buf[64]; @@ -19,9 +20,9 @@ public: static const size_t OUTPUT_SIZE = 20; CSHA1(); - CSHA1& Write(const unsigned char *data, size_t len); + CSHA1& Write(const unsigned char* data, size_t len); void Finalize(unsigned char hash[OUTPUT_SIZE]); CSHA1& Reset(); }; -#endif +#endif // BITCOIN_SHA1_H diff --git a/src/crypto/sha2.cpp b/src/crypto/sha2.cpp index 72f191afcd..613aac2d71 100644 --- a/src/crypto/sha2.cpp +++ b/src/crypto/sha2.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "crypto/sha2.h" @@ -9,11 +9,11 @@ #include <string.h> // Internal implementation code. -namespace { - +namespace +{ /// Internal SHA-256 implementation. -namespace sha256 { - +namespace sha256 +{ uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); } uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); } uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); } @@ -22,9 +22,8 @@ uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); } /** One round of SHA-256. */ -void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t &d, - uint32_t e, uint32_t f, uint32_t g, uint32_t &h, - uint32_t k, uint32_t w) { +void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w) +{ uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; uint32_t t2 = Sigma0(a) + Maj(a, b, c); d += t1; @@ -32,7 +31,8 @@ void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t &d, } /** Initialize SHA-256 state. */ -void inline Initialize(uint32_t *s) { +void inline Initialize(uint32_t* s) +{ s[0] = 0x6a09e667ul; s[1] = 0xbb67ae85ul; s[2] = 0x3c6ef372ul; @@ -44,20 +44,21 @@ void inline Initialize(uint32_t *s) { } /** Perform one SHA-256 transformation, processing a 64-byte chunk. */ -void Transform(uint32_t *s, const unsigned char *chunk) { +void Transform(uint32_t* s, const unsigned char* chunk) +{ uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); - Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12)); - Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16)); - Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20)); - Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24)); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28)); - Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32)); - Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36)); + Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); + Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12)); + Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16)); + Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20)); + Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24)); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28)); + Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32)); + Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36)); Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40)); Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44)); Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48)); @@ -65,56 +66,56 @@ void Transform(uint32_t *s, const unsigned char *chunk) { Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56)); Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60)); - Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0( w1)); - Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0( w2)); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1( w0) + w11 + sigma0( w3)); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1( w1) + w12 + sigma0( w4)); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1( w2) + w13 + sigma0( w5)); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1( w3) + w14 + sigma0( w6)); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1( w4) + w15 + sigma0( w7)); - Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1( w5) + w0 + sigma0( w8)); - Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1( w6) + w1 + sigma0( w9)); - Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1( w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1( w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1( w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0( w0)); - - Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0( w1)); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0( w2)); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1( w0) + w11 + sigma0( w3)); - Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1( w1) + w12 + sigma0( w4)); - Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1( w2) + w13 + sigma0( w5)); - Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1( w3) + w14 + sigma0( w6)); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1( w4) + w15 + sigma0( w7)); - Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1( w5) + w0 + sigma0( w8)); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1( w6) + w1 + sigma0( w9)); - Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1( w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1( w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1( w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0( w0)); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0( w1)); - Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0( w2)); - Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1( w0) + w11 + sigma0( w3)); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1( w1) + w12 + sigma0( w4)); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1( w2) + w13 + sigma0( w5)); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1( w3) + w14 + sigma0( w6)); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1( w4) + w15 + sigma0( w7)); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1( w5) + w0 + sigma0( w8)); - Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1( w6) + w1 + sigma0( w9)); - Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1( w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1( w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1( w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0( w0)); + Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); s[0] += a; s[1] += b; @@ -126,11 +127,11 @@ void Transform(uint32_t *s, const unsigned char *chunk) { s[7] += h; } -} // namespace sha256 +} // namespace sha256 /// Internal SHA-512 implementation. -namespace sha512 { - +namespace sha512 +{ uint64_t inline Ch(uint64_t x, uint64_t y, uint64_t z) { return z ^ (x & (y ^ z)); } uint64_t inline Maj(uint64_t x, uint64_t y, uint64_t z) { return (x & y) | (z & (x | y)); } uint64_t inline Sigma0(uint64_t x) { return (x >> 28 | x << 36) ^ (x >> 34 | x << 30) ^ (x >> 39 | x << 25); } @@ -139,9 +140,8 @@ uint64_t inline sigma0(uint64_t x) { return (x >> 1 | x << 63) ^ (x >> 8 | x << uint64_t inline sigma1(uint64_t x) { return (x >> 19 | x << 45) ^ (x >> 61 | x << 3) ^ (x >> 6); } /** One round of SHA-512. */ -void inline Round(uint64_t a, uint64_t b, uint64_t c, uint64_t &d, - uint64_t e, uint64_t f, uint64_t g, uint64_t &h, - uint64_t k, uint64_t w) { +void inline Round(uint64_t a, uint64_t b, uint64_t c, uint64_t& d, uint64_t e, uint64_t f, uint64_t g, uint64_t& h, uint64_t k, uint64_t w) +{ uint64_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; uint64_t t2 = Sigma0(a) + Maj(a, b, c); d += t1; @@ -149,7 +149,8 @@ void inline Round(uint64_t a, uint64_t b, uint64_t c, uint64_t &d, } /** Initialize SHA-256 state. */ -void inline Initialize(uint64_t *s) { +void inline Initialize(uint64_t* s) +{ s[0] = 0x6a09e667f3bcc908ull; s[1] = 0xbb67ae8584caa73bull; s[2] = 0x3c6ef372fe94f82bull; @@ -161,20 +162,21 @@ void inline Initialize(uint64_t *s) { } /** Perform one SHA-512 transformation, processing a 128-byte chunk. */ -void Transform(uint64_t *s, const unsigned char *chunk) { +void Transform(uint64_t* s, const unsigned char* chunk) +{ uint64_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; uint64_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - Round(a, b, c, d, e, f, g, h, 0x428a2f98d728ae22ull, w0 = ReadBE64(chunk + 0)); - Round(h, a, b, c, d, e, f, g, 0x7137449123ef65cdull, w1 = ReadBE64(chunk + 8)); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcfec4d3b2full, w2 = ReadBE64(chunk + 16)); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba58189dbbcull, w3 = ReadBE64(chunk + 24)); - Round(e, f, g, h, a, b, c, d, 0x3956c25bf348b538ull, w4 = ReadBE64(chunk + 32)); - Round(d, e, f, g, h, a, b, c, 0x59f111f1b605d019ull, w5 = ReadBE64(chunk + 40)); - Round(c, d, e, f, g, h, a, b, 0x923f82a4af194f9bull, w6 = ReadBE64(chunk + 48)); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5da6d8118ull, w7 = ReadBE64(chunk + 56)); - Round(a, b, c, d, e, f, g, h, 0xd807aa98a3030242ull, w8 = ReadBE64(chunk + 64)); - Round(h, a, b, c, d, e, f, g, 0x12835b0145706fbeull, w9 = ReadBE64(chunk + 72)); + Round(a, b, c, d, e, f, g, h, 0x428a2f98d728ae22ull, w0 = ReadBE64(chunk + 0)); + Round(h, a, b, c, d, e, f, g, 0x7137449123ef65cdull, w1 = ReadBE64(chunk + 8)); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcfec4d3b2full, w2 = ReadBE64(chunk + 16)); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba58189dbbcull, w3 = ReadBE64(chunk + 24)); + Round(e, f, g, h, a, b, c, d, 0x3956c25bf348b538ull, w4 = ReadBE64(chunk + 32)); + Round(d, e, f, g, h, a, b, c, 0x59f111f1b605d019ull, w5 = ReadBE64(chunk + 40)); + Round(c, d, e, f, g, h, a, b, 0x923f82a4af194f9bull, w6 = ReadBE64(chunk + 48)); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5da6d8118ull, w7 = ReadBE64(chunk + 56)); + Round(a, b, c, d, e, f, g, h, 0xd807aa98a3030242ull, w8 = ReadBE64(chunk + 64)); + Round(h, a, b, c, d, e, f, g, 0x12835b0145706fbeull, w9 = ReadBE64(chunk + 72)); Round(g, h, a, b, c, d, e, f, 0x243185be4ee4b28cull, w10 = ReadBE64(chunk + 80)); Round(f, g, h, a, b, c, d, e, 0x550c7dc3d5ffb4e2ull, w11 = ReadBE64(chunk + 88)); Round(e, f, g, h, a, b, c, d, 0x72be5d74f27b896full, w12 = ReadBE64(chunk + 96)); @@ -182,73 +184,73 @@ void Transform(uint64_t *s, const unsigned char *chunk) { Round(c, d, e, f, g, h, a, b, 0x9bdc06a725c71235ull, w14 = ReadBE64(chunk + 112)); Round(b, c, d, e, f, g, h, a, 0xc19bf174cf692694ull, w15 = ReadBE64(chunk + 120)); - Round(a, b, c, d, e, f, g, h, 0xe49b69c19ef14ad2ull, w0 += sigma1(w14) + w9 + sigma0( w1)); - Round(h, a, b, c, d, e, f, g, 0xefbe4786384f25e3ull, w1 += sigma1(w15) + w10 + sigma0( w2)); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc68b8cd5b5ull, w2 += sigma1( w0) + w11 + sigma0( w3)); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc77ac9c65ull, w3 += sigma1( w1) + w12 + sigma0( w4)); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f592b0275ull, w4 += sigma1( w2) + w13 + sigma0( w5)); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa6ea6e483ull, w5 += sigma1( w3) + w14 + sigma0( w6)); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcbd41fbd4ull, w6 += sigma1( w4) + w15 + sigma0( w7)); - Round(b, c, d, e, f, g, h, a, 0x76f988da831153b5ull, w7 += sigma1( w5) + w0 + sigma0( w8)); - Round(a, b, c, d, e, f, g, h, 0x983e5152ee66dfabull, w8 += sigma1( w6) + w1 + sigma0( w9)); - Round(h, a, b, c, d, e, f, g, 0xa831c66d2db43210ull, w9 += sigma1( w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xb00327c898fb213full, w10 += sigma1( w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7beef0ee4ull, w11 += sigma1( w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf33da88fc2ull, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147930aa725ull, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351e003826full, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x142929670a0e6e70ull, w15 += sigma1(w13) + w8 + sigma0( w0)); - - Round(a, b, c, d, e, f, g, h, 0x27b70a8546d22ffcull, w0 += sigma1(w14) + w9 + sigma0( w1)); - Round(h, a, b, c, d, e, f, g, 0x2e1b21385c26c926ull, w1 += sigma1(w15) + w10 + sigma0( w2)); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc5ac42aedull, w2 += sigma1( w0) + w11 + sigma0( w3)); - Round(f, g, h, a, b, c, d, e, 0x53380d139d95b3dfull, w3 += sigma1( w1) + w12 + sigma0( w4)); - Round(e, f, g, h, a, b, c, d, 0x650a73548baf63deull, w4 += sigma1( w2) + w13 + sigma0( w5)); - Round(d, e, f, g, h, a, b, c, 0x766a0abb3c77b2a8ull, w5 += sigma1( w3) + w14 + sigma0( w6)); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e47edaee6ull, w6 += sigma1( w4) + w15 + sigma0( w7)); - Round(b, c, d, e, f, g, h, a, 0x92722c851482353bull, w7 += sigma1( w5) + w0 + sigma0( w8)); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a14cf10364ull, w8 += sigma1( w6) + w1 + sigma0( w9)); - Round(h, a, b, c, d, e, f, g, 0xa81a664bbc423001ull, w9 += sigma1( w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70d0f89791ull, w10 += sigma1( w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xc76c51a30654be30ull, w11 += sigma1( w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xd192e819d6ef5218ull, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd69906245565a910ull, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xf40e35855771202aull, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x106aa07032bbd1b8ull, w15 += sigma1(w13) + w8 + sigma0( w0)); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116b8d2d0c8ull, w0 += sigma1(w14) + w9 + sigma0( w1)); - Round(h, a, b, c, d, e, f, g, 0x1e376c085141ab53ull, w1 += sigma1(w15) + w10 + sigma0( w2)); - Round(g, h, a, b, c, d, e, f, 0x2748774cdf8eeb99ull, w2 += sigma1( w0) + w11 + sigma0( w3)); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5e19b48a8ull, w3 += sigma1( w1) + w12 + sigma0( w4)); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3c5c95a63ull, w4 += sigma1( w2) + w13 + sigma0( w5)); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4ae3418acbull, w5 += sigma1( w3) + w14 + sigma0( w6)); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f7763e373ull, w6 += sigma1( w4) + w15 + sigma0( w7)); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3d6b2b8a3ull, w7 += sigma1( w5) + w0 + sigma0( w8)); - Round(a, b, c, d, e, f, g, h, 0x748f82ee5defb2fcull, w8 += sigma1( w6) + w1 + sigma0( w9)); - Round(h, a, b, c, d, e, f, g, 0x78a5636f43172f60ull, w9 += sigma1( w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x84c87814a1f0ab72ull, w10 += sigma1( w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x8cc702081a6439ecull, w11 += sigma1( w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x90befffa23631e28ull, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xa4506cebde82bde9ull, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7b2c67915ull, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0xc67178f2e372532bull, w15 += sigma1(w13) + w8 + sigma0( w0)); - - Round(a, b, c, d, e, f, g, h, 0xca273eceea26619cull, w0 += sigma1(w14) + w9 + sigma0( w1)); - Round(h, a, b, c, d, e, f, g, 0xd186b8c721c0c207ull, w1 += sigma1(w15) + w10 + sigma0( w2)); - Round(g, h, a, b, c, d, e, f, 0xeada7dd6cde0eb1eull, w2 += sigma1( w0) + w11 + sigma0( w3)); - Round(f, g, h, a, b, c, d, e, 0xf57d4f7fee6ed178ull, w3 += sigma1( w1) + w12 + sigma0( w4)); - Round(e, f, g, h, a, b, c, d, 0x06f067aa72176fbaull, w4 += sigma1( w2) + w13 + sigma0( w5)); - Round(d, e, f, g, h, a, b, c, 0x0a637dc5a2c898a6ull, w5 += sigma1( w3) + w14 + sigma0( w6)); - Round(c, d, e, f, g, h, a, b, 0x113f9804bef90daeull, w6 += sigma1( w4) + w15 + sigma0( w7)); - Round(b, c, d, e, f, g, h, a, 0x1b710b35131c471bull, w7 += sigma1( w5) + w0 + sigma0( w8)); - Round(a, b, c, d, e, f, g, h, 0x28db77f523047d84ull, w8 += sigma1( w6) + w1 + sigma0( w9)); - Round(h, a, b, c, d, e, f, g, 0x32caab7b40c72493ull, w9 += sigma1( w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x3c9ebe0a15c9bebcull, w10 += sigma1( w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1( w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 += sigma1(w13) + w8 + sigma0( w0)); + Round(a, b, c, d, e, f, g, h, 0xe49b69c19ef14ad2ull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786384f25e3ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc68b8cd5b5ull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc77ac9c65ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f592b0275ull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa6ea6e483ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcbd41fbd4ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da831153b5ull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152ee66dfabull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d2db43210ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c898fb213full, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7beef0ee4ull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf33da88fc2ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147930aa725ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351e003826full, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x142929670a0e6e70ull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a8546d22ffcull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b21385c26c926ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc5ac42aedull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d139d95b3dfull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x650a73548baf63deull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb3c77b2a8ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e47edaee6ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c851482353bull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a14cf10364ull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664bbc423001ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70d0f89791ull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a30654be30ull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819d6ef5218ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd69906245565a910ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e35855771202aull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa07032bbd1b8ull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116b8d2d0c8ull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c085141ab53ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774cdf8eeb99ull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5e19b48a8ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3c5c95a63ull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4ae3418acbull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f7763e373ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3d6b2b8a3ull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee5defb2fcull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f43172f60ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814a1f0ab72ull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc702081a6439ecull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa23631e28ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506cebde82bde9ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7b2c67915ull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2e372532bull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0xca273eceea26619cull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0xd186b8c721c0c207ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0xeada7dd6cde0eb1eull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0xf57d4f7fee6ed178ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x06f067aa72176fbaull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x0a637dc5a2c898a6ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x113f9804bef90daeull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x1b710b35131c471bull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x28db77f523047d84ull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0x32caab7b40c72493ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x3c9ebe0a15c9bebcull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 += sigma1(w13) + w8 + sigma0(w0)); s[0] += a; s[1] += b; @@ -260,19 +262,21 @@ void Transform(uint64_t *s, const unsigned char *chunk) { s[7] += h; } -} // namespace sha512 +} // namespace sha512 -} // namespace +} // namespace ////// SHA-256 -CSHA256::CSHA256() : bytes(0) { +CSHA256::CSHA256() : bytes(0) +{ sha256::Initialize(s); } -CSHA256& CSHA256::Write(const unsigned char *data, size_t len) { - const unsigned char *end = data + len; +CSHA256& CSHA256::Write(const unsigned char* data, size_t len) +{ + const unsigned char* end = data + len; size_t bufsize = bytes % 64; if (bufsize && bufsize + len >= 64) { // Fill the buffer, and process it. @@ -296,23 +300,25 @@ CSHA256& CSHA256::Write(const unsigned char *data, size_t len) { return *this; } -void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) { +void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) +{ static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; WriteBE64(sizedesc, bytes << 3); Write(pad, 1 + ((119 - (bytes % 64)) % 64)); Write(sizedesc, 8); WriteBE32(hash, s[0]); - WriteBE32(hash+4, s[1]); - WriteBE32(hash+8, s[2]); - WriteBE32(hash+12, s[3]); - WriteBE32(hash+16, s[4]); - WriteBE32(hash+20, s[5]); - WriteBE32(hash+24, s[6]); - WriteBE32(hash+28, s[7]); + WriteBE32(hash + 4, s[1]); + WriteBE32(hash + 8, s[2]); + WriteBE32(hash + 12, s[3]); + WriteBE32(hash + 16, s[4]); + WriteBE32(hash + 20, s[5]); + WriteBE32(hash + 24, s[6]); + WriteBE32(hash + 28, s[7]); } -CSHA256& CSHA256::Reset() { +CSHA256& CSHA256::Reset() +{ bytes = 0; sha256::Initialize(s); return *this; @@ -320,12 +326,14 @@ CSHA256& CSHA256::Reset() { ////// SHA-512 -CSHA512::CSHA512() : bytes(0) { +CSHA512::CSHA512() : bytes(0) +{ sha512::Initialize(s); } -CSHA512& CSHA512::Write(const unsigned char *data, size_t len) { - const unsigned char *end = data + len; +CSHA512& CSHA512::Write(const unsigned char* data, size_t len) +{ + const unsigned char* end = data + len; size_t bufsize = bytes % 128; if (bufsize && bufsize + len >= 128) { // Fill the buffer, and process it. @@ -349,23 +357,25 @@ CSHA512& CSHA512::Write(const unsigned char *data, size_t len) { return *this; } -void CSHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) { +void CSHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) +{ static const unsigned char pad[128] = {0x80}; unsigned char sizedesc[16] = {0x00}; - WriteBE64(sizedesc+8, bytes << 3); + WriteBE64(sizedesc + 8, bytes << 3); Write(pad, 1 + ((239 - (bytes % 128)) % 128)); Write(sizedesc, 16); WriteBE64(hash, s[0]); - WriteBE64(hash+8, s[1]); - WriteBE64(hash+16, s[2]); - WriteBE64(hash+24, s[3]); - WriteBE64(hash+32, s[4]); - WriteBE64(hash+40, s[5]); - WriteBE64(hash+48, s[6]); - WriteBE64(hash+56, s[7]); + WriteBE64(hash + 8, s[1]); + WriteBE64(hash + 16, s[2]); + WriteBE64(hash + 24, s[3]); + WriteBE64(hash + 32, s[4]); + WriteBE64(hash + 40, s[5]); + WriteBE64(hash + 48, s[6]); + WriteBE64(hash + 56, s[7]); } -CSHA512& CSHA512::Reset() { +CSHA512& CSHA512::Reset() +{ bytes = 0; sha512::Initialize(s); return *this; @@ -373,7 +383,8 @@ CSHA512& CSHA512::Reset() { ////// HMAC-SHA-512 -CHMAC_SHA512::CHMAC_SHA512(const unsigned char *key, size_t keylen) { +CHMAC_SHA512::CHMAC_SHA512(const unsigned char* key, size_t keylen) +{ unsigned char rkey[128]; if (keylen <= 128) { memcpy(rkey, key, keylen); @@ -383,16 +394,17 @@ CHMAC_SHA512::CHMAC_SHA512(const unsigned char *key, size_t keylen) { memset(rkey + 64, 0, 64); } - for (int n=0; n<128; n++) + for (int n = 0; n < 128; n++) rkey[n] ^= 0x5c; outer.Write(rkey, 128); - for (int n=0; n<128; n++) + for (int n = 0; n < 128; n++) rkey[n] ^= 0x5c ^ 0x36; inner.Write(rkey, 128); } -void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) { +void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) +{ unsigned char temp[64]; inner.Finalize(temp); outer.Write(temp, 64).Finalize(hash); diff --git a/src/crypto/sha2.h b/src/crypto/sha2.h index 088d5e194c..a6cbe58554 100644 --- a/src/crypto/sha2.h +++ b/src/crypto/sha2.h @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_SHA2_H @@ -9,7 +9,8 @@ #include <stdlib.h> /** A hasher class for SHA-256. */ -class CSHA256 { +class CSHA256 +{ private: uint32_t s[8]; unsigned char buf[64]; @@ -19,13 +20,14 @@ public: static const size_t OUTPUT_SIZE = 32; CSHA256(); - CSHA256& Write(const unsigned char *data, size_t len); + CSHA256& Write(const unsigned char* data, size_t len); void Finalize(unsigned char hash[OUTPUT_SIZE]); CSHA256& Reset(); }; /** A hasher class for SHA-512. */ -class CSHA512 { +class CSHA512 +{ private: uint64_t s[8]; unsigned char buf[128]; @@ -35,13 +37,14 @@ public: static const size_t OUTPUT_SIZE = 64; CSHA512(); - CSHA512& Write(const unsigned char *data, size_t len); + CSHA512& Write(const unsigned char* data, size_t len); void Finalize(unsigned char hash[OUTPUT_SIZE]); CSHA512& Reset(); }; /** A hasher class for HMAC-SHA-512. */ -class CHMAC_SHA512 { +class CHMAC_SHA512 +{ private: CSHA512 outer; CSHA512 inner; @@ -49,12 +52,13 @@ private: public: static const size_t OUTPUT_SIZE = 64; - CHMAC_SHA512(const unsigned char *key, size_t keylen); - CHMAC_SHA512& Write(const unsigned char *data, size_t len) { + CHMAC_SHA512(const unsigned char* key, size_t keylen); + CHMAC_SHA512& Write(const unsigned char* data, size_t len) + { inner.Write(data, len); return *this; } void Finalize(unsigned char hash[OUTPUT_SIZE]); }; -#endif +#endif // BITCOIN_SHA2_H diff --git a/src/db.cpp b/src/db.cpp index 24206d34e1..12650e459f 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -30,7 +30,6 @@ using namespace boost; unsigned int nWalletDBUpdated; - // // CDB // @@ -94,15 +93,15 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1); dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); int ret = dbenv.open(path.string().c_str(), - DB_CREATE | - DB_INIT_LOCK | - DB_INIT_LOG | - DB_INIT_MPOOL | - DB_INIT_TXN | - DB_THREAD | - DB_RECOVER | - nEnvFlags, - S_IRUSR | S_IWUSR); + DB_CREATE | + DB_INIT_LOCK | + DB_INIT_LOG | + DB_INIT_MPOOL | + DB_INIT_TXN | + DB_THREAD | + DB_RECOVER | + nEnvFlags, + S_IRUSR | S_IWUSR); if (ret != 0) return error("CDBEnv::Open : Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret)); @@ -121,21 +120,21 @@ void CDBEnv::MakeMock() LogPrint("db", "CDBEnv::MakeMock\n"); dbenv.set_cachesize(1, 0, 1); - dbenv.set_lg_bsize(10485760*4); + dbenv.set_lg_bsize(10485760 * 4); dbenv.set_lg_max(10485760); dbenv.set_lk_max_locks(10000); dbenv.set_lk_max_objects(10000); dbenv.set_flags(DB_AUTO_COMMIT, 1); dbenv.log_set_config(DB_LOG_IN_MEMORY, 1); int ret = dbenv.open(NULL, - DB_CREATE | - DB_INIT_LOCK | - DB_INIT_LOG | - DB_INIT_MPOOL | - DB_INIT_TXN | - DB_THREAD | - DB_PRIVATE, - S_IRUSR | S_IWUSR); + DB_CREATE | + DB_INIT_LOCK | + DB_INIT_LOG | + DB_INIT_MPOOL | + DB_INIT_TXN | + DB_THREAD | + DB_PRIVATE, + S_IRUSR | S_IWUSR); if (ret > 0) throw runtime_error(strprintf("CDBEnv::MakeMock : Error %d opening database environment.", ret)); @@ -160,30 +159,27 @@ CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDB return (fRecovered ? RECOVER_OK : RECOVER_FAIL); } -bool CDBEnv::Salvage(std::string strFile, bool fAggressive, - std::vector<CDBEnv::KeyValPair >& vResult) +bool CDBEnv::Salvage(std::string strFile, bool fAggressive, std::vector<CDBEnv::KeyValPair>& vResult) { LOCK(cs_db); assert(mapFileUseCount.count(strFile) == 0); u_int32_t flags = DB_SALVAGE; - if (fAggressive) flags |= DB_AGGRESSIVE; + if (fAggressive) + flags |= DB_AGGRESSIVE; stringstream strDump; Db db(&dbenv, 0); int result = db.verify(strFile.c_str(), NULL, &strDump, flags); - if (result == DB_VERIFY_BAD) - { + if (result == DB_VERIFY_BAD) { LogPrintf("CDBEnv::Salvage : Database salvage found errors, all data may not be recoverable.\n"); - if (!fAggressive) - { + if (!fAggressive) { LogPrintf("CDBEnv::Salvage : Rerun with aggressive mode to ignore errors and continue.\n"); return false; } } - if (result != 0 && result != DB_VERIFY_BAD) - { + if (result != 0 && result != DB_VERIFY_BAD) { LogPrintf("CDBEnv::Salvage : Database salvage failed with result %d.\n", result); return false; } @@ -201,13 +197,11 @@ bool CDBEnv::Salvage(std::string strFile, bool fAggressive, getline(strDump, strLine); // Skip past header std::string keyHex, valueHex; - while (!strDump.eof() && keyHex != "DATA=END") - { + while (!strDump.eof() && keyHex != "DATA=END") { getline(strDump, keyHex); - if (keyHex != "DATA_END") - { + if (keyHex != "DATA_END") { getline(strDump, valueHex); - vResult.push_back(make_pair(ParseHex(keyHex),ParseHex(valueHex))); + vResult.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex))); } } @@ -224,8 +218,7 @@ void CDBEnv::CheckpointLSN(const std::string& strFile) } -CDB::CDB(const std::string& strFilename, const char* pszMode) : - pdb(NULL), activeTxn(NULL) +CDB::CDB(const std::string& strFilename, const char* pszMode) : pdb(NULL), activeTxn(NULL) { int ret; fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); @@ -245,28 +238,25 @@ CDB::CDB(const std::string& strFilename, const char* pszMode) : strFile = strFilename; ++bitdb.mapFileUseCount[strFile]; pdb = bitdb.mapDb[strFile]; - if (pdb == NULL) - { + if (pdb == NULL) { pdb = new Db(&bitdb.dbenv, 0); bool fMockDb = bitdb.IsMock(); - if (fMockDb) - { - DbMpoolFile*mpf = pdb->get_mpf(); + if (fMockDb) { + DbMpoolFile* mpf = pdb->get_mpf(); ret = mpf->set_flags(DB_MPOOL_NOFILE, 1); if (ret != 0) throw runtime_error(strprintf("CDB : Failed to configure for no temp file backing for database %s", strFile)); } - ret = pdb->open(NULL, // Txn pointer - fMockDb ? NULL : strFile.c_str(), // Filename + ret = pdb->open(NULL, // Txn pointer + fMockDb ? NULL : strFile.c_str(), // Filename fMockDb ? strFile.c_str() : "main", // Logical db name - DB_BTREE, // Database type - nFlags, // Flags + DB_BTREE, // Database type + nFlags, // Flags 0); - if (ret != 0) - { + if (ret != 0) { delete pdb; pdb = NULL; --bitdb.mapFileUseCount[strFile]; @@ -274,8 +264,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode) : throw runtime_error(strprintf("CDB : Error %d, can't open database %s", ret, strFile)); } - if (fCreate && !Exists(string("version"))) - { + if (fCreate && !Exists(string("version"))) { bool fTmp = fReadOnly; fReadOnly = false; WriteVersion(CLIENT_VERSION); @@ -297,7 +286,7 @@ void CDB::Flush() if (fReadOnly) nMinutes = 1; - bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0); + bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); } void CDB::Close() @@ -321,8 +310,7 @@ void CDBEnv::CloseDb(const string& strFile) { { LOCK(cs_db); - if (mapDb[strFile] != NULL) - { + if (mapDb[strFile] != NULL) { // Close the database handle Db* pdb = mapDb[strFile]; pdb->close(0); @@ -343,12 +331,10 @@ bool CDBEnv::RemoveDb(const string& strFile) bool CDB::Rewrite(const string& strFile, const char* pszSkip) { - while (true) - { + while (true) { { LOCK(bitdb.cs_db); - if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) - { + if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) { // Flush log data to the dat file bitdb.CloseDb(strFile); bitdb.CheckpointLSN(strFile); @@ -361,32 +347,27 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) CDB db(strFile.c_str(), "r"); Db* pdbCopy = new Db(&bitdb.dbenv, 0); - int ret = pdbCopy->open(NULL, // Txn pointer - strFileRes.c_str(), // Filename - "main", // Logical db name - DB_BTREE, // Database type - DB_CREATE, // Flags + int ret = pdbCopy->open(NULL, // Txn pointer + strFileRes.c_str(), // Filename + "main", // Logical db name + DB_BTREE, // Database type + DB_CREATE, // Flags 0); - if (ret > 0) - { + if (ret > 0) { LogPrintf("CDB::Rewrite : Can't create database file %s\n", strFileRes); fSuccess = false; } Dbc* pcursor = db.GetCursor(); if (pcursor) - while (fSuccess) - { + while (fSuccess) { CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT); - if (ret == DB_NOTFOUND) - { + if (ret == DB_NOTFOUND) { pcursor->close(); break; - } - else if (ret != 0) - { + } else if (ret != 0) { pcursor->close(); fSuccess = false; break; @@ -394,8 +375,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) if (pszSkip && strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0) continue; - if (strncmp(&ssKey[0], "\x07version", 8) == 0) - { + if (strncmp(&ssKey[0], "\x07version", 8) == 0) { // Update version: ssValue.clear(); ssValue << CLIENT_VERSION; @@ -406,8 +386,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) if (ret2 > 0) fSuccess = false; } - if (fSuccess) - { + if (fSuccess) { db.Close(); bitdb.CloseDb(strFile); if (pdbCopy->close(0)) @@ -415,8 +394,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) delete pdbCopy; } } - if (fSuccess) - { + if (fSuccess) { Db dbA(&bitdb.dbenv, 0); if (dbA.remove(strFile.c_str(), NULL, 0)) fSuccess = false; @@ -445,13 +423,11 @@ void CDBEnv::Flush(bool fShutdown) { LOCK(cs_db); map<string, int>::iterator mi = mapFileUseCount.begin(); - while (mi != mapFileUseCount.end()) - { + while (mi != mapFileUseCount.end()) { string strFile = (*mi).first; int nRefCount = (*mi).second; LogPrint("db", "CDBEnv::Flush : Flushing %s (refcount = %d)...\n", strFile, nRefCount); - if (nRefCount == 0) - { + if (nRefCount == 0) { // Move log data to the dat file CloseDb(strFile); LogPrint("db", "CDBEnv::Flush : %s checkpoint\n", strFile); @@ -461,16 +437,13 @@ void CDBEnv::Flush(bool fShutdown) dbenv.lsn_reset(strFile.c_str(), 0); LogPrint("db", "CDBEnv::Flush : %s closed\n", strFile); mapFileUseCount.erase(mi++); - } - else + } else mi++; } LogPrint("db", "CDBEnv::Flush : Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart); - if (fShutdown) - { + if (fShutdown) { char** listp; - if (mapFileUseCount.empty()) - { + if (mapFileUseCount.empty()) { dbenv.log_archive(&listp, DB_ARCH_REMOVE); Close(); if (!fMockDb) @@ -479,4 +452,3 @@ void CDBEnv::Flush(bool fShutdown) } } } - @@ -54,7 +54,9 @@ public: * This must be called BEFORE strFile is opened. * Returns true if strFile is OK. */ - enum VerifyResult { VERIFY_OK, RECOVER_OK, RECOVER_FAIL }; + enum VerifyResult { VERIFY_OK, + RECOVER_OK, + RECOVER_FAIL }; VerifyResult Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile)); /* * Salvage data from a file that Verify says is bad. @@ -66,7 +68,7 @@ public: typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair; bool Salvage(std::string strFile, bool fAggressive, std::vector<KeyValPair>& vResult); - bool Open(const boost::filesystem::path &path); + bool Open(const boost::filesystem::path& path); void Close(); void Flush(bool fShutdown); void CheckpointLSN(const std::string& strFile); @@ -74,7 +76,7 @@ public: void CloseDb(const std::string& strFile); bool RemoveDb(const std::string& strFile); - DbTxn *TxnBegin(int flags=DB_TXN_WRITE_NOSYNC) + DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC) { DbTxn* ptxn = NULL; int ret = dbenv.txn_begin(NULL, &ptxn, flags); @@ -93,10 +95,10 @@ class CDB protected: Db* pdb; std::string strFile; - DbTxn *activeTxn; + DbTxn* activeTxn; bool fReadOnly; - explicit CDB(const std::string& strFilename, const char* pszMode="r+"); + explicit CDB(const std::string& strFilename, const char* pszMode = "r+"); ~CDB() { Close(); } public: @@ -108,7 +110,7 @@ private: void operator=(const CDB&); protected: - template<typename K, typename T> + template <typename K, typename T> bool Read(const K& key, T& value) { if (!pdb) @@ -132,8 +134,7 @@ protected: try { CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION); ssValue >> value; - } - catch (const std::exception &) { + } catch (const std::exception&) { return false; } @@ -143,8 +144,8 @@ protected: return (ret == 0); } - template<typename K, typename T> - bool Write(const K& key, const T& value, bool fOverwrite=true) + template <typename K, typename T> + bool Write(const K& key, const T& value, bool fOverwrite = true) { if (!pdb) return false; @@ -172,7 +173,7 @@ protected: return (ret == 0); } - template<typename K> + template <typename K> bool Erase(const K& key) { if (!pdb) @@ -194,7 +195,7 @@ protected: return (ret == 0 || ret == DB_NOTFOUND); } - template<typename K> + template <typename K> bool Exists(const K& key) { if (!pdb) @@ -225,18 +226,16 @@ protected: return pcursor; } - int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT) + int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags = DB_NEXT) { // Read at cursor Dbt datKey; - if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) - { + if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) { datKey.set_data(&ssKey[0]); datKey.set_size(ssKey.size()); } Dbt datValue; - if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) - { + if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) { datValue.set_data(&ssValue[0]); datValue.set_size(ssValue.size()); } diff --git a/src/hash.cpp b/src/hash.cpp index bddd8abf38..218607a6fd 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -1,6 +1,6 @@ #include "hash.h" -inline uint32_t ROTL32 ( uint32_t x, int8_t r ) +inline uint32_t ROTL32(uint32_t x, int8_t r) { return (x << r) | (x >> (32 - r)); } @@ -9,41 +9,48 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char { // The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp uint32_t h1 = nHashSeed; - const uint32_t c1 = 0xcc9e2d51; - const uint32_t c2 = 0x1b873593; + if (vDataToHash.size() > 0) + { + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; - const int nblocks = vDataToHash.size() / 4; + const int nblocks = vDataToHash.size() / 4; - //---------- - // body - const uint32_t * blocks = (const uint32_t *)(&vDataToHash[0] + nblocks*4); + //---------- + // body + const uint32_t* blocks = (const uint32_t*)(&vDataToHash[0] + nblocks * 4); - for(int i = -nblocks; i; i++) - { - uint32_t k1 = blocks[i]; + for (int i = -nblocks; i; i++) { + uint32_t k1 = blocks[i]; - k1 *= c1; - k1 = ROTL32(k1,15); - k1 *= c2; + k1 *= c1; + k1 = ROTL32(k1, 15); + k1 *= c2; - h1 ^= k1; - h1 = ROTL32(h1,13); - h1 = h1*5+0xe6546b64; - } + h1 ^= k1; + h1 = ROTL32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; + } - //---------- - // tail - const uint8_t * tail = (const uint8_t*)(&vDataToHash[0] + nblocks*4); + //---------- + // tail + const uint8_t* tail = (const uint8_t*)(&vDataToHash[0] + nblocks * 4); - uint32_t k1 = 0; + uint32_t k1 = 0; - switch(vDataToHash.size() & 3) - { - case 3: k1 ^= tail[2] << 16; - case 2: k1 ^= tail[1] << 8; - case 1: k1 ^= tail[0]; - k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; - }; + switch (vDataToHash.size() & 3) { + case 3: + k1 ^= tail[2] << 16; + case 2: + k1 ^= tail[1] << 8; + case 1: + k1 ^= tail[0]; + k1 *= c1; + k1 = ROTL32(k1, 15); + k1 *= c2; + h1 ^= k1; + }; + } //---------- // finalization diff --git a/src/init.cpp b/src/init.cpp index 67f53e044c..980c589b29 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -45,7 +45,7 @@ using namespace boost; using namespace std; #ifdef ENABLE_WALLET -CWallet* pwalletMain; +CWallet* pwalletMain = NULL; #endif #ifdef WIN32 @@ -109,7 +109,7 @@ bool ShutdownRequested() return fRequestShutdown; } -static CCoinsViewDB *pcoinsdbview; +static CCoinsViewDB *pcoinsdbview = NULL; void Shutdown() { @@ -160,11 +160,13 @@ void Shutdown() if (pwalletMain) bitdb.Flush(true); #endif +#ifndef WIN32 boost::filesystem::remove(GetPidFile()); +#endif UnregisterAllWallets(); #ifdef ENABLE_WALLET - if (pwalletMain) - delete pwalletMain; + delete pwalletMain; + pwalletMain = NULL; #endif LogPrintf("%s: done\n", __func__); } @@ -228,7 +230,9 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -maxorphanblocks=<n> " + strprintf(_("Keep at most <n> unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n"; strUsage += " -maxorphantx=<n> " + strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS) + "\n"; strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n"; +#ifndef WIN32 strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n"; +#endif strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n"; #if !defined(WIN32) strUsage += " -sysperms " + _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)") + "\n"; @@ -658,7 +662,7 @@ bool AppInit2(boost::thread_group& threadGroup) // cost to you of processing a transaction. if (mapArgs.count("-minrelaytxfee")) { - int64_t n = 0; + CAmount n = 0; if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0) ::minRelayTxFee = CFeeRate(n); else @@ -668,7 +672,7 @@ bool AppInit2(boost::thread_group& threadGroup) #ifdef ENABLE_WALLET if (mapArgs.count("-mintxfee")) { - int64_t n = 0; + CAmount n = 0; if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) CWallet::minTxFee = CFeeRate(n); else @@ -676,7 +680,7 @@ bool AppInit2(boost::thread_group& threadGroup) } if (mapArgs.count("-paytxfee")) { - int64_t nFeePerK = 0; + CAmount nFeePerK = 0; if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"])); if (nFeePerK > nHighTransactionFeeWarning) @@ -697,6 +701,7 @@ bool AppInit2(boost::thread_group& threadGroup) fIsBareMultisigStd = GetArg("-permitbaremultisig", true) != 0; // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log + // Sanity check if (!InitSanityCheck()) return InitError(_("Initialization sanity check failed. Bitcoin Core is shutting down.")); @@ -714,7 +719,9 @@ bool AppInit2(boost::thread_group& threadGroup) static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); if (!lock.try_lock()) return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running."), strDataDir)); - +#ifndef WIN32 + CreatePidFile(GetPidFile(), getpid()); +#endif if (GetBoolArg("-shrinkdebugfile", !fDebug)) ShrinkDebugFile(); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); @@ -1052,7 +1059,7 @@ bool AppInit2(boost::thread_group& threadGroup) } boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; - CAutoFile est_filein = CAutoFile(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); + CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); // Allowed to fail as this file IS missing on first startup. if (est_filein) mempool.ReadFeeEstimates(est_filein); @@ -1153,7 +1160,7 @@ bool AppInit2(boost::thread_group& threadGroup) CWalletDB walletdb(strWalletFile); CBlockLocator locator; if (walletdb.ReadBestBlock(locator)) - pindexRescan = chainActive.FindFork(locator); + pindexRescan = FindForkInGlobalIndex(chainActive, locator); else pindexRescan = chainActive.Genesis(); } diff --git a/src/init.h b/src/init.h index cf1d1e7e39..aaf8c07e6e 100644 --- a/src/init.h +++ b/src/init.h @@ -10,8 +10,9 @@ class CWallet; -namespace boost { - class thread_group; +namespace boost +{ +class thread_group; } // namespace boost extern CWallet* pwalletMain; @@ -22,8 +23,7 @@ void Shutdown(); bool AppInit2(boost::thread_group& threadGroup); /* The help message mode determines what help message to show */ -enum HelpMessageMode -{ +enum HelpMessageMode { HMM_BITCOIND, HMM_BITCOIN_QT }; diff --git a/src/key.cpp b/src/key.cpp index 8ed787654a..c2251b4f2a 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -220,7 +220,7 @@ public: return o2i_ECPublicKey(&pkey, &pbegin, pubkey.size()) != NULL; } - bool Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) { + bool Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, bool lowS) { vchSig.clear(); ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); if (sig == NULL) @@ -232,7 +232,7 @@ public: BIGNUM *halforder = BN_CTX_get(ctx); EC_GROUP_get_order(group, order, ctx); BN_rshift1(halforder, order); - if (BN_cmp(sig->s, halforder) > 0) { + if (lowS && BN_cmp(sig->s, halforder) > 0) { // enforce low S values, by negating the value (modulo the order) if above order/2. BN_sub(sig->s, order, sig->s); } @@ -467,7 +467,7 @@ CPubKey CKey::GetPubKey() const { return pubkey; } -bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const { +bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, bool lowS) const { if (!fValid) return false; #ifdef USE_SECP256K1 @@ -484,7 +484,7 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const { #else CECKey key; key.SetSecretBytes(vch); - return key.Sign(hash, vchSig); + return key.Sign(hash, vchSig, lowS); #endif } @@ -26,27 +26,29 @@ class CKeyID : public uint160 { public: - CKeyID() : uint160(0) { } - CKeyID(const uint160 &in) : uint160(in) { } + CKeyID() : uint160(0) {} + CKeyID(const uint160& in) : uint160(in) {} }; /** A reference to a CScript: the Hash160 of its serialization (see script.h) */ class CScriptID : public uint160 { public: - CScriptID() : uint160(0) { } - CScriptID(const uint160 &in) : uint160(in) { } + CScriptID() : uint160(0) {} + CScriptID(const uint160& in) : uint160(in) {} }; /** An encapsulated public key. */ -class CPubKey { +class CPubKey +{ private: // Just store the serialized data. // Its length can very cheaply be computed from the first byte. unsigned char vch[65]; // Compute the length of a pubkey with a given first byte. - unsigned int static GetLen(unsigned char chHeader) { + unsigned int static GetLen(unsigned char chHeader) + { if (chHeader == 2 || chHeader == 3) return 33; if (chHeader == 4 || chHeader == 6 || chHeader == 7) @@ -55,66 +57,79 @@ private: } // Set this key data to be invalid - void Invalidate() { + void Invalidate() + { vch[0] = 0xFF; } public: // Construct an invalid public key. - CPubKey() { + CPubKey() + { Invalidate(); } // Initialize a public key using begin/end iterators to byte data. - template<typename T> - void Set(const T pbegin, const T pend) { + template <typename T> + void Set(const T pbegin, const T pend) + { int len = pend == pbegin ? 0 : GetLen(pbegin[0]); - if (len && len == (pend-pbegin)) + if (len && len == (pend - pbegin)) memcpy(vch, (unsigned char*)&pbegin[0], len); else Invalidate(); } // Construct a public key using begin/end iterators to byte data. - template<typename T> - CPubKey(const T pbegin, const T pend) { + template <typename T> + CPubKey(const T pbegin, const T pend) + { Set(pbegin, pend); } // Construct a public key from a byte vector. - CPubKey(const std::vector<unsigned char> &vch) { + CPubKey(const std::vector<unsigned char>& vch) + { Set(vch.begin(), vch.end()); } // Simple read-only vector-like interface to the pubkey data. unsigned int size() const { return GetLen(vch[0]); } - const unsigned char *begin() const { return vch; } - const unsigned char *end() const { return vch+size(); } - const unsigned char &operator[](unsigned int pos) const { return vch[pos]; } + const unsigned char* begin() const { return vch; } + const unsigned char* end() const { return vch + size(); } + const unsigned char& operator[](unsigned int pos) const { return vch[pos]; } // Comparator implementation. - friend bool operator==(const CPubKey &a, const CPubKey &b) { + friend bool operator==(const CPubKey& a, const CPubKey& b) + { return a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) == 0; } - friend bool operator!=(const CPubKey &a, const CPubKey &b) { + friend bool operator!=(const CPubKey& a, const CPubKey& b) + { return !(a == b); } - friend bool operator<(const CPubKey &a, const CPubKey &b) { + friend bool operator<(const CPubKey& a, const CPubKey& b) + { return a.vch[0] < b.vch[0] || (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0); } // Implement serialization, as if this was a byte vector. - unsigned int GetSerializeSize(int nType, int nVersion) const { + unsigned int GetSerializeSize(int nType, int nVersion) const + { return size() + 1; } - template<typename Stream> void Serialize(Stream &s, int nType, int nVersion) const { + template <typename Stream> + void Serialize(Stream& s, int nType, int nVersion) const + { unsigned int len = size(); ::WriteCompactSize(s, len); s.write((char*)vch, len); } - template<typename Stream> void Unserialize(Stream &s, int nType, int nVersion) { + template <typename Stream> + void Unserialize(Stream& s, int nType, int nVersion) + { unsigned int len = ::ReadCompactSize(s); if (len <= 65) { s.read((char*)vch, len); @@ -128,19 +143,22 @@ public: } // Get the KeyID of this public key (hash of its serialization) - CKeyID GetID() const { - return CKeyID(Hash160(vch, vch+size())); + CKeyID GetID() const + { + return CKeyID(Hash160(vch, vch + size())); } // Get the 256-bit hash of this public key. - uint256 GetHash() const { - return Hash(vch, vch+size()); + uint256 GetHash() const + { + return Hash(vch, vch + size()); } // Check syntactic correctness. // // Note that this is consensus critical as CheckSig() calls it! - bool IsValid() const { + bool IsValid() const + { return size() > 0; } @@ -148,16 +166,17 @@ public: bool IsFullyValid() const; // Check whether this is a compressed public key. - bool IsCompressed() const { + bool IsCompressed() const + { return size() == 33; } // Verify a DER signature (~72 bytes). // If this public key is not fully valid, the return value will be false. - bool Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const; + bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const; // Recover a public key from a compact signature. - bool RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig); + bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig); // Turn this public key into an uncompressed public key. bool Decompress(); @@ -172,7 +191,8 @@ public: typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey; /** An encapsulated private key. */ -class CKey { +class CKey +{ private: // Whether this private key is valid. We check for correctness when modifying the key // data, so fValid should always correspond to the actual state. @@ -185,33 +205,38 @@ private: unsigned char vch[32]; // Check whether the 32-byte array pointed to be vch is valid keydata. - bool static Check(const unsigned char *vch); -public: + bool static Check(const unsigned char* vch); +public: // Construct an invalid private key. - CKey() : fValid(false), fCompressed(false) { + CKey() : fValid(false), fCompressed(false) + { LockObject(vch); } // Copy constructor. This is necessary because of memlocking. - CKey(const CKey &secret) : fValid(secret.fValid), fCompressed(secret.fCompressed) { + CKey(const CKey& secret) : fValid(secret.fValid), fCompressed(secret.fCompressed) + { LockObject(vch); memcpy(vch, secret.vch, sizeof(vch)); } // Destructor (again necessary because of memlocking). - ~CKey() { + ~CKey() + { UnlockObject(vch); } - friend bool operator==(const CKey &a, const CKey &b) { + friend bool operator==(const CKey& a, const CKey& b) + { return a.fCompressed == b.fCompressed && a.size() == b.size() && memcmp(&a.vch[0], &b.vch[0], a.size()) == 0; } // Initialize using begin and end iterators to byte data. - template<typename T> - void Set(const T pbegin, const T pend, bool fCompressedIn) { + template <typename T> + void Set(const T pbegin, const T pend, bool fCompressedIn) + { if (pend - pbegin != 32) { fValid = false; return; @@ -227,8 +252,8 @@ public: // Simple read-only vector-like interface. unsigned int size() const { return (fValid ? 32 : 0); } - const unsigned char *begin() const { return vch; } - const unsigned char *end() const { return vch + size(); } + const unsigned char* begin() const { return vch; } + const unsigned char* end() const { return vch + size(); } // Check whether this private key is valid. bool IsValid() const { return fValid; } @@ -237,7 +262,7 @@ public: bool IsCompressed() const { return fCompressed; } // Initialize from a CPrivKey (serialized OpenSSL private key data). - bool SetPrivKey(const CPrivKey &vchPrivKey, bool fCompressed); + bool SetPrivKey(const CPrivKey& vchPrivKey, bool fCompressed); // Generate a new private key using a cryptographic PRNG. void MakeNewKey(bool fCompressed); @@ -251,23 +276,23 @@ public: CPubKey GetPubKey() const; // Create a DER-serialized signature. - bool Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const; + bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, bool lowS = true) const; // Create a compact signature (65 bytes), which allows reconstructing the used public key. // The format is one header byte, followed by two times 32 bytes for the serialized r and s values. // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, // 0x1D = second key with even y, 0x1E = second key with odd y, // add 0x04 for compressed keys. - bool SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const; + bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const; // Derive BIP32 child key. bool Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const; // Load private key and check that public key matches. - bool Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck); + bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck); // Check whether an element of a signature (r or s) is valid. - static bool CheckSignatureElement(const unsigned char *vch, int len, bool half); + static bool CheckSignatureElement(const unsigned char* vch, int len, bool half); }; struct CExtPubKey { @@ -277,14 +302,15 @@ struct CExtPubKey { unsigned char vchChainCode[32]; CPubKey pubkey; - friend bool operator==(const CExtPubKey &a, const CExtPubKey &b) { + friend bool operator==(const CExtPubKey& a, const CExtPubKey& b) + { return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.pubkey == b.pubkey; } void Encode(unsigned char code[74]) const; void Decode(const unsigned char code[74]); - bool Derive(CExtPubKey &out, unsigned int nChild) const; + bool Derive(CExtPubKey& out, unsigned int nChild) const; }; struct CExtKey { @@ -294,16 +320,17 @@ struct CExtKey { unsigned char vchChainCode[32]; CKey key; - friend bool operator==(const CExtKey &a, const CExtKey &b) { + friend bool operator==(const CExtKey& a, const CExtKey& b) + { return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.key == b.key; } void Encode(unsigned char code[74]) const; void Decode(const unsigned char code[74]); - bool Derive(CExtKey &out, unsigned int nChild) const; + bool Derive(CExtKey& out, unsigned int nChild) const; CExtPubKey Neuter() const; - void SetMaster(const unsigned char *seed, unsigned int nSeedLen); + void SetMaster(const unsigned char* seed, unsigned int nSeedLen); }; /** Check that required EC support is available at runtime */ diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp index 9e849696a8..8ce3e7b470 100644 --- a/src/leveldbwrapper.cpp +++ b/src/leveldbwrapper.cpp @@ -12,7 +12,8 @@ #include <leveldb/filter_policy.h> #include <memenv.h> -void HandleError(const leveldb::Status &status) throw(leveldb_error) { +void HandleError(const leveldb::Status& status) throw(leveldb_error) +{ if (status.ok()) return; LogPrintf("%s\n", status.ToString()); @@ -25,7 +26,8 @@ void HandleError(const leveldb::Status &status) throw(leveldb_error) { throw leveldb_error("Unknown database error"); } -static leveldb::Options GetOptions(size_t nCacheSize) { +static leveldb::Options GetOptions(size_t nCacheSize) +{ leveldb::Options options; options.block_cache = leveldb::NewLRUCache(nCacheSize / 2); options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously @@ -40,7 +42,8 @@ static leveldb::Options GetOptions(size_t nCacheSize) { return options; } -CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory, bool fWipe) { +CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe) +{ penv = NULL; readoptions.verify_checksums = true; iteroptions.verify_checksums = true; @@ -64,7 +67,8 @@ CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path &path, size_t nCa LogPrintf("Opened LevelDB successfully\n"); } -CLevelDBWrapper::~CLevelDBWrapper() { +CLevelDBWrapper::~CLevelDBWrapper() +{ delete pdb; pdb = NULL; delete options.filter_policy; @@ -75,7 +79,8 @@ CLevelDBWrapper::~CLevelDBWrapper() { options.env = NULL; } -bool CLevelDBWrapper::WriteBatch(CLevelDBBatch &batch, bool fSync) throw(leveldb_error) { +bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync) throw(leveldb_error) +{ leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch); HandleError(status); return true; diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h index 29bc71f99d..da5ba61c7b 100644 --- a/src/leveldbwrapper.h +++ b/src/leveldbwrapper.h @@ -17,10 +17,10 @@ class leveldb_error : public std::runtime_error { public: - leveldb_error(const std::string &msg) : std::runtime_error(msg) {} + leveldb_error(const std::string& msg) : std::runtime_error(msg) {} }; -void HandleError(const leveldb::Status &status) throw(leveldb_error); +void HandleError(const leveldb::Status& status) throw(leveldb_error); // Batch of changes queued to be written to a CLevelDBWrapper class CLevelDBBatch @@ -31,7 +31,9 @@ private: leveldb::WriteBatch batch; public: - template<typename K, typename V> void Write(const K& key, const V& value) { + template <typename K, typename V> + void Write(const K& key, const V& value) + { CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(ssKey.GetSerializeSize(key)); ssKey << key; @@ -45,7 +47,9 @@ public: batch.Put(slKey, slValue); } - template<typename K> void Erase(const K& key) { + template <typename K> + void Erase(const K& key) + { CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(ssKey.GetSerializeSize(key)); ssKey << key; @@ -59,7 +63,7 @@ class CLevelDBWrapper { private: // custom environment this database is using (may be NULL in case of default environment) - leveldb::Env *penv; + leveldb::Env* penv; // database options used leveldb::Options options; @@ -77,13 +81,15 @@ private: leveldb::WriteOptions syncoptions; // the database itself - leveldb::DB *pdb; + leveldb::DB* pdb; public: - CLevelDBWrapper(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory = false, bool fWipe = false); + CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false); ~CLevelDBWrapper(); - template<typename K, typename V> bool Read(const K& key, V& value) const throw(leveldb_error) { + template <typename K, typename V> + bool Read(const K& key, V& value) const throw(leveldb_error) + { CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(ssKey.GetSerializeSize(key)); ssKey << key; @@ -100,19 +106,23 @@ public: try { CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION); ssValue >> value; - } catch(const std::exception &) { + } catch (const std::exception&) { return false; } return true; } - template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error) { + template <typename K, typename V> + bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error) + { CLevelDBBatch batch; batch.Write(key, value); return WriteBatch(batch, fSync); } - template<typename K> bool Exists(const K& key) const throw(leveldb_error) { + template <typename K> + bool Exists(const K& key) const throw(leveldb_error) + { CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(ssKey.GetSerializeSize(key)); ssKey << key; @@ -129,26 +139,31 @@ public: return true; } - template<typename K> bool Erase(const K& key, bool fSync = false) throw(leveldb_error) { + template <typename K> + bool Erase(const K& key, bool fSync = false) throw(leveldb_error) + { CLevelDBBatch batch; batch.Erase(key); return WriteBatch(batch, fSync); } - bool WriteBatch(CLevelDBBatch &batch, bool fSync = false) throw(leveldb_error); + bool WriteBatch(CLevelDBBatch& batch, bool fSync = false) throw(leveldb_error); // not available for LevelDB; provide for compatibility with BDB - bool Flush() { + bool Flush() + { return true; } - bool Sync() throw(leveldb_error) { + bool Sync() throw(leveldb_error) + { CLevelDBBatch batch; return WriteBatch(batch, true); } // not exactly clean encapsulation, but it's easiest for now - leveldb::Iterator *NewIterator() { + leveldb::Iterator* NewIterator() + { return pdb->NewIterator(iteroptions); } }; diff --git a/src/limitedmap.h b/src/limitedmap.h index 58593688af..03727d7c42 100644 --- a/src/limitedmap.h +++ b/src/limitedmap.h @@ -1,15 +1,16 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2012-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_LIMITEDMAP_H #define BITCOIN_LIMITEDMAP_H -#include <assert.h> // TODO: remove +#include <assert.h> #include <map> /** STL-like map container that only keeps the N elements with the highest value. */ -template <typename K, typename V> class limitedmap +template <typename K, typename V> +class limitedmap { public: typedef K key_type; @@ -36,10 +37,8 @@ public: void insert(const value_type& x) { std::pair<iterator, bool> ret = map.insert(x); - if (ret.second) - { - if (nMaxSize && map.size() == nMaxSize) - { + if (ret.second) { + if (nMaxSize && map.size() == nMaxSize) { map.erase(rmap.begin()->second); rmap.erase(rmap.begin()); } @@ -54,42 +53,36 @@ public: return; std::pair<rmap_iterator, rmap_iterator> itPair = rmap.equal_range(itTarget->second); for (rmap_iterator it = itPair.first; it != itPair.second; ++it) - if (it->second == itTarget) - { + if (it->second == itTarget) { rmap.erase(it); map.erase(itTarget); return; } // Shouldn't ever get here - assert(0); //TODO remove me - map.erase(itTarget); + assert(0); } void update(const_iterator itIn, const mapped_type& v) { - //TODO: When we switch to C++11, use map.erase(itIn, itIn) to get the non-const iterator + // TODO: When we switch to C++11, use map.erase(itIn, itIn) to get the non-const iterator. iterator itTarget = map.find(itIn->first); if (itTarget == map.end()) return; std::pair<rmap_iterator, rmap_iterator> itPair = rmap.equal_range(itTarget->second); for (rmap_iterator it = itPair.first; it != itPair.second; ++it) - if (it->second == itTarget) - { + if (it->second == itTarget) { rmap.erase(it); itTarget->second = v; rmap.insert(make_pair(v, itTarget)); return; } // Shouldn't ever get here - assert(0); //TODO remove me - itTarget->second = v; - rmap.insert(make_pair(v, itTarget)); + assert(0); } size_type max_size() const { return nMaxSize; } size_type max_size(size_type s) { if (s) - while (map.size() > s) - { + while (map.size() > s) { map.erase(rmap.begin()->second); rmap.erase(rmap.begin()); } diff --git a/src/main.cpp b/src/main.cpp index 15c3916a6f..5d46c30a9b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,7 @@ #include "txmempool.h" #include "ui_interface.h" #include "util.h" +#include "utilmoneystr.h" #include <sstream> @@ -25,8 +26,8 @@ #include <boost/filesystem/fstream.hpp> #include <boost/thread.hpp> -using namespace std; using namespace boost; +using namespace std; #if defined(NDEBUG) # error "Bitcoin cannot be compiled without assertions." @@ -391,72 +392,19 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals) nodeSignals.FinalizeNode.disconnect(&FinalizeNode); } -////////////////////////////////////////////////////////////////////////////// -// -// CChain implementation -// - -CBlockIndex *CChain::SetTip(CBlockIndex *pindex) { - if (pindex == NULL) { - vChain.clear(); - return NULL; - } - vChain.resize(pindex->nHeight + 1); - while (pindex && vChain[pindex->nHeight] != pindex) { - vChain[pindex->nHeight] = pindex; - pindex = pindex->pprev; - } - return pindex; -} - -CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const { - int nStep = 1; - std::vector<uint256> vHave; - vHave.reserve(32); - - if (!pindex) - pindex = Tip(); - while (pindex) { - vHave.push_back(pindex->GetBlockHash()); - // Stop when we have added the genesis block. - if (pindex->nHeight == 0) - break; - // Exponentially larger steps back, plus the genesis block. - int nHeight = std::max(pindex->nHeight - nStep, 0); - if (Contains(pindex)) { - // Use O(1) CChain index if possible. - pindex = (*this)[nHeight]; - } else { - // Otherwise, use O(log n) skiplist. - pindex = pindex->GetAncestor(nHeight); - } - if (vHave.size() > 10) - nStep *= 2; - } - - return CBlockLocator(vHave); -} - -CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const { +CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) +{ // Find the first block the caller has in the main chain BOOST_FOREACH(const uint256& hash, locator.vHave) { BlockMap::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) { CBlockIndex* pindex = (*mi).second; - if (Contains(pindex)) + if (chain.Contains(pindex)) return pindex; } } - return Genesis(); -} - -const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const { - if (pindex->nHeight > Height()) - pindex = pindex->GetAncestor(Height()); - while (pindex && !Contains(pindex)) - pindex = pindex->pprev; - return pindex; + return chain.Genesis(); } CCoinsViewCache *pcoinsTip = NULL; @@ -697,7 +645,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) // IsStandard() will have already returned false // and this method isn't called. vector<vector<unsigned char> > stack; - if (!EvalScript(stack, tx.vin[i].scriptSig, tx, i, false)) + if (!EvalScript(stack, tx.vin[i].scriptSig, false, BaseSignatureChecker())) return false; if (whichType == TX_SCRIPTHASH) @@ -781,7 +729,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) REJECT_INVALID, "bad-txns-oversize"); // Check for negative or overflow output values - int64_t nValueOut = 0; + CAmount nValueOut = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) { if (txout.nValue < 0) @@ -823,19 +771,19 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) return true; } -int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree) +CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree) { { LOCK(mempool.cs); uint256 hash = tx.GetHash(); double dPriorityDelta = 0; - int64_t nFeeDelta = 0; + CAmount nFeeDelta = 0; mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); if (dPriorityDelta > 0 || nFeeDelta > 0) return 0; } - int64_t nMinFee = ::minRelayTxFee.GetFee(nBytes); + CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes); if (fAllowFree) { @@ -898,7 +846,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa CCoinsView dummy; CCoinsViewCache view(dummy); - int64_t nValueIn = 0; + CAmount nValueIn = 0; { LOCK(pool.cs); CCoinsViewMemPool viewMemPool(*pcoinsTip, pool); @@ -950,15 +898,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa hash.ToString(), nSigOps, MAX_TX_SIGOPS), REJECT_NONSTANDARD, "bad-txns-too-many-sigops"); - int64_t nValueOut = tx.GetValueOut(); - int64_t nFees = nValueIn-nValueOut; + CAmount nValueOut = tx.GetValueOut(); + CAmount nFees = nValueIn-nValueOut; double dPriority = view.GetPriority(tx, chainActive.Height()); CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height()); unsigned int nSize = entry.GetTxSize(); // Don't accept it if it can't get into a block - int64_t txMinFee = GetMinRelayFee(tx, nSize, true); + CAmount txMinFee = GetMinRelayFee(tx, nSize, true); if (fLimitFree && nFees < txMinFee) return state.DoS(0, error("AcceptToMemoryPool : not enough fees %s, %d < %d", hash.ToString(), nFees, txMinFee), @@ -995,7 +943,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS)) + if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true)) { return error("AcceptToMemoryPool: : ConnectInputs failed %s", hash.ToString()); } @@ -1082,7 +1030,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos) { // Open history file to append - CAutoFile fileout = CAutoFile(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); + CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); if (!fileout) return error("WriteBlockToDisk : OpenBlockFile failed"); @@ -1110,7 +1058,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) block.SetNull(); // Open history file to read - CAutoFile filein = CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION); + CAutoFile filein(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION); if (!filein) return error("ReadBlockFromDisk : OpenBlockFile failed"); @@ -1178,7 +1126,7 @@ void static PruneOrphanBlocks() mapOrphanBlocks.erase(hash); } -int64_t GetBlockValue(int nHeight, int64_t nFees) +CAmount GetBlockValue(int nHeight, const CAmount& nFees) { int64_t nSubsidy = 50 * COIN; int halvings = nHeight / Params().SubsidyHalvingInterval(); @@ -1368,12 +1316,12 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach bool CScriptCheck::operator()() const { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; - if (!VerifyScript(scriptSig, scriptPubKey, *ptxTo, nIn, nFlags)) - return error("CScriptCheck() : %s VerifySignature failed", ptxTo->GetHash().ToString()); + if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore))) + return error("CScriptCheck() : %s:%d VerifySignature failed", ptxTo->GetHash().ToString(), nIn); return true; } -bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, std::vector<CScriptCheck> *pvChecks) +bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks) { if (!tx.IsCoinBase()) { @@ -1389,8 +1337,8 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // This is also true for mempool checks. CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; int nSpendHeight = pindexPrev->nHeight + 1; - int64_t nValueIn = 0; - int64_t nFees = 0; + CAmount nValueIn = 0; + CAmount nFees = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) { const COutPoint &prevout = tx.vin[i].prevout; @@ -1414,11 +1362,12 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi } if (nValueIn < tx.GetValueOut()) - return state.DoS(100, error("CheckInputs() : %s value in < value out", tx.GetHash().ToString()), + return state.DoS(100, error("CheckInputs() : %s value in (%s) < value out (%s)", + tx.GetHash().ToString(), FormatMoney(nValueIn), FormatMoney(tx.GetValueOut())), REJECT_INVALID, "bad-txns-in-belowout"); // Tally transaction fees - int64_t nTxFee = nValueIn - tx.GetValueOut(); + CAmount nTxFee = nValueIn - tx.GetValueOut(); if (nTxFee < 0) return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString()), REJECT_INVALID, "bad-txns-fee-negative"); @@ -1441,7 +1390,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi assert(coins); // Verify signature - CScriptCheck check(*coins, tx, i, flags); + CScriptCheck check(*coins, tx, i, flags, cacheStore); if (pvChecks) { pvChecks->push_back(CScriptCheck()); check.swap(pvChecks->back()); @@ -1454,7 +1403,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // avoid splitting the network between upgraded and // non-upgraded nodes. CScriptCheck check(*coins, tx, i, - flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS); + flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore); if (check()) return state.Invalid(false, REJECT_NONSTANDARD, "non-mandatory-script-verify-flag"); } @@ -1650,15 +1599,14 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C int64_t nBIP16SwitchTime = 1333238400; bool fStrictPayToScriptHash = (pindex->GetBlockTime() >= nBIP16SwitchTime); - unsigned int flags = SCRIPT_VERIFY_NOCACHE | - (fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE); + unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE; CBlockUndo blockundo; CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL); int64_t nTimeStart = GetTimeMicros(); - int64_t nFees = 0; + CAmount nFees = 0; int nInputs = 0; unsigned int nSigOps = 0; CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); @@ -1695,7 +1643,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C nFees += view.GetValueIn(tx)-tx.GetValueOut(); std::vector<CScriptCheck> vChecks; - if (!CheckInputs(tx, state, view, fScriptChecks, flags, nScriptCheckThreads ? &vChecks : NULL)) + if (!CheckInputs(tx, state, view, fScriptChecks, flags, false, nScriptCheckThreads ? &vChecks : NULL)) return false; control.Add(vChecks); } @@ -1739,7 +1687,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) return error("ConnectBlock() : FindUndoPos failed"); if (!blockundo.WriteToDisk(pos, pindex->pprev->GetBlockHash())) - return state.Abort(_("Failed to write undo data")); + return state.Abort("Failed to write undo data"); // update nUndoPos in block index pindex->nUndoPos = pos.nPos; @@ -1750,12 +1698,12 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C CDiskBlockIndex blockindex(pindex); if (!pblocktree->WriteBlockIndex(blockindex)) - return state.Abort(_("Failed to write block index")); + return state.Abort("Failed to write block index"); } if (fTxIndex) if (!pblocktree->WriteTxIndex(vPos)) - return state.Abort(_("Failed to write transaction index")); + return state.Abort("Failed to write transaction index"); // add this block to the view's block chain bool ret; @@ -1790,7 +1738,7 @@ bool static WriteChainState(CValidationState &state) { FlushBlockFile(); pblocktree->Sync(); if (!pcoinsTip->Flush()) - return state.Abort(_("Failed to write to coin database")); + return state.Abort("Failed to write to coin database"); nLastWrite = GetTimeMicros(); } return true; @@ -1838,7 +1786,7 @@ bool static DisconnectTip(CValidationState &state) { // Read block from disk. CBlock block; if (!ReadBlockFromDisk(block, pindexDelete)) - return state.Abort(_("Failed to read block")); + return state.Abort("Failed to read block"); // Apply the block atomically to the chain state. int64_t nStart = GetTimeMicros(); { @@ -1887,7 +1835,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * CBlock block; if (!pblock) { if (!ReadBlockFromDisk(block, pindexNew)) - return state.Abort(_("Failed to read block")); + return state.Abort("Failed to read block"); pblock = █ } // Apply the block atomically to the chain state. @@ -2041,7 +1989,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo CheckForkWarningConditions(); if (!pblocktree->Flush()) - return state.Abort(_("Failed to sync block index")); + return state.Abort("Failed to sync block index"); return true; } @@ -2078,10 +2026,10 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { // Relay inventory, but don't relay old inventory during initial block download. int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(); { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) - pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip)); + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) + pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip)); } uiInterface.NotifyBlockTip(hashNewTip); @@ -2148,7 +2096,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl setBlockIndexValid.insert(pindexNew); if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew))) - return state.Abort(_("Failed to write block index")); + return state.Abort("Failed to write block index"); return true; } @@ -2200,7 +2148,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd } if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) - return state.Abort(_("Failed to write file info")); + return state.Abort("Failed to write file info"); if (fUpdatedLast) pblocktree->WriteLastBlockFile(nLastBlockFile); @@ -2218,15 +2166,15 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne pos.nPos = infoLastBlockFile.nUndoSize; nNewSize = (infoLastBlockFile.nUndoSize += nAddSize); if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) - return state.Abort(_("Failed to write block info")); + return state.Abort("Failed to write block info"); } else { CBlockFileInfo info; if (!pblocktree->ReadBlockFileInfo(nFile, info)) - return state.Abort(_("Failed to read block info")); + return state.Abort("Failed to read block info"); pos.nPos = info.nUndoSize; nNewSize = (info.nUndoSize += nAddSize); if (!pblocktree->WriteBlockFileInfo(nFile, info)) - return state.Abort(_("Failed to write block info")); + return state.Abort("Failed to write block info"); } unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE; @@ -2289,13 +2237,12 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo if (!CheckTransaction(tx, state)) return error("CheckBlock() : CheckTransaction failed"); - // Check for duplicate txids. This is caught by ConnectInputs(), - // but catching it earlier avoids a potential DoS attack: - set<uint256> uniqueTx; - BOOST_FOREACH(const CTransaction &tx, block.vtx) { - uniqueTx.insert(tx.GetHash()); - } - if (uniqueTx.size() != block.vtx.size()) + // Check for merkle tree malleability (CVE-2012-2459): repeating sequences + // of transactions in a block without affecting the merkle root of a block, + // while still invalidating it. + bool mutated; + uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated); + if (mutated) return state.DoS(100, error("CheckBlock() : duplicate transaction"), REJECT_INVALID, "bad-txns-duplicate", true); @@ -2309,7 +2256,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo REJECT_INVALID, "bad-blk-sigops", true); // Check merkle root - if (fCheckMerkleRoot && block.hashMerkleRoot != block.BuildMerkleTree()) + if (fCheckMerkleRoot && block.hashMerkleRoot != hashMerkleRoot2) return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"), REJECT_INVALID, "bad-txnmrklroot", true); @@ -2326,7 +2273,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex if (miSelf != mapBlockIndex.end()) { pindex = miSelf->second; if (pindex->nStatus & BLOCK_FAILED_MASK) - return state.Invalid(error("AcceptBlock() : block is marked invalid"), 0, "duplicate"); + return state.Invalid(error("%s : block is marked invalid", __func__), 0, "duplicate"); } CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(); @@ -2336,12 +2283,12 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex int64_t deltaTime = block.GetBlockTime() - pcheckpoint->GetBlockTime(); if (deltaTime < 0) { - return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"), + return state.DoS(100, error("%s : block with timestamp before last checkpoint", __func__), REJECT_CHECKPOINT, "time-too-old"); } if (!CheckMinWork(block.nBits, pcheckpoint->nBits, deltaTime)) { - return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"), + return state.DoS(100, error("%s : block with too little proof-of-work", __func__), REJECT_INVALID, "bad-diffbits"); } } @@ -2352,35 +2299,36 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex if (hash != Params().HashGenesisBlock()) { BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); if (mi == mapBlockIndex.end()) - return state.DoS(10, error("AcceptBlock() : prev block not found"), 0, "bad-prevblk"); + return state.DoS(10, error("%s : prev block not found", __func__), 0, "bad-prevblk"); pindexPrev = (*mi).second; nHeight = pindexPrev->nHeight+1; // Check proof of work - if (block.nBits != GetNextWorkRequired(pindexPrev, &block)) - return state.DoS(100, error("AcceptBlock() : incorrect proof of work"), + if ((!Params().SkipProofOfWorkCheck()) && + (block.nBits != GetNextWorkRequired(pindexPrev, &block))) + return state.DoS(100, error("%s : incorrect proof of work", __func__), REJECT_INVALID, "bad-diffbits"); // Check timestamp against prev if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) - return state.Invalid(error("AcceptBlock() : block's timestamp is too early"), + return state.Invalid(error("%s : block's timestamp is too early", __func__), REJECT_INVALID, "time-too-old"); // Check that the block chain matches the known block chain up to a checkpoint if (!Checkpoints::CheckBlock(nHeight, hash)) - return state.DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight), + return state.DoS(100, error("%s : rejected by checkpoint lock-in at %d", __func__, nHeight), REJECT_CHECKPOINT, "checkpoint mismatch"); // Don't accept any forks from the main chain prior to last checkpoint CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(); if (pcheckpoint && nHeight < pcheckpoint->nHeight) - return state.DoS(100, error("AcceptBlock() : forked chain older than last checkpoint (height %d)", nHeight)); + return state.DoS(100, error("%s : forked chain older than last checkpoint (height %d)", __func__, nHeight)); // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: if (block.nVersion < 2 && CBlockIndex::IsSuperMajority(2, pindexPrev, Params().RejectBlockOutdatedMajority())) { - return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"), + return state.Invalid(error("%s : rejected nVersion=1 block", __func__), REJECT_OBSOLETE, "bad-version"); } } @@ -2443,11 +2391,11 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, return error("AcceptBlock() : FindBlockPos failed"); if (dbp == NULL) if (!WriteBlockToDisk(block, blockPos)) - return state.Abort(_("Failed to write block")); + return state.Abort("Failed to write block"); if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) return error("AcceptBlock() : ReceivedBlockTransactions failed"); } catch(std::runtime_error &e) { - return state.Abort(_("System error: ") + e.what()); + return state.Abort(std::string("System error: ") + e.what()); } return true; @@ -2770,10 +2718,12 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) { -bool AbortNode(const std::string &strMessage) { +bool AbortNode(const std::string &strMessage, const std::string &userMessage) { strMiscWarning = strMessage; LogPrintf("*** %s\n", strMessage); - uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_ERROR); + uiInterface.ThreadSafeMessageBox( + userMessage.empty() ? _("Error: A fatal internal error occured, see debug.log for details") : userMessage, + "", CClientUIInterface::MSG_ERROR); StartShutdown(); return false; } @@ -2784,7 +2734,7 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes) // Check for nMinDiskSpace bytes (currently 50MB) if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) - return AbortNode(_("Error: Disk space is low!")); + return AbortNode("Disk space is low!", _("Error: Disk space is low!")); return true; } @@ -3136,6 +3086,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) int nLoaded = 0; try { + // This takes over fileIn and calls fclose() on it in the CBufferedFile destructor CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION); uint64_t nStartByte = 0; if (dbp) { @@ -3192,9 +3143,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) LogPrintf("%s : Deserialize or I/O error - %s", __func__, e.what()); } } - fclose(fileIn); } catch(std::runtime_error &e) { - AbortNode(_("Error: system error: ") + e.what()); + AbortNode(std::string("System error: ") + e.what()); } if (nLoaded > 0) LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart); @@ -3709,7 +3659,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LOCK(cs_main); // Find the last block the caller has in the main chain - CBlockIndex* pindex = chainActive.FindFork(locator); + CBlockIndex* pindex = FindForkInGlobalIndex(chainActive, locator); // Send the rest of the chain if (pindex) @@ -3756,7 +3706,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else { // Find the last block the caller has in the main chain - pindex = chainActive.FindFork(locator); + pindex = FindForkInGlobalIndex(chainActive, locator); if (pindex) pindex = chainActive.Next(pindex); } @@ -4503,7 +4453,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) bool CBlockUndo::WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock) { // Open history file to append - CAutoFile fileout = CAutoFile(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION); + CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION); if (!fileout) return error("CBlockUndo::WriteToDisk : OpenUndoFile failed"); @@ -4535,7 +4485,7 @@ bool CBlockUndo::WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock) bool CBlockUndo::ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock) { // Open history file to read - CAutoFile filein = CAutoFile(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); + CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); if (!filein) return error("CBlockUndo::ReadFromDisk : OpenBlockFile failed"); diff --git a/src/main.h b/src/main.h index 5acc551793..cad7eebfb7 100644 --- a/src/main.h +++ b/src/main.h @@ -10,12 +10,14 @@ #include "config/bitcoin-config.h" #endif +#include "chain.h" #include "chainparams.h" #include "coins.h" #include "core.h" #include "net.h" #include "pow.h" #include "script/script.h" +#include "script/sigcache.h" #include "script/standard.h" #include "sync.h" #include "txmempool.h" @@ -113,7 +115,6 @@ static const uint64_t nMinDiskSpace = 52428800; class CBlockTreeDB; -struct CDiskBlockPos; class CTxUndo; class CScriptCheck; class CValidationState; @@ -172,12 +173,12 @@ std::string GetWarnings(std::string strFor); bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ bool ActivateBestChain(CValidationState &state, CBlock *pblock = NULL); -int64_t GetBlockValue(int nHeight, int64_t nFees); +CAmount GetBlockValue(int nHeight, const CAmount& nFees); /** Create a new block index entry for a given block hash */ CBlockIndex * InsertBlockIndex(uint256 hash); /** Abort with a message */ -bool AbortNode(const std::string &msg); +bool AbortNode(const std::string &msg, const std::string &userMessage=""); /** Get statistics from node state */ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats); /** Increase a node's misbehavior score. */ @@ -189,51 +190,11 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa bool* pfMissingInputs, bool fRejectInsaneFee=false); - - - - - - struct CNodeStateStats { int nMisbehavior; int nSyncHeight; }; -struct CDiskBlockPos -{ - int nFile; - unsigned int nPos; - - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(VARINT(nFile)); - READWRITE(VARINT(nPos)); - } - - CDiskBlockPos() { - SetNull(); - } - - CDiskBlockPos(int nFileIn, unsigned int nPosIn) { - nFile = nFileIn; - nPos = nPosIn; - } - - friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) { - return (a.nFile == b.nFile && a.nPos == b.nPos); - } - - friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) { - return !(a == b); - } - - void SetNull() { nFile = -1; nPos = 0; } - bool IsNull() const { return (nFile == -1); } -}; - struct CDiskTxPos : public CDiskBlockPos { unsigned int nTxOffset; // after header @@ -260,7 +221,7 @@ struct CDiskTxPos : public CDiskBlockPos }; -int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); +CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); // // Check transaction inputs, and make sure any @@ -298,9 +259,8 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma // Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) // This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it // instead of being performed inline. -bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks = true, - unsigned int flags = STANDARD_SCRIPT_VERIFY_FLAGS, - std::vector<CScriptCheck> *pvChecks = NULL); +bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, + unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL); // Apply the effects of this transaction on the UTXO set represented by view void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight); @@ -342,12 +302,13 @@ private: const CTransaction *ptxTo; unsigned int nIn; unsigned int nFlags; + bool cacheStore; public: - CScriptCheck(): ptxTo(0), nIn(0), nFlags(0) {} - CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn) : + CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false) {} + CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), - ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn) { } + ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn) { } bool operator()() const; @@ -356,6 +317,7 @@ public: std::swap(ptxTo, check.ptxTo); std::swap(nIn, check.nIn); std::swap(nFlags, check.nFlags); + std::swap(cacheStore, check.cacheStore); } }; @@ -545,288 +507,6 @@ public: } }; -enum BlockStatus { - BLOCK_VALID_UNKNOWN = 0, - BLOCK_VALID_HEADER = 1, // parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future - BLOCK_VALID_TREE = 2, // parent found, difficulty matches, timestamp >= median previous, checkpoint - BLOCK_VALID_TRANSACTIONS = 3, // only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids, sigops, size, merkle root - BLOCK_VALID_CHAIN = 4, // outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends, BIP30 - BLOCK_VALID_SCRIPTS = 5, // scripts/signatures ok - BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS | - BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS, - - BLOCK_HAVE_DATA = 8, // full block available in blk*.dat - BLOCK_HAVE_UNDO = 16, // undo data available in rev*.dat - BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO, - - BLOCK_FAILED_VALID = 32, // stage after last reached validness failed - BLOCK_FAILED_CHILD = 64, // descends from failed block - BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD, -}; - -/** The block chain is a tree shaped structure starting with the - * genesis block at the root, with each block potentially having multiple - * candidates to be the next block. A blockindex may have multiple pprev pointing - * to it, but at most one of them can be part of the currently active branch. - */ -class CBlockIndex -{ -public: - // pointer to the hash of the block, if any. memory is owned by this CBlockIndex - const uint256* phashBlock; - - // pointer to the index of the predecessor of this block - CBlockIndex* pprev; - - // pointer to the index of some further predecessor of this block - CBlockIndex* pskip; - - // height of the entry in the chain. The genesis block has height 0 - int nHeight; - - // Which # file this block is stored in (blk?????.dat) - int nFile; - - // Byte offset within blk?????.dat where this block's data is stored - unsigned int nDataPos; - - // Byte offset within rev?????.dat where this block's undo data is stored - unsigned int nUndoPos; - - // (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block - uint256 nChainWork; - - // Number of transactions in this block. - // Note: in a potential headers-first mode, this number cannot be relied upon - unsigned int nTx; - - // (memory only) Number of transactions in the chain up to and including this block - unsigned int nChainTx; // change to 64-bit type when necessary; won't happen before 2030 - - // Verification status of this block. See enum BlockStatus - unsigned int nStatus; - - // block header - int nVersion; - uint256 hashMerkleRoot; - unsigned int nTime; - unsigned int nBits; - unsigned int nNonce; - - // (memory only) Sequencial id assigned to distinguish order in which blocks are received. - uint32_t nSequenceId; - - void SetNull() - { - phashBlock = NULL; - pprev = NULL; - pskip = NULL; - nHeight = 0; - nFile = 0; - nDataPos = 0; - nUndoPos = 0; - nChainWork = 0; - nTx = 0; - nChainTx = 0; - nStatus = 0; - nSequenceId = 0; - - nVersion = 0; - hashMerkleRoot = 0; - nTime = 0; - nBits = 0; - nNonce = 0; - } - - CBlockIndex() - { - SetNull(); - } - - CBlockIndex(CBlockHeader& block) - { - SetNull(); - - nVersion = block.nVersion; - hashMerkleRoot = block.hashMerkleRoot; - nTime = block.nTime; - nBits = block.nBits; - nNonce = block.nNonce; - } - - CDiskBlockPos GetBlockPos() const { - CDiskBlockPos ret; - if (nStatus & BLOCK_HAVE_DATA) { - ret.nFile = nFile; - ret.nPos = nDataPos; - } - return ret; - } - - CDiskBlockPos GetUndoPos() const { - CDiskBlockPos ret; - if (nStatus & BLOCK_HAVE_UNDO) { - ret.nFile = nFile; - ret.nPos = nUndoPos; - } - return ret; - } - - CBlockHeader GetBlockHeader() const - { - CBlockHeader block; - block.nVersion = nVersion; - if (pprev) - block.hashPrevBlock = pprev->GetBlockHash(); - block.hashMerkleRoot = hashMerkleRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - return block; - } - - uint256 GetBlockHash() const - { - return *phashBlock; - } - - int64_t GetBlockTime() const - { - return (int64_t)nTime; - } - - uint256 GetBlockWork() const - { - return GetProofIncrement(nBits); - } - - enum { nMedianTimeSpan=11 }; - - int64_t GetMedianTimePast() const - { - int64_t pmedian[nMedianTimeSpan]; - int64_t* pbegin = &pmedian[nMedianTimeSpan]; - int64_t* pend = &pmedian[nMedianTimeSpan]; - - const CBlockIndex* pindex = this; - for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev) - *(--pbegin) = pindex->GetBlockTime(); - - std::sort(pbegin, pend); - return pbegin[(pend - pbegin)/2]; - } - - /** - * Returns true if there are nRequired or more blocks of minVersion or above - * in the last Params().ToCheckBlockUpgradeMajority() blocks, starting at pstart - * and going backwards. - */ - static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, - unsigned int nRequired); - - std::string ToString() const - { - return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", - pprev, nHeight, - hashMerkleRoot.ToString(), - GetBlockHash().ToString()); - } - - // Check whether this block index entry is valid up to the passed validity level. - bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const - { - assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. - if (nStatus & BLOCK_FAILED_MASK) - return false; - return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); - } - - // Raise the validity level of this block index entry. - // Returns true if the validity was changed. - bool RaiseValidity(enum BlockStatus nUpTo) - { - assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. - if (nStatus & BLOCK_FAILED_MASK) - return false; - if ((nStatus & BLOCK_VALID_MASK) < nUpTo) { - nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo; - return true; - } - return false; - } - - // Build the skiplist pointer for this entry. - void BuildSkip(); - - // Efficiently find an ancestor of this block. - CBlockIndex* GetAncestor(int height); - const CBlockIndex* GetAncestor(int height) const; -}; - -/** Used to marshal pointers into hashes for db storage. */ -class CDiskBlockIndex : public CBlockIndex -{ -public: - uint256 hashPrev; - - CDiskBlockIndex() { - hashPrev = 0; - } - - explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex) { - hashPrev = (pprev ? pprev->GetBlockHash() : 0); - } - - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - if (!(nType & SER_GETHASH)) - READWRITE(VARINT(nVersion)); - - READWRITE(VARINT(nHeight)); - READWRITE(VARINT(nStatus)); - READWRITE(VARINT(nTx)); - if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) - READWRITE(VARINT(nFile)); - if (nStatus & BLOCK_HAVE_DATA) - READWRITE(VARINT(nDataPos)); - if (nStatus & BLOCK_HAVE_UNDO) - READWRITE(VARINT(nUndoPos)); - - // block header - READWRITE(this->nVersion); - READWRITE(hashPrev); - READWRITE(hashMerkleRoot); - READWRITE(nTime); - READWRITE(nBits); - READWRITE(nNonce); - } - - uint256 GetBlockHash() const - { - CBlockHeader block; - block.nVersion = nVersion; - block.hashPrevBlock = hashPrev; - block.hashMerkleRoot = hashMerkleRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - return block.GetHash(); - } - - - std::string ToString() const - { - std::string str = "CDiskBlockIndex("; - str += CBlockIndex::ToString(); - str += strprintf("\n hashBlock=%s, hashPrev=%s)", - GetBlockHash().ToString(), - hashPrev.ToString()); - return str; - } -}; - /** Capture information about block/transaction validation */ class CValidationState { private: @@ -898,65 +578,8 @@ public: bool VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth); }; -/** An in-memory indexed chain of blocks. */ -class CChain { -private: - std::vector<CBlockIndex*> vChain; - -public: - /** Returns the index entry for the genesis block of this chain, or NULL if none. */ - CBlockIndex *Genesis() const { - return vChain.size() > 0 ? vChain[0] : NULL; - } - - /** Returns the index entry for the tip of this chain, or NULL if none. */ - CBlockIndex *Tip() const { - return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL; - } - - /** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */ - CBlockIndex *operator[](int nHeight) const { - if (nHeight < 0 || nHeight >= (int)vChain.size()) - return NULL; - return vChain[nHeight]; - } - - /** Compare two chains efficiently. */ - friend bool operator==(const CChain &a, const CChain &b) { - return a.vChain.size() == b.vChain.size() && - a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1]; - } - - /** Efficiently check whether a block is present in this chain. */ - bool Contains(const CBlockIndex *pindex) const { - return (*this)[pindex->nHeight] == pindex; - } - - /** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */ - CBlockIndex *Next(const CBlockIndex *pindex) const { - if (Contains(pindex)) - return (*this)[pindex->nHeight + 1]; - else - return NULL; - } - - /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */ - int Height() const { - return vChain.size() - 1; - } - - /** Set/initialize a chain with a given tip. Returns the forking point. */ - CBlockIndex *SetTip(CBlockIndex *pindex); - - /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */ - CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const; - - /** Find the last common block between this chain and a locator. */ - CBlockIndex *FindFork(const CBlockLocator &locator) const; - - /** Find the last common block between this chain and a block index entry. */ - const CBlockIndex *FindFork(const CBlockIndex *pindex) const; -}; +/** Find the last common block between the parameter chain and a locator. */ +CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); /** The currently-connected chain of blocks. */ extern CChain chainActive; @@ -970,7 +593,7 @@ extern CBlockTreeDB *pblocktree; struct CBlockTemplate { CBlock block; - std::vector<int64_t> vTxFees; + std::vector<CAmount> vTxFees; std::vector<int64_t> vTxSigOps; }; diff --git a/src/miner.cpp b/src/miner.cpp index d05ddbeb1f..280349e8c2 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -111,7 +111,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); // Collect memory pool transactions into the block - int64_t nFees = 0; + CAmount nFees = 0; { LOCK2(cs_main, mempool.cs); @@ -135,7 +135,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) COrphan* porphan = NULL; double dPriority = 0; - int64_t nTotalIn = 0; + CAmount nTotalIn = 0; bool fMissingInputs = false; BOOST_FOREACH(const CTxIn& txin, tx.vin) { @@ -170,7 +170,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) const CCoins* coins = view.AccessCoins(txin.prevout.hash); assert(coins); - int64_t nValueIn = coins->vout[txin.prevout.n].nValue; + CAmount nValueIn = coins->vout[txin.prevout.n].nValue; nTotalIn += nValueIn; int nConf = pindexPrev->nHeight - coins->nHeight + 1; @@ -229,7 +229,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // Skip free transactions if we're past the minimum block size: const uint256& hash = tx.GetHash(); double dPriorityDelta = 0; - int64_t nFeeDelta = 0; + CAmount nFeeDelta = 0; mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) continue; @@ -247,7 +247,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) if (!view.HaveInputs(tx)) continue; - int64_t nTxFees = view.GetValueIn(tx)-tx.GetValueOut(); + CAmount nTxFees = view.GetValueIn(tx)-tx.GetValueOut(); nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) @@ -257,7 +257,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // policy here, but we still have to ensure that the block we // create only contains transactions that are valid in new blocks. CValidationState state; - if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS)) + if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true)) continue; CTxUndo txundo; diff --git a/src/mruset.h b/src/mruset.h index b9f325d874..1691875f57 100644 --- a/src/mruset.h +++ b/src/mruset.h @@ -10,7 +10,8 @@ #include <utility> /** STL-like set container that only keeps the most recent N elements. */ -template <typename T> class mruset +template <typename T> +class mruset { public: typedef T key_type; @@ -32,17 +33,19 @@ public: bool empty() const { return set.empty(); } iterator find(const key_type& k) const { return set.find(k); } size_type count(const key_type& k) const { return set.count(k); } - void clear() { set.clear(); queue.clear(); } + void clear() + { + set.clear(); + queue.clear(); + } bool inline friend operator==(const mruset<T>& a, const mruset<T>& b) { return a.set == b.set; } bool inline friend operator==(const mruset<T>& a, const std::set<T>& b) { return a.set == b; } bool inline friend operator<(const mruset<T>& a, const mruset<T>& b) { return a.set < b.set; } std::pair<iterator, bool> insert(const key_type& x) { std::pair<iterator, bool> ret = set.insert(x); - if (ret.second) - { - if (nMaxSize && queue.size() == nMaxSize) - { + if (ret.second) { + if (nMaxSize && queue.size() == nMaxSize) { set.erase(queue.front()); queue.pop_front(); } @@ -54,8 +57,7 @@ public: size_type max_size(size_type s) { if (s) - while (queue.size() > s) - { + while (queue.size() > s) { set.erase(queue.front()); queue.pop_front(); } diff --git a/src/net.cpp b/src/net.cpp index ab547e2fd7..866bac2c0e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1957,7 +1957,7 @@ bool CAddrDB::Write(const CAddrMan& addr) // open temp output file, and associate with CAutoFile boost::filesystem::path pathTmp = GetDataDir() / tmpfn; FILE *file = fopen(pathTmp.string().c_str(), "wb"); - CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION); + CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); if (!fileout) return error("%s : Failed to open file %s", __func__, pathTmp.string()); @@ -1982,7 +1982,7 @@ bool CAddrDB::Read(CAddrMan& addr) { // open input file, and associate with CAutoFile FILE *file = fopen(pathAddr.string().c_str(), "rb"); - CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION); + CAutoFile filein(file, SER_DISK, CLIENT_VERSION); if (!filein) return error("%s : Failed to open file %s", __func__, pathAddr.string()); diff --git a/src/noui.cpp b/src/noui.cpp index 8b00fd4057..f786a20db5 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -35,7 +35,7 @@ static bool noui_ThreadSafeMessageBox(const std::string& message, const std::str return false; } -static void noui_InitMessage(const std::string &message) +static void noui_InitMessage(const std::string& message) { LogPrintf("init message: %s\n", message); } diff --git a/src/pow.cpp b/src/pow.cpp index 893f6c18be..d50222849c 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -81,6 +81,10 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) bool fNegative; bool fOverflow; uint256 bnTarget; + + if (Params().SkipProofOfWorkCheck()) + return true; + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); // Check range diff --git a/src/protocol.cpp b/src/protocol.cpp index 341de0602a..0e28f3abbd 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -24,7 +24,6 @@ CMessageHeader::CMessageHeader() { memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE); memset(pchCommand, 0, sizeof(pchCommand)); - pchCommand[1] = 1; nMessageSize = -1; nChecksum = 0; } @@ -32,6 +31,7 @@ CMessageHeader::CMessageHeader() CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn) { memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE); + memset(pchCommand, 0, sizeof(pchCommand)); strncpy(pchCommand, pszCommand, COMMAND_SIZE); nMessageSize = nMessageSizeIn; nChecksum = 0; @@ -39,10 +39,7 @@ CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSize std::string CMessageHeader::GetCommand() const { - if (pchCommand[COMMAND_SIZE-1] == 0) - return std::string(pchCommand, pchCommand + strlen(pchCommand)); - else - return std::string(pchCommand, pchCommand + COMMAND_SIZE); + return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE)); } bool CMessageHeader::IsValid() const diff --git a/src/protocol.h b/src/protocol.h index 82d29e66de..b73041a9fd 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef __cplusplus -# error This header can only be compiled as C++. +#error This header can only be compiled as C++. #endif #ifndef __INCLUDED_PROTOCOL_H__ @@ -28,43 +28,43 @@ */ class CMessageHeader { - public: - CMessageHeader(); - CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn); +public: + CMessageHeader(); + CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn); - std::string GetCommand() const; - bool IsValid() const; + std::string GetCommand() const; + bool IsValid() const; - ADD_SERIALIZE_METHODS; + ADD_SERIALIZE_METHODS; - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(FLATDATA(pchMessageStart)); - READWRITE(FLATDATA(pchCommand)); - READWRITE(nMessageSize); - READWRITE(nChecksum); - } + template <typename Stream, typename Operation> + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { + READWRITE(FLATDATA(pchMessageStart)); + READWRITE(FLATDATA(pchCommand)); + READWRITE(nMessageSize); + READWRITE(nChecksum); + } // TODO: make private (improves encapsulation) - public: - enum { - COMMAND_SIZE=12, - MESSAGE_SIZE_SIZE=sizeof(int), - CHECKSUM_SIZE=sizeof(int), - - MESSAGE_SIZE_OFFSET=MESSAGE_START_SIZE+COMMAND_SIZE, - CHECKSUM_OFFSET=MESSAGE_SIZE_OFFSET+MESSAGE_SIZE_SIZE, - HEADER_SIZE=MESSAGE_START_SIZE+COMMAND_SIZE+MESSAGE_SIZE_SIZE+CHECKSUM_SIZE - }; - char pchMessageStart[MESSAGE_START_SIZE]; - char pchCommand[COMMAND_SIZE]; - unsigned int nMessageSize; - unsigned int nChecksum; +public: + enum { + COMMAND_SIZE = 12, + MESSAGE_SIZE_SIZE = sizeof(int), + CHECKSUM_SIZE = sizeof(int), + + MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE, + CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE, + HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE + }; + char pchMessageStart[MESSAGE_START_SIZE]; + char pchCommand[COMMAND_SIZE]; + unsigned int nMessageSize; + unsigned int nChecksum; }; /** nServices flags */ -enum -{ +enum { NODE_NETWORK = (1 << 0), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that @@ -79,68 +79,69 @@ enum /** A CService with information about it as peer */ class CAddress : public CService { - public: - CAddress(); - explicit CAddress(CService ipIn, uint64_t nServicesIn=NODE_NETWORK); - - void Init(); - - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - if (ser_action.ForRead()) - Init(); - if (nType & SER_DISK) - READWRITE(nVersion); - if ((nType & SER_DISK) || - (nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) - READWRITE(nTime); - READWRITE(nServices); - READWRITE(*(CService*)this); - } +public: + CAddress(); + explicit CAddress(CService ipIn, uint64_t nServicesIn = NODE_NETWORK); + + void Init(); + + ADD_SERIALIZE_METHODS; + + template <typename Stream, typename Operation> + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { + if (ser_action.ForRead()) + Init(); + if (nType & SER_DISK) + READWRITE(nVersion); + if ((nType & SER_DISK) || + (nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) + READWRITE(nTime); + READWRITE(nServices); + READWRITE(*(CService*)this); + } // TODO: make private (improves encapsulation) - public: - uint64_t nServices; +public: + uint64_t nServices; - // disk and network only - unsigned int nTime; + // disk and network only + unsigned int nTime; - // memory only - int64_t nLastTry; + // memory only + int64_t nLastTry; }; /** inv message data */ class CInv { - public: - CInv(); - CInv(int typeIn, const uint256& hashIn); - CInv(const std::string& strType, const uint256& hashIn); +public: + CInv(); + CInv(int typeIn, const uint256& hashIn); + CInv(const std::string& strType, const uint256& hashIn); - ADD_SERIALIZE_METHODS; + ADD_SERIALIZE_METHODS; - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(type); - READWRITE(hash); - } + template <typename Stream, typename Operation> + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { + READWRITE(type); + READWRITE(hash); + } - friend bool operator<(const CInv& a, const CInv& b); + friend bool operator<(const CInv& a, const CInv& b); - bool IsKnownType() const; - const char* GetCommand() const; - std::string ToString() const; + bool IsKnownType() const; + const char* GetCommand() const; + std::string ToString() const; // TODO: make private (improves encapsulation) - public: - int type; - uint256 hash; +public: + int type; + uint256 hash; }; -enum -{ +enum { MSG_TX = 1, MSG_BLOCK, // Nodes may always request a MSG_FILTERED_BLOCK in a getdata, however, diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 6cc6b99ceb..5e2fdc6c30 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -16,6 +16,7 @@ #include "splashscreen.h" #include "utilitydialog.h" #include "winshutdownmonitor.h" + #ifdef ENABLE_WALLET #include "paymentserver.h" #include "walletmodel.h" @@ -26,6 +27,7 @@ #include "rpcserver.h" #include "ui_interface.h" #include "util.h" + #ifdef ENABLE_WALLET #include "wallet.h" #endif @@ -34,15 +36,16 @@ #include <boost/filesystem/operations.hpp> #include <boost/thread.hpp> + #include <QApplication> #include <QDebug> #include <QLibraryInfo> #include <QLocale> #include <QMessageBox> #include <QSettings> +#include <QThread> #include <QTimer> #include <QTranslator> -#include <QThread> #if defined(QT_STATICPLUGIN) #include <QtPlugin> @@ -70,6 +73,7 @@ Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin); // Declare meta types used for QMetaObject::invokeMethod Q_DECLARE_METATYPE(bool*) +Q_DECLARE_METATYPE(CAmount) static void InitMessage(const std::string &message) { @@ -338,7 +342,9 @@ void BitcoinApplication::createWindow(bool isaTestNet) void BitcoinApplication::createSplashScreen(bool isaTestNet) { - SplashScreen *splash = new SplashScreen(QPixmap(), 0, isaTestNet); + SplashScreen *splash = new SplashScreen(0, isaTestNet); + // We don't hold a direct pointer to the splash screen after creation, so use + // Qt::WA_DeleteOnClose to make sure that the window will be deleted eventually. splash->setAttribute(Qt::WA_DeleteOnClose); splash->show(); connect(this, SIGNAL(splashFinished(QWidget*)), splash, SLOT(slotFinish(QWidget*))); @@ -423,8 +429,6 @@ void BitcoinApplication::initializeResult(int retval) } #endif - emit splashFinished(window); - // If -min option passed, start window minimized. if(GetBoolArg("-min", false)) { @@ -434,6 +438,8 @@ void BitcoinApplication::initializeResult(int retval) { window->show(); } + emit splashFinished(window); + #ifdef ENABLE_WALLET // Now that initialization/startup is done, process any command-line // bitcoin: URIs or payment requests: @@ -504,6 +510,9 @@ int main(int argc, char *argv[]) // Register meta types used for QMetaObject::invokeMethod qRegisterMetaType< bool* >(); + // Need to pass name here as CAmount is a typedef (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType) + // IMPORTANT if it is no longer a typedef use the normal variant above + qRegisterMetaType< CAmount >("CAmount"); /// 3. Application identification // must be set before OptionsModel is initialized or translations are loaded, diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index 6466039013..6e35bf17b3 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -44,7 +44,7 @@ public: void fixup(QString &input) const { bool valid = false; - qint64 val = parse(input, &valid); + CAmount val = parse(input, &valid); if(valid) { input = BitcoinUnits::format(currentUnit, val, false, BitcoinUnits::separatorAlways); @@ -52,12 +52,12 @@ public: } } - qint64 value(bool *valid_out=0) const + CAmount value(bool *valid_out=0) const { return parse(text(), valid_out); } - void setValue(qint64 value) + void setValue(const CAmount& value) { lineEdit()->setText(BitcoinUnits::format(currentUnit, value, false, BitcoinUnits::separatorAlways)); emit valueChanged(); @@ -66,9 +66,9 @@ public: void stepBy(int steps) { bool valid = false; - qint64 val = value(&valid); + CAmount val = value(&valid); val = val + steps * singleStep; - val = qMin(qMax(val, Q_INT64_C(0)), BitcoinUnits::maxMoney()); + val = qMin(qMax(val, CAmount(0)), BitcoinUnits::maxMoney()); setValue(val); } @@ -78,7 +78,7 @@ public: if(text().isEmpty()) // Allow step-up with empty field return StepUpEnabled; bool valid = false; - qint64 val = value(&valid); + CAmount val = value(&valid); if(valid) { if(val > 0) @@ -92,7 +92,7 @@ public: void setDisplayUnit(int unit) { bool valid = false; - qint64 val = value(&valid); + CAmount val = value(&valid); currentUnit = unit; @@ -102,7 +102,7 @@ public: clear(); } - void setSingleStep(qint64 step) + void setSingleStep(const CAmount& step) { singleStep = step; } @@ -140,7 +140,7 @@ public: } private: int currentUnit; - qint64 singleStep; + CAmount singleStep; mutable QSize cachedMinimumSizeHint; /** @@ -148,9 +148,9 @@ private: * return validity. * @note Must return 0 if !valid. */ - qint64 parse(const QString &text, bool *valid_out=0) const + CAmount parse(const QString &text, bool *valid_out=0) const { - qint64 val = 0; + CAmount val = 0; bool valid = BitcoinUnits::parse(currentUnit, text, &val); if(valid) { @@ -253,12 +253,12 @@ QWidget *BitcoinAmountField::setupTabChain(QWidget *prev) return unit; } -qint64 BitcoinAmountField::value(bool *valid_out) const +CAmount BitcoinAmountField::value(bool *valid_out) const { return amount->value(valid_out); } -void BitcoinAmountField::setValue(qint64 value) +void BitcoinAmountField::setValue(const CAmount& value) { amount->setValue(value); } @@ -285,7 +285,7 @@ void BitcoinAmountField::setDisplayUnit(int newUnit) unit->setValue(newUnit); } -void BitcoinAmountField::setSingleStep(qint64 step) +void BitcoinAmountField::setSingleStep(const CAmount& step) { amount->setSingleStep(step); } diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index c713f5d687..e52feeb46e 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -5,30 +5,32 @@ #ifndef BITCOINAMOUNTFIELD_H #define BITCOINAMOUNTFIELD_H +#include "amount.h" + #include <QWidget> +class AmountSpinBox; + QT_BEGIN_NAMESPACE class QValueComboBox; QT_END_NAMESPACE -class AmountSpinBox; - /** Widget for entering bitcoin amounts. */ class BitcoinAmountField: public QWidget { Q_OBJECT - Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY valueChanged USER true) + Q_PROPERTY(CAmount value READ value WRITE setValue NOTIFY valueChanged USER true) public: explicit BitcoinAmountField(QWidget *parent = 0); - qint64 value(bool *valid=0) const; - void setValue(qint64 value); + CAmount value(bool *value=0) const; + void setValue(const CAmount& value); /** Set single step in satoshis **/ - void setSingleStep(qint64 step); + void setSingleStep(const CAmount& step); /** Make read-only **/ void setReadOnly(bool fReadOnly); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 790301a1eb..7380fbd240 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -14,6 +14,7 @@ #include "optionsmodel.h" #include "rpcconsole.h" #include "utilitydialog.h" + #ifdef ENABLE_WALLET #include "walletframe.h" #include "walletmodel.h" @@ -24,8 +25,8 @@ #endif #include "init.h" -#include "util.h" #include "ui_interface.h" +#include "util.h" #include <iostream> @@ -50,8 +51,8 @@ #include <QVBoxLayout> #if QT_VERSION < 0x050000 -#include <QUrl> #include <QTextDocument> +#include <QUrl> #else #include <QUrlQuery> #endif @@ -661,6 +662,9 @@ void BitcoinGUI::setNumConnections(int count) void BitcoinGUI::setNumBlocks(int count) { + if(!clientModel) + return; + // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text) statusBar()->clearMessage(); @@ -831,7 +835,7 @@ void BitcoinGUI::changeEvent(QEvent *e) #ifndef Q_OS_MAC // Ignored on Mac if(e->type() == QEvent::WindowStateChange) { - if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray()) + if(clientModel && clientModel->getOptionsModel() && clientModel->getOptionsModel()->getMinimizeToTray()) { QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e); if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized()) @@ -846,21 +850,21 @@ void BitcoinGUI::changeEvent(QEvent *e) void BitcoinGUI::closeEvent(QCloseEvent *event) { - if(clientModel) - { #ifndef Q_OS_MAC // Ignored on Mac + if(clientModel && clientModel->getOptionsModel()) + { if(!clientModel->getOptionsModel()->getMinimizeToTray() && !clientModel->getOptionsModel()->getMinimizeOnClose()) { QApplication::quit(); } -#endif } +#endif QMainWindow::closeEvent(event); } #ifdef ENABLE_WALLET -void BitcoinGUI::incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address) +void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address) { // On new transaction, make an info balloon message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"), @@ -916,8 +920,7 @@ bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient) gotoSendCoinsPage(); return true; } - else - return false; + return false; } void BitcoinGUI::setEncryptionStatus(int status) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 30b05cb7d9..8af6eda867 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -9,6 +9,8 @@ #include "config/bitcoin-config.h" #endif +#include "amount.h" + #include <QLabel> #include <QMainWindow> #include <QMap> @@ -159,7 +161,7 @@ public slots: bool handlePaymentRequest(const SendCoinsRecipient& recipient); /** Show incoming transaction notification for new transactions. */ - void incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address); + void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address); #endif private slots: diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 3b4b40aae3..25c811183f 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -195,21 +195,11 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet corrupted"), QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet requires newer version of Bitcoin Core"), QT_TRANSLATE_NOOP("bitcoin-core", "Error opening block database"), QT_TRANSLATE_NOOP("bitcoin-core", "Error"), +QT_TRANSLATE_NOOP("bitcoin-core", "Error: A fatal internal error occured, see debug.log for details"), QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low!"), QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unsupported argument -tor found, use -onion."), QT_TRANSLATE_NOOP("bitcoin-core", "Error: Wallet locked, unable to create transaction!"), -QT_TRANSLATE_NOOP("bitcoin-core", "Error: system error: "), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to read block info"), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to read block"), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to sync block index"), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write block index"), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write block info"), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write block"), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write file info"), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write to coin database"), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write transaction index"), -QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write undo data"), QT_TRANSLATE_NOOP("bitcoin-core", "Fee (in BTC/kB) to add to transactions you send (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Force safe mode (default: 0)"), QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins (default: 0)"), @@ -231,6 +221,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s'") QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid netmask specified in -whitelist: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Keep at most <n> unconnectable blocks in memory (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Keep at most <n> unconnectable transactions in memory (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Limit size of signature cache to <n> entries (default: 50000)"), QT_TRANSLATE_NOOP("bitcoin-core", "Listen for connections on <port> (default: 8333 or testnet: 18333)"), QT_TRANSLATE_NOOP("bitcoin-core", "Loading addresses..."), @@ -245,7 +236,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Need to specify a port with -whitebind: '%s'" QT_TRANSLATE_NOOP("bitcoin-core", "Node relay options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Not enough file descriptors available."), QT_TRANSLATE_NOOP("bitcoin-core", "Only accept block chain matching built-in checkpoints (default: 1)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network <net> (IPv4, IPv6 or Tor)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network <net> (ipv4, ipv6 or onion)"), QT_TRANSLATE_NOOP("bitcoin-core", "Options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Password for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp (default: 1)"), @@ -282,7 +273,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Specify wallet file (within data directory)") QT_TRANSLATE_NOOP("bitcoin-core", "Specify your own public address"), QT_TRANSLATE_NOOP("bitcoin-core", "Spend unconfirmed change when sending transactions (default: 1)"), QT_TRANSLATE_NOOP("bitcoin-core", "Stop running after importing blocks from disk (default: 0)"), -QT_TRANSLATE_NOOP("bitcoin-core", "System error: "), QT_TRANSLATE_NOOP("bitcoin-core", "This help message"), QT_TRANSLATE_NOOP("bitcoin-core", "This is experimental software."), QT_TRANSLATE_NOOP("bitcoin-core", "This is intended for regression testing tools and app development."), diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index 3215363fa0..423b559bf7 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -91,12 +91,13 @@ int BitcoinUnits::decimals(int unit) } } -QString BitcoinUnits::format(int unit, qint64 n, bool fPlus, SeparatorStyle separators) +QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators) { // Note: not using straight sprintf here because we do NOT want // localized number formatting. if(!valid(unit)) return QString(); // Refuse to format invalid unit + qint64 n = (qint64)nIn; qint64 coin = factor(unit); int num_decimals = decimals(unit); qint64 n_abs = (n > 0 ? n : -n); @@ -138,12 +139,12 @@ QString BitcoinUnits::format(int unit, qint64 n, bool fPlus, SeparatorStyle sepa // Please take care to use formatHtmlWithUnit instead, when // appropriate. -QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign, SeparatorStyle separators) +QString BitcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators) { return format(unit, amount, plussign, separators) + QString(" ") + name(unit); } -QString BitcoinUnits::formatHtmlWithUnit(int unit, qint64 amount, bool plussign, SeparatorStyle separators) +QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators) { QString str(formatWithUnit(unit, amount, plussign, separators)); str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML)); @@ -151,7 +152,7 @@ QString BitcoinUnits::formatHtmlWithUnit(int unit, qint64 amount, bool plussign, } -bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out) +bool BitcoinUnits::parse(int unit, const QString &value, CAmount *val_out) { if(!valid(unit) || value.isEmpty()) return false; // Refuse to parse invalid unit or empty string @@ -182,7 +183,7 @@ bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out) { return false; // Longer numbers will exceed 63 bits } - qint64 retvalue = str.toLongLong(&ok); + CAmount retvalue(str.toLongLong(&ok)); if(val_out) { *val_out = retvalue; @@ -226,7 +227,7 @@ QVariant BitcoinUnits::data(const QModelIndex &index, int role) const return QVariant(); } -qint64 BitcoinUnits::maxMoney() +CAmount BitcoinUnits::maxMoney() { return MAX_MONEY; } diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h index be9dca6012..a392c42b9b 100644 --- a/src/qt/bitcoinunits.h +++ b/src/qt/bitcoinunits.h @@ -5,6 +5,8 @@ #ifndef BITCOINUNITS_H #define BITCOINUNITS_H +#include "amount.h" + #include <QAbstractListModel> #include <QString> @@ -85,12 +87,12 @@ public: //! Number of decimals left static int decimals(int unit); //! Format as string - static QString format(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard); + static QString format(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard); //! Format as string (with unit) - static QString formatWithUnit(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard); - static QString formatHtmlWithUnit(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard); + static QString formatWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard); + static QString formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard); //! Parse string to coin amount - static bool parse(int unit, const QString &value, qint64 *val_out); + static bool parse(int unit, const QString &value, CAmount *val_out); //! Gets title for amount column including current display unit if optionsModel reference available */ static QString getAmountColumnTitle(int unit); ///@} @@ -117,7 +119,7 @@ public: } //! Return maximum number of base units (Satoshis) - static qint64 maxMoney(); + static CAmount maxMoney(); private: QList<BitcoinUnits::Unit> unitlist; diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index d10463fd8f..ba0febe546 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -29,7 +29,7 @@ #include <QTreeWidgetItem> using namespace std; -QList<qint64> CoinControlDialog::payAmounts; +QList<CAmount> CoinControlDialog::payAmounts; CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); CoinControlDialog::CoinControlDialog(QWidget *parent) : @@ -443,10 +443,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) return; // nPayAmount - qint64 nPayAmount = 0; + CAmount nPayAmount = 0; bool fDust = false; CMutableTransaction txDummy; - foreach(const qint64 &amount, CoinControlDialog::payAmounts) + foreach(const CAmount &amount, CoinControlDialog::payAmounts) { nPayAmount += amount; @@ -460,10 +460,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) } QString sPriorityLabel = tr("none"); - int64_t nAmount = 0; - int64_t nPayFee = 0; - int64_t nAfterFee = 0; - int64_t nChange = 0; + CAmount nAmount = 0; + CAmount nPayFee = 0; + CAmount nAfterFee = 0; + CAmount nChange = 0; unsigned int nBytes = 0; unsigned int nBytesInputs = 0; double dPriority = 0; @@ -684,7 +684,7 @@ void CoinControlDialog::updateView() itemWalletAddress->setText(COLUMN_ADDRESS, sWalletAddress); } - int64_t nSum = 0; + CAmount nSum = 0; double dPrioritySum = 0; int nChildren = 0; int nInputSum = 0; diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 4f7422642f..9eaa8eb41d 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -5,6 +5,8 @@ #ifndef COINCONTROLDIALOG_H #define COINCONTROLDIALOG_H +#include "amount.h" + #include <QAbstractButton> #include <QAction> #include <QDialog> @@ -14,13 +16,15 @@ #include <QString> #include <QTreeWidgetItem> -namespace Ui { - class CoinControlDialog; -} class WalletModel; + class CCoinControl; class CTxMemPool; +namespace Ui { + class CoinControlDialog; +} + class CoinControlDialog : public QDialog { Q_OBJECT @@ -35,7 +39,7 @@ public: static void updateLabels(WalletModel*, QDialog*); static QString getPriorityLabel(const CTxMemPool& pool, double); - static QList<qint64> payAmounts; + static QList<CAmount> payAmounts; static CCoinControl *coinControl; private: diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index fc22871a6b..91bb10755a 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -221,7 +221,7 @@ QString formatBitcoinURI(const SendCoinsRecipient &info) return ret; } -bool isDust(const QString& address, qint64 amount) +bool isDust(const QString& address, const CAmount& amount) { CTxDestination dest = CBitcoinAddress(address.toStdString()).Get(); CScript script = GetScriptForDestination(dest); diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 67e11e59a0..0939c78f64 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -5,6 +5,8 @@ #ifndef GUIUTIL_H #define GUIUTIL_H +#include "amount.h" + #include <QHeaderView> #include <QMessageBox> #include <QObject> @@ -46,7 +48,7 @@ namespace GUIUtil QString formatBitcoinURI(const SendCoinsRecipient &info); // Returns true if given address+amount meets "dust" definition - bool isDust(const QString& address, qint64 amount); + bool isDust(const QString& address, const CAmount& amount); // HTML escaping for rich text controls QString HtmlEscape(const QString& str, bool fMultiLine=false); diff --git a/src/qt/intro.h b/src/qt/intro.h index 295a75562f..e3e396d369 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -12,7 +12,7 @@ class FreespaceChecker; namespace Ui { -class Intro; + class Intro; } /** Introduction screen (pre-GUI startup). diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index a527602b5a..5c3abef2e7 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -19,7 +19,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+11"/> + <location line="+14"/> <source>Copy the currently selected address to the system clipboard</source> <translation>Copy the currently selected address to the system clipboard</translation> </message> @@ -29,7 +29,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+58"/> + <location line="+67"/> <source>C&lose</source> <translation type="unfinished"></translation> </message> @@ -39,12 +39,12 @@ <translation>&Copy Address</translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="-47"/> + <location filename="../forms/addressbookpage.ui" line="-53"/> <source>Delete the currently selected address from the list</source> <translation>Delete the currently selected address from the list</translation> </message> <message> - <location line="+27"/> + <location line="+30"/> <source>Export the data in the current tab to a file</source> <translation>Export the data in the current tab to a file</translation> </message> @@ -54,7 +54,7 @@ <translation>&Export</translation> </message> <message> - <location line="-27"/> + <location line="-30"/> <source>&Delete</source> <translation>&Delete</translation> </message> @@ -286,17 +286,17 @@ <context> <name>BitcoinGUI</name> <message> - <location filename="../bitcoingui.cpp" line="+300"/> + <location filename="../bitcoingui.cpp" line="+327"/> <source>Sign &message...</source> <translation>Sign &message...</translation> </message> <message> - <location line="+339"/> + <location line="+348"/> <source>Synchronizing with network...</source> <translation>Synchronizing with network...</translation> </message> <message> - <location line="-411"/> + <location line="-420"/> <source>&Overview</source> <translation>&Overview</translation> </message> @@ -377,13 +377,13 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+168"/> + <location line="+175"/> <location line="+5"/> <source>Bitcoin Core client</source> <translation type="unfinished"></translation> </message> <message> - <location line="+156"/> + <location line="+158"/> <source>Importing blocks from disk...</source> <translation>Importing blocks from disk...</translation> </message> @@ -393,7 +393,7 @@ <translation>Reindexing blocks on disk...</translation> </message> <message> - <location line="-409"/> + <location line="-418"/> <source>Send coins to a Bitcoin address</source> <translation>Send coins to a Bitcoin address</translation> </message> @@ -428,12 +428,12 @@ <translation>&Verify message...</translation> </message> <message> - <location line="+437"/> + <location line="+446"/> <source>Bitcoin</source> <translation>Bitcoin</translation> </message> <message> - <location line="-655"/> + <location line="-664"/> <source>Wallet</source> <translation>Wallet</translation> </message> @@ -500,12 +500,12 @@ </message> <message> <location line="-289"/> - <location line="+386"/> + <location line="+393"/> <source>[testnet]</source> <translation>[testnet]</translation> </message> <message> - <location line="-411"/> + <location line="-418"/> <source>Bitcoin Core</source> <translation type="unfinished">Bitcoin Core</translation> </message> @@ -546,7 +546,7 @@ <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location line="+310"/> + <location line="+316"/> <source>%n active connection(s) to Bitcoin network</source> <translation> <numerusform>%n active connection to Bitcoin network</numerusform> @@ -554,7 +554,7 @@ </translation> </message> <message> - <location line="+22"/> + <location line="+25"/> <source>No block source available...</source> <translation>No block source available...</translation> </message> @@ -665,7 +665,7 @@ Address: %4 </translation> </message> <message> - <location line="+69"/> + <location line="+68"/> <source>Wallet is <b>encrypted</b> and currently <b>unlocked</b></source> <translation>Wallet is <b>encrypted</b> and currently <b>unlocked</b></translation> </message> @@ -678,7 +678,7 @@ Address: %4 <context> <name>ClientModel</name> <message> - <location filename="../clientmodel.cpp" line="+138"/> + <location filename="../clientmodel.cpp" line="+139"/> <source>Network Alert</source> <translation>Network Alert</translation> </message> @@ -736,7 +736,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+13"/> + <location line="+16"/> <source>Tree mode</source> <translation type="unfinished"></translation> </message> @@ -1059,7 +1059,7 @@ Address: %4 <context> <name>HelpMessageDialog</name> <message> - <location filename="../utilitydialog.cpp" line="+29"/> + <location filename="../utilitydialog.cpp" line="+31"/> <source>Bitcoin Core</source> <translation type="unfinished">Bitcoin Core</translation> </message> @@ -1201,7 +1201,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+11"/> + <location line="+10"/> <source>Select payment request file</source> <translation type="unfinished"></translation> </message> @@ -1430,12 +1430,12 @@ Address: %4 <translation>&OK</translation> </message> <message> - <location line="+7"/> + <location line="+13"/> <source>&Cancel</source> <translation>&Cancel</translation> </message> <message> - <location filename="../optionsdialog.cpp" line="+68"/> + <location filename="../optionsdialog.cpp" line="+71"/> <source>default</source> <translation>default</translation> </message> @@ -1479,23 +1479,18 @@ Address: %4 <translation>Form</translation> </message> <message> - <location line="+52"/> - <location line="+394"/> + <location line="+53"/> + <location line="+372"/> <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source> <translation>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</translation> </message> <message> - <location line="-401"/> - <source>Wallet</source> - <translation>Wallet</translation> - </message> - <message> - <location line="+33"/> + <location line="-133"/> <source>Watch-only:</source> <translation type="unfinished"></translation> </message> <message> - <location line="+43"/> + <location line="+10"/> <source>Available:</source> <translation type="unfinished"></translation> </message> @@ -1505,62 +1500,72 @@ Address: %4 <translation>Your current spendable balance</translation> </message> <message> - <location line="+16"/> + <location line="+41"/> <source>Pending:</source> <translation type="unfinished"></translation> </message> <message> - <location line="+16"/> + <location line="-236"/> <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source> <translation>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</translation> </message> <message> - <location line="+16"/> + <location line="+112"/> <source>Immature:</source> <translation>Immature:</translation> </message> <message> - <location line="+16"/> + <location line="-29"/> <source>Mined balance that has not yet matured</source> <translation>Mined balance that has not yet matured</translation> </message> <message> - <location line="+23"/> + <location line="-163"/> + <source>Balances</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+147"/> <source>Total:</source> <translation>Total:</translation> </message> <message> - <location line="+16"/> + <location line="+61"/> <source>Your current total balance</source> <translation>Your current total balance</translation> </message> <message> - <location line="+38"/> + <location line="+92"/> <source>Your current balance in watch-only addresses</source> <translation type="unfinished"></translation> </message> <message> - <location line="+25"/> + <location line="+23"/> + <source>Spendable:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+49"/> + <source>Recent transactions</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-317"/> <source>Unconfirmed transactions to watch-only addresses</source> <translation type="unfinished"></translation> </message> <message> - <location line="+25"/> + <location line="+50"/> <source>Mined balance in watch-only addresses that has not yet matured</source> <translation type="unfinished"></translation> </message> <message> - <location line="+44"/> + <location line="+128"/> <source>Current total balance in watch-only addresses</source> <translation type="unfinished"></translation> </message> <message> - <location line="+67"/> - <source><b>Recent transactions</b></source> - <translation><b>Recent transactions</b></translation> - </message> - <message> - <location filename="../overviewpage.cpp" line="+123"/> + <location filename="../overviewpage.cpp" line="+131"/> <location line="+1"/> <source>out of sync</source> <translation>out of sync</translation> @@ -1569,7 +1574,7 @@ Address: %4 <context> <name>PaymentServer</name> <message> - <location filename="../paymentserver.cpp" line="+405"/> + <location filename="../paymentserver.cpp" line="+410"/> <location line="+14"/> <location line="+7"/> <source>URI handling</source> @@ -1681,7 +1686,7 @@ Address: %4 <context> <name>PeerTableModel</name> <message> - <location filename="../peertablemodel.cpp" line="+112"/> + <location filename="../peertablemodel.cpp" line="+118"/> <source>User Agent</source> <translation type="unfinished"></translation> </message> @@ -1699,17 +1704,17 @@ Address: %4 <context> <name>QObject</name> <message> - <location filename="../bitcoinunits.cpp" line="+200"/> + <location filename="../bitcoinunits.cpp" line="+196"/> <source>Amount</source> <translation type="unfinished">Amount</translation> </message> <message> - <location filename="../guiutil.cpp" line="+97"/> + <location filename="../guiutil.cpp" line="+106"/> <source>Enter a Bitcoin address (e.g. %1)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+673"/> + <location line="+698"/> <source>%1 d</source> <translation type="unfinished"></translation> </message> @@ -1795,7 +1800,7 @@ Address: %4 <location line="+23"/> <location line="+36"/> <location line="+23"/> - <location line="+462"/> + <location line="+465"/> <location line="+23"/> <location line="+23"/> <location line="+23"/> @@ -1813,7 +1818,7 @@ Address: %4 <translation>N/A</translation> </message> <message> - <location line="-987"/> + <location line="-990"/> <source>Client version</source> <translation>Client version</translation> </message> @@ -1873,7 +1878,7 @@ Address: %4 <translation>Current number of blocks</translation> </message> <message> - <location line="+300"/> + <location line="+303"/> <source>Received</source> <translation type="unfinished"></translation> </message> @@ -1889,7 +1894,7 @@ Address: %4 </message> <message> <location line="+39"/> - <location filename="../rpcconsole.cpp" line="+234"/> + <location filename="../rpcconsole.cpp" line="+236"/> <location line="+327"/> <source>Select a peer to view detailed information.</source> <translation type="unfinished"></translation> @@ -1965,7 +1970,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="-761"/> + <location line="-764"/> <source>Last block time</source> <translation>Last block time</translation> </message> @@ -1990,7 +1995,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+13"/> + <location line="+16"/> <source>Totals</source> <translation type="unfinished"></translation> </message> @@ -2005,7 +2010,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="-354"/> + <location filename="../forms/rpcconsole.ui" line="-357"/> <source>Build date</source> <translation>Build date</translation> </message> @@ -2163,12 +2168,12 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+78"/> + <location line="+75"/> <source>Requested payments history</source> <translation type="unfinished"></translation> </message> <message> - <location line="-98"/> + <location line="-95"/> <source>&Request payment</source> <translation type="unfinished"></translation> </message> @@ -2183,7 +2188,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+14"/> + <location line="+17"/> <source>Remove the selected entries from the list</source> <translation type="unfinished"></translation> </message> @@ -2221,12 +2226,12 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+7"/> + <location line="+10"/> <source>Copy &Address</source> <translation type="unfinished"></translation> </message> <message> - <location line="+7"/> + <location line="+10"/> <source>&Save Image...</source> <translation type="unfinished"></translation> </message> @@ -2279,7 +2284,7 @@ Address: %4 <context> <name>RecentRequestsTableModel</name> <message> - <location filename="../recentrequeststablemodel.cpp" line="+24"/> + <location filename="../recentrequeststablemodel.cpp" line="+26"/> <source>Date</source> <translation type="unfinished">Date</translation> </message> @@ -2333,7 +2338,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+7"/> + <location line="+10"/> <source>automatically selected</source> <translation type="unfinished"></translation> </message> @@ -2398,22 +2403,22 @@ Address: %4 <translation>Add &Recipient</translation> </message> <message> - <location line="-23"/> + <location line="-20"/> <source>Clear all fields of the form.</source> <translation type="unfinished"></translation> </message> <message> - <location line="-271"/> + <location line="-274"/> <source>Dust:</source> <translation type="unfinished"></translation> </message> <message> - <location line="+274"/> + <location line="+277"/> <source>Clear &All</source> <translation>Clear &All</translation> </message> <message> - <location line="+58"/> + <location line="+55"/> <source>Balance:</source> <translation>Balance:</translation> </message> @@ -2653,7 +2658,7 @@ Address: %4 <context> <name>ShutdownWindow</name> <message> - <location filename="../utilitydialog.cpp" line="+51"/> + <location filename="../utilitydialog.cpp" line="+47"/> <source>Bitcoin Core is shutting down...</source> <translation type="unfinished"></translation> </message> @@ -2671,7 +2676,7 @@ Address: %4 <translation>Signatures - Sign / Verify a Message</translation> </message> <message> - <location line="+10"/> + <location line="+13"/> <source>&Sign Message</source> <translation>&Sign Message</translation> </message> @@ -2848,7 +2853,7 @@ Address: %4 <context> <name>SplashScreen</name> <message> - <location filename="../splashscreen.cpp" line="+32"/> + <location filename="../splashscreen.cpp" line="+34"/> <source>Bitcoin Core</source> <translation type="unfinished">Bitcoin Core</translation> </message> @@ -2874,7 +2879,7 @@ Address: %4 <context> <name>TransactionDesc</name> <message> - <location filename="../transactiondesc.cpp" line="+33"/> + <location filename="../transactiondesc.cpp" line="+34"/> <source>Open until %1</source> <translation>Open until %1</translation> </message> @@ -3098,7 +3103,7 @@ Address: %4 <context> <name>TransactionTableModel</name> <message> - <location filename="../transactiontablemodel.cpp" line="+237"/> + <location filename="../transactiontablemodel.cpp" line="+235"/> <source>Date</source> <translation>Date</translation> </message> @@ -3166,7 +3171,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+51"/> + <location line="+48"/> <source>Received with</source> <translation>Received with</translation> </message> @@ -3191,12 +3196,17 @@ Address: %4 <translation>Mined</translation> </message> <message> - <location line="+41"/> + <location line="+28"/> + <source>watch-only</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+15"/> <source>(n/a)</source> <translation>(n/a)</translation> </message> <message> - <location line="+193"/> + <location line="+210"/> <source>Transaction status. Hover over this field to show number of confirmations.</source> <translation>Transaction status. Hover over this field to show number of confirmations.</translation> </message> @@ -3212,6 +3222,11 @@ Address: %4 </message> <message> <location line="+2"/> + <source>Whether or not a watch-only address is involved in this transaction.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> <source>Destination address of transaction.</source> <translation>Destination address of transaction.</translation> </message> @@ -3224,7 +3239,7 @@ Address: %4 <context> <name>TransactionView</name> <message> - <location filename="../transactionview.cpp" line="+60"/> + <location filename="../transactionview.cpp" line="+67"/> <location line="+16"/> <source>All</source> <translation>All</translation> @@ -3325,12 +3340,17 @@ Address: %4 <translation>Show transaction details</translation> </message> <message> - <location line="+163"/> + <location line="+179"/> <source>Export Transaction History</source> <translation type="unfinished"></translation> </message> <message> - <location line="+19"/> + <location line="+12"/> + <source>Watch-only</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+9"/> <source>Exporting Failed</source> <translation type="unfinished"></translation> </message> @@ -3350,7 +3370,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="-22"/> + <location line="-24"/> <source>Comma separated file (*.csv)</source> <translation>Comma separated file (*.csv)</translation> </message> @@ -3360,7 +3380,7 @@ Address: %4 <translation>Confirmed</translation> </message> <message> - <location line="+1"/> + <location line="+3"/> <source>Date</source> <translation>Date</translation> </message> @@ -3398,7 +3418,7 @@ Address: %4 <context> <name>UnitDisplayStatusBarControl</name> <message> - <location filename="../bitcoingui.cpp" line="+101"/> + <location filename="../bitcoingui.cpp" line="+103"/> <source>Unit to show amounts in. Click to select another unit.</source> <translation type="unfinished"></translation> </message> @@ -3465,7 +3485,7 @@ Address: %4 <context> <name>bitcoin-core</name> <message> - <location filename="../bitcoinstrings.cpp" line="+249"/> + <location filename="../bitcoinstrings.cpp" line="+240"/> <source>Options:</source> <translation>Options:</translation> </message> @@ -3495,22 +3515,22 @@ Address: %4 <translation>Maintain at most <n> connections to peers (default: 125)</translation> </message> <message> - <location line="-62"/> + <location line="-53"/> <source>Connect to a node to retrieve peer addresses, and disconnect</source> <translation>Connect to a node to retrieve peer addresses, and disconnect</translation> </message> <message> - <location line="+103"/> + <location line="+94"/> <source>Specify your own public address</source> <translation>Specify your own public address</translation> </message> <message> - <location line="+7"/> + <location line="+6"/> <source>Threshold for disconnecting misbehaving peers (default: 100)</source> <translation>Threshold for disconnecting misbehaving peers (default: 100)</translation> </message> <message> - <location line="-181"/> + <location line="-171"/> <source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source> <translation>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</translation> </message> @@ -3525,17 +3545,17 @@ Address: %4 <translation>Accept command line and JSON-RPC commands</translation> </message> <message> - <location line="+99"/> + <location line="+90"/> <source>Run in the background as a daemon and accept commands</source> <translation>Run in the background as a daemon and accept commands</translation> </message> <message> - <location line="+36"/> + <location line="+35"/> <source>Use the test network</source> <translation>Use the test network</translation> </message> <message> - <location line="-134"/> + <location line="-124"/> <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source> <translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation> </message> @@ -3756,6 +3776,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. </message> <message> <location line="+2"/> + <source>Error: A fatal internal error occured, see debug.log for details</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> <source>Error: Disk space is low!</source> <translation>Error: Disk space is low!</translation> </message> @@ -3766,65 +3791,10 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. </message> <message> <location line="+1"/> - <source>Error: system error: </source> - <translation>Error: system error: </translation> - </message> - <message> - <location line="+1"/> <source>Failed to listen on any port. Use -listen=0 if you want this.</source> <translation>Failed to listen on any port. Use -listen=0 if you want this.</translation> </message> <message> - <location line="+1"/> - <source>Failed to read block info</source> - <translation>Failed to read block info</translation> - </message> - <message> - <location line="+1"/> - <source>Failed to read block</source> - <translation>Failed to read block</translation> - </message> - <message> - <location line="+1"/> - <source>Failed to sync block index</source> - <translation>Failed to sync block index</translation> - </message> - <message> - <location line="+1"/> - <source>Failed to write block index</source> - <translation>Failed to write block index</translation> - </message> - <message> - <location line="+1"/> - <source>Failed to write block info</source> - <translation>Failed to write block info</translation> - </message> - <message> - <location line="+1"/> - <source>Failed to write block</source> - <translation>Failed to write block</translation> - </message> - <message> - <location line="+1"/> - <source>Failed to write file info</source> - <translation>Failed to write file info</translation> - </message> - <message> - <location line="+1"/> - <source>Failed to write to coin database</source> - <translation>Failed to write to coin database</translation> - </message> - <message> - <location line="+1"/> - <source>Failed to write transaction index</source> - <translation>Failed to write transaction index</translation> - </message> - <message> - <location line="+1"/> - <source>Failed to write undo data</source> - <translation>Failed to write undo data</translation> - </message> - <message> <location line="+2"/> <source>Force safe mode (default: 0)</source> <translation type="unfinished"></translation> @@ -3860,12 +3830,17 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+21"/> + <location line="+22"/> <source>Not enough file descriptors available.</source> <translation>Not enough file descriptors available.</translation> </message> <message> - <location line="+5"/> + <location line="+2"/> + <source>Only connect to nodes in network <net> (ipv4, ipv6 or onion)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> <source>Prepend debug output with timestamp (default: 1)</source> <translation type="unfinished"></translation> </message> @@ -3905,7 +3880,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+4"/> + <location line="+3"/> <source>This is intended for regression testing tools and app development.</source> <translation type="unfinished"></translation> </message> @@ -3940,7 +3915,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Imports blocks from external blk000??.dat file</translation> </message> <message> - <location line="-195"/> + <location line="-185"/> <source>(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source> <translation type="unfinished"></translation> </message> @@ -4080,12 +4055,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+4"/> + <location line="+5"/> <source>Error: Unsupported argument -tor found, use -onion.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+14"/> + <location line="+3"/> <source>Fee (in BTC/kB) to add to transactions you send (default: %s)</source> <translation type="unfinished"></translation> </message> @@ -4131,6 +4106,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. </message> <message> <location line="+1"/> + <source>Keep at most <n> unconnectable transactions in memory (default: %u)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> <source>Limit size of signature cache to <n> entries (default: 50000)</source> <translation type="unfinished"></translation> </message> @@ -4170,12 +4150,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Only accept block chain matching built-in checkpoints (default: 1)</translation> </message> <message> - <location line="+1"/> - <source>Only connect to nodes in network <net> (IPv4, IPv6 or Tor)</source> - <translation>Only connect to nodes in network <net> (IPv4, IPv6 or Tor)</translation> - </message> - <message> - <location line="+4"/> + <location line="+5"/> <source>Print block on startup, if found in block index</source> <translation type="unfinished"></translation> </message> @@ -4255,12 +4230,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Specify connection timeout in milliseconds (default: 5000)</translation> </message> <message> - <location line="+7"/> - <source>System error: </source> - <translation>System error: </translation> - </message> - <message> - <location line="+2"/> + <location line="+8"/> <source>This is experimental software.</source> <translation type="unfinished"></translation> </message> @@ -4340,22 +4310,22 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>wallet.dat corrupt, salvage failed</translation> </message> <message> - <location line="-64"/> + <location line="-63"/> <source>Password for JSON-RPC connections</source> <translation>Password for JSON-RPC connections</translation> </message> <message> - <location line="-164"/> + <location line="-155"/> <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source> <translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation> </message> <message> - <location line="+210"/> + <location line="+200"/> <source>Upgrade wallet to latest format</source> <translation>Upgrade wallet to latest format</translation> </message> <message> - <location line="-27"/> + <location line="-26"/> <source>Set key pool size to <n> (default: 100)</source> <translation>Set key pool size to <n> (default: 100)</translation> </message> @@ -4365,12 +4335,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Rescan the block chain for missing wallet transactions</translation> </message> <message> - <location line="+36"/> + <location line="+35"/> <source>Use OpenSSL (https) for JSON-RPC connections</source> <translation>Use OpenSSL (https) for JSON-RPC connections</translation> </message> <message> - <location line="-31"/> + <location line="-30"/> <source>Server certificate file (default: server.cert)</source> <translation>Server certificate file (default: server.cert)</translation> </message> @@ -4380,22 +4350,22 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Server private key (default: server.pem)</translation> </message> <message> - <location line="+19"/> + <location line="+18"/> <source>This help message</source> <translation>This help message</translation> </message> <message> - <location line="-118"/> + <location line="-108"/> <source>Allow DNS lookups for -addnode, -seednode and -connect</source> <translation>Allow DNS lookups for -addnode, -seednode and -connect</translation> </message> <message> - <location line="+68"/> + <location line="+59"/> <source>Loading addresses...</source> <translation>Loading addresses...</translation> </message> <message> - <location line="-42"/> + <location line="-33"/> <source>Error loading wallet.dat: Wallet corrupted</source> <translation>Error loading wallet.dat: Wallet corrupted</translation> </message> @@ -4405,7 +4375,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Error loading wallet.dat</translation> </message> <message> - <location line="+33"/> + <location line="+23"/> <source>Invalid -proxy address: '%s'</source> <translation>Invalid -proxy address: '%s'</translation> </message> @@ -4415,7 +4385,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Unknown network specified in -onlynet: '%s'</translation> </message> <message> - <location line="-122"/> + <location line="-112"/> <source>Cannot resolve -bind address: '%s'</source> <translation>Cannot resolve -bind address: '%s'</translation> </message> @@ -4425,7 +4395,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Cannot resolve -externalip address: '%s'</translation> </message> <message> - <location line="+56"/> + <location line="+46"/> <source>Invalid amount for -paytxfee=<amount>: '%s'</source> <translation>Invalid amount for -paytxfee=<amount>: '%s'</translation> </message> @@ -4440,22 +4410,22 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Insufficient funds</translation> </message> <message> - <location line="+13"/> + <location line="+14"/> <source>Loading block index...</source> <translation>Loading block index...</translation> </message> <message> - <location line="-70"/> + <location line="-61"/> <source>Add a node to connect to and attempt to keep the connection open</source> <translation>Add a node to connect to and attempt to keep the connection open</translation> </message> <message> - <location line="+71"/> + <location line="+62"/> <source>Loading wallet...</source> <translation>Loading wallet...</translation> </message> <message> - <location line="-66"/> + <location line="-57"/> <source>Cannot downgrade wallet</source> <translation>Cannot downgrade wallet</translation> </message> @@ -4465,22 +4435,22 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Cannot write default address</translation> </message> <message> - <location line="+86"/> + <location line="+77"/> <source>Rescanning...</source> <translation>Rescanning...</translation> </message> <message> - <location line="-73"/> + <location line="-64"/> <source>Done loading</source> <translation>Done loading</translation> </message> <message> - <location line="+101"/> + <location line="+91"/> <source>To use the %s option</source> <translation>To use the %s option</translation> </message> <message> - <location line="-93"/> + <location line="-83"/> <source>Error</source> <translation>Error</translation> </message> diff --git a/src/qt/openuridialog.h b/src/qt/openuridialog.h index 28da7d6d9d..67a5f167d1 100644 --- a/src/qt/openuridialog.h +++ b/src/qt/openuridialog.h @@ -8,7 +8,7 @@ #include <QDialog> namespace Ui { -class OpenURIDialog; + class OpenURIDialog; } class OpenURIDialog : public QDialog diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index c775a7f8d6..279467129f 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -17,11 +17,13 @@ #include "main.h" // for MAX_SCRIPTCHECK_THREADS #include "netbase.h" #include "txdb.h" // for -dbcache defaults + #ifdef ENABLE_WALLET #include "wallet.h" // for CWallet::minTxFee #endif #include <boost/thread.hpp> + #include <QDir> #include <QIntValidator> #include <QLocale> diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 99928ebe4d..cb80bd0e3d 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -15,6 +15,7 @@ #include "main.h" #include "net.h" #include "txdb.h" // for -dbcache defaults + #ifdef ENABLE_WALLET #include "wallet.h" #include "walletdb.h" @@ -274,9 +275,9 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in #ifdef ENABLE_WALLET case Fee: { // core option - can be changed on-the-fly // Todo: Add is valid check and warn via message, if not - qint64 nTransactionFee = value.toLongLong(); + CAmount nTransactionFee(value.toLongLong()); payTxFee = CFeeRate(nTransactionFee, 1000); - settings.setValue("nTransactionFee", nTransactionFee); + settings.setValue("nTransactionFee", qint64(nTransactionFee)); emit transactionFeeChanged(nTransactionFee); break; } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 80adab89c8..42ea3bf8e5 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -5,6 +5,8 @@ #ifndef OPTIONSMODEL_H #define OPTIONSMODEL_H +#include "amount.h" + #include <QAbstractListModel> QT_BEGIN_NAMESPACE @@ -82,7 +84,7 @@ private: signals: void displayUnitChanged(int unit); - void transactionFeeChanged(qint64); + void transactionFeeChanged(const CAmount&); void coinControlFeaturesChanged(bool); }; diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 90762bea5d..669d5474fd 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -146,7 +146,7 @@ OverviewPage::~OverviewPage() delete ui; } -void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance) +void OverviewPage::setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance) { int unit = walletModel->getOptionsModel()->getDisplayUnit(); currentBalance = balance; @@ -220,7 +220,7 @@ void OverviewPage::setWalletModel(WalletModel *model) // Keep up to date with wallet setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64))); + connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index f46374efba..03f239008f 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -5,6 +5,8 @@ #ifndef OVERVIEWPAGE_H #define OVERVIEWPAGE_H +#include "amount.h" + #include <QWidget> class ClientModel; @@ -34,8 +36,8 @@ public: void showOutOfSyncWarning(bool fShow); public slots: - void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, - qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); + void setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, + const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); signals: void transactionClicked(const QModelIndex &index); @@ -44,12 +46,12 @@ private: Ui::OverviewPage *ui; ClientModel *clientModel; WalletModel *walletModel; - qint64 currentBalance; - qint64 currentUnconfirmedBalance; - qint64 currentImmatureBalance; - qint64 currentWatchOnlyBalance; - qint64 currentWatchUnconfBalance; - qint64 currentWatchImmatureBalance; + CAmount currentBalance; + CAmount currentUnconfirmedBalance; + CAmount currentImmatureBalance; + CAmount currentWatchOnlyBalance; + CAmount currentWatchUnconfBalance; + CAmount currentWatchImmatureBalance; TxViewDelegate *txdelegate; TransactionFilterProxy *filter; diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index acce42e203..7aefffe24a 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -13,6 +13,7 @@ #include <openssl/x509.h> #include <openssl/x509_vfy.h> + #include <QDateTime> #include <QDebug> #include <QSslCertificate> @@ -195,9 +196,9 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c return fResult; } -QList<std::pair<CScript,qint64> > PaymentRequestPlus::getPayTo() const +QList<std::pair<CScript,CAmount> > PaymentRequestPlus::getPayTo() const { - QList<std::pair<CScript,qint64> > result; + QList<std::pair<CScript,CAmount> > result; for (int i = 0; i < details.outputs_size(); i++) { const unsigned char* scriptStr = (const unsigned char*)details.outputs(i).script().data(); diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h index 3c4861a4d4..3d94d93269 100644 --- a/src/qt/paymentrequestplus.h +++ b/src/qt/paymentrequestplus.h @@ -33,7 +33,7 @@ public: bool getMerchant(X509_STORE* certStore, QString& merchant) const; // Returns list of outputs, amount - QList<std::pair<CScript,qint64> > getPayTo() const; + QList<std::pair<CScript,CAmount> > getPayTo() const; const payments::PaymentDetails& getDetails() const { return details; } diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index cc4478f39f..707de55290 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -532,10 +532,10 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins request.getMerchant(PaymentServer::certStore, recipient.authenticatedMerchant); - QList<std::pair<CScript, qint64> > sendingTos = request.getPayTo(); + QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo(); QStringList addresses; - foreach(const PAIRTYPE(CScript, qint64)& sendingTo, sendingTos) { + foreach(const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { // Extract and check destination addresses CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) { diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 663cb157a4..7a7e38e25e 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -5,6 +5,8 @@ #ifndef RECEIVECOINSDIALOG_H #define RECEIVECOINSDIALOG_H +#include "guiutil.h" + #include <QDialog> #include <QHeaderView> #include <QItemSelection> @@ -13,13 +15,12 @@ #include <QPoint> #include <QVariant> -#include "guiutil.h" +class OptionsModel; +class WalletModel; namespace Ui { class ReceiveCoinsDialog; } -class OptionsModel; -class WalletModel; QT_BEGIN_NAMESPACE class QModelIndex; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 11089b2497..8129353d4b 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -16,10 +16,12 @@ #include "util.h" #include "json/json_spirit_value.h" + +#include <openssl/crypto.h> + #ifdef ENABLE_WALLET #include <db_cxx.h> #endif -#include <openssl/crypto.h> #include <QKeyEvent> #include <QScrollBar> diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 64bb5c29b3..1ffff92758 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -14,14 +14,14 @@ class ClientModel; -QT_BEGIN_NAMESPACE -class QItemSelection; -QT_END_NAMESPACE - namespace Ui { class RPCConsole; } +QT_BEGIN_NAMESPACE +class QItemSelection; +QT_END_NAMESPACE + /** Local Bitcoin RPC console. */ class RPCConsole: public QDialog { diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 25e3d2a0dc..ce94131cce 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -92,13 +92,13 @@ void SendCoinsDialog::setModel(WalletModel *model) setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64))); + connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); // Coin Control connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels())); connect(model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool))); - connect(model->getOptionsModel(), SIGNAL(transactionFeeChanged(qint64)), this, SLOT(coinControlUpdateLabels())); + connect(model->getOptionsModel(), SIGNAL(transactionFeeChanged(CAmount)), this, SLOT(coinControlUpdateLabels())); ui->frameCoinControl->setVisible(model->getOptionsModel()->getCoinControlFeatures()); coinControlUpdateLabels(); } @@ -203,7 +203,7 @@ void SendCoinsDialog::on_sendButton_clicked() return; } - qint64 txFee = currentTransaction.getTransactionFee(); + CAmount txFee = currentTransaction.getTransactionFee(); QString questionString = tr("Are you sure you want to send?"); questionString.append("<br /><br />%1"); @@ -218,7 +218,7 @@ void SendCoinsDialog::on_sendButton_clicked() // add total amount in all subdivision units questionString.append("<hr />"); - qint64 totalAmount = currentTransaction.getTotalTransactionAmount() + txFee; + CAmount totalAmount = currentTransaction.getTotalTransactionAmount() + txFee; QStringList alternativeUnits; foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) { @@ -384,8 +384,8 @@ bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv) return true; } -void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, - qint64 watchBalance, qint64 watchUnconfirmedBalance, qint64 watchImmatureBalance) +void SendCoinsDialog::setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, + const CAmount& watchBalance, const CAmount& watchUnconfirmedBalance, const CAmount& watchImmatureBalance) { Q_UNUSED(unconfirmedBalance); Q_UNUSED(immatureBalance); diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 6cdf4a00c8..74cc4bde56 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -14,14 +14,14 @@ class OptionsModel; class SendCoinsEntry; class SendCoinsRecipient; -QT_BEGIN_NAMESPACE -class QUrl; -QT_END_NAMESPACE - namespace Ui { class SendCoinsDialog; } +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + /** Dialog for sending bitcoins */ class SendCoinsDialog : public QDialog { @@ -47,8 +47,8 @@ public slots: void accept(); SendCoinsEntry *addEntry(); void updateTabsAndLabels(); - void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, - qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); + void setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, + const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); private: Ui::SendCoinsDialog *ui; diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 5dd110b36a..4fe610794f 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -4,23 +4,24 @@ #include "splashscreen.h" -#include "version.h" #include "clientversion.h" #include "init.h" #include "ui_interface.h" #include "util.h" +#include "version.h" + #ifdef ENABLE_WALLET #include "wallet.h" #endif #include <QApplication> +#include <QCloseEvent> +#include <QDesktopWidget> #include <QPainter> -SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTestNet) : - QSplashScreen(pixmap, f) +SplashScreen::SplashScreen(Qt::WindowFlags f, bool isTestNet) : + QWidget(0, f), curAlignment(0) { - setAutoFillBackground(true); - // set reference point, paddings int paddingRight = 50; int paddingTop = 50; @@ -38,15 +39,14 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest QString font = "Arial"; // load the bitmap for writing some text over it - QPixmap newPixmap; if(isTestNet) { - newPixmap = QPixmap(":/images/splash_testnet"); + pixmap = QPixmap(":/images/splash_testnet"); } else { - newPixmap = QPixmap(":/images/splash"); + pixmap = QPixmap(":/images/splash"); } - QPainter pixPaint(&newPixmap); + QPainter pixPaint(&pixmap); pixPaint.setPen(QColor(100,100,100)); // check font size and drawing with @@ -61,7 +61,7 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest pixPaint.setFont(QFont(font, 33*fontFactor)); fm = pixPaint.fontMetrics(); titleTextWidth = fm.width(titleText); - pixPaint.drawText(newPixmap.width()-titleTextWidth-paddingRight,paddingTop,titleText); + pixPaint.drawText(pixmap.width()-titleTextWidth-paddingRight,paddingTop,titleText); pixPaint.setFont(QFont(font, 15*fontFactor)); @@ -72,11 +72,11 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest pixPaint.setFont(QFont(font, 10*fontFactor)); titleVersionVSpace -= 5; } - pixPaint.drawText(newPixmap.width()-titleTextWidth-paddingRight+2,paddingTop+titleVersionVSpace,versionText); + pixPaint.drawText(pixmap.width()-titleTextWidth-paddingRight+2,paddingTop+titleVersionVSpace,versionText); // draw copyright stuff pixPaint.setFont(QFont(font, 10*fontFactor)); - pixPaint.drawText(newPixmap.width()-titleTextWidth-paddingRight,paddingTop+titleCopyrightVSpace,copyrightText); + pixPaint.drawText(pixmap.width()-titleTextWidth-paddingRight,paddingTop+titleCopyrightVSpace,copyrightText); // draw testnet string if testnet is on if(isTestNet) { @@ -85,12 +85,22 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest pixPaint.setFont(boldFont); fm = pixPaint.fontMetrics(); int testnetAddTextWidth = fm.width(testnetAddText); - pixPaint.drawText(newPixmap.width()-testnetAddTextWidth-10,15,testnetAddText); + pixPaint.drawText(pixmap.width()-testnetAddTextWidth-10,15,testnetAddText); } pixPaint.end(); - this->setPixmap(newPixmap); + // Set window title + if(isTestNet) + setWindowTitle(titleText + " " + testnetAddText); + else + setWindowTitle(titleText); + + // Resize window and move to center of desktop, disallow resizing + QRect r(QPoint(), pixmap.size()); + resize(r.size()); + setFixedSize(r.size()); + move(QApplication::desktop()->screenGeometry().center() - r.center()); subscribeToCoreSignals(); } @@ -102,7 +112,8 @@ SplashScreen::~SplashScreen() void SplashScreen::slotFinish(QWidget *mainWin) { - finish(mainWin); + Q_UNUSED(mainWin); + hide(); } static void InitMessage(SplashScreen *splash, const std::string &message) @@ -146,3 +157,25 @@ void SplashScreen::unsubscribeFromCoreSignals() pwalletMain->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); #endif } + +void SplashScreen::showMessage(const QString &message, int alignment, const QColor &color) +{ + curMessage = message; + curAlignment = alignment; + curColor = color; + update(); +} + +void SplashScreen::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + painter.drawPixmap(0, 0, pixmap); + QRect r = rect().adjusted(5, 5, -5, -5); + painter.setPen(curColor); + painter.drawText(r, curAlignment, curMessage); +} + +void SplashScreen::closeEvent(QCloseEvent *event) +{ + event->ignore(); +} diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index d79038d81d..89c21e6457 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -7,25 +7,41 @@ #include <QSplashScreen> -/** class for the splashscreen with information of the running client +/** Class for the splashscreen with information of the running client. + * + * @note this is intentionally not a QSplashScreen. Bitcoin Core initialization + * can take a long time, and in that case a progress window that cannot be + * moved around and minimized has turned out to be frustrating to the user. */ -class SplashScreen : public QSplashScreen +class SplashScreen : public QWidget { Q_OBJECT public: - explicit SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTestNet); + explicit SplashScreen(Qt::WindowFlags f, bool isTestNet); ~SplashScreen(); +protected: + void paintEvent(QPaintEvent *event); + void closeEvent(QCloseEvent *event); + public slots: /** Slot to call finish() method as it's not defined as slot */ void slotFinish(QWidget *mainWin); + /** Show message and progress */ + void showMessage(const QString &message, int alignment, const QColor &color); + private: /** Connect core signals to splash screen */ void subscribeToCoreSignals(); /** Disconnect core signals to splash screen */ void unsubscribeFromCoreSignals(); + + QPixmap pixmap; + QString curMessage; + QColor curColor; + int curAlignment; }; #endif // SPLASHSCREEN_H diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 727b8dc66d..1efad8259b 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -6,13 +6,13 @@ #include "bitcoinunits.h" #include "guiutil.h" +#include "paymentserver.h" +#include "transactionrecord.h" #include "base58.h" #include "db.h" #include "main.h" -#include "paymentserver.h" #include "script/script.h" -#include "transactionrecord.h" #include "timedata.h" #include "ui_interface.h" #include "util.h" @@ -56,9 +56,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(ISMINE_ALL); - int64_t nDebit = wtx.GetDebit(ISMINE_ALL); - int64_t nNet = nCredit - nDebit; + CAmount nCredit = wtx.GetCredit(ISMINE_ALL); + CAmount nDebit = wtx.GetDebit(ISMINE_ALL); + CAmount nNet = nCredit - nDebit; strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx); int nRequests = wtx.GetRequestCount(); @@ -132,7 +132,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // // Coinbase // - int64_t nUnmatured = 0; + CAmount nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) nUnmatured += wallet->GetCredit(txout, ISMINE_ALL); strHTML += "<b>" + tr("Credit") + ":</b> "; @@ -206,13 +206,13 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (fAllToMe) { // Payment to self - int64_t nChange = wtx.GetChange(); - int64_t nValue = nCredit - nChange; + CAmount nChange = wtx.GetChange(); + CAmount nValue = nCredit - nChange; strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>"; strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>"; } - int64_t nTxFee = nDebit - wtx.GetValueOut(); + CAmount nTxFee = nDebit - wtx.GetValueOut(); if (nTxFee > 0) strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>"; } diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index 6ab029173b..2a0f621d1e 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -78,7 +78,7 @@ void TransactionFilterProxy::setTypeFilter(quint32 modes) invalidateFilter(); } -void TransactionFilterProxy::setMinAmount(qint64 minimum) +void TransactionFilterProxy::setMinAmount(const CAmount& minimum) { this->minAmount = minimum; invalidateFilter(); diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h index f408317b53..ca31ee8f87 100644 --- a/src/qt/transactionfilterproxy.h +++ b/src/qt/transactionfilterproxy.h @@ -5,6 +5,8 @@ #ifndef TRANSACTIONFILTERPROXY_H #define TRANSACTIONFILTERPROXY_H +#include "amount.h" + #include <QDateTime> #include <QSortFilterProxyModel> @@ -38,7 +40,7 @@ public: @note Type filter takes a bit field created with TYPE() or ALL_TYPES */ void setTypeFilter(quint32 modes); - void setMinAmount(qint64 minimum); + void setMinAmount(const CAmount& minimum); void setWatchOnlyFilter(WatchOnlyFilter filter); /** Set maximum number of rows returned, -1 if unlimited. */ @@ -58,7 +60,7 @@ private: QString addrPrefix; quint32 typeFilter; WatchOnlyFilter watchOnlyFilter; - qint64 minAmount; + CAmount minAmount; int limitRows; bool showInactive; }; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 20c1449c92..afb343f349 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -32,9 +32,9 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * { QList<TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(true); - int64_t nDebit = wtx.GetDebit(ISMINE_ALL); - int64_t nNet = nCredit - nDebit; + CAmount nCredit = wtx.GetCredit(true); + CAmount nDebit = wtx.GetDebit(ISMINE_ALL); + CAmount nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map<std::string, std::string> mapValue = wtx.mapValue; @@ -97,7 +97,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * if (fAllFromMe && fAllToMe) { // Payment to self - int64_t nChange = wtx.GetChange(); + CAmount nChange = wtx.GetChange(); parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange)); @@ -108,7 +108,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * // // Debit // - int64_t nTxFee = nDebit - wtx.GetValueOut(); + CAmount nTxFee = nDebit - wtx.GetValueOut(); for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { @@ -138,7 +138,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * sub.address = mapValue["to"]; } - int64_t nValue = txout.nValue; + CAmount nValue = txout.nValue; /* Add fee to first output */ if (nTxFee > 0) { diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 626b7654c6..9276c9f0af 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -5,6 +5,7 @@ #ifndef TRANSACTIONRECORD_H #define TRANSACTIONRECORD_H +#include "amount.h" #include "uint256.h" #include <QList> @@ -94,7 +95,7 @@ public: TransactionRecord(uint256 hash, qint64 time, Type type, const std::string &address, - qint64 debit, qint64 credit): + const CAmount& debit, const CAmount& credit): hash(hash), time(time), type(type), address(address), debit(debit), credit(credit), idx(0) { @@ -111,8 +112,8 @@ public: qint64 time; Type type; std::string address; - qint64 debit; - qint64 credit; + CAmount debit; + CAmount credit; /**@}*/ /** Subtransaction index, for sort key */ diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 2b869b4ea5..e34d776818 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -546,7 +546,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const case ToAddress: return formatTxToAddress(rec, true); case Amount: - return rec->credit + rec->debit; + return qint64(rec->credit + rec->debit); } break; case Qt::ToolTipRole: @@ -583,7 +583,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const case LabelRole: return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address)); case AmountRole: - return rec->credit + rec->debit; + return qint64(rec->credit + rec->debit); case TxIDRole: return rec->getTxID(); case TxHashRole: diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index a7ba100cd2..d153973872 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -304,7 +304,7 @@ void TransactionView::changedAmount(const QString &amount) { if(!transactionProxyModel) return; - qint64 amount_parsed = 0; + CAmount amount_parsed = 0; if(BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amount, &amount_parsed)) { transactionProxyModel->setMinAmount(amount_parsed); diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 7df9d1bc2d..84f88dff5a 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -15,6 +15,7 @@ #include <stdio.h> +#include <QCloseEvent> #include <QLabel> #include <QRegExp> #include <QVBoxLayout> @@ -106,18 +107,26 @@ void HelpMessageDialog::on_okButton_accepted() /** "Shutdown" window */ +ShutdownWindow::ShutdownWindow(QWidget *parent, Qt::WindowFlags f): + QWidget(parent, f) +{ + QVBoxLayout *layout = new QVBoxLayout(); + layout->addWidget(new QLabel( + tr("Bitcoin Core is shutting down...") + "<br /><br />" + + tr("Do not shut down the computer until this window disappears."))); + setLayout(layout); +} + void ShutdownWindow::showShutdownWindow(BitcoinGUI *window) { if (!window) return; // Show a simple window indicating shutdown status - QWidget *shutdownWindow = new QWidget(); - QVBoxLayout *layout = new QVBoxLayout(); - layout->addWidget(new QLabel( - tr("Bitcoin Core is shutting down...") + "<br /><br />" + - tr("Do not shut down the computer until this window disappears."))); - shutdownWindow->setLayout(layout); + QWidget *shutdownWindow = new ShutdownWindow(); + // We don't hold a direct pointer to the shutdown window after creation, so use + // Qt::WA_DeleteOnClose to make sure that the window will be deleted eventually. + shutdownWindow->setAttribute(Qt::WA_DeleteOnClose); shutdownWindow->setWindowTitle(window->windowTitle()); // Center shutdown window at where main window was @@ -125,3 +134,8 @@ void ShutdownWindow::showShutdownWindow(BitcoinGUI *window) shutdownWindow->move(global.x() - shutdownWindow->width() / 2, global.y() - shutdownWindow->height() / 2); shutdownWindow->show(); } + +void ShutdownWindow::closeEvent(QCloseEvent *event) +{ + event->ignore(); +} diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h index 154bb70b8b..ae5045cca9 100644 --- a/src/qt/utilitydialog.h +++ b/src/qt/utilitydialog.h @@ -37,12 +37,16 @@ private slots: /** "Shutdown" window */ -class ShutdownWindow : public QObject +class ShutdownWindow : public QWidget { Q_OBJECT public: + ShutdownWindow(QWidget *parent=0, Qt::WindowFlags f=0); static void showShutdownWindow(BitcoinGUI *window); + +protected: + void closeEvent(QCloseEvent *event); }; #endif // UTILITYDIALOG_H diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ed90914ba7..b8701a23a6 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -55,11 +55,11 @@ WalletModel::~WalletModel() unsubscribeFromCoreSignals(); } -qint64 WalletModel::getBalance(const CCoinControl *coinControl) const +CAmount WalletModel::getBalance(const CCoinControl *coinControl) const { if (coinControl) { - qint64 nBalance = 0; + CAmount nBalance = 0; std::vector<COutput> vCoins; wallet->AvailableCoins(vCoins, true, coinControl); BOOST_FOREACH(const COutput& out, vCoins) @@ -72,12 +72,12 @@ qint64 WalletModel::getBalance(const CCoinControl *coinControl) const return wallet->GetBalance(); } -qint64 WalletModel::getUnconfirmedBalance() const +CAmount WalletModel::getUnconfirmedBalance() const { return wallet->GetUnconfirmedBalance(); } -qint64 WalletModel::getImmatureBalance() const +CAmount WalletModel::getImmatureBalance() const { return wallet->GetImmatureBalance(); } @@ -87,17 +87,17 @@ bool WalletModel::haveWatchOnly() const return fHaveWatchOnly; } -qint64 WalletModel::getWatchBalance() const +CAmount WalletModel::getWatchBalance() const { return wallet->GetWatchOnlyBalance(); } -qint64 WalletModel::getWatchUnconfirmedBalance() const +CAmount WalletModel::getWatchUnconfirmedBalance() const { return wallet->GetUnconfirmedWatchOnlyBalance(); } -qint64 WalletModel::getWatchImmatureBalance() const +CAmount WalletModel::getWatchImmatureBalance() const { return wallet->GetImmatureWatchOnlyBalance(); } @@ -137,12 +137,12 @@ void WalletModel::pollBalanceChanged() void WalletModel::checkBalanceChanged() { - qint64 newBalance = getBalance(); - qint64 newUnconfirmedBalance = getUnconfirmedBalance(); - qint64 newImmatureBalance = getImmatureBalance(); - qint64 newWatchOnlyBalance = 0; - qint64 newWatchUnconfBalance = 0; - qint64 newWatchImmatureBalance = 0; + CAmount newBalance = getBalance(); + CAmount newUnconfirmedBalance = getUnconfirmedBalance(); + CAmount newImmatureBalance = getImmatureBalance(); + CAmount newWatchOnlyBalance = 0; + CAmount newWatchUnconfBalance = 0; + CAmount newWatchImmatureBalance = 0; if (haveWatchOnly()) { newWatchOnlyBalance = getWatchBalance(); @@ -194,9 +194,9 @@ bool WalletModel::validateAddress(const QString &address) WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl) { - qint64 total = 0; + CAmount total = 0; QList<SendCoinsRecipient> recipients = transaction.getRecipients(); - std::vector<std::pair<CScript, int64_t> > vecSend; + std::vector<std::pair<CScript, CAmount> > vecSend; if(recipients.empty()) { @@ -211,7 +211,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact { if (rcp.paymentRequest.IsInitialized()) { // PaymentRequest... - int64_t subtotal = 0; + CAmount subtotal = 0; const payments::PaymentDetails& details = rcp.paymentRequest.getDetails(); for (int i = 0; i < details.outputs_size(); i++) { @@ -220,7 +220,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact subtotal += out.amount(); const unsigned char* scriptStr = (const unsigned char*)out.script().data(); CScript scriptPubKey(scriptStr, scriptStr+out.script().size()); - vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, out.amount())); + vecSend.push_back(std::pair<CScript, CAmount>(scriptPubKey, out.amount())); } if (subtotal <= 0) { @@ -242,7 +242,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact ++nAddresses; CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); - vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, rcp.amount)); + vecSend.push_back(std::pair<CScript, CAmount>(scriptPubKey, rcp.amount)); total += rcp.amount; } @@ -252,7 +252,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact return DuplicateAddress; } - qint64 nBalance = getBalance(coinControl); + CAmount nBalance = getBalance(coinControl); if(total > nBalance) { @@ -263,7 +263,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact LOCK2(cs_main, wallet->cs_wallet); transaction.newPossibleKeyChange(wallet); - int64_t nFeeRequired = 0; + CAmount nFeeRequired = 0; std::string strFailReason; CWalletTx *newTx = transaction.getTransaction(); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 111ae2178c..b1d0f28f12 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -37,7 +37,7 @@ class SendCoinsRecipient { public: explicit SendCoinsRecipient() : amount(0), nVersion(SendCoinsRecipient::CURRENT_VERSION) { } - explicit SendCoinsRecipient(const QString &addr, const QString &label, quint64 amount, const QString &message): + explicit SendCoinsRecipient(const QString &addr, const QString &label, const CAmount& amount, const QString &message): address(addr), label(label), amount(amount), message(message), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} // If from an insecure payment request, this is used for storing @@ -47,7 +47,7 @@ public: // Todo: This is a hack, should be replaced with a cleaner solution! QString address; QString label; - qint64 amount; + CAmount amount; // If from a payment request, this is used for storing the memo QString message; @@ -125,13 +125,13 @@ public: TransactionTableModel *getTransactionTableModel(); RecentRequestsTableModel *getRecentRequestsTableModel(); - qint64 getBalance(const CCoinControl *coinControl = NULL) const; - qint64 getUnconfirmedBalance() const; - qint64 getImmatureBalance() const; + CAmount getBalance(const CCoinControl *coinControl = NULL) const; + CAmount getUnconfirmedBalance() const; + CAmount getImmatureBalance() const; bool haveWatchOnly() const; - qint64 getWatchBalance() const; - qint64 getWatchUnconfirmedBalance() const; - qint64 getWatchImmatureBalance() const; + CAmount getWatchBalance() const; + CAmount getWatchUnconfirmedBalance() const; + CAmount getWatchImmatureBalance() const; EncryptionStatus getEncryptionStatus() const; bool processingQueuedTransactions() { return fProcessingQueuedTransactions; } @@ -210,12 +210,12 @@ private: RecentRequestsTableModel *recentRequestsTableModel; // Cache some values to be able to detect changes - qint64 cachedBalance; - qint64 cachedUnconfirmedBalance; - qint64 cachedImmatureBalance; - qint64 cachedWatchOnlyBalance; - qint64 cachedWatchUnconfBalance; - qint64 cachedWatchImmatureBalance; + CAmount cachedBalance; + CAmount cachedUnconfirmedBalance; + CAmount cachedImmatureBalance; + CAmount cachedWatchOnlyBalance; + CAmount cachedWatchUnconfBalance; + CAmount cachedWatchImmatureBalance; EncryptionStatus cachedEncryptionStatus; int cachedNumBlocks; @@ -227,8 +227,8 @@ private: signals: // Signal that balance in wallet changed - void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, - qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); + void balanceChanged(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, + const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); // Encryption status of wallet changed void encryptionStatusChanged(int status); diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 943f13e208..ddd2d09bb5 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -31,19 +31,19 @@ CWalletTx *WalletModelTransaction::getTransaction() return walletTransaction; } -qint64 WalletModelTransaction::getTransactionFee() +CAmount WalletModelTransaction::getTransactionFee() { return fee; } -void WalletModelTransaction::setTransactionFee(qint64 newFee) +void WalletModelTransaction::setTransactionFee(const CAmount& newFee) { fee = newFee; } -qint64 WalletModelTransaction::getTotalTransactionAmount() +CAmount WalletModelTransaction::getTotalTransactionAmount() { - qint64 totalTransactionAmount = 0; + CAmount totalTransactionAmount = 0; foreach(const SendCoinsRecipient &rcp, recipients) { totalTransactionAmount += rcp.amount; diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h index b7e85bcd11..4eadfbe4d1 100644 --- a/src/qt/walletmodeltransaction.h +++ b/src/qt/walletmodeltransaction.h @@ -26,10 +26,10 @@ public: CWalletTx *getTransaction(); - void setTransactionFee(qint64 newFee); - qint64 getTransactionFee(); + void setTransactionFee(const CAmount& newFee); + CAmount getTransactionFee(); - qint64 getTotalTransactionAmount(); + CAmount getTotalTransactionAmount(); void newPossibleKeyChange(CWallet *wallet); CReserveKey *getPossibleKeyChange(); @@ -38,7 +38,7 @@ private: const QList<SendCoinsRecipient> recipients; CWalletTx *walletTransaction; CReserveKey *keyChange; - qint64 fee; + CAmount fee; }; #endif // WALLETMODELTRANSACTION_H diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index b40ddc0a2f..eff50593bd 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -92,7 +92,7 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui) connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int))); // Pass through transaction notifications - connect(this, SIGNAL(incomingTransaction(QString,int,qint64,QString,QString)), gui, SLOT(incomingTransaction(QString,int,qint64,QString,QString))); + connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString))); } } diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 9cfa8d6760..cafba517fd 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -5,6 +5,8 @@ #ifndef WALLETVIEW_H #define WALLETVIEW_H +#include "amount.h" + #include <QStackedWidget> class BitcoinGUI; @@ -111,7 +113,7 @@ signals: /** Encryption status of wallet changed */ void encryptionStatusChanged(int status); /** Notify that a new transaction appeared */ - void incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address); + void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address); }; #endif // WALLETVIEW_H diff --git a/src/random.cpp b/src/random.cpp index fb5258a442..998e7dfb08 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -8,8 +8,8 @@ #ifdef WIN32 #include "compat.h" // for Windows API #endif -#include "serialize.h" // for begin_ptr(vec) -#include "util.h" // for LogPrint() +#include "serialize.h" // for begin_ptr(vec) +#include "util.h" // for LogPrint() #include "utilstrencodings.h" // for GetTime() #include <limits> @@ -56,28 +56,25 @@ void RandAddSeedPerfmon() #ifdef WIN32 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom // Seed with the entire set of perfmon data - std::vector <unsigned char> vData(250000,0); + std::vector<unsigned char> vData(250000, 0); long ret = 0; unsigned long nSize = 0; const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data - while (true) - { + while (true) { nSize = vData.size(); ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize); if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize) break; - vData.resize(std::max((vData.size()*3)/2, nMaxSize)); // Grow size of buffer exponentially + vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially } RegCloseKey(HKEY_PERFORMANCE_DATA); - if (ret == ERROR_SUCCESS) - { - RAND_add(begin_ptr(vData), nSize, nSize/100.0); + if (ret == ERROR_SUCCESS) { + RAND_add(begin_ptr(vData), nSize, nSize / 100.0); OPENSSL_cleanse(begin_ptr(vData), nSize); LogPrint("rand", "%s: %lu bytes\n", __func__, nSize); } else { static bool warned = false; // Warn only once - if (!warned) - { + if (!warned) { LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret); warned = true; } @@ -85,7 +82,7 @@ void RandAddSeedPerfmon() #endif } -bool GetRandBytes(unsigned char *buf, int num) +bool GetRandBytes(unsigned char* buf, int num) { if (RAND_bytes(buf, num) != 1) { LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL)); @@ -126,18 +123,17 @@ 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) - { + if (fDeterministic) { insecure_rand_Rz = insecure_rand_Rw = 11; } else { uint32_t tmp; do { GetRandBytes((unsigned char*)&tmp, 4); - } while(tmp == 0 || tmp == 0x9068ffffU); + } while (tmp == 0 || tmp == 0x9068ffffU); insecure_rand_Rz = tmp; do { GetRandBytes((unsigned char*)&tmp, 4); - } while(tmp == 0 || tmp == 0x464fffffU); + } while (tmp == 0 || tmp == 0x464fffffU); insecure_rand_Rw = tmp; } } diff --git a/src/random.h b/src/random.h index a599b08478..161ebe8986 100644 --- a/src/random.h +++ b/src/random.h @@ -19,7 +19,7 @@ void RandAddSeedPerfmon(); /** * Functions to gather random data via the OpenSSL PRNG */ -bool GetRandBytes(unsigned char *buf, int num); +bool GetRandBytes(unsigned char* buf, int num); uint64_t GetRand(uint64_t nMax); int GetRandInt(int nMax); uint256 GetRandHash(); diff --git a/src/rpcclient.h b/src/rpcclient.h index 1233ea3875..307aa2aab8 100644 --- a/src/rpcclient.h +++ b/src/rpcclient.h @@ -10,6 +10,6 @@ #include "json/json_spirit_utils.h" #include "json/json_spirit_writer_template.h" -json_spirit::Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams); +json_spirit::Array RPCConvertValues(const std::string& strMethod, const std::vector<std::string>& strParams); #endif // _BITCOINRPC_CLIENT_H_ diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 82eaf5d037..e794bf69e0 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -273,7 +273,7 @@ Value prioritisetransaction(const Array& params, bool fHelp) uint256 hash; hash.SetHex(params[0].get_str()); - int64_t nAmount = 0; + CAmount nAmount = 0; if (params[2].get_real() != 0.0) nAmount = AmountFromValue(params[2]); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 95f42eb47f..bc19d1372a 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -11,6 +11,7 @@ #include "sync.h" #include "timedata.h" #include "util.h" +#include "version.h" #include <boost/foreach.hpp> @@ -367,23 +368,29 @@ Value getnetworkinfo(const Array& params, bool fHelp) "Returns an object containing various state info regarding P2P networking.\n" "\nResult:\n" "{\n" - " \"version\": xxxxx, (numeric) the server version\n" - " \"protocolversion\": xxxxx, (numeric) the protocol version\n" - " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n" - " \"timeoffset\": xxxxx, (numeric) the time offset\n" - " \"connections\": xxxxx, (numeric) the number of connections\n" - " \"networks\": [ (array) information per network\n" - " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n" - " \"limited\": xxx, (boolean) is the network limited using -onlynet?\n" - " \"reachable\": xxx, (boolean) is the network reachable?\n" - " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n" - " },\n" + " \"version\": xxxxx, (numeric) the server version\n" + " \"subversion\": \"/Satoshi:x.x.x/\", (string) the server subversion string\n" + " \"protocolversion\": xxxxx, (numeric) the protocol version\n" + " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n" + " \"timeoffset\": xxxxx, (numeric) the time offset\n" + " \"connections\": xxxxx, (numeric) the number of connections\n" + " \"networks\": [ (array) information per network\n" + " {\n" + " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n" + " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n" + " \"reachable\": true|false, (boolean) is the network reachable?\n" + " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n" + " }\n" + " ,...\n" " ],\n" - " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n" - " \"localaddresses\": [, (array) list of local addresses\n" - " \"address\": \"xxxx\", (string) network address\n" - " \"port\": xxx, (numeric) network port\n" - " \"score\": xxx (numeric) relative score\n" + " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n" + " \"localaddresses\": [ (array) list of local addresses\n" + " {\n" + " \"address\": \"xxxx\", (string) network address\n" + " \"port\": xxx, (numeric) network port\n" + " \"score\": xxx (numeric) relative score\n" + " }\n" + " ,...\n" " ]\n" "}\n" "\nExamples:\n" @@ -392,8 +399,10 @@ Value getnetworkinfo(const Array& params, bool fHelp) ); Object obj; - obj.push_back(Pair("version", (int)CLIENT_VERSION)); - obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); + obj.push_back(Pair("version", CLIENT_VERSION)); + obj.push_back(Pair("subversion", + FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()))); + obj.push_back(Pair("protocolversion",PROTOCOL_VERSION)); obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index dbb0966ae2..e50a278bc8 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -269,7 +269,7 @@ Value listunspent(const Array& params, bool fHelp) continue; } - int64_t nValue = out.tx->vout[out.i].nValue; + CAmount nValue = out.tx->vout[out.i].nValue; const CScript& pk = out.tx->vout[out.i].scriptPubKey; Object entry; entry.push_back(Pair("txid", out.tx->GetHash().GetHex())); @@ -367,7 +367,7 @@ Value createrawtransaction(const Array& params, bool fHelp) setAddress.insert(address); CScript scriptPubKey = GetScriptForDestination(address.Get()); - int64_t nAmount = AmountFromValue(s.value_); + CAmount nAmount = AmountFromValue(s.value_); CTxOut out(nAmount, scriptPubKey); rawTx.vout.push_back(out); @@ -687,7 +687,7 @@ Value signrawtransaction(const Array& params, bool fHelp) BOOST_FOREACH(const CMutableTransaction& txv, txVariants) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); } - if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STANDARD_SCRIPT_VERIFY_FLAGS)) + if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, SignatureChecker(mergedTx, i))) fComplete = false; } diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 190de62282..1a41344da5 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -88,18 +88,18 @@ static inline int64_t roundint64(double d) return (int64_t)(d > 0 ? d + 0.5 : d - 0.5); } -int64_t AmountFromValue(const Value& value) +CAmount AmountFromValue(const Value& value) { double dAmount = value.get_real(); if (dAmount <= 0.0 || dAmount > 21000000.0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); - int64_t nAmount = roundint64(dAmount * COIN); + CAmount nAmount = roundint64(dAmount * COIN); if (!MoneyRange(nAmount)) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); return nAmount; } -Value ValueFromAmount(int64_t amount) +Value ValueFromAmount(const CAmount& amount) { return (double)amount / (double)COIN; } diff --git a/src/rpcserver.h b/src/rpcserver.h index 820c1bc081..d440035f15 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -6,6 +6,7 @@ #ifndef _BITCOINRPC_SERVER_H_ #define _BITCOINRPC_SERVER_H_ +#include "amount.h" #include "uint256.h" #include "rpcprotocol.h" @@ -116,8 +117,8 @@ extern void InitRPCMining(); extern void ShutdownRPCMining(); extern int64_t nWalletUnlockTime; -extern int64_t AmountFromValue(const json_spirit::Value& value); -extern json_spirit::Value ValueFromAmount(int64_t amount); +extern CAmount AmountFromValue(const json_spirit::Value& value); +extern json_spirit::Value ValueFromAmount(const CAmount& amount); extern double GetDifficulty(const CBlockIndex* blockindex = NULL); extern std::string HelpRequiringPassphrase(); extern std::string HelpExampleCli(std::string methodname, std::string args); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 35637362a4..d7c0c0ef5c 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -230,15 +230,20 @@ Value setaccount(const Array& params, bool fHelp) if (params.size() > 1) strAccount = AccountFromValue(params[1]); - // Detect when changing the account of an address that is the 'unused current key' of another account: - if (pwalletMain->mapAddressBook.count(address.Get())) + // Only add the account if the address is yours. + if (IsMine(*pwalletMain, address.Get())) { - string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name; - if (address == GetAccountAddress(strOldAccount)) - GetAccountAddress(strOldAccount, true); + // Detect when changing the account of an address that is the 'unused current key' of another account: + if (pwalletMain->mapAddressBook.count(address.Get())) + { + string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name; + if (address == GetAccountAddress(strOldAccount)) + GetAccountAddress(strOldAccount, true); + } + pwalletMain->SetAddressBook(address.Get(), strAccount, "receive"); } - - pwalletMain->SetAddressBook(address.Get(), strAccount, "receive"); + else + throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address"); return Value::null; } @@ -331,7 +336,7 @@ Value sendtoaddress(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); // Amount - int64_t nAmount = AmountFromValue(params[1]); + CAmount nAmount = AmountFromValue(params[1]); // Wallet comments CWalletTx wtx; @@ -375,7 +380,7 @@ Value listaddressgroupings(const Array& params, bool fHelp) ); Array jsonGroupings; - map<CTxDestination, int64_t> balances = pwalletMain->GetAddressBalances(); + map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances(); BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings()) { Array jsonGrouping; @@ -483,7 +488,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) nMinDepth = params[1].get_int(); // Tally - int64_t nAmount = 0; + CAmount nAmount = 0; for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; @@ -532,7 +537,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount); // Tally - int64_t nAmount = 0; + CAmount nAmount = 0; for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; @@ -552,9 +557,9 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) } -int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter) +CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter) { - int64_t nBalance = 0; + CAmount nBalance = 0; // Tally wallet transactions for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) @@ -563,7 +568,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) continue; - int64_t nReceived, nSent, nFee; + CAmount nReceived, nSent, nFee; wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) @@ -577,7 +582,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi return nBalance; } -int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter) +CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter) { CWalletDB walletdb(pwalletMain->strWalletFile); return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); @@ -627,14 +632,14 @@ Value getbalance(const Array& params, bool fHelp) // Calculate total balance a different way from GetBalance() // (GetBalance() sums up all unspent TxOuts) // getbalance and getbalance '*' 0 should return the same number - int64_t nBalance = 0; + CAmount nBalance = 0; for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0) continue; - int64_t allFee; + CAmount allFee; string strSentAccount; list<COutputEntry> listReceived; list<COutputEntry> listSent; @@ -653,7 +658,7 @@ Value getbalance(const Array& params, bool fHelp) string strAccount = AccountFromValue(params[0]); - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, filter); + CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter); return ValueFromAmount(nBalance); } @@ -692,7 +697,7 @@ Value movecmd(const Array& params, bool fHelp) string strFrom = AccountFromValue(params[0]); string strTo = AccountFromValue(params[1]); - int64_t nAmount = AmountFromValue(params[2]); + CAmount nAmount = AmountFromValue(params[2]); if (params.size() > 3) // unused parameter, used to be nMinDepth, keep type-checking it though (void)params[3].get_int(); @@ -766,7 +771,7 @@ Value sendfrom(const Array& params, bool fHelp) CBitcoinAddress address(params[1].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - int64_t nAmount = AmountFromValue(params[2]); + CAmount nAmount = AmountFromValue(params[2]); int nMinDepth = 1; if (params.size() > 3) nMinDepth = params[3].get_int(); @@ -781,7 +786,7 @@ Value sendfrom(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); + CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -834,9 +839,9 @@ Value sendmany(const Array& params, bool fHelp) wtx.mapValue["comment"] = params[3].get_str(); set<CBitcoinAddress> setAddress; - vector<pair<CScript, int64_t> > vecSend; + vector<pair<CScript, CAmount> > vecSend; - int64_t totalAmount = 0; + CAmount totalAmount = 0; BOOST_FOREACH(const Pair& s, sendTo) { CBitcoinAddress address(s.name_); @@ -848,7 +853,7 @@ Value sendmany(const Array& params, bool fHelp) setAddress.insert(address); CScript scriptPubKey = GetScriptForDestination(address.Get()); - int64_t nAmount = AmountFromValue(s.value_); + CAmount nAmount = AmountFromValue(s.value_); totalAmount += nAmount; vecSend.push_back(make_pair(scriptPubKey, nAmount)); @@ -857,13 +862,13 @@ Value sendmany(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); + CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (totalAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); // Send CReserveKey keyChange(pwalletMain); - int64_t nFeeRequired = 0; + CAmount nFeeRequired = 0; string strFailReason; bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason); if (!fCreated) @@ -923,7 +928,7 @@ Value addmultisigaddress(const Array& params, bool fHelp) struct tallyitem { - int64_t nAmount; + CAmount nAmount; int nConf; vector<uint256> txids; bool fIsWatchonly; @@ -995,7 +1000,7 @@ Value ListReceived(const Array& params, bool fByAccounts) if (it == mapTally.end() && !fIncludeEmpty) continue; - int64_t nAmount = 0; + CAmount nAmount = 0; int nConf = std::numeric_limits<int>::max(); bool fIsWatchonly = false; if (it != mapTally.end()) @@ -1038,7 +1043,7 @@ Value ListReceived(const Array& params, bool fByAccounts) { for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it) { - int64_t nAmount = (*it).second.nAmount; + CAmount nAmount = (*it).second.nAmount; int nConf = (*it).second.nConf; Object obj; if((*it).second.fIsWatchonly) @@ -1125,7 +1130,7 @@ static void MaybePushAddress(Object & entry, const CTxDestination &dest) void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter) { - int64_t nFee; + CAmount nFee; string strSentAccount; list<COutputEntry> listReceived; list<COutputEntry> listSent; @@ -1355,7 +1360,7 @@ Value listaccounts(const Array& params, bool fHelp) if(params[1].get_bool()) includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY; - map<string, int64_t> mapAccountBalances; + map<string, CAmount> mapAccountBalances; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) { if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me mapAccountBalances[entry.second.name] = 0; @@ -1364,7 +1369,7 @@ Value listaccounts(const Array& params, bool fHelp) for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - int64_t nFee; + CAmount nFee; string strSentAccount; list<COutputEntry> listReceived; list<COutputEntry> listSent; @@ -1391,7 +1396,7 @@ Value listaccounts(const Array& params, bool fHelp) mapAccountBalances[entry.strAccount] += entry.nCreditDebit; Object ret; - BOOST_FOREACH(const PAIRTYPE(string, int64_t)& accountBalance, mapAccountBalances) { + BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) { ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second))); } return ret; @@ -1534,10 +1539,10 @@ Value gettransaction(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); const CWalletTx& wtx = pwalletMain->mapWallet[hash]; - int64_t nCredit = wtx.GetCredit(filter != 0); - int64_t nDebit = wtx.GetDebit(filter); - int64_t nNet = nCredit - nDebit; - int64_t nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0); + CAmount nCredit = wtx.GetCredit(filter != 0); + CAmount nDebit = wtx.GetDebit(filter); + CAmount nNet = nCredit - nDebit; + CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0); entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); if (wtx.IsFromMe(filter)) @@ -1937,7 +1942,7 @@ Value settxfee(const Array& params, bool fHelp) ); // Amount - int64_t nAmount = 0; + CAmount nAmount = 0; if (params[0].get_real() != 0.0) nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index fd3e4f1ff7..56140f19db 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -9,14 +9,10 @@ #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha2.h" -#include "random.h" #include "script/script.h" #include "uint256.h" #include "util.h" -#include <boost/thread.hpp> -#include <boost/tuple/tuple_comparison.hpp> - using namespace std; typedef vector<unsigned char> valtype; @@ -132,7 +128,7 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { return true; } -bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags) +bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker) { CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); @@ -637,19 +633,19 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co valtype& vch = stacktop(-1); valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32); if (opcode == OP_RIPEMD160) - CRIPEMD160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CRIPEMD160().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_SHA1) - CSHA1().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CSHA1().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_SHA256) - CSHA256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CSHA256().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_HASH160) - CHash160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CHash160().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_HASH256) - CHash256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CHash256().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); popstack(stack); stack.push_back(vchHash); } - break; + break; case OP_CODESEPARATOR: { @@ -675,7 +671,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co scriptCode.FindAndDelete(CScript(vchSig)); bool fSuccess = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && - CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, flags); + checker.CheckSig(vchSig, vchPubKey, scriptCode); popstack(stack); popstack(stack); @@ -736,7 +732,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co // Check signature bool fOk = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && - CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, flags); + checker.CheckSig(vchSig, vchPubKey, scriptCode); if (fOk) { isig++; @@ -839,7 +835,8 @@ public: itBegin = it; } } - s.write((char*)&itBegin[0], it-itBegin); + if (itBegin != scriptCode.end()) + s.write((char*)&itBegin[0], it-itBegin); } /** Serialize an input of txTo */ @@ -896,7 +893,7 @@ public: } // anon namespace -uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) +uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) { if (nIn >= txTo.vin.size()) { LogPrintf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn); @@ -920,70 +917,19 @@ uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsig return ss.GetHash(); } -// Valid signature cache, to avoid doing expensive ECDSA signature checking -// twice for every transaction (once when accepted into memory pool, and -// again when accepted into the block chain) -class CSignatureCache +bool SignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const { -private: - // sigdata_type is (signature hash, signature, public key): - typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type; - std::set< sigdata_type> setValid; - boost::shared_mutex cs_sigcache; - -public: - bool - Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) - { - boost::shared_lock<boost::shared_mutex> lock(cs_sigcache); - - sigdata_type k(hash, vchSig, pubKey); - std::set<sigdata_type>::iterator mi = setValid.find(k); - if (mi != setValid.end()) - return true; - return false; - } - - void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) - { - // DoS prevention: limit cache size to less than 10MB - // (~200 bytes per cache entry times 50,000 entries) - // Since there are a maximum of 20,000 signature operations per block - // 50,000 is a reasonable default. - int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000); - if (nMaxCacheSize <= 0) return; - - boost::unique_lock<boost::shared_mutex> lock(cs_sigcache); - - while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize) - { - // Evict a random entry. Random because that helps - // foil would-be DoS attackers who might try to pre-generate - // and re-use a set of valid signatures just-slightly-greater - // than our cache size. - uint256 randomHash = GetRandHash(); - std::vector<unsigned char> unused; - std::set<sigdata_type>::iterator it = - setValid.lower_bound(sigdata_type(randomHash, unused, unused)); - if (it == setValid.end()) - it = setValid.begin(); - setValid.erase(*it); - } - - sigdata_type k(hash, vchSig, pubKey); - setValid.insert(k); - } -}; + return pubkey.Verify(sighash, vchSig); +} -bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int flags) +bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const { - static CSignatureCache signatureCache; - CPubKey pubkey(vchPubKey); if (!pubkey.IsValid()) return false; // Hash type is one byte tacked on to the end of the signature + vector<unsigned char> vchSig(vchSigIn); if (vchSig.empty()) return false; int nHashType = vchSig.back(); @@ -991,26 +937,20 @@ bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char>& vchPubK uint256 sighash = SignatureHash(scriptCode, txTo, nIn, nHashType); - if (signatureCache.Get(sighash, vchSig, pubkey)) - return true; - - if (!pubkey.Verify(sighash, vchSig)) + if (!VerifySignature(vchSig, pubkey, sighash)) return false; - if (!(flags & SCRIPT_VERIFY_NOCACHE)) - signatureCache.Set(sighash, vchSig, pubkey); - return true; } -bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags) +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker) { vector<vector<unsigned char> > stack, stackCopy; - if (!EvalScript(stack, scriptSig, txTo, nIn, flags)) + if (!EvalScript(stack, scriptSig, flags, checker)) return false; if (flags & SCRIPT_VERIFY_P2SH) stackCopy = stack; - if (!EvalScript(stack, scriptPubKey, txTo, nIn, flags)) + if (!EvalScript(stack, scriptPubKey, flags, checker)) return false; if (stack.empty()) return false; @@ -1033,7 +973,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); popstack(stackCopy); - if (!EvalScript(stackCopy, pubKey2, txTo, nIn, flags)) + if (!EvalScript(stackCopy, pubKey2, flags, checker)) return false; if (stackCopy.empty()) return false; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index adca2142ac..0ff73964ba 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -10,6 +10,7 @@ #include <stdint.h> #include <string> +class CPubKey; class CScript; class CTransaction; class uint256; @@ -30,16 +31,40 @@ enum SCRIPT_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts SCRIPT_VERIFY_STRICTENC = (1U << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys SCRIPT_VERIFY_LOW_S = (1U << 2), // enforce low S values (<n/2) in signatures (depends on STRICTENC) - SCRIPT_VERIFY_NOCACHE = (1U << 3), // do not store results in signature cache (but do query it) - SCRIPT_VERIFY_NULLDUMMY = (1U << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length + SCRIPT_VERIFY_NULLDUMMY = (1U << 3), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length }; bool IsCanonicalPubKey(const std::vector<unsigned char> &vchPubKey, unsigned int flags); bool IsCanonicalSignature(const std::vector<unsigned char> &vchSig, unsigned int flags); uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); -bool CheckSig(std::vector<unsigned char> vchSig, const std::vector<unsigned char> &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int flags); -bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags); -bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags); + +class BaseSignatureChecker +{ +public: + virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const + { + return false; + } + + virtual ~BaseSignatureChecker() {} +}; + +class SignatureChecker : public BaseSignatureChecker +{ +private: + const CTransaction& txTo; + unsigned int nIn; + +protected: + virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; + +public: + SignatureChecker(const CTransaction& txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {} + bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const; +}; + +bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker); +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker); #endif // H_BITCOIN_SCRIPT_INTERPRETER diff --git a/src/script/script.h b/src/script/script.h index 07a4229f85..caf176476f 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -304,7 +304,7 @@ private: // If the input vector's most significant byte is 0x80, remove it from // the result's msb and return a negative. if (vch.back() & 0x80) - return -(result & ~(0x80ULL << (8 * (vch.size() - 1)))); + return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1))))); return result; } @@ -340,9 +340,7 @@ public: CScript() { } CScript(const CScript& b) : std::vector<unsigned char>(b.begin(), b.end()) { } CScript(const_iterator pbegin, const_iterator pend) : std::vector<unsigned char>(pbegin, pend) { } -#ifndef _MSC_VER CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector<unsigned char>(pbegin, pend) { } -#endif CScript& operator+=(const CScript& b) { @@ -546,7 +544,7 @@ public: { while (end() - pc >= (long)b.size() && memcmp(&pc[0], &b[0], b.size()) == 0) { - erase(pc, pc + b.size()); + pc = erase(pc, pc + b.size()); ++nFound; } } diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp new file mode 100644 index 0000000000..ab366898d8 --- /dev/null +++ b/src/script/sigcache.cpp @@ -0,0 +1,88 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "sigcache.h" + +#include "key.h" +#include "random.h" +#include "uint256.h" +#include "util.h" + +#include <boost/thread.hpp> +#include <boost/tuple/tuple_comparison.hpp> + +namespace { + +// Valid signature cache, to avoid doing expensive ECDSA signature checking +// twice for every transaction (once when accepted into memory pool, and +// again when accepted into the block chain) +class CSignatureCache +{ +private: + // sigdata_type is (signature hash, signature, public key): + typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type; + std::set< sigdata_type> setValid; + boost::shared_mutex cs_sigcache; + +public: + bool + Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) + { + boost::shared_lock<boost::shared_mutex> lock(cs_sigcache); + + sigdata_type k(hash, vchSig, pubKey); + std::set<sigdata_type>::iterator mi = setValid.find(k); + if (mi != setValid.end()) + return true; + return false; + } + + void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) + { + // DoS prevention: limit cache size to less than 10MB + // (~200 bytes per cache entry times 50,000 entries) + // Since there are a maximum of 20,000 signature operations per block + // 50,000 is a reasonable default. + int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000); + if (nMaxCacheSize <= 0) return; + + boost::unique_lock<boost::shared_mutex> lock(cs_sigcache); + + while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize) + { + // Evict a random entry. Random because that helps + // foil would-be DoS attackers who might try to pre-generate + // and re-use a set of valid signatures just-slightly-greater + // than our cache size. + uint256 randomHash = GetRandHash(); + std::vector<unsigned char> unused; + std::set<sigdata_type>::iterator it = + setValid.lower_bound(sigdata_type(randomHash, unused, unused)); + if (it == setValid.end()) + it = setValid.begin(); + setValid.erase(*it); + } + + sigdata_type k(hash, vchSig, pubKey); + setValid.insert(k); + } +}; + +} + +bool CachingSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const +{ + static CSignatureCache signatureCache; + + if (signatureCache.Get(sighash, vchSig, pubkey)) + return true; + + if (!SignatureChecker::VerifySignature(vchSig, pubkey, sighash)) + return false; + + if (store) + signatureCache.Set(sighash, vchSig, pubkey); + return true; +} diff --git a/src/script/sigcache.h b/src/script/sigcache.h new file mode 100644 index 0000000000..46b8f4d335 --- /dev/null +++ b/src/script/sigcache.h @@ -0,0 +1,26 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef H_BITCOIN_SCRIPT_SIGCACHE +#define H_BITCOIN_SCRIPT_SIGCACHE + +#include "script/interpreter.h" + +#include <vector> + +class CPubKey; + +class CachingSignatureChecker : public SignatureChecker +{ +private: + bool store; + +public: + CachingSignatureChecker(const CTransaction& txToIn, unsigned int nInIn, bool storeIn=true) : SignatureChecker(txToIn, nInIn), store(storeIn) {} + + bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; +}; + +#endif // H_BITCOIN_SCRIPT_SIGCACHE diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 8abd8d221d..da77e7d1f1 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -123,7 +123,7 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutabl } // Test solution - return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS); + return VerifyScript(txin.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, SignatureChecker(txTo, nIn)); } bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType) @@ -174,7 +174,7 @@ static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& if (sigs.count(pubkey)) continue; // Already got a sig for this pubkey - if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0)) + if (SignatureChecker(txTo, nIn).CheckSig(sig, pubkey, scriptPubKey)) { sigs[pubkey] = sig; break; @@ -252,9 +252,9 @@ CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsign Solver(scriptPubKey, txType, vSolutions); vector<valtype> stack1; - EvalScript(stack1, scriptSig1, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC); + EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker()); vector<valtype> stack2; - EvalScript(stack2, scriptSig2, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC); + EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker()); return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2); } diff --git a/src/serialize.h b/src/serialize.h index 57f5fd069b..ff11edc06c 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -245,7 +245,7 @@ uint64_t ReadCompactSize(Stream& is) uint64_t xSize; READDATA(is, xSize); nSizeRet = xSize; - if (nSizeRet < 0x100000000LLu) + if (nSizeRet < 0x100000000ULL) throw std::ios_base::failure("non-canonical ReadCompactSize()"); } if (nSizeRet > (uint64_t)MAX_SIZE) @@ -921,7 +921,7 @@ public: Init(nTypeIn, nVersionIn); } - CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn, int nVersionIn) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0]) + CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) { Init(nTypeIn, nVersionIn); } @@ -1154,7 +1154,7 @@ public: -/** RAII wrapper for FILE*. +/** Non-refcounted RAII wrapper for FILE* * * Will automatically close the file when it goes out of scope if not null. * If you're returning the file pointer, return file.release(). @@ -1162,12 +1162,17 @@ public: */ class CAutoFile { -protected: - FILE* file; -public: +private: + // Disallow copies + CAutoFile(const CAutoFile&); + CAutoFile& operator=(const CAutoFile&); + int nType; int nVersion; + + FILE* file; +public: CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) { file = filenew; @@ -1182,9 +1187,10 @@ public: void fclose() { - if (file != NULL && file != stdin && file != stdout && file != stderr) + if (file) { ::fclose(file); - file = NULL; + file = NULL; + } } FILE* release() { FILE* ret = file; file = NULL; return ret; } @@ -1252,13 +1258,23 @@ public: } }; -/** Wrapper around a FILE* that implements a ring buffer to - * deserialize from. It guarantees the ability to rewind - * a given number of bytes. */ +/** Non-refcounted RAII wrapper around a FILE* that implements a ring buffer to + * deserialize from. It guarantees the ability to rewind a given number of bytes. + * + * Will automatically close the file when it goes out of scope if not null. + * If you need to close the file early, use file.fclose() instead of fclose(file). + */ class CBufferedFile { private: - FILE *src; // source file + // Disallow copies + CBufferedFile(const CBufferedFile&); + CBufferedFile& operator=(const CBufferedFile&); + + int nType; + int nVersion; + + FILE *src; // source file uint64_t nSrcPos; // how many bytes have been read from source uint64_t nReadPos; // how many bytes have been read from this uint64_t nReadLimit; // up to which position we're allowed to read @@ -1285,12 +1301,25 @@ protected: } public: - int nType; - int nVersion; - CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) : - src(fileIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0), - nType(nTypeIn), nVersion(nVersionIn) { + nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0) + { + src = fileIn; + nType = nTypeIn; + nVersion = nVersionIn; + } + + ~CBufferedFile() + { + fclose(); + } + + void fclose() + { + if (src) { + ::fclose(src); + src = NULL; + } } // check whether we're at the end of the source file diff --git a/src/sync.cpp b/src/sync.cpp index d424f7bc95..ef35c9d646 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -32,8 +32,7 @@ void PrintLockContention(const char* pszName, const char* pszFile, int nLine) // Complain if any thread tries to lock in a different order. // -struct CLockLocation -{ +struct CLockLocation { CLockLocation(const char* pszName, const char* pszFile, int nLine) { mutexName = pszName; @@ -43,7 +42,7 @@ struct CLockLocation std::string ToString() const { - return mutexName+" "+sourceFile+":"+itostr(sourceLine); + return mutexName + " " + sourceFile + ":" + itostr(sourceLine); } std::string MutexName() const { return mutexName; } @@ -54,7 +53,7 @@ private: int sourceLine; }; -typedef std::vector< std::pair<void*, CLockLocation> > LockStack; +typedef std::vector<std::pair<void*, CLockLocation> > LockStack; static boost::mutex dd_mutex; static std::map<std::pair<void*, void*>, LockStack> lockorders; @@ -65,17 +64,19 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, { LogPrintf("POTENTIAL DEADLOCK DETECTED\n"); LogPrintf("Previous lock order was:\n"); - BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2) - { - if (i.first == mismatch.first) LogPrintf(" (1)"); - if (i.first == mismatch.second) LogPrintf(" (2)"); + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s2) { + if (i.first == mismatch.first) + LogPrintf(" (1)"); + if (i.first == mismatch.second) + LogPrintf(" (2)"); LogPrintf(" %s\n", i.second.ToString()); } LogPrintf("Current lock order is:\n"); - BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1) - { - if (i.first == mismatch.first) LogPrintf(" (1)"); - if (i.first == mismatch.second) LogPrintf(" (2)"); + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s1) { + if (i.first == mismatch.first) + LogPrintf(" (1)"); + if (i.first == mismatch.second) + LogPrintf(" (2)"); LogPrintf(" %s\n", i.second.ToString()); } } @@ -91,8 +92,9 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) (*lockstack).push_back(std::make_pair(c, locklocation)); if (!fTry) { - BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack)) { - if (i.first == c) break; + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, (*lockstack)) { + if (i.first == c) + break; std::pair<void*, void*> p1 = std::make_pair(i.first, c); if (lockorders.count(p1)) @@ -100,8 +102,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) lockorders[p1] = (*lockstack); std::pair<void*, void*> p2 = std::make_pair(c, i.first); - if (lockorders.count(p2)) - { + if (lockorders.count(p2)) { potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); break; } @@ -112,8 +113,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) static void pop_lock() { - if (fDebug) - { + if (fDebug) { const CLockLocation& locklocation = (*lockstack).rbegin()->second; LogPrint("lock", "Unlocked: %s\n", locklocation.ToString()); } @@ -135,17 +135,17 @@ void LeaveCritical() std::string LocksHeld() { std::string result; - BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)&i, *lockstack) + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack) result += i.second.ToString() + std::string("\n"); return result; } -void AssertLockHeldInternal(const char *pszName, const char* pszFile, int nLine, void *cs) +void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) { - BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)&i, *lockstack) - if (i.first == cs) return; - fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", - pszName, pszFile, nLine, LocksHeld().c_str()); + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack) + if (i.first == cs) + return; + fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); abort(); } diff --git a/src/sync.h b/src/sync.h index 4b81b4bd32..cd0aa7b20e 100644 --- a/src/sync.h +++ b/src/sync.h @@ -48,7 +48,6 @@ LEAVE_CRITICAL_SECTION(mutex); // no RAII */ - /////////////////////////////// // // // THE ACTUAL IMPLEMENTATION // @@ -63,17 +62,17 @@ class LOCKABLE AnnotatedMixin : public PARENT public: void lock() EXCLUSIVE_LOCK_FUNCTION() { - PARENT::lock(); + PARENT::lock(); } void unlock() UNLOCK_FUNCTION() { - PARENT::unlock(); + PARENT::unlock(); } bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { - return PARENT::try_lock(); + return PARENT::try_lock(); } }; @@ -91,11 +90,13 @@ typedef boost::condition_variable CConditionVariable; void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false); void LeaveCritical(); std::string LocksHeld(); -void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void *cs); +void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs); #else -void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {} +void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) +{ +} void static inline LeaveCritical() {} -void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void *cs) {} +void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {} #endif #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) @@ -104,7 +105,7 @@ void PrintLockContention(const char* pszName, const char* pszFile, int nLine); #endif /** Wrapper around boost::unique_lock<Mutex> */ -template<typename Mutex> +template <typename Mutex> class CMutexLock { private: @@ -114,11 +115,10 @@ private: { EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex())); #ifdef DEBUG_LOCKCONTENTION - if (!lock.try_lock()) - { + if (!lock.try_lock()) { PrintLockContention(pszName, pszFile, nLine); #endif - lock.lock(); + lock.lock(); #ifdef DEBUG_LOCKCONTENTION } #endif @@ -157,19 +157,19 @@ public: typedef CMutexLock<CCriticalSection> 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 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) \ - { \ +#define ENTER_CRITICAL_SECTION(cs) \ + { \ EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \ - (cs).lock(); \ + (cs).lock(); \ } #define LEAVE_CRITICAL_SECTION(cs) \ - { \ - (cs).unlock(); \ - LeaveCritical(); \ + { \ + (cs).unlock(); \ + LeaveCritical(); \ } class CSemaphore @@ -182,7 +182,8 @@ private: public: CSemaphore(int init) : value(init) {} - void wait() { + void wait() + { boost::unique_lock<boost::mutex> lock(mutex); while (value < 1) { condition.wait(lock); @@ -190,7 +191,8 @@ public: value--; } - bool try_wait() { + bool try_wait() + { boost::unique_lock<boost::mutex> lock(mutex); if (value < 1) return false; @@ -198,7 +200,8 @@ public: return true; } - void post() { + void post() + { { boost::unique_lock<boost::mutex> lock(mutex); value++; @@ -211,31 +214,35 @@ public: class CSemaphoreGrant { private: - CSemaphore *sem; + CSemaphore* sem; bool fHaveGrant; public: - void Acquire() { + void Acquire() + { if (fHaveGrant) return; sem->wait(); fHaveGrant = true; } - void Release() { + void Release() + { if (!fHaveGrant) return; sem->post(); fHaveGrant = false; } - bool TryAcquire() { + bool TryAcquire() + { if (!fHaveGrant && sem->try_wait()) fHaveGrant = true; return fHaveGrant; } - void MoveTo(CSemaphoreGrant &grant) { + void MoveTo(CSemaphoreGrant& grant) + { grant.Release(); grant.sem = sem; grant.fHaveGrant = fHaveGrant; @@ -245,18 +252,21 @@ public: CSemaphoreGrant() : sem(NULL), fHaveGrant(false) {} - CSemaphoreGrant(CSemaphore &sema, bool fTry = false) : sem(&sema), fHaveGrant(false) { + CSemaphoreGrant(CSemaphore& sema, bool fTry = false) : sem(&sema), fHaveGrant(false) + { if (fTry) TryAcquire(); else Acquire(); } - ~CSemaphoreGrant() { + ~CSemaphoreGrant() + { Release(); } - operator bool() { + operator bool() + { return fHaveGrant; } }; diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index af01e5518c..7bec12b665 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -27,7 +27,11 @@ extern bool AddOrphanTx(const CTransaction& tx, NodeId peer); extern void EraseOrphansFor(NodeId peer); extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans); -extern std::map<uint256, CTransaction> mapOrphanTransactions; +struct COrphanTx { + CTransaction tx; + NodeId fromPeer; +}; +extern std::map<uint256, COrphanTx> mapOrphanTransactions; extern std::map<uint256, std::set<uint256> > mapOrphanTransactionsByPrev; CService ip(uint32_t i) @@ -149,11 +153,11 @@ BOOST_AUTO_TEST_CASE(DoS_checknbits) CTransaction RandomOrphan() { - std::map<uint256, CTransaction>::iterator it; + std::map<uint256, COrphanTx>::iterator it; it = mapOrphanTransactions.lower_bound(GetRandHash()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); - return it->second; + return it->second.tx; } BOOST_AUTO_TEST_CASE(DoS_mapOrphans) diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index 4bee0f6b6e..af2a9a214f 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -15,7 +15,7 @@ extern CWallet* pwalletMain; BOOST_AUTO_TEST_SUITE(accounting_tests) static void -GetResults(CWalletDB& walletdb, std::map<int64_t, CAccountingEntry>& results) +GetResults(CWalletDB& walletdb, std::map<CAmount, CAccountingEntry>& results) { std::list<CAccountingEntry> aes; @@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) std::vector<CWalletTx*> vpwtx; CWalletTx wtx; CAccountingEntry ae; - std::map<int64_t, CAccountingEntry> results; + std::map<CAmount, CAccountingEntry> results; LOCK(pwalletMain->cs_wallet); diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index fe68e9e974..c298c805da 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58) std::vector<unsigned char> sourcedata = ParseHex(test[0].get_str()); std::string base58string = test[1].get_str(); BOOST_CHECK_MESSAGE( - EncodeBase58(&sourcedata[0], &sourcedata[sourcedata.size()]) == base58string, + EncodeBase58(begin_ptr(sourcedata), end_ptr(sourcedata)) == base58string, strTest); } } @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest); } } - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::UNITTEST); } // Goal: check that generated keys match test vectors @@ -243,7 +243,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) CTxDestination nodest = CNoDestination(); BOOST_CHECK(!dummyAddr.Set(nodest)); - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::UNITTEST); } // Goal: check that base58 parsing code is robust against a variety of corrupted data diff --git a/src/test/bctest.py b/src/test/bctest.py index 1839f4fef4..ef461014ea 100644 --- a/src/test/bctest.py +++ b/src/test/bctest.py @@ -7,9 +7,11 @@ import os import json import sys -def bctest(testDir, testObj): - execargs = testObj['exec'] +def bctest(testDir, testObj, exeext): + execprog = testObj['exec'] + exeext + execargs = testObj['args'] + execrun = [execprog] + execargs stdinCfg = None inputData = None if "input" in testObj: @@ -22,12 +24,11 @@ def bctest(testDir, testObj): if "output_cmp" in testObj: outputFn = testObj['output_cmp'] outputData = open(testDir + "/" + outputFn).read() - - proc = subprocess.Popen(execargs, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen(execrun, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True) try: outs = proc.communicate(input=inputData) except OSError: - print("OSError, Failed to execute " + execargs[0]) + print("OSError, Failed to execute " + execprog) sys.exit(1) if outputData and (outs[0] != outputData): @@ -41,13 +42,13 @@ def bctest(testDir, testObj): print("Return code mismatch for " + outputFn) sys.exit(1) -def bctester(testDir, input_basename): +def bctester(testDir, input_basename, buildenv): input_filename = testDir + "/" + input_basename raw_data = open(input_filename).read() input_data = json.loads(raw_data) for testObj in input_data: - bctest(testDir, testObj) + bctest(testDir, testObj, buildenv.exeext) sys.exit(0) diff --git a/src/test/bignum.h b/src/test/bignum.h index a75f5250fa..86980b2af6 100644 --- a/src/test/bignum.h +++ b/src/test/bignum.h @@ -63,11 +63,11 @@ public: int getint() const { - unsigned long n = BN_get_word(this); + BN_ULONG n = BN_get_word(this); if (!BN_is_negative(this)) - return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n); + return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n); else - return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n); + return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n); } void setint64(int64_t sn) diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py index 40690c2fed..0eece14cfe 100755 --- a/src/test/bitcoin-util-test.py +++ b/src/test/bitcoin-util-test.py @@ -5,8 +5,9 @@ import os import bctest +import buildenv if __name__ == '__main__': bctest.bctester(os.environ["srcdir"] + "/test/data", - "bitcoin-util-test.json") + "bitcoin-util-test.json",buildenv) diff --git a/src/test/buildenv.py.in b/src/test/buildenv.py.in new file mode 100644 index 0000000000..1618bdeb76 --- /dev/null +++ b/src/test/buildenv.py.in @@ -0,0 +1,2 @@ +#!/usr/bin/python +exeext="@EXEEXT@" diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp index fdea12846a..67d40a45c7 100644 --- a/src/test/checkblock_tests.cpp +++ b/src/test/checkblock_tests.cpp @@ -35,7 +35,7 @@ bool read_block(const std::string& filename, CBlock& block) fseek(fp, 8, SEEK_SET); // skip msgheader/size - CAutoFile filein = CAutoFile(fp, SER_DISK, CLIENT_VERSION); + CAutoFile filein(fp, SER_DISK, CLIENT_VERSION); if (!filein) return false; filein >> block; diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index a3eec270ee..68232a2ff1 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -32,7 +32,7 @@ void TestVector(const Hasher &h, const In &in, const Out &out) { size_t len = insecure_rand() % ((in.size() - pos + 1) / 2 + 1); hasher.Write((unsigned char*)&in[pos], len); pos += len; - if (pos > 0 && pos + 2 * out.size() > in.size()) { + if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) { // Test that writing the rest at once to a copy of a hasher works. Hasher(hasher).Write((unsigned char*)&in[pos], in.size() - pos).Finalize(&hash[0]); BOOST_CHECK(hash == out); diff --git a/src/test/data/bitcoin-util-test.json b/src/test/data/bitcoin-util-test.json index cb74d73ef2..f8424b72a3 100644 --- a/src/test/data/bitcoin-util-test.json +++ b/src/test/data/bitcoin-util-test.json @@ -1,33 +1,41 @@ [ - { "exec": ["./bitcoin-tx", "-create"], + { "exec": "././bitcoin-tx", + "args": ["-create"], "output_cmp": "blanktx.hex" }, - { "exec": ["./bitcoin-tx", "-"], + { "exec": "./bitcoin-tx", + "args": ["-"], "input": "blanktx.hex", "output_cmp": "blanktx.hex" }, - { "exec": ["./bitcoin-tx", "-", "delin=1"], + { "exec": "./bitcoin-tx", + "args": ["-", "delin=1"], "input": "tx394b54bb.hex", "output_cmp": "tt-delin1-out.hex" }, - { "exec": ["./bitcoin-tx", "-", "delin=31"], + { "exec": "./bitcoin-tx", + "args": ["-", "delin=31"], "input": "tx394b54bb.hex", "return_code": 1 }, - { "exec": ["./bitcoin-tx", "-", "delout=1"], + { "exec": "./bitcoin-tx", + "args": ["-", "delout=1"], "input": "tx394b54bb.hex", "output_cmp": "tt-delout1-out.hex" }, - { "exec": ["./bitcoin-tx", "-", "delout=2"], + { "exec": "./bitcoin-tx", + "args": ["-", "delout=2"], "input": "tx394b54bb.hex", "return_code": 1 }, - { "exec": ["./bitcoin-tx", "-", "locktime=317000"], + { "exec": "./bitcoin-tx", + "args": ["-", "locktime=317000"], "input": "tx394b54bb.hex", "output_cmp": "tt-locktime317000-out.hex" }, - { "exec": - ["./bitcoin-tx", "-create", + { "exec": "./bitcoin-tx", + "args": + ["-create", "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", "in=bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c:18", "in=22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc:1", @@ -35,7 +43,8 @@ "outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46"], "output_cmp": "txcreate1.hex" }, - { "exec": ["./bitcoin-tx", "-create", "outscript=0:"], + { "exec": "./bitcoin-tx", + "args": ["-create", "outscript=0:"], "output_cmp": "txcreate2.hex" } ] diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json index 75de4716f8..35a6794b01 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -1,4 +1,13 @@ [ +[" +Format is: [scriptPubKey, scriptSig, flags, ... comments] +It is evaluated as if there was a crediting coinbase transaction with two 0 +pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey, +followed by a spending transaction which spends this output as only input (and +correct prevout hash), using the given scriptSig. All nLockTimes are 0, all +nSequences are max. +"], + ["", "DEPTH", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"], [" ", "DEPTH", "P2SH,STRICTENC", "and multiple spaces should not change that."], [" ", "DEPTH", "P2SH,STRICTENC"], @@ -373,5 +382,21 @@ ["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "OP_RESERVED in P2SH should fail"], ["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "OP_VER in P2SH should fail"], -["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"] +["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"], + +["0x47 0x30440220304eff7556bba9560df47873275e64db45f3cd735998ce3f00d2e57b1bb5f31302205c0c9d14b8b80d43e2ac9b87532f1af6d8a3271262bc694ec4e14068392bb0a001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "P2PK, bad sig"], +["0x47 0x3044022037fcdb8e08f41e27588de8bc036d2c4b16eb3d09c1ba53b8f47a0a9c27722a39022058664b7a53b507e71dfafb77193e3786c3f0c119d78ce9104480ee7ece04f09301 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG", "", "P2PKH, bad pubkey"], +["0x47 0x3044022035e5b6742d299861c84cebaf2ea64145ee427a95facab39e2594d6deebb0c1d602200acb16778faa2e467a59006f342f2535b1418d55ba63a8605b387b7f9ac86d9a01", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "P2PK anyonecanpay marked with normal hashtype"], +["0x47 0x3044022029b2b8765ca950cf75a69e80b73b7ddfcaa8b27080c2db4c23b36aae60688e790220598ff368e17872ee065aa54d7d3a590682ca5204325b23b31d7da3c4a21ae67901 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", "P2SH(P2PK), bad redeemscript"], +["0x47 0x30440220647f906e63890df5ef1d3fed47ba892b31976c634281079e2bd38504fb54a1fb022021e8811f38fbe90efb6b74cb78da01d9badbac3bafdf70a861d7538a220d0b2601 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "P2SH", "P2SH(P2PKH), bad sig"], +["0 0x47 0x304402203ef170402f8887f2ac183f31b1f503b0bc60bfc968dd469b097ea6124aefac5002200612febadc4e4cacc086982cb85830a17af3680c1b6a3cf77c1708af7621cf1301 0 0x47 0x304402207821838251a24a2234844f68e7169e6d11945cdf052ea12bd3e4e37457aceb4402200b6b46c81361e314c740ae5133c072af5fa5c209d65d2db1679e1716f19a538101", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "3-of-3, 2 sigs"], +["0 0 0x47 0x304402204661f7795e8db7be3132e8974e9a76d1d24b31f23df94c6fbcea07d1c205789102203f5e45a1c0b085279b58d11b36d5fea5449c3cf16f844ad10124e9b65e8777d201 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", "P2SH(2-of-3), 1 sig"], +["0x47 0x304402200052bc1600ca45c71f3538720fe62a5e8548dffd137af04467598c98466e9c0a0220789318ddbc9991ee477974089220a2feb6a6298a7c93d5ff6c25a92a2f4b48d501", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "STRICTENC", "P2PK with too much R padding"], +["0x48 0x304502206eb7b92628bfb3c4d2a04b65b986987bcbb1af4fceedb144d5a0437b7ee410590221005f57a52df4aa26366742eed0db182fce51fbcd7159011b0644a7c05943eb228901", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "STRICTENC", "P2PK with too much S padding"], +["0x47 0x30440220d8ad1efd55a3d2b8896495c38aba72056e1b3ca4a6ca15760e843eb1a9b9907602203eb0e8f3d6bec998262dfd03eaeb0f31c4e5105965436dec77550724b3771f3201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "STRICTENC", "P2PK with too little R padding"], +["0x48 0x304502206c43e065c8a8db3bbe69015afb86a51fb2fc8870defd41d436da2a197d9d6c12022100fcec35816ee2d84ec271ad159fcabf5dd712157051169e48ac328a7818cdb51e01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "LOW_S,STRICTENC", "P2PK with high S"], +["0x01 0x01 0x47 0x304402200e48ba1cf4d7182db94ffb57bd72ea31b5545dc0d1c512e665779b4fb2badc52022054b8388dfc074c708a75b62359b7be46402751ee40c0a111aef38a837b6ed09801 0x47 0x304402201c9820f59c49107bb30e6175cfc9ec95f897b03beb628b4bc854d2b80392aa0602200235d986ae418bcd111b8814f4c26a0ab5f475fb542a44884fc14912a97a252301 0x47 0x304402204cd7894c6f10a871f5b0c1f9c13228f8cdd4050248f0d0f498ee86be69ee3080022051bd2932c7d585eb600c7194235c74da820935f0d67972fd9545673aa1fd023301", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "NULLDUMMY", "3-of-3 with nonzero dummy"], + +["The End"] + ] diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index c1db4c6061..653f60d982 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_valid.json @@ -1,4 +1,13 @@ [ +[" +Format is: [scriptPubKey, scriptSig, flags, ... comments] +It is evaluated as if there was a crediting coinbase transaction with two 0 +pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey, +followed by a spending transaction which spends this output as only input (and +correct prevout hash), using the given scriptSig. All nLockTimes are 0, all +nSequences are max. +"], + ["", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"], [" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "and multiple spaces should not change that."], [" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], @@ -518,5 +527,21 @@ "P2SH,STRICTENC", "Basic PUSHDATA1 signedness check"], -["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"] +["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"], + +["0x47 0x3044022007415aa37ce7eaa6146001ac8bdefca0ddcba0e37c5dc08c4ac99392124ebac802207d382307fd53f65778b07b9c63b6e196edeadf0be719130c5db21ff1e700d67501", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "P2PK"], +["0x47 0x3044022069d40999786aeb2fd874f9eb2636461a062dc963471627ed8390a3a5f9556f640220350132a52415ce622f2aadd07f791c591500917ec1f8c5edbc5381ef7942534d01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", "", "P2PKH"], +["0x47 0x30440220519f2a6632ffa134c7811ea2819e9dcc951f0c7baf461f2dffdd09133f3b080a02203ec6bab5eb6619ed7f41b8701d7c6d70cfc83bb26c5c97f54b2ca6e304fc2bb581", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "P2PK anyonecanpay"], +["0x47 0x30440220279dad2170ffb5639f0a1ea71fc462ee37d75d420d86f84c978bac523c09b7f20220683b2789f5c5528a9e0a0d78f6e40db3f616cf1adb5a5fdef117d5974795cfe201 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", "P2SH(P2PK)"], +["0x47 0x3044022066acbfb5ac96b7cbf3f05a2aaf358c32438c45d1d7359dee9fc1ee636940735f02205606a03fd8cbf6a6fcbcba60c8abb1e385c0b5753cb57a97538159106fd3684e01 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "", "P2SH(P2PKH), bad sig but no VERIFY_P2SH"], +["0 0x47 0x3044022004e791dd30a64c70e55e84e150c002af9feb3ce0ab1f20e86c53d1209003927502205a60453987fcd72aebaaacebc8ce4b15449cdd79e54cc82cefb83e69dbcfeabf01 0x47 0x304402201d021808ce93dd8574cc4f99ae4f11b44305528b0aecbd9f156f08315173643802200944a0ea5c884bd86180aef76d8b1e444860776b251e47d2d6c651a1c6f9930801 0x47 0x30440220446336d7b7de05ebb5683b82b05248ec7d78e88ae8d6125985f5776c887a4cf90220674ab2b2c2f954ba1cf35457d273c90d0c0c1c224d0ae128628740e81129486801", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "3-of-3"], +["0 0x47 0x30440220288b06d057cf0eac434ed0c3be9257cc0ca144dd99c11cc8f1a49467a37d8e8002203c496c72253c528e6bc81c42e683aba974d46041a96ef7b00915c863eb2a702901 0x47 0x304402207ffb4da33f40cac839a43000a187bd76a1ee5bf95e46dc1534b38bb7bd0321db022038c078f29d1831f8eb68ffdc2634c654fb01c3467b6457b98ad220653bb2478501 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", "P2SH(2-of-3)"], +["0x47 0x304402200001cae94b795baaafb05db38cf24cd75560cab2c36c91e29fac7d0fd2a723a3022058e2e56e568ce7c4b2b106210d114e1faa079407a6ed4154f230667c7d3583bc01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "P2PK with too much R padding but no STRICTENC"], +["0x48 0x304502206d01de7c2a40ac2bb1231ed97f3890a1782f421d4c28b97166deff317990288f0221005e720213b089355be2cf785d81a82c59307d30e1624f450ed9ca1ebbc11cca6d01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "P2PK with too much S padding but no STRICTENC"], +["0x47 0x30440220f3d8889602147d60d26c1d3b21b8db183eac02bf6d2fec1424c0ef377ca6fd7b02202bae8bfe39d00a432d4538a592e338b0ffc44c17d4b7056043d55063cf91f5ef01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "P2PK with too little R padding but no STRICTENC"], +["0x48 0x3045022021bf9184d94f208ac9f4757ebca9b1cbebf008cfc244fe5be1360b1b9aba0e92022100e55074f72f3a1bfddf2ea4ea7ba984f78822e136fe04c8f9c1363238e0233bd801", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "STRICTENC", "P2PK with high S but no LOW_S"], +["0x48 0x304502205c3e81aaf2aad0673f349035b180eba783eba7797af91c979920dea6b17a16d6022100d1d46825c68da1b325f320a3503dad27bb818227f64a38d153554bfd360c0e5301", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "LOW_S", "P2PK with high S but no STRICTENC"], +["0x01 0x01 0x47 0x3044022046ce33d1771b0127dd4c4cef8fdc3218ebdfa60e3793ed700292d8ebd93fb1f402201029d47a414db83e96e31443c2d8b552f971469c4800f5eff7df2f0648521aed01 0x47 0x304402205c53911ad55b054920043962bbda98cf6e57e2db1cd5611138251490baabaa8702201dc80dfceae6007e7772dc13ff6e7ca66a983cb017fe5d46d30118462d83bcf801 0x47 0x304402201937e44a4ec12364f9d32f9d25e7ecbc68aee9ef90069af80efef4c05f6ace9602206c515101c00c75710b32ff7ff8dbaf7c9a0be6e86ed14a0755b47626604f31fd01", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "3-of-3 with nonzero dummy but no NULLDUMMY"], + +["The End"] ] diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 8cadcdd716..8a984304f4 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -16,7 +16,8 @@ BOOST_AUTO_TEST_SUITE(getarg_tests) static void ResetArgs(const std::string& strArg) { std::vector<std::string> vecArg; - boost::split(vecArg, strArg, boost::is_space(), boost::token_compress_on); + if (strArg.size()) + boost::split(vecArg, strArg, boost::is_space(), boost::token_compress_on); // Insert dummy executable name: vecArg.insert(vecArg.begin(), "testbitcoin"); diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 8863ba4004..70a800af51 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -11,9 +11,9 @@ BOOST_AUTO_TEST_SUITE(main_tests) BOOST_AUTO_TEST_CASE(subsidy_limit_test) { - uint64_t nSum = 0; + CAmount nSum = 0; for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) { - uint64_t nSubsidy = GetBlockValue(nHeight, 0); + CAmount nSubsidy = GetBlockValue(nHeight, 0); BOOST_CHECK(nSubsidy <= 50 * COIN); nSum += nSubsidy * 1000; BOOST_CHECK(MoneyRange(nSum)); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 9e4669eba9..bad5c13ac2 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -253,6 +253,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) chainActive.Tip()->nHeight--; SetMockTime(0); + mempool.clear(); BOOST_FOREACH(CTransaction *tx, txFirst) delete tx; diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index cb37740068..5a2ec1cb31 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -82,19 +82,19 @@ BOOST_AUTO_TEST_CASE(multisig_verify) keys.clear(); keys += key[0],key[1]; // magic operator+= from boost.assign s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, flags)); + BOOST_CHECK(VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0))); for (int i = 0; i < 4; i++) { keys.clear(); keys += key[i]; s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, flags), strprintf("a&b 1: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0)), strprintf("a&b 1: %d", i)); keys.clear(); keys += key[1],key[i]; s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, flags), strprintf("a&b 2: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0)), strprintf("a&b 2: %d", i)); } // Test a OR b: @@ -104,16 +104,16 @@ BOOST_AUTO_TEST_CASE(multisig_verify) keys += key[i]; s = sign_multisig(a_or_b, keys, txTo[1], 0); if (i == 0 || i == 1) - BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, flags), strprintf("a|b: %d", i)); + BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)), strprintf("a|b: %d", i)); else - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, flags), strprintf("a|b: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)), strprintf("a|b: %d", i)); } s.clear(); s << OP_0 << OP_0; - BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, flags)); + BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0))); s.clear(); s << OP_0 << OP_1; - BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, flags)); + BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0))); for (int i = 0; i < 4; i++) @@ -123,9 +123,9 @@ BOOST_AUTO_TEST_CASE(multisig_verify) keys += key[i],key[j]; s = sign_multisig(escrow, keys, txTo[2], 0); if (i < j && i < 3 && j < 3) - BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, flags), strprintf("escrow 1: %d %d", i, j)); + BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0)), strprintf("escrow 1: %d %d", i, j)); else - BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, flags), strprintf("escrow 2: %d %d", i, j)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0)), strprintf("escrow 2: %d %d", i, j)); } } diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 1dc2a3d82f..91da0c4420 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -14,7 +14,7 @@ using namespace std; using namespace json_spirit; -extern Array createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL); +extern Array createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL); extern Value CallRPC(string args); extern CWallet* pwalletMain; @@ -53,10 +53,10 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig) BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error); BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error); - string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing + string short1(address1Hex, address1Hex + sizeof(address1Hex) - 2); // last byte missing BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error); - string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing + string short2(address1Hex + 1, address1Hex + sizeof(address1Hex)); // first byte missing BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error); } @@ -68,26 +68,30 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) LOCK2(cs_main, pwalletMain->cs_wallet); CPubKey demoPubkey = pwalletMain->GenerateNewKey(); - CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID())); - Value retValue; - string strAccount = "walletDemoAccount"; - string strPurpose = "receive"; - BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */ - CWalletDB walletdb(pwalletMain->strWalletFile); - CAccount account; - account.vchPubKey = demoPubkey; - pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose); - walletdb.WriteAccount(strAccount, account); - }); - - - /********************************* - * setaccount - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount")); - BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error); - /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X (33 chars) is an illegal address (should be 34 chars) */ - BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X nullaccount"), runtime_error); + CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID())); + Value retValue; + string strAccount = "walletDemoAccount"; + string strPurpose = "receive"; + BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */ + CWalletDB walletdb(pwalletMain->strWalletFile); + CAccount account; + account.vchPubKey = demoPubkey; + pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose); + walletdb.WriteAccount(strAccount, account); + }); + + CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey(); + CBitcoinAddress setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID())); + + /********************************* + * setaccount + *********************************/ + BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount")); + /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ is not owned by the test wallet. */ + BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount"), runtime_error); + BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error); + /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X (33 chars) is an illegal address (should be 34 chars) */ + BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X nullaccount"), runtime_error); /********************************* * listunspent @@ -97,12 +101,12 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error); BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error); BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error); - BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []")); + BOOST_CHECK_NO_THROW(r = CallRPC("listunspent 0 1 []")); BOOST_CHECK(r.get_array().empty()); /********************************* - * listreceivedbyaddress - *********************************/ + * listreceivedbyaddress + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress")); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0")); BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error); @@ -111,8 +115,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error); /********************************* - * listreceivedbyaccount - *********************************/ + * listreceivedbyaccount + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount")); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0")); BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error); @@ -121,59 +125,58 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error); /********************************* - * getrawchangeaddress - *********************************/ + * getrawchangeaddress + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress")); /********************************* - * getnewaddress - *********************************/ + * getnewaddress + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getnewaddress")); BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount")); /********************************* - * getaccountaddress - *********************************/ + * getaccountaddress + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\"")); - BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account - BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount)); - BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get()); - - /********************************* - * getaccount - *********************************/ - BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error); - BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString())); - - /********************************* - * signmessage + verifymessage - *********************************/ - BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage")); - BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error); - /* Should throw error because this address is not loaded in the wallet */ - BOOST_CHECK_THROW(CallRPC("signmessage 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ mymessage"), runtime_error); - - /* missing arguments */ - BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString()), runtime_error); - BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str()), runtime_error); - /* Illegal address */ - BOOST_CHECK_THROW(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error); - /* wrong address */ - BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + retValue.get_str() + " mymessage").get_bool() == false); - /* Correct address and signature but wrong message */ - BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false); - /* Correct address, message and signature*/ - BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true); - - /********************************* - * getaddressesbyaccount - *********************************/ - BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error); - BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount)); - Array arr = retValue.get_array(); - BOOST_CHECK(arr.size() > 0); - BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get()); + BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account + BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount)); + BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get()); + /********************************* + * getaccount + *********************************/ + BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error); + BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString())); + + /********************************* + * signmessage + verifymessage + *********************************/ + BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage")); + BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error); + /* Should throw error because this address is not loaded in the wallet */ + BOOST_CHECK_THROW(CallRPC("signmessage 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ mymessage"), runtime_error); + + /* missing arguments */ + BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), runtime_error); + BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), runtime_error); + /* Illegal address */ + BOOST_CHECK_THROW(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error); + /* wrong address */ + BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + retValue.get_str() + " mymessage").get_bool() == false); + /* Correct address and signature but wrong message */ + BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false); + /* Correct address, message and signature*/ + BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true); + + /********************************* + * getaddressesbyaccount + *********************************/ + BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error); + BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount)); + Array arr = retValue.get_array(); + BOOST_CHECK(arr.size() > 0); + BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get()); } diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index e6cf00c2d0..6c32a263a9 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -42,7 +42,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict) txTo.vin[0].scriptSig = scriptSig; txTo.vout[0].nValue = 1; - return VerifyScript(scriptSig, scriptPubKey, txTo, 0, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE); + return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, SignatureChecker(txTo, 0)); } @@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE(sign) { CScript sigSave = txTo[i].vin[0].scriptSig; txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; - bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC)(); + bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false)(); if (i == j) BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); else diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index cb543a0cf1..6ed3e03f53 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -5,12 +5,13 @@ #include "data/script_invalid.json.h" #include "data/script_valid.json.h" +#include "core_io.h" #include "key.h" #include "keystore.h" #include "main.h" #include "script/script.h" #include "script/sign.h" -#include "core_io.h" +#include "util.h" #include <fstream> #include <stdint.h> @@ -36,6 +37,7 @@ using namespace boost::algorithm; static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; unsigned int ParseScriptFlags(string strFlags); +string FormatScriptFlags(unsigned int flags); Array read_json(const std::string& jsondata) @@ -52,6 +54,350 @@ read_json(const std::string& jsondata) BOOST_AUTO_TEST_SUITE(script_tests) +CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) +{ + CMutableTransaction txCredit; + txCredit.nVersion = 1; + txCredit.nLockTime = 0; + txCredit.vin.resize(1); + txCredit.vout.resize(1); + txCredit.vin[0].prevout.SetNull(); + txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0); + txCredit.vin[0].nSequence = std::numeric_limits<unsigned int>::max(); + txCredit.vout[0].scriptPubKey = scriptPubKey; + txCredit.vout[0].nValue = 0; + + return txCredit; +} + +CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMutableTransaction& txCredit) +{ + CMutableTransaction txSpend; + txSpend.nVersion = 1; + txSpend.nLockTime = 0; + txSpend.vin.resize(1); + txSpend.vout.resize(1); + txSpend.vin[0].prevout.hash = txCredit.GetHash(); + txSpend.vin[0].prevout.n = 0; + txSpend.vin[0].scriptSig = scriptSig; + txSpend.vin[0].nSequence = std::numeric_limits<unsigned int>::max(); + txSpend.vout[0].scriptPubKey = CScript(); + txSpend.vout[0].nValue = 0; + + return txSpend; +} + +void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message) +{ + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, SignatureChecker(BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)), 0)) == expect, message); +} + +namespace +{ +const unsigned char vchKey0[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; +const unsigned char vchKey1[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}; +const unsigned char vchKey2[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0}; + +struct KeyData +{ + CKey key0, key0C, key1, key1C, key2, key2C; + CPubKey pubkey0, pubkey0C, pubkey0H; + CPubKey pubkey1, pubkey1C; + CPubKey pubkey2, pubkey2C; + + KeyData() + { + + key0.Set(vchKey0, vchKey0 + 32, false); + key0C.Set(vchKey0, vchKey0 + 32, true); + pubkey0 = key0.GetPubKey(); + pubkey0H = key0.GetPubKey(); + pubkey0C = key0C.GetPubKey(); + *const_cast<unsigned char*>(&pubkey0H[0]) = 0x06 | (pubkey0H[64] & 1); + + key1.Set(vchKey1, vchKey1 + 32, false); + key1C.Set(vchKey1, vchKey1 + 32, true); + pubkey1 = key1.GetPubKey(); + pubkey1C = key1C.GetPubKey(); + + key2.Set(vchKey2, vchKey2 + 32, false); + key2C.Set(vchKey2, vchKey2 + 32, true); + pubkey2 = key2.GetPubKey(); + pubkey2C = key2C.GetPubKey(); + } +}; + +const KeyData keys; + +class TestBuilder +{ +private: + CScript scriptPubKey; + CTransaction creditTx; + CMutableTransaction spendTx; + bool havePush; + std::vector<unsigned char> push; + std::string comment; + int flags; + + void DoPush() + { + if (havePush) { + spendTx.vin[0].scriptSig << push; + havePush = false; + } + } + + void DoPush(const std::vector<unsigned char>& data) + { + DoPush(); + push = data; + havePush = true; + } + +public: + TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_) + { + if (P2SH) { + creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << redeemScript.GetID() << OP_EQUAL); + } else { + creditTx = BuildCreditingTransaction(redeemScript); + } + spendTx = BuildSpendingTransaction(CScript(), creditTx); + } + + TestBuilder& Add(const CScript& script) + { + spendTx.vin[0].scriptSig += script; + return *this; + } + + TestBuilder& Num(int num) + { + spendTx.vin[0].scriptSig << CScriptNum(num); + return *this; + } + + TestBuilder& Push(const std::string& hex) + { + DoPush(ParseHex(hex)); + return *this; + } + + TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32) + { + uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType); + std::vector<unsigned char> vchSig, r, s; + do { + key.Sign(hash, vchSig, lenS <= 32); + r = std::vector<unsigned char>(vchSig.begin() + 4, vchSig.begin() + 4 + vchSig[3]); + s = std::vector<unsigned char>(vchSig.begin() + 6 + vchSig[3], vchSig.begin() + 6 + vchSig[3] + vchSig[5 + vchSig[3]]); + } while (lenR != r.size() || lenS != s.size()); + vchSig.push_back(static_cast<unsigned char>(nHashType)); + DoPush(vchSig); + return *this; + } + + TestBuilder& Push(const CPubKey& pubkey) + { + DoPush(std::vector<unsigned char>(pubkey.begin(), pubkey.end())); + return *this; + } + + TestBuilder& PushRedeem() + { + DoPush(static_cast<std::vector<unsigned char> >(scriptPubKey)); + return *this; + } + + TestBuilder& EditPush(unsigned int pos, const std::string& hexin, const std::string& hexout) + { + assert(havePush); + std::vector<unsigned char> datain = ParseHex(hexin); + std::vector<unsigned char> dataout = ParseHex(hexout); + assert(pos + datain.size() <= push.size()); + BOOST_CHECK_MESSAGE(std::vector<unsigned char>(push.begin() + pos, push.begin() + pos + datain.size()) == datain, comment); + push.erase(push.begin() + pos, push.begin() + pos + datain.size()); + push.insert(push.begin() + pos, dataout.begin(), dataout.end()); + return *this; + } + + TestBuilder& DamagePush(unsigned int pos) + { + assert(havePush); + assert(pos < push.size()); + push[pos] ^= 1; + return *this; + } + + TestBuilder& Test(bool expect) + { + TestBuilder copy = *this; // Make a copy so we can rollback the push. + DoPush(); + DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, expect, comment); + *this = copy; + return *this; + } + + operator std::string() + { + DoPush(); + return "[\"" + + FormatScript(spendTx.vin[0].scriptSig) + "\", \"" + + FormatScript(creditTx.vout[0].scriptPubKey) + "\", \"" + + FormatScriptFlags(flags) + "\", \"" + + comment + "\"],\n"; + } + + std::string GetComment() + { + return comment; + } + + const CScript& GetScriptPubKey() + { + return creditTx.vout[0].scriptPubKey; + } +}; +} + +BOOST_AUTO_TEST_CASE(script_build) +{ + std::vector<TestBuilder> good; + std::vector<TestBuilder> bad; + + good.push_back(TestBuilder(CScript() << keys.pubkey0 << OP_CHECKSIG, + "P2PK", 0 + ).PushSig(keys.key0)); + bad.push_back(TestBuilder(CScript() << keys.pubkey0 << OP_CHECKSIG, + "P2PK, bad sig", 0 + ).PushSig(keys.key0).DamagePush(10)); + + good.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << keys.pubkey1C.GetID() << OP_EQUALVERIFY << OP_CHECKSIG, + "P2PKH", 0 + ).PushSig(keys.key1).Push(keys.pubkey1C)); + bad.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << keys.pubkey2C.GetID() << OP_EQUALVERIFY << OP_CHECKSIG, + "P2PKH, bad pubkey", 0 + ).PushSig(keys.key2).Push(keys.pubkey2C).DamagePush(5)); + + good.push_back(TestBuilder(CScript() << keys.pubkey1 << OP_CHECKSIG, + "P2PK anyonecanpay", 0 + ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY)); + bad.push_back(TestBuilder(CScript() << keys.pubkey1 << OP_CHECKSIG, + "P2PK anyonecanpay marked with normal hashtype", 0 + ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY).EditPush(70, "81", "01")); + + good.push_back(TestBuilder(CScript() << keys.pubkey0C << OP_CHECKSIG, + "P2SH(P2PK)", SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key0).PushRedeem()); + bad.push_back(TestBuilder(CScript() << keys.pubkey0C << OP_CHECKSIG, + "P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key0).PushRedeem().DamagePush(10)); + + good.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << keys.pubkey1.GetID() << OP_EQUALVERIFY << OP_CHECKSIG, + "P2SH(P2PKH), bad sig but no VERIFY_P2SH", 0, true + ).PushSig(keys.key0).DamagePush(10).PushRedeem()); + bad.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << keys.pubkey1.GetID() << OP_EQUALVERIFY << OP_CHECKSIG, + "P2SH(P2PKH), bad sig", SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key0).DamagePush(10).PushRedeem()); + + good.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG, + "3-of-3", 0 + ).Num(0).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2)); + bad.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG, + "3-of-3, 2 sigs", 0 + ).Num(0).PushSig(keys.key0).PushSig(keys.key1).Num(0)); + + good.push_back(TestBuilder(CScript() << OP_2 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG, + "P2SH(2-of-3)", SCRIPT_VERIFY_P2SH, true + ).Num(0).PushSig(keys.key1).PushSig(keys.key2).PushRedeem()); + bad.push_back(TestBuilder(CScript() << OP_2 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG, + "P2SH(2-of-3), 1 sig", SCRIPT_VERIFY_P2SH, true + ).Num(0).PushSig(keys.key1).Num(0).PushRedeem()); + + good.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, + "P2PK with too much R padding but no STRICTENC", 0 + ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000")); + bad.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, + "P2PK with too much R padding", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000")); + good.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, + "P2PK with too much S padding but no STRICTENC", 0 + ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100")); + bad.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, + "P2PK with too much S padding", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100")); + good.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, + "P2PK with too little R padding but no STRICTENC", 0 + ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); + bad.push_back(TestBuilder(CScript() << keys.pubkey1C << OP_CHECKSIG, + "P2PK with too little R padding", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); + + good.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG, + "P2PK with high S but no LOW_S", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key2, SIGHASH_ALL, 32, 33)); + good.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG, + "P2PK with high S but no STRICTENC", SCRIPT_VERIFY_LOW_S + ).PushSig(keys.key2, SIGHASH_ALL, 32, 33)); + bad.push_back(TestBuilder(CScript() << keys.pubkey2C << OP_CHECKSIG, + "P2PK with high S", SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key2, SIGHASH_ALL, 32, 33)); + + good.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG, + "3-of-3 with nonzero dummy but no NULLDUMMY", 0 + ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2)); + bad.push_back(TestBuilder(CScript() << OP_3 << keys.pubkey0C << keys.pubkey1C << keys.pubkey2C << OP_3 << OP_CHECKMULTISIG, + "3-of-3 with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY + ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2)); + + std::map<std::string, Array> tests_good; + std::map<std::string, Array> tests_bad; + + { + Array json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); + Array json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); + + BOOST_FOREACH(Value& tv, json_good) { + Array test = tv.get_array(); + if (test.size() >= 4) { + tests_good[test[3].get_str()] = test; + } + } + BOOST_FOREACH(Value& tv, json_bad) { + Array test = tv.get_array(); + if (test.size() >= 4) { + tests_bad[test[3].get_str()] = test; + } + } + } + + std::string strGood; + std::string strBad; + + BOOST_FOREACH(TestBuilder& test, good) { + test.Test(true); + BOOST_CHECK_MESSAGE(tests_good.count(test.GetComment()) > 0, "Missing auto script_valid test: " + test.GetComment()); + BOOST_CHECK_MESSAGE(ParseScript(tests_good[test.GetComment()][1].get_str()) == test.GetScriptPubKey(), "ScriptPubKey mismatch in auto script_valid test: " + test.GetComment()); + strGood += test; + } + BOOST_FOREACH(TestBuilder& test, bad) { + test.Test(false); + BOOST_CHECK_MESSAGE(tests_bad.count(test.GetComment()) > 0, "Missing auto script_invalid test: " + test.GetComment()); + BOOST_CHECK_MESSAGE(ParseScript(tests_bad[test.GetComment()][1].get_str()) == test.GetScriptPubKey(), "ScriptPubKey mismatch in auto script_invalid test: " + test.GetComment()); + strBad += test; + } + +#if 0 + FILE* valid = fopen("script_valid.json.gen", "w"); + fputs(strGood.c_str(), valid); + fclose(valid); + FILE* invalid = fopen("script_invalid.json.gen", "w"); + fputs(strBad.c_str(), invalid); + fclose(invalid); +#endif +} + BOOST_AUTO_TEST_CASE(script_valid) { // Read tests from test/data/script_valid.json @@ -67,7 +413,9 @@ BOOST_AUTO_TEST_CASE(script_valid) string strTest = write_string(tv, false); if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments) { - BOOST_ERROR("Bad test: " << strTest); + if (test.size() != 1) { + BOOST_ERROR("Bad test: " << strTest); + } continue; } string scriptSigString = test[0].get_str(); @@ -76,8 +424,7 @@ BOOST_AUTO_TEST_CASE(script_valid) CScript scriptPubKey = ParseScript(scriptPubKeyString); unsigned int scriptflags = ParseScriptFlags(test[2].get_str()); - CTransaction tx; - BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, scriptflags), strTest); + DoTest(scriptPubKey, scriptSig, scriptflags, true, strTest); } } @@ -90,9 +437,11 @@ BOOST_AUTO_TEST_CASE(script_invalid) { Array test = tv.get_array(); string strTest = write_string(tv, false); - if (test.size() < 2) // Allow size > 2; extra stuff ignored (useful for comments) + if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments) { - BOOST_ERROR("Bad test: " << strTest); + if (test.size() != 1) { + BOOST_ERROR("Bad test: " << strTest); + } continue; } string scriptSigString = test[0].get_str(); @@ -101,8 +450,7 @@ BOOST_AUTO_TEST_CASE(script_invalid) CScript scriptPubKey = ParseScript(scriptPubKeyString); unsigned int scriptflags = ParseScriptFlags(test[2].get_str()); - CTransaction tx; - BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, scriptflags), strTest); + DoTest(scriptPubKey, scriptSig, scriptflags, false, strTest); } } @@ -116,18 +464,18 @@ BOOST_AUTO_TEST_CASE(script_PushData) static const unsigned char pushdata4[] = { OP_PUSHDATA4, 1, 0, 0, 0, 0x5a }; vector<vector<unsigned char> > directStack; - BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), CTransaction(), 0, true)); + BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), true, BaseSignatureChecker())); vector<vector<unsigned char> > pushdata1Stack; - BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), CTransaction(), 0, true)); + BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), true, BaseSignatureChecker())); BOOST_CHECK(pushdata1Stack == directStack); vector<vector<unsigned char> > pushdata2Stack; - BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), CTransaction(), 0, true)); + BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), true, BaseSignatureChecker())); BOOST_CHECK(pushdata2Stack == directStack); vector<vector<unsigned char> > pushdata4Stack; - BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), CTransaction(), 0, true)); + BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), true, BaseSignatureChecker())); BOOST_CHECK(pushdata4Stack == directStack); } @@ -173,27 +521,19 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) CScript scriptPubKey12; scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG; - CMutableTransaction txFrom12; - txFrom12.vout.resize(1); - txFrom12.vout[0].scriptPubKey = scriptPubKey12; - - CMutableTransaction txTo12; - txTo12.vin.resize(1); - txTo12.vout.resize(1); - txTo12.vin[0].prevout.n = 0; - txTo12.vin[0].prevout.hash = txFrom12.GetHash(); - txTo12.vout[0].nValue = 1; + CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12); + CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12); CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, flags)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0))); txTo12.vout[0].nValue = 2; - BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, flags)); + BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0))); CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, flags)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, SignatureChecker(txTo12, 0))); CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, flags)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0))); } BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) @@ -207,60 +547,52 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) CScript scriptPubKey23; scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG; - CMutableTransaction txFrom23; - txFrom23.vout.resize(1); - txFrom23.vout[0].scriptPubKey = scriptPubKey23; - - CMutableTransaction txTo23; - txTo23.vin.resize(1); - txTo23.vout.resize(1); - txTo23.vin[0].prevout.n = 0; - txTo23.vin[0].prevout.hash = txFrom23.GetHash(); - txTo23.vout[0].nValue = 1; + CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23); + CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), txFrom23); std::vector<CKey> keys; keys.push_back(key1); keys.push_back(key2); CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, flags)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0))); keys.clear(); keys.push_back(key1); keys.push_back(key3); CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, flags)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0))); keys.clear(); keys.push_back(key2); keys.push_back(key3); CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, flags)); + BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0))); keys.clear(); keys.push_back(key2); keys.push_back(key2); // Can't re-use sig CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, flags)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0))); keys.clear(); keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, flags)); + BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0))); keys.clear(); keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, flags)); + BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0))); keys.clear(); keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, flags)); + BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, SignatureChecker(txTo23, 0))); keys.clear(); keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, flags)); + BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, SignatureChecker(txTo23, 0))); keys.clear(); // Must have signatures CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, flags)); + BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, SignatureChecker(txTo23, 0))); } BOOST_AUTO_TEST_CASE(script_combineSigs) @@ -278,17 +610,10 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) keystore.AddKey(key); } - CMutableTransaction txFrom; - txFrom.vout.resize(1); - txFrom.vout[0].scriptPubKey = GetScriptForDestination(keys[0].GetPubKey().GetID()); + CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID())); + CMutableTransaction txTo = BuildSpendingTransaction(CScript(), txFrom); CScript& scriptPubKey = txFrom.vout[0].scriptPubKey; - CMutableTransaction txTo; - txTo.vin.resize(1); - txTo.vout.resize(1); - txTo.vin[0].prevout.n = 0; - txTo.vin[0].prevout.hash = txFrom.GetHash(); CScript& scriptSig = txTo.vin[0].scriptSig; - txTo.vout[0].nValue = 1; CScript empty; CScript combined = CombineSignatures(scriptPubKey, txTo, 0, empty, empty); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 68fad8d038..6e5f0e3fac 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -31,7 +31,7 @@ struct TestingSetup { TestingSetup() { fPrintToDebugLog = false; // don't want to write to debug.log file - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::UNITTEST); noui_connect(); #ifdef ENABLE_WALLET bitdb.MakeMock(); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 41d8ee9f19..823afa1680 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -17,6 +17,7 @@ #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/split.hpp> #include <boost/test/unit_test.hpp> +#include <boost/assign/list_of.hpp> #include "json/json_spirit_writer_template.h" using namespace std; @@ -26,22 +27,22 @@ using namespace boost::algorithm; // In script_tests.cpp extern Array read_json(const std::string& jsondata); -unsigned int ParseScriptFlags(string strFlags){ +static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of + (string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE) + (string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH) + (string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC) + (string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S) + (string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY); + +unsigned int ParseScriptFlags(string strFlags) +{ + if (strFlags.empty()) { + return 0; + } unsigned int flags = 0; vector<string> words; split(words, strFlags, is_any_of(",")); - // Note how NOCACHE is not included as it is a runtime-only flag. - static map<string, unsigned int> mapFlagNames; - if (mapFlagNames.size() == 0) - { - mapFlagNames["NONE"] = SCRIPT_VERIFY_NONE; - mapFlagNames["P2SH"] = SCRIPT_VERIFY_P2SH; - mapFlagNames["STRICTENC"] = SCRIPT_VERIFY_STRICTENC; - mapFlagNames["LOW_S"] = SCRIPT_VERIFY_LOW_S; - mapFlagNames["NULLDUMMY"] = SCRIPT_VERIFY_NULLDUMMY; - } - BOOST_FOREACH(string word, words) { if (!mapFlagNames.count(word)) @@ -52,6 +53,22 @@ unsigned int ParseScriptFlags(string strFlags){ return flags; } +string FormatScriptFlags(unsigned int flags) +{ + if (flags == 0) { + return ""; + } + string ret; + std::map<string, unsigned int>::const_iterator it = mapFlagNames.begin(); + while (it != mapFlagNames.end()) { + if (flags & it->second) { + ret += it->first + ","; + } + it++; + } + return ret.substr(0, ret.size() - 1); +} + BOOST_AUTO_TEST_SUITE(transaction_tests) BOOST_AUTO_TEST_CASE(tx_valid) @@ -121,7 +138,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - tx, i, verify_flags), + verify_flags, SignatureChecker(tx, i)), strTest); } } @@ -194,7 +211,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - tx, i, verify_flags); + verify_flags, SignatureChecker(tx, i)); } BOOST_CHECK_MESSAGE(!fValid, strTest); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index e077c9de3b..6378bd0941 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -171,7 +171,7 @@ BOOST_AUTO_TEST_CASE(util_FormatMoney) BOOST_AUTO_TEST_CASE(util_ParseMoney) { - int64_t ret = 0; + CAmount ret = 0; BOOST_CHECK(ParseMoney("0.0", ret)); BOOST_CHECK_EQUAL(ret, 0); diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index 3887efbd0d..90fc470e06 100644 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_SUITE(wallet_tests) static CWallet wallet; static vector<COutput> vCoins; -static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0) +static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0) { static int nextLockTime = 0; CMutableTransaction tx; @@ -66,7 +66,7 @@ static bool equal_sets(CoinSet a, CoinSet b) BOOST_AUTO_TEST_CASE(coin_selection_tests) { CoinSet setCoinsRet, setCoinsRet2; - int64_t nValueRet; + CAmount nValueRet; LOCK(wallet.cs_wallet); diff --git a/src/threadsafety.h b/src/threadsafety.h index 9ee39372e1..7515d050e7 100644 --- a/src/threadsafety.h +++ b/src/threadsafety.h @@ -13,24 +13,24 @@ // See http://clang.llvm.org/docs/LanguageExtensions.html#threadsafety // for documentation. The clang compiler can do advanced static analysis // of locking when given the -Wthread-safety option. -#define LOCKABLE __attribute__ ((lockable)) -#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) -#define GUARDED_BY(x) __attribute__ ((guarded_by(x))) -#define GUARDED_VAR __attribute__ ((guarded_var)) -#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x))) -#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var)) -#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) -#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) -#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) -#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__))) -#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__))) -#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) -#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) -#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__ ((exclusive_locks_required(__VA_ARGS__))) -#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__))) -#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) +#define LOCKABLE __attribute__((lockable)) +#define SCOPED_LOCKABLE __attribute__((scoped_lockable)) +#define GUARDED_BY(x) __attribute__((guarded_by(x))) +#define GUARDED_VAR __attribute__((guarded_var)) +#define PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x))) +#define PT_GUARDED_VAR __attribute__((pt_guarded_var)) +#define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) +#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__))) +#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__))) +#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) +#define LOCK_RETURNED(x) __attribute__((lock_returned(x))) +#define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__))) +#define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) #else #define LOCKABLE #define SCOPED_LOCKABLE @@ -50,6 +50,6 @@ #define EXCLUSIVE_LOCKS_REQUIRED(...) #define SHARED_LOCKS_REQUIRED(...) #define NO_THREAD_SAFETY_ANALYSIS -#endif // __GNUC__ +#endif // __GNUC__ -#endif // BITCOIN_THREADSAFETY_H +#endif // BITCOIN_THREADSAFETY_H diff --git a/src/timedata.h b/src/timedata.h index 155f6872da..2c20f4efd5 100644 --- a/src/timedata.h +++ b/src/timedata.h @@ -15,15 +15,16 @@ class CNetAddr; /** Median filter over a stream of values. * Returns the median of the last N numbers */ -template <typename T> class CMedianFilter +template <typename T> +class CMedianFilter { private: std::vector<T> vValues; std::vector<T> vSorted; unsigned int nSize; + public: - CMedianFilter(unsigned int size, T initial_value): - nSize(size) + CMedianFilter(unsigned int size, T initial_value) : nSize(size) { vValues.reserve(size); vValues.push_back(initial_value); @@ -32,8 +33,7 @@ public: void input(T value) { - if(vValues.size() == nSize) - { + if (vValues.size() == nSize) { vValues.erase(vValues.begin()); } vValues.push_back(value); @@ -46,14 +46,13 @@ public: T median() const { int size = vSorted.size(); - assert(size>0); - if(size & 1) // Odd number of elements + assert(size > 0); + if (size & 1) // Odd number of elements { - return vSorted[size/2]; - } - else // Even number of elements + return vSorted[size / 2]; + } else // Even number of elements { - return (vSorted[size/2-1] + vSorted[size/2]) / 2; + return (vSorted[size / 2 - 1] + vSorted[size / 2]) / 2; } } @@ -62,7 +61,7 @@ public: return vValues.size(); } - std::vector<T> sorted () const + std::vector<T> sorted() const { return vSorted; } diff --git a/src/txdb.cpp b/src/txdb.cpp index 79838b6116..d5f424fabd 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -117,7 +117,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); stats.hashBlock = GetBestBlock(); ss << stats.hashBlock; - int64_t nTotalAmount = 0; + CAmount nTotalAmount = 0; while (pcursor->Valid()) { boost::this_thread::interruption_point(); try { diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 52d07bf6a0..d923c2204a 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -7,6 +7,7 @@ #include "core.h" #include "util.h" +#include "utilmoneystr.h" #include <boost/circular_buffer.hpp> @@ -18,7 +19,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(): nHeight = MEMPOOL_HEIGHT; } -CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, int64_t _nFee, +CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, int64_t _nTime, double _dPriority, unsigned int _nHeight): tx(_tx), nFee(_nFee), nTime(_nTime), dPriority(_dPriority), nHeight(_nHeight) @@ -36,7 +37,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other) double CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const { - int64_t nValueIn = tx.GetValueOut()+nFee; + CAmount nValueIn = tx.GetValueOut()+nFee; double deltaPriority = ((double)(currentHeight-nHeight)*nValueIn)/nModSize; double dResult = dPriority + deltaPriority; return dResult; @@ -601,24 +602,24 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein) return true; } -void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, int64_t nFeeDelta) +void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, const CAmount& nFeeDelta) { { LOCK(cs); - std::pair<double, int64_t> &deltas = mapDeltas[hash]; + std::pair<double, CAmount> &deltas = mapDeltas[hash]; deltas.first += dPriorityDelta; deltas.second += nFeeDelta; } - LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, nFeeDelta); + LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, FormatMoney(nFeeDelta)); } -void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, int64_t &nFeeDelta) +void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta) { LOCK(cs); - std::map<uint256, std::pair<double, int64_t> >::iterator pos = mapDeltas.find(hash); + std::map<uint256, std::pair<double, CAmount> >::iterator pos = mapDeltas.find(hash); if (pos == mapDeltas.end()) return; - const std::pair<double, int64_t> &deltas = pos->second; + const std::pair<double, CAmount> &deltas = pos->second; dPriorityDelta += deltas.first; nFeeDelta += deltas.second; } diff --git a/src/txmempool.h b/src/txmempool.h index b9d50ee0bc..c35ea52d4e 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -29,7 +29,7 @@ class CTxMemPoolEntry { private: CTransaction tx; - int64_t nFee; // Cached to avoid expensive parent-transaction lookups + CAmount nFee; // Cached to avoid expensive parent-transaction lookups size_t nTxSize; // ... and avoid recomputing tx size size_t nModSize; // ... and modified size for priority int64_t nTime; // Local time when entering the mempool @@ -37,14 +37,14 @@ private: unsigned int nHeight; // Chain height when entering the mempool public: - CTxMemPoolEntry(const CTransaction& _tx, int64_t _nFee, + CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, int64_t _nTime, double _dPriority, unsigned int _nHeight); CTxMemPoolEntry(); CTxMemPoolEntry(const CTxMemPoolEntry& other); const CTransaction& GetTx() const { return this->tx; } double GetPriority(unsigned int currentHeight) const; - int64_t GetFee() const { return nFee; } + CAmount GetFee() const { return nFee; } size_t GetTxSize() const { return nTxSize; } int64_t GetTime() const { return nTime; } unsigned int GetHeight() const { return nHeight; } @@ -76,7 +76,7 @@ public: mutable CCriticalSection cs; std::map<uint256, CTxMemPoolEntry> mapTx; std::map<COutPoint, CInPoint> mapNextTx; - std::map<uint256, std::pair<double, int64_t> > mapDeltas; + std::map<uint256, std::pair<double, CAmount> > mapDeltas; CTxMemPool(const CFeeRate& _minRelayFee); ~CTxMemPool(); @@ -102,8 +102,8 @@ public: void AddTransactionsUpdated(unsigned int n); /** Affect CreateNewBlock prioritisation of transactions */ - void PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, int64_t nFeeDelta); - void ApplyDeltas(const uint256 hash, double &dPriorityDelta, int64_t &nFeeDelta); + void PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, const CAmount& nFeeDelta); + void ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta); void ClearPrioritisation(const uint256 hash); unsigned long size() diff --git a/src/uint256.cpp b/src/uint256.cpp index feda0ca5a9..79406f2475 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -10,13 +10,13 @@ #include <stdio.h> #include <string.h> -template<unsigned int BITS> +template <unsigned int BITS> base_uint<BITS>::base_uint(const std::string& str) { SetHex(str); } -template<unsigned int BITS> +template <unsigned int BITS> base_uint<BITS>::base_uint(const std::vector<unsigned char>& vch) { if (vch.size() != sizeof(pn)) @@ -24,7 +24,7 @@ base_uint<BITS>::base_uint(const std::vector<unsigned char>& vch) memcpy(pn, &vch[0], sizeof(pn)); } -template<unsigned int BITS> +template <unsigned int BITS> base_uint<BITS>& base_uint<BITS>::operator<<=(unsigned int shift) { base_uint<BITS> a(*this); @@ -33,15 +33,15 @@ base_uint<BITS>& base_uint<BITS>::operator<<=(unsigned int shift) int k = shift / 32; shift = shift % 32; for (int i = 0; i < WIDTH; i++) { - if (i+k+1 < WIDTH && shift != 0) - pn[i+k+1] |= (a.pn[i] >> (32-shift)); - if (i+k < WIDTH) - pn[i+k] |= (a.pn[i] << shift); + if (i + k + 1 < WIDTH && shift != 0) + pn[i + k + 1] |= (a.pn[i] >> (32 - shift)); + if (i + k < WIDTH) + pn[i + k] |= (a.pn[i] << shift); } return *this; } -template<unsigned int BITS> +template <unsigned int BITS> base_uint<BITS>& base_uint<BITS>::operator>>=(unsigned int shift) { base_uint<BITS> a(*this); @@ -50,15 +50,15 @@ base_uint<BITS>& base_uint<BITS>::operator>>=(unsigned int shift) int k = shift / 32; shift = shift % 32; for (int i = 0; i < WIDTH; i++) { - if (i-k-1 >= 0 && shift != 0) - pn[i-k-1] |= (a.pn[i] << (32-shift)); - if (i-k >= 0) - pn[i-k] |= (a.pn[i] >> shift); + if (i - k - 1 >= 0 && shift != 0) + pn[i - k - 1] |= (a.pn[i] << (32 - shift)); + if (i - k >= 0) + pn[i - k] |= (a.pn[i] >> shift); } return *this; } -template<unsigned int BITS> +template <unsigned int BITS> base_uint<BITS>& base_uint<BITS>::operator*=(uint32_t b32) { uint64_t carry = 0; @@ -70,7 +70,7 @@ base_uint<BITS>& base_uint<BITS>::operator*=(uint32_t b32) return *this; } -template<unsigned int BITS> +template <unsigned int BITS> base_uint<BITS>& base_uint<BITS>::operator*=(const base_uint& b) { base_uint<BITS> a = *this; @@ -86,12 +86,12 @@ base_uint<BITS>& base_uint<BITS>::operator*=(const base_uint& b) return *this; } -template<unsigned int BITS> +template <unsigned int BITS> base_uint<BITS>& base_uint<BITS>::operator/=(const base_uint& b) { - base_uint<BITS> div = b; // make a copy, so we can shift. + base_uint<BITS> div = b; // make a copy, so we can shift. base_uint<BITS> num = *this; // make a copy, so we can subtract. - *this = 0; // the quotient. + *this = 0; // the quotient. int num_bits = num.bits(); int div_bits = div.bits(); if (div_bits == 0) @@ -112,9 +112,10 @@ base_uint<BITS>& base_uint<BITS>::operator/=(const base_uint& b) return *this; } -template<unsigned int BITS> -int base_uint<BITS>::CompareTo(const base_uint<BITS>& b) const { - for (int i = WIDTH-1; i >= 0; i--) { +template <unsigned int BITS> +int base_uint<BITS>::CompareTo(const base_uint<BITS>& b) const +{ + for (int i = WIDTH - 1; i >= 0; i--) { if (pn[i] < b.pn[i]) return -1; if (pn[i] > b.pn[i]) @@ -123,9 +124,10 @@ int base_uint<BITS>::CompareTo(const base_uint<BITS>& b) const { return 0; } -template<unsigned int BITS> -bool base_uint<BITS>::EqualTo(uint64_t b) const { - for (int i = WIDTH-1; i >= 2; i--) { +template <unsigned int BITS> +bool base_uint<BITS>::EqualTo(uint64_t b) const +{ + for (int i = WIDTH - 1; i >= 2; i--) { if (pn[i]) return false; } @@ -136,7 +138,7 @@ bool base_uint<BITS>::EqualTo(uint64_t b) const { return true; } -template<unsigned int BITS> +template <unsigned int BITS> double base_uint<BITS>::getdouble() const { double ret = 0.0; @@ -148,19 +150,19 @@ double base_uint<BITS>::getdouble() const return ret; } -template<unsigned int BITS> +template <unsigned int BITS> std::string base_uint<BITS>::GetHex() const { - char psz[sizeof(pn)*2 + 1]; + char psz[sizeof(pn) * 2 + 1]; for (unsigned int i = 0; i < sizeof(pn); i++) - sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); - return std::string(psz, psz + sizeof(pn)*2); + sprintf(psz + i * 2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); + return std::string(psz, psz + sizeof(pn) * 2); } -template<unsigned int BITS> +template <unsigned int BITS> void base_uint<BITS>::SetHex(const char* psz) { - memset(pn,0,sizeof(pn)); + memset(pn, 0, sizeof(pn)); // skip leading spaces while (isspace(*psz)) @@ -186,28 +188,28 @@ void base_uint<BITS>::SetHex(const char* psz) } } -template<unsigned int BITS> +template <unsigned int BITS> void base_uint<BITS>::SetHex(const std::string& str) { SetHex(str.c_str()); } -template<unsigned int BITS> +template <unsigned int BITS> std::string base_uint<BITS>::ToString() const { return (GetHex()); } -template<unsigned int BITS> +template <unsigned int BITS> unsigned int base_uint<BITS>::bits() const { - for (int pos = WIDTH-1; pos >= 0; pos--) { + for (int pos = WIDTH - 1; pos >= 0; pos--) { if (pn[pos]) { for (int bits = 31; bits > 0; bits--) { - if (pn[pos] & 1<<bits) - return 32*pos + bits + 1; + if (pn[pos] & 1 << bits) + return 32 * pos + bits + 1; } - return 32*pos + 1; + return 32 * pos + 1; } } return 0; @@ -249,16 +251,16 @@ template unsigned int base_uint<256>::bits() const; // This implementation directly uses shifts instead of going // through an intermediate MPI representation. -uint256& uint256::SetCompact(uint32_t nCompact, bool *pfNegative, bool *pfOverflow) +uint256& uint256::SetCompact(uint32_t nCompact, bool* pfNegative, bool* pfOverflow) { int nSize = nCompact >> 24; uint32_t nWord = nCompact & 0x007fffff; if (nSize <= 3) { - nWord >>= 8*(3-nSize); + nWord >>= 8 * (3 - nSize); *this = nWord; } else { *this = nWord; - *this <<= 8*(nSize-3); + *this <<= 8 * (nSize - 3); } if (pfNegative) *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0; @@ -274,9 +276,9 @@ uint32_t uint256::GetCompact(bool fNegative) const int nSize = (bits() + 7) / 8; uint32_t nCompact = 0; if (nSize <= 3) { - nCompact = GetLow64() << 8*(3-nSize); + nCompact = GetLow64() << 8 * (3 - nSize); } else { - uint256 bn = *this >> 8*(nSize-3); + uint256 bn = *this >> 8 * (nSize - 3); nCompact = bn.GetLow64(); } // The 0x00800000 bit denotes the sign. @@ -295,27 +297,46 @@ uint32_t uint256::GetCompact(bool fNegative) const static void inline HashMix(uint32_t& a, uint32_t& b, uint32_t& c) { // Taken from lookup3, by Bob Jenkins. - a -= c; a ^= ((c << 4) | (c >> 28)); c += b; - b -= a; b ^= ((a << 6) | (a >> 26)); a += c; - c -= b; c ^= ((b << 8) | (b >> 24)); b += a; - a -= c; a ^= ((c << 16) | (c >> 16)); c += b; - b -= a; b ^= ((a << 19) | (a >> 13)); a += c; - c -= b; c ^= ((b << 4) | (b >> 28)); b += a; + a -= c; + a ^= ((c << 4) | (c >> 28)); + c += b; + b -= a; + b ^= ((a << 6) | (a >> 26)); + a += c; + c -= b; + c ^= ((b << 8) | (b >> 24)); + b += a; + a -= c; + a ^= ((c << 16) | (c >> 16)); + c += b; + b -= a; + b ^= ((a << 19) | (a >> 13)); + a += c; + c -= b; + c ^= ((b << 4) | (b >> 28)); + b += a; } static void inline HashFinal(uint32_t& a, uint32_t& b, uint32_t& c) { // Taken from lookup3, by Bob Jenkins. - c ^= b; c -= ((b << 14) | (b >> 18)); - a ^= c; a -= ((c << 11) | (c >> 21)); - b ^= a; b -= ((a << 25) | (a >> 7)); - c ^= b; c -= ((b << 16) | (b >> 16)); - a ^= c; a -= ((c << 4) | (c >> 28)); - b ^= a; b -= ((a << 14) | (a >> 18)); - c ^= b; c -= ((b << 24) | (b >> 8)); + c ^= b; + c -= ((b << 14) | (b >> 18)); + a ^= c; + a -= ((c << 11) | (c >> 21)); + b ^= a; + b -= ((a << 25) | (a >> 7)); + c ^= b; + c -= ((b << 16) | (b >> 16)); + a ^= c; + a -= ((c << 4) | (c >> 28)); + b ^= a; + b -= ((a << 14) | (a >> 18)); + c ^= b; + c -= ((b << 24) | (b >> 8)); } -uint64_t uint256::GetHash(const uint256 &salt) const +uint64_t uint256::GetHash(const uint256& salt) const { uint32_t a, b, c; a = b = c = 0xdeadbeef + (WIDTH << 2); diff --git a/src/util.cpp b/src/util.cpp index 0ac0f70a79..632d0965bf 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -472,6 +472,7 @@ void ReadConfigFile(map<string, string>& mapSettingsRet, ClearDatadirCache(); } +#ifndef WIN32 boost::filesystem::path GetPidFile() { boost::filesystem::path pathPidFile(GetArg("-pid", "bitcoind.pid")); @@ -479,7 +480,6 @@ boost::filesystem::path GetPidFile() return pathPidFile; } -#ifndef WIN32 void CreatePidFile(const boost::filesystem::path &path, pid_t pid) { FILE* file = fopen(path.string().c_str(), "w"); @@ -618,7 +618,7 @@ void ShrinkDebugFile() { // Restart the file with some of the end std::vector <char> vch(200000,0); - fseek(file, -vch.size(), SEEK_END); + fseek(file, -((long)vch.size()), SEEK_END); int nBytes = fread(begin_ptr(vch), 1, vch.size(), file); fclose(file); diff --git a/src/util.h b/src/util.h index e72c99adc7..4b2415278b 100644 --- a/src/util.h +++ b/src/util.h @@ -93,8 +93,8 @@ bool TryCreateDirectory(const boost::filesystem::path& p); boost::filesystem::path GetDefaultDataDir(); const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); boost::filesystem::path GetConfigFile(); -boost::filesystem::path GetPidFile(); #ifndef WIN32 +boost::filesystem::path GetPidFile(); void CreatePidFile(const boost::filesystem::path &path, pid_t pid); #endif void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet); diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp index c169355f05..1a5635bfb8 100644 --- a/src/utilmoneystr.cpp +++ b/src/utilmoneystr.cpp @@ -10,7 +10,7 @@ using namespace std; -string FormatMoney(int64_t n, bool fPlus) +string FormatMoney(const CAmount& n, bool fPlus) { // Note: not using straight sprintf here because we do NOT want // localized number formatting. @@ -34,12 +34,12 @@ string FormatMoney(int64_t n, bool fPlus) } -bool ParseMoney(const string& str, int64_t& nRet) +bool ParseMoney(const string& str, CAmount& nRet) { return ParseMoney(str.c_str(), nRet); } -bool ParseMoney(const char* pszIn, int64_t& nRet) +bool ParseMoney(const char* pszIn, CAmount& nRet) { string strWhole; int64_t nUnits = 0; @@ -73,7 +73,7 @@ bool ParseMoney(const char* pszIn, int64_t& nRet) if (nUnits < 0 || nUnits > COIN) return false; int64_t nWhole = atoi64(strWhole); - int64_t nValue = nWhole*COIN + nUnits; + CAmount nValue = nWhole*COIN + nUnits; nRet = nValue; return true; diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h index f0c61aa138..65415afd3f 100644 --- a/src/utilmoneystr.h +++ b/src/utilmoneystr.h @@ -12,8 +12,10 @@ #include <stdint.h> #include <string> -std::string FormatMoney(int64_t n, bool fPlus=false); -bool ParseMoney(const std::string& str, int64_t& nRet); -bool ParseMoney(const char* pszIn, int64_t& nRet); +#include "amount.h" + +std::string FormatMoney(const CAmount& n, bool fPlus=false); +bool ParseMoney(const std::string& str, CAmount& nRet); +bool ParseMoney(const char* pszIn, CAmount& nRet); #endif // BITCOIN_UTILMONEYSTR_H diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 2cec3023b5..b9e64c5fe1 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -16,7 +16,7 @@ using namespace std; // safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything // even possibly remotely dangerous like & or > -static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@"); +static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@()"); string SanitizeString(const string& str) { string strResult; diff --git a/src/version.cpp b/src/version.cpp index e441cc463f..95632fdab7 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -16,7 +16,7 @@ const std::string CLIENT_NAME("Satoshi"); // Client version number -#define CLIENT_VERSION_SUFFIX "" +#define CLIENT_VERSION_SUFFIX "" // The following part of the code determines the CLIENT_BUILD variable. @@ -35,40 +35,40 @@ const std::string CLIENT_NAME("Satoshi"); // First, include build.h if requested #ifdef HAVE_BUILD_INFO -# include "build.h" +#include "build.h" #endif // git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$ #ifdef GIT_ARCHIVE -# define GIT_COMMIT_ID "$Format:%h$" -# define GIT_COMMIT_DATE "$Format:%cD$" +#define GIT_COMMIT_ID "$Format:%h$" +#define GIT_COMMIT_DATE "$Format:%cD$" #endif -#define BUILD_DESC_WITH_SUFFIX(maj,min,rev,build,suffix) \ +#define BUILD_DESC_WITH_SUFFIX(maj, min, rev, build, suffix) \ "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-" DO_STRINGIZE(suffix) -#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \ +#define BUILD_DESC_FROM_COMMIT(maj, min, rev, build, commit) \ "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit -#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \ +#define BUILD_DESC_FROM_UNKNOWN(maj, min, rev, build) \ "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk" #ifndef BUILD_DESC -# ifdef BUILD_SUFFIX -# define BUILD_DESC BUILD_DESC_WITH_SUFFIX(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, BUILD_SUFFIX) -# elif defined(GIT_COMMIT_ID) -# define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID) -# else -# define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) -# endif +#ifdef BUILD_SUFFIX +#define BUILD_DESC BUILD_DESC_WITH_SUFFIX(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, BUILD_SUFFIX) +#elif defined(GIT_COMMIT_ID) +#define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID) +#else +#define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) +#endif #endif #ifndef BUILD_DATE -# ifdef GIT_COMMIT_DATE -# define BUILD_DATE GIT_COMMIT_DATE -# else -# define BUILD_DATE __DATE__ ", " __TIME__ -# endif +#ifdef GIT_COMMIT_DATE +#define BUILD_DATE GIT_COMMIT_DATE +#else +#define BUILD_DATE __DATE__ ", " __TIME__ +#endif #endif const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX); @@ -76,10 +76,10 @@ const std::string CLIENT_DATE(BUILD_DATE); static std::string FormatVersion(int nVersion) { - if (nVersion%100 == 0) - return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100); + 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); + return strprintf("%d.%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, nVersion % 100); } std::string FormatFullVersion() diff --git a/src/wallet.cpp b/src/wallet.cpp index 6bfaec3681..b20b0007ce 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -35,8 +35,8 @@ CFeeRate CWallet::minTxFee = CFeeRate(10000); // Override with -mintxfee struct CompareValueOnly { - bool operator()(const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t1, - const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t2) const + bool operator()(const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t1, + const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t2) const { return t1.first < t2.first; } @@ -646,7 +646,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl CWalletTx wtx(this,tx); // Get merkle branch if transaction was found in a block if (pblock) - wtx.SetMerkleBranch(pblock); + wtx.SetMerkleBranch(*pblock); return AddToWallet(wtx); } } @@ -697,7 +697,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const return ISMINE_NO; } -int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const +CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const { { LOCK(cs_wallet); @@ -781,7 +781,7 @@ int CWalletTx::GetRequestCount() const } void CWalletTx::GetAmounts(list<COutputEntry>& listReceived, - list<COutputEntry>& listSent, int64_t& nFee, string& strSentAccount, const isminefilter& filter) const + list<COutputEntry>& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const { nFee = 0; listReceived.clear(); @@ -789,10 +789,10 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived, strSentAccount = strFromAccount; // Compute fee: - int64_t nDebit = GetDebit(filter); + CAmount nDebit = GetDebit(filter); if (nDebit > 0) // debit>0 means we signed/sent this transaction { - int64_t nValueOut = GetValueOut(); + CAmount nValueOut = GetValueOut(); nFee = nDebit - nValueOut; } @@ -835,12 +835,12 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived, } -void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee, const isminefilter& filter) const +void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived, + CAmount& nSent, CAmount& nFee, const isminefilter& filter) const { nReceived = nSent = nFee = 0; - int64_t allFee; + CAmount allFee; string strSentAccount; list<COutputEntry> listReceived; list<COutputEntry> listSent; @@ -1011,9 +1011,9 @@ void CWallet::ResendWalletTransactions() // -int64_t CWallet::GetBalance() const +CAmount CWallet::GetBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1027,9 +1027,9 @@ int64_t CWallet::GetBalance() const return nTotal; } -int64_t CWallet::GetUnconfirmedBalance() const +CAmount CWallet::GetUnconfirmedBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1042,9 +1042,9 @@ int64_t CWallet::GetUnconfirmedBalance() const return nTotal; } -int64_t CWallet::GetImmatureBalance() const +CAmount CWallet::GetImmatureBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1056,9 +1056,9 @@ int64_t CWallet::GetImmatureBalance() const return nTotal; } -int64_t CWallet::GetWatchOnlyBalance() const +CAmount CWallet::GetWatchOnlyBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1072,9 +1072,9 @@ int64_t CWallet::GetWatchOnlyBalance() const return nTotal; } -int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const +CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1087,9 +1087,9 @@ int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const return nTotal; } -int64_t CWallet::GetImmatureWatchOnlyBalance() const +CAmount CWallet::GetImmatureWatchOnlyBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1137,8 +1137,8 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const } } -static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > >vValue, int64_t nTotalLower, int64_t nTargetValue, - vector<char>& vfBest, int64_t& nBest, int iterations = 1000) +static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, + vector<char>& vfBest, CAmount& nBest, int iterations = 1000) { vector<char> vfIncluded; @@ -1150,7 +1150,7 @@ static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,uns for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++) { vfIncluded.assign(vValue.size(), false); - int64_t nTotal = 0; + CAmount nTotal = 0; bool fReachedTarget = false; for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++) { @@ -1183,18 +1183,18 @@ static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,uns } } -bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins, - set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const +bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins, + set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const { setCoinsRet.clear(); nValueRet = 0; // List of values less than target - pair<int64_t, pair<const CWalletTx*,unsigned int> > coinLowestLarger; - coinLowestLarger.first = std::numeric_limits<int64_t>::max(); + pair<CAmount, pair<const CWalletTx*,unsigned int> > coinLowestLarger; + coinLowestLarger.first = std::numeric_limits<CAmount>::max(); coinLowestLarger.second.first = NULL; - vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > > vValue; - int64_t nTotalLower = 0; + vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > > vValue; + CAmount nTotalLower = 0; random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); @@ -1209,9 +1209,9 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT continue; int i = output.i; - int64_t n = pcoin->vout[i].nValue; + CAmount n = pcoin->vout[i].nValue; - pair<int64_t,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i)); + pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i)); if (n == nTargetValue) { @@ -1252,7 +1252,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT // Solve subset sum by stochastic approximation sort(vValue.rbegin(), vValue.rend(), CompareValueOnly()); vector<char> vfBest; - int64_t nBest; + CAmount nBest; ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000); if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT) @@ -1284,7 +1284,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT return true; } -bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl* coinControl) const +bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const { vector<COutput> vCoins; AvailableCoins(vCoins, true, coinControl); @@ -1310,11 +1310,11 @@ bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsign -bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) +bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend, + CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) { - int64_t nValue = 0; - BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) + CAmount nValue = 0; + BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend) { if (nValue < 0) { @@ -1343,10 +1343,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, txNew.vout.clear(); wtxNew.fFromMe = true; - int64_t nTotalValue = nValue + nFeeRet; + CAmount nTotalValue = nValue + nFeeRet; double dPriority = 0; // vouts to the payees - BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) + BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend) { CTxOut txout(s.second, s.first); if (txout.IsDust(::minRelayTxFee)) @@ -1359,7 +1359,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, // Choose coins to use set<pair<const CWalletTx*,unsigned int> > setCoins; - int64_t nValueIn = 0; + CAmount nValueIn = 0; if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl)) { strFailReason = _("Insufficient funds"); @@ -1367,14 +1367,14 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, } BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) { - int64_t nCredit = pcoin.first->vout[pcoin.second].nValue; + CAmount nCredit = pcoin.first->vout[pcoin.second].nValue; //The priority after the next block (depth+1) is used instead of the current, //reflecting an assumption the user would accept a bit more delay for //a chance at a free transaction. dPriority += (double)nCredit * (pcoin.first->GetDepthInMainChain()+1); } - int64_t nChange = nValueIn - nValue - nFeeRet; + CAmount nChange = nValueIn - nValue - nFeeRet; if (nChange > 0) { @@ -1450,7 +1450,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, } dPriority = wtxNew.ComputePriority(dPriority, nBytes); - int64_t nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); + CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); if (nFeeRet >= nFeeNeeded) break; // Done, enough fee included. @@ -1481,10 +1481,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, return true; } -bool CWallet::CreateTransaction(CScript scriptPubKey, int64_t nValue, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) +bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue, + CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) { - vector< pair<CScript, int64_t> > vecSend; + vector< pair<CScript, CAmount> > vecSend; vecSend.push_back(make_pair(scriptPubKey, nValue)); return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl); } @@ -1539,7 +1539,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) -string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew) +string CWallet::SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew) { // Check amount if (nValue <= 0) @@ -1560,7 +1560,7 @@ string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWallet // Create and send the transaction CReserveKey reservekey(this); - int64_t nFeeRequired; + CAmount nFeeRequired; if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError)) { if (nValue + nFeeRequired > GetBalance()) @@ -1576,10 +1576,10 @@ string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWallet -int64_t CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) +CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) { // payTxFee is user-set "I want to pay this much" - int64_t nFeeNeeded = payTxFee.GetFee(nTxBytes); + CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes); // User didn't set: use -txconfirmtarget to estimate... if (nFeeNeeded == 0) nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes); @@ -1838,9 +1838,9 @@ int64_t CWallet::GetOldestKeyPoolTime() return keypool.nTime; } -std::map<CTxDestination, int64_t> CWallet::GetAddressBalances() +std::map<CTxDestination, CAmount> CWallet::GetAddressBalances() { - map<CTxDestination, int64_t> balances; + map<CTxDestination, CAmount> balances; { LOCK(cs_wallet); @@ -1866,7 +1866,7 @@ std::map<CTxDestination, int64_t> CWallet::GetAddressBalances() if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr)) continue; - int64_t n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue; + CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue; if (!balances.count(addr)) balances[addr] = 0; @@ -2229,48 +2229,34 @@ CWalletKey::CWalletKey(int64_t nExpires) nTimeExpires = nExpires; } -int CMerkleTx::SetMerkleBranch(const CBlock* pblock) +int CMerkleTx::SetMerkleBranch(const CBlock& block) { AssertLockHeld(cs_main); CBlock blockTmp; - if (pblock == NULL) { - CCoins coins; - if (pcoinsTip->GetCoins(GetHash(), coins)) { - CBlockIndex *pindex = chainActive[coins.nHeight]; - if (pindex) { - if (!ReadBlockFromDisk(blockTmp, pindex)) - return 0; - pblock = &blockTmp; - } - } - } - - if (pblock) { - // Update the tx's hashBlock - hashBlock = pblock->GetHash(); - - // Locate the transaction - for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++) - if (pblock->vtx[nIndex] == *(CTransaction*)this) - break; - if (nIndex == (int)pblock->vtx.size()) - { - vMerkleBranch.clear(); - nIndex = -1; - LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n"); - return 0; - } + // Update the tx's hashBlock + hashBlock = block.GetHash(); - // Fill in merkle branch - vMerkleBranch = pblock->GetMerkleBranch(nIndex); + // Locate the transaction + for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++) + if (block.vtx[nIndex] == *(CTransaction*)this) + break; + if (nIndex == (int)block.vtx.size()) + { + vMerkleBranch.clear(); + nIndex = -1; + LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n"); + return 0; } + // Fill in merkle branch + vMerkleBranch = block.GetMerkleBranch(nIndex); + // Is the tx in a block that's in the main chain BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi == mapBlockIndex.end()) return 0; - CBlockIndex* pindex = (*mi).second; + const CBlockIndex* pindex = (*mi).second; if (!pindex || !chainActive.Contains(pindex)) return 0; diff --git a/src/wallet.h b/src/wallet.h index 3461446b8b..f3fffb2253 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -30,9 +30,9 @@ extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; // -paytxfee default -static const int64_t DEFAULT_TRANSACTION_FEE = 0; +static const CAmount DEFAULT_TRANSACTION_FEE = 0; // -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB -static const int nHighTransactionFeeWarning = 0.01 * COIN; +static const CAmount nHighTransactionFeeWarning = 0.01 * COIN; // Largest (in bytes) free transaction we're willing to create static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; @@ -98,7 +98,7 @@ public: class CWallet : public CCryptoKeyStore, public CWalletInterface { private: - bool SelectCoins(int64_t nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl *coinControl = NULL) const; + bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const; CWalletDB *pwalletdbEncryption; @@ -182,7 +182,7 @@ public: bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL) const; - bool SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const; + bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const; bool IsSpent(const uint256& hash, unsigned int n) const; @@ -253,21 +253,21 @@ public: int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); void ResendWalletTransactions(); - int64_t GetBalance() const; - int64_t GetUnconfirmedBalance() const; - int64_t GetImmatureBalance() const; - int64_t GetWatchOnlyBalance() const; - int64_t GetUnconfirmedWatchOnlyBalance() const; - int64_t GetImmatureWatchOnlyBalance() const; - bool CreateTransaction(const std::vector<std::pair<CScript, int64_t> >& vecSend, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); - bool CreateTransaction(CScript scriptPubKey, int64_t nValue, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); + CAmount GetBalance() const; + CAmount GetUnconfirmedBalance() const; + CAmount GetImmatureBalance() const; + CAmount GetWatchOnlyBalance() const; + CAmount GetUnconfirmedWatchOnlyBalance() const; + CAmount GetImmatureWatchOnlyBalance() const; + bool CreateTransaction(const std::vector<std::pair<CScript, CAmount> >& vecSend, + CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); + bool CreateTransaction(CScript scriptPubKey, const CAmount& nValue, + CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); - std::string SendMoney(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew); + std::string SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew); static CFeeRate minTxFee; - static int64_t GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); + static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); bool NewKeyPool(); bool TopUpKeyPool(unsigned int kpSize = 0); @@ -279,24 +279,24 @@ public: void GetAllReserveKeys(std::set<CKeyID>& setAddress) const; std::set< std::set<CTxDestination> > GetAddressGroupings(); - std::map<CTxDestination, int64_t> GetAddressBalances(); + std::map<CTxDestination, CAmount> GetAddressBalances(); std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const; isminetype IsMine(const CTxIn& txin) const; - int64_t GetDebit(const CTxIn& txin, const isminefilter& filter) const; + CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const; isminetype IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); } - int64_t GetCredit(const CTxOut& txout, const isminefilter& filter) const + CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); return ((IsMine(txout) & filter) ? txout.nValue : 0); } bool IsChange(const CTxOut& txout) const; - int64_t GetChange(const CTxOut& txout) const + CAmount GetChange(const CTxOut& txout) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetChange() : value out of range"); @@ -313,9 +313,9 @@ public: { return (GetDebit(tx, ISMINE_ALL) > 0); } - int64_t GetDebit(const CTransaction& tx, const isminefilter& filter) const + CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const { - int64_t nDebit = 0; + CAmount nDebit = 0; BOOST_FOREACH(const CTxIn& txin, tx.vin) { nDebit += GetDebit(txin, filter); @@ -324,9 +324,9 @@ public: } return nDebit; } - int64_t GetCredit(const CTransaction& tx, const isminefilter& filter) const + CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const { - int64_t nCredit = 0; + CAmount nCredit = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) { nCredit += GetCredit(txout, filter); @@ -335,9 +335,9 @@ public: } return nCredit; } - int64_t GetChange(const CTransaction& tx) const + CAmount GetChange(const CTransaction& tx) const { - int64_t nChange = 0; + CAmount nChange = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) { nChange += GetChange(txout); @@ -457,7 +457,7 @@ static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue) struct COutputEntry { CTxDestination destination; - int64_t amount; + CAmount amount; int vout; }; @@ -504,7 +504,7 @@ public: READWRITE(nIndex); } - int SetMerkleBranch(const CBlock* pblock=NULL); + int SetMerkleBranch(const CBlock& block); // Return depth of transaction in blockchain: // -1 : not in blockchain, and not in memory pool (conflicted transaction) @@ -545,15 +545,15 @@ public: mutable bool fImmatureWatchCreditCached; mutable bool fAvailableWatchCreditCached; mutable bool fChangeCached; - mutable int64_t nDebitCached; - mutable int64_t nCreditCached; - mutable int64_t nImmatureCreditCached; - mutable int64_t nAvailableCreditCached; - mutable int64_t nWatchDebitCached; - mutable int64_t nWatchCreditCached; - mutable int64_t nImmatureWatchCreditCached; - mutable int64_t nAvailableWatchCreditCached; - mutable int64_t nChangeCached; + mutable CAmount nDebitCached; + mutable CAmount nCreditCached; + mutable CAmount nImmatureCreditCached; + mutable CAmount nAvailableCreditCached; + mutable CAmount nWatchDebitCached; + mutable CAmount nWatchCreditCached; + mutable CAmount nImmatureWatchCreditCached; + mutable CAmount nAvailableWatchCreditCached; + mutable CAmount nChangeCached; CWalletTx() { @@ -670,12 +670,12 @@ public: } // filter decides which addresses will count towards the debit - int64_t GetDebit(const isminefilter& filter) const + CAmount GetDebit(const isminefilter& filter) const { if (vin.empty()) return 0; - int64_t debit = 0; + CAmount debit = 0; if(filter & ISMINE_SPENDABLE) { if (fDebitCached) @@ -701,7 +701,7 @@ public: return debit; } - int64_t GetCredit(bool fUseCache=true) const + CAmount GetCredit(bool fUseCache=true) const { // Must wait until coinbase is safely deep enough in the chain before valuing it if (IsCoinBase() && GetBlocksToMaturity() > 0) @@ -715,7 +715,7 @@ public: return nCreditCached; } - int64_t GetImmatureCredit(bool fUseCache=true) const + CAmount GetImmatureCredit(bool fUseCache=true) const { if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain()) { @@ -729,7 +729,7 @@ public: return 0; } - int64_t GetAvailableCredit(bool fUseCache=true) const + CAmount GetAvailableCredit(bool fUseCache=true) const { if (pwallet == 0) return 0; @@ -741,7 +741,7 @@ public: if (fUseCache && fAvailableCreditCached) return nAvailableCreditCached; - int64_t nCredit = 0; + CAmount nCredit = 0; uint256 hashTx = GetHash(); for (unsigned int i = 0; i < vout.size(); i++) { @@ -759,7 +759,7 @@ public: return nCredit; } - int64_t GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const + CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const { if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain()) { @@ -773,7 +773,7 @@ public: return 0; } - int64_t GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const + CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const { if (pwallet == 0) return 0; @@ -785,7 +785,7 @@ public: if (fUseCache && fAvailableWatchCreditCached) return nAvailableWatchCreditCached; - int64_t nCredit = 0; + CAmount nCredit = 0; for (unsigned int i = 0; i < vout.size(); i++) { if (!pwallet->IsSpent(GetHash(), i)) @@ -802,7 +802,7 @@ public: return nCredit; } - int64_t GetChange() const + CAmount GetChange() const { if (fChangeCached) return nChangeCached; @@ -812,10 +812,10 @@ public: } void GetAmounts(std::list<COutputEntry>& listReceived, - std::list<COutputEntry>& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter) const; + std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const; - void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee, const isminefilter& filter) const; + void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived, + CAmount& nSent, CAmount& nFee, const isminefilter& filter) const; bool IsFromMe(const isminefilter& filter) const { @@ -949,7 +949,7 @@ class CAccountingEntry { public: std::string strAccount; - int64_t nCreditDebit; + CAmount nCreditDebit; int64_t nTime; std::string strOtherAccount; std::string strComment; diff --git a/src/walletdb.cpp b/src/walletdb.cpp index a84f44db01..3e5a664a5d 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -187,12 +187,12 @@ bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry) return WriteAccountingEntry(++nAccountingEntryNumber, acentry); } -int64_t CWalletDB::GetAccountCreditDebit(const string& strAccount) +CAmount CWalletDB::GetAccountCreditDebit(const string& strAccount) { list<CAccountingEntry> entries; ListAccountCreditDebit(strAccount, entries); - int64_t nCreditDebit = 0; + CAmount nCreditDebit = 0; BOOST_FOREACH (const CAccountingEntry& entry, entries) nCreditDebit += entry.nCreditDebit; @@ -391,13 +391,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, wss.fAnyUnordered = true; pwallet->AddToWallet(wtx, true); - //// debug print - //LogPrintf("LoadWallet %s\n", wtx.GetHash().ToString()); - //LogPrintf(" %12d %s %s %s\n", - // wtx.vout[0].nValue, - // DateTimeStrFormat("%Y-%m-%d %H:%M:%S", wtx.GetBlockTime()), - // wtx.hashBlock.ToString(), - // wtx.mapValue["message"]); } else if (strType == "acentry") { @@ -708,7 +701,6 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash, vector<CWalletTx>& vWtx) { pwallet->vchDefaultKey = CPubKey(); - CWalletScanState wss; bool fNoncriticalErrors = false; DBErrors result = DB_LOAD_OK; diff --git a/src/walletdb.h b/src/walletdb.h index 2c5b608f3d..f3d6e61f8b 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_WALLETDB_H #define BITCOIN_WALLETDB_H +#include "amount.h" #include "db.h" #include "key.h" #include "keystore.h" @@ -118,7 +119,7 @@ public: bool EraseDestData(const std::string &address, const std::string &key); bool WriteAccountingEntry(const CAccountingEntry& acentry); - int64_t GetAccountCreditDebit(const std::string& strAccount); + CAmount GetAccountCreditDebit(const std::string& strAccount); void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries); DBErrors ReorderTransactions(CWallet* pwallet); |