diff --git a/main.cpp b/main.cpp index 31b6d1f4..17575607 100644 --- a/main.cpp +++ b/main.cpp @@ -898,14 +898,7 @@ bool IsInitialBlockDownload() pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60); } -bool IsLockdown() -{ - if (!pindexBest) - return false; - return (bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6); -} - -void Lockdown(CBlockIndex* pindexNew) +void InvalidChainFound(CBlockIndex* pindexNew) { if (pindexNew->bnChainWork > bnBestInvalidWork) { @@ -913,11 +906,10 @@ void Lockdown(CBlockIndex* pindexNew) CTxDB().WriteBestInvalidWork(bnBestInvalidWork); MainFrameRepaint(); } - printf("Lockdown: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str()); - printf("Lockdown: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str()); - printf("Lockdown: IsLockdown()=%d\n", (IsLockdown() ? 1 : 0)); - if (IsLockdown()) - printf("Lockdown: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n"); + printf("InvalidChainFound: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str()); + printf("InvalidChainFound: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str()); + if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6) + printf("InvalidChainFound: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n"); } @@ -927,6 +919,9 @@ void Lockdown(CBlockIndex* pindexNew) + + + bool CTransaction::DisconnectInputs(CTxDB& txdb) { // Relinquish previous transactions' spent pointers @@ -1282,7 +1277,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash)) { txdb.TxnAbort(); - Lockdown(pindexNew); + InvalidChainFound(pindexNew); return error("SetBestChain() : ConnectBlock failed"); } txdb.TxnCommit(); @@ -1298,7 +1293,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) if (!Reorganize(txdb, pindexNew)) { txdb.TxnAbort(); - Lockdown(pindexNew); + InvalidChainFound(pindexNew); return error("SetBestChain() : Reorganize failed"); } } @@ -1571,16 +1566,16 @@ bool ScanMessageStart(Stream& s) } } -bool CheckDiskSpace(int64 nAdditionalBytes) +bool CheckDiskSpace(uint64 nAdditionalBytes) { uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available; // Check for 15MB because database could create another 10MB log file at any time - if (nFreeBytesAvailable < (int64)15000000 + nAdditionalBytes) + if (nFreeBytesAvailable < (uint64)15000000 + nAdditionalBytes) { fShutdown = true; string strMessage = _("Warning: Disk space is low "); - strWarning = strMessage; + strMiscWarning = strMessage; printf("*** %s\n", strMessage.c_str()); ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION); CreateThread(Shutdown, NULL); @@ -1648,17 +1643,7 @@ bool LoadBlockIndex(bool fAllowNew) if (!fAllowNew) return false; - // Genesis Block: - // GetHash() = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f - // hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b - // txNew.vin[0].scriptSig = 486604799 4 0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854 - // txNew.vout[0].nValue = 5000000000 - // txNew.vout[0].scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG - // block.nVersion = 1 - // block.nTime = 1231006505 - // block.nBits = 0x1d00ffff - // block.nNonce = 2083236893 // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1) // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0) // CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73) @@ -1672,9 +1657,7 @@ bool LoadBlockIndex(bool fAllowNew) txNew.vout.resize(1); txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); txNew.vout[0].nValue = 50 * COIN; - CBigNum bnPubKey; - bnPubKey.SetHex("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704"); - txNew.vout[0].scriptPubKey = CScript() << bnPubKey << OP_CHECKSIG; + txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; CBlock block; block.vtx.push_back(txNew); block.hashPrevBlock = 0; @@ -1686,11 +1669,10 @@ bool LoadBlockIndex(bool fAllowNew) //// debug print printf("%s\n", block.GetHash().ToString().c_str()); - printf("%s\n", block.hashMerkleRoot.ToString().c_str()); printf("%s\n", hashGenesisBlock.ToString().c_str()); - txNew.vout[0].scriptPubKey.print(); - block.print(); + printf("%s\n", block.hashMerkleRoot.ToString().c_str()); assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); + block.print(); assert(block.GetHash() == hashGenesisBlock); @@ -1798,6 +1780,111 @@ void PrintBlockTree() +////////////////////////////////////////////////////////////////////////////// +// +// CAlert +// + +map mapAlerts; +CCriticalSection cs_mapAlerts; + +string GetWarnings(string strFor) +{ + int nPriority = 0; + string strStatusBar; + string strRPC; + + // Misc warnings like out of disk space and clock is wrong + if (strMiscWarning != "") + { + nPriority = 1000; + strStatusBar = strMiscWarning; + } + + // Longer invalid proof-of-work chain + if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6) + { + nPriority = 2000; + strStatusBar = strRPC = "WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."; + } + + // Alerts + CRITICAL_BLOCK(cs_mapAlerts) + { + foreach(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) + { + const CAlert& alert = item.second; + if (alert.AppliesToMe() && alert.nPriority > nPriority) + { + nPriority = alert.nPriority; + strStatusBar = alert.strStatusBar; + strRPC = alert.strRPCError; + } + } + } + + if (strFor == "statusbar") + return strStatusBar; + else if (strFor == "rpc") + return strRPC; + assert(("GetWarnings() : invalid parameter", false)); + return "error"; +} + +bool CAlert::ProcessAlert() +{ + if (!CheckSignature()) + return false; + if (!IsInEffect()) + return false; + + CRITICAL_BLOCK(cs_mapAlerts) + { + // Cancel previous alerts + for (map::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();) + { + const CAlert& alert = (*mi).second; + if (Cancels(alert)) + { + printf("cancelling alert %d\n", alert.nID); + mapAlerts.erase(mi++); + } + else if (!alert.IsInEffect()) + { + printf("expiring alert %d\n", alert.nID); + mapAlerts.erase(mi++); + } + else + mi++; + } + + // Check if this alert has been cancelled + foreach(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) + { + const CAlert& alert = item.second; + if (alert.Cancels(*this)) + { + printf("alert already cancelled by %d\n", alert.nID); + return false; + } + } + + // Add to mapAlerts + mapAlerts.insert(make_pair(GetHash(), *this)); + } + + printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe()); + MainFrameRepaint(); + return true; +} + + + + + + + + ////////////////////////////////////////////////////////////////////////////// // // Messages @@ -1827,7 +1914,7 @@ bool ProcessMessages(CNode* pfrom) if (vRecv.empty()) return true; //if (fDebug) - // printf("ProcessMessages(%d bytes)\n", vRecv.size()); + // printf("ProcessMessages(%u bytes)\n", vRecv.size()); // // Message format @@ -1869,6 +1956,11 @@ bool ProcessMessages(CNode* pfrom) // Message size unsigned int nMessageSize = hdr.nMessageSize; + if (nMessageSize > MAX_SIZE) + { + printf("ProcessMessage(%s, %u bytes) : nMessageSize > MAX_SIZE\n", strCommand.c_str(), nMessageSize); + continue; + } if (nMessageSize > vRecv.size()) { // Rewind and wait for rest of message @@ -1889,7 +1981,7 @@ bool ProcessMessages(CNode* pfrom) memcpy(&nChecksum, &hash, sizeof(nChecksum)); if (nChecksum != hdr.nChecksum) { - printf("ProcessMessage(%s, %d bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n", + printf("ProcessMessage(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n", strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum); continue; } @@ -1906,15 +1998,15 @@ bool ProcessMessages(CNode* pfrom) } catch (std::ios_base::failure& e) { - if (strstr(e.what(), "CDataStream::read() : end of data")) + if (strstr(e.what(), "end of data")) { // Allow exceptions from underlength message on vRecv - printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what()); + printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what()); } - else if (strstr(e.what(), ": size too large")) + else if (strstr(e.what(), "size too large")) { // Allow exceptions from overlong size - printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what()); + printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what()); } else { @@ -1928,7 +2020,7 @@ bool ProcessMessages(CNode* pfrom) } if (!fRet) - printf("ProcessMessage(%s, %d bytes) FAILED\n", strCommand.c_str(), nMessageSize); + printf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize); } vRecv.Compact(); @@ -1965,14 +2057,13 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CAddress addrMe; CAddress addrFrom; uint64 nNonce = 1; - string strSubVer; vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe; if (pfrom->nVersion == 10300) pfrom->nVersion = 300; if (pfrom->nVersion >= 106 && !vRecv.empty()) vRecv >> addrFrom >> nNonce; if (pfrom->nVersion >= 106 && !vRecv.empty()) - vRecv >> strSubVer; + vRecv >> pfrom->strSubVer; if (pfrom->nVersion >= 209 && !vRecv.empty()) vRecv >> pfrom->nStartingHeight; @@ -2010,6 +2101,11 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->PushGetBlocks(pindexBest, uint256(0)); } + // Relay alerts + CRITICAL_BLOCK(cs_mapAlerts) + foreach(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) + item.second.RelayTo(pfrom); + pfrom->fSuccessfullyConnected = true; printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight); @@ -2362,6 +2458,22 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } + else if (strCommand == "alert") + { + CAlert alert; + vRecv >> alert; + + if (alert.ProcessAlert()) + { + // Relay + pfrom->setKnown.insert(alert.GetHash()); + CRITICAL_BLOCK(cs_vNodes) + foreach(CNode* pnode, vNodes) + alert.RelayTo(pnode); + } + } + + else { // Ignore unknown commands for extensibility @@ -2695,7 +2807,7 @@ void BitcoinMiner() map mapTestPool; vector vfAlreadyAdded(mapTransactions.size()); bool fFoundSomething = true; - unsigned int nBlockSize = 0; + uint64 nBlockSize = 0; while (fFoundSomething && nBlockSize < MAX_SIZE/2) { fFoundSomething = false; diff --git a/main.h b/main.h index 333fa839..0fb36eb1 100644 --- a/main.h +++ b/main.h @@ -14,7 +14,6 @@ class CBlockIndex; class CWalletTx; class CKeyItem; -static const unsigned int MAX_SIZE = 0x02000000; static const unsigned int MAX_BLOCK_SIZE = 1000000; static const int64 COIN = 100000000; static const int64 CENT = 1000000; @@ -61,7 +60,7 @@ extern int fMinimizeOnClose; -bool CheckDiskSpace(int64 nAdditionalBytes=0); +bool CheckDiskSpace(uint64 nAdditionalBytes=0); FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); FILE* AppendBlockFile(unsigned int& nFileRet); bool AddKey(const CKey& key); @@ -85,7 +84,7 @@ void ThreadBitcoinMiner(void* parg); void BitcoinMiner(); bool CheckProofOfWork(uint256 hash, unsigned int nBits); bool IsInitialBlockDownload(); -bool IsLockdown(); +string GetWarnings(string strFor); @@ -298,7 +297,6 @@ public: int64 nValue; CScript scriptPubKey; -public: CTxOut() { SetNull(); @@ -475,6 +473,10 @@ public: if (vin.empty() || vout.empty()) return error("CTransaction::CheckTransaction() : vin or vout empty"); + // Size limits + if (::GetSerializeSize(*this, SER_DISK) > MAX_SIZE) + return error("CTransaction::CheckTransaction() : size limits failed"); + // Check for negative or overflow output values int64 nValueOut = 0; foreach(const CTxOut& txout, vout) @@ -1469,6 +1471,214 @@ public: +// +// Alert messages are broadcast as a vector of signed data. Unserializing may +// not read the entire buffer if the alert is for a newer version, but older +// versions can still relay the original data. +// +class CUnsignedAlert +{ +public: + int nVersion; + int64 nRelayUntil; // when newer nodes stop relaying to newer nodes + int64 nExpiration; + int nID; + int nCancel; + set setCancel; + int nMinVer; // lowest version inclusive + int nMaxVer; // highest version inclusive + set setSubVer; // empty matches all + int nPriority; + + // Actions + string strComment; + string strStatusBar; + string strRPCError; + + IMPLEMENT_SERIALIZE + ( + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(nRelayUntil); + READWRITE(nExpiration); + READWRITE(nID); + READWRITE(nCancel); + READWRITE(setCancel); + READWRITE(nMinVer); + READWRITE(nMaxVer); + READWRITE(setSubVer); + READWRITE(nPriority); + + READWRITE(strComment); + READWRITE(strStatusBar); + READWRITE(strRPCError); + ) + + void SetNull() + { + nVersion = 1; + nRelayUntil = 0; + nExpiration = 0; + nID = 0; + nCancel = 0; + setCancel.clear(); + nMinVer = 0; + nMaxVer = 0; + setSubVer.clear(); + nPriority = 0; + + strComment.clear(); + strStatusBar.clear(); + strRPCError.clear(); + } + + string ToString() const + { + string strSetCancel; + foreach(int n, setCancel) + strSetCancel += strprintf("%d ", n); + string strSetSubVer; + foreach(string str, setSubVer) + strSetSubVer += "\"" + str + "\" "; + return strprintf( + "CAlert(\n" + " nVersion = %d\n" + " nRelayUntil = %"PRI64d"\n" + " nExpiration = %"PRI64d"\n" + " nID = %d\n" + " nCancel = %d\n" + " setCancel = %s\n" + " nMinVer = %d\n" + " nMaxVer = %d\n" + " setSubVer = %s\n" + " nPriority = %d\n" + " strComment = \"%s\"\n" + " strStatusBar = \"%s\"\n" + " strRPCError = \"%s\"\n" + ")\n", + nVersion, + nRelayUntil, + nExpiration, + nID, + nCancel, + strSetCancel.c_str(), + nMinVer, + nMaxVer, + strSetSubVer.c_str(), + nPriority, + strComment.c_str(), + strStatusBar.c_str(), + strRPCError.c_str()); + } + + void print() const + { + printf("%s", ToString().c_str()); + } +}; + +class CAlert : public CUnsignedAlert +{ +public: + vector vchMsg; + vector vchSig; + + CAlert() + { + SetNull(); + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(vchMsg); + READWRITE(vchSig); + ) + + void SetNull() + { + CUnsignedAlert::SetNull(); + vchMsg.clear(); + vchSig.clear(); + } + + bool IsNull() const + { + return (nExpiration == 0); + } + + uint256 GetHash() const + { + return SerializeHash(*this); + } + + bool IsInEffect() const + { + return (GetAdjustedTime() < nExpiration); + } + + bool Cancels(const CAlert& alert) const + { + if (!IsInEffect()) + false; + return (alert.nID <= nCancel || setCancel.count(alert.nID)); + } + + bool AppliesTo(int nVersion, string strSubVerIn) const + { + return (IsInEffect() && + nMinVer <= nVersion && nVersion <= nMaxVer && + (setSubVer.empty() || setSubVer.count(strSubVerIn))); + } + + bool AppliesToMe() const + { + return AppliesTo(VERSION, ::pszSubVer); + } + + bool RelayTo(CNode* pnode) const + { + if (!IsInEffect()) + return false; + // returns true if wasn't already contained in the set + if (pnode->setKnown.insert(GetHash()).second) + { + if (AppliesTo(pnode->nVersion, pnode->strSubVer) || + AppliesToMe() || + GetAdjustedTime() < nRelayUntil) + { + pnode->PushMessage("alert", *this); + return true; + } + } + return false; + } + + bool CheckSignature() + { + CKey key; + if (!key.SetPubKey(ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"))) + return error("CAlert::CheckSignature() : SetPubKey failed"); + if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) + return error("CAlert::CheckSignature() : verify signature failed"); + + // Now unserialize the data + CDataStream sMsg(vchMsg); + sMsg >> *(CUnsignedAlert*)this; + return true; + } + + bool ProcessAlert(); +}; + + + + + + + + + + extern map mapTransactions; extern map mapWallet; extern vector vWalletUpdated; diff --git a/net.h b/net.h index 5b24f7a1..e12a8e11 100644 --- a/net.h +++ b/net.h @@ -504,6 +504,7 @@ public: unsigned int nMessageStart; CAddress addr; int nVersion; + string strSubVer; bool fClient; bool fInbound; bool fNetworkNode; @@ -520,10 +521,11 @@ public: uint256 hashLastGetBlocksEnd; int nStartingHeight; - // flood + // flood relay vector vAddrToSend; set setAddrKnown; bool fGetAddr; + set setKnown; // inventory based relay set setInventoryKnown; @@ -557,6 +559,7 @@ public: nMessageStart = -1; addr = addrIn; nVersion = 0; + strSubVer = ""; fClient = false; // set by version message fInbound = fInboundIn; fNetworkNode = false; diff --git a/rpc.cpp b/rpc.cpp index c71a004d..a1151e59 100644 --- a/rpc.cpp +++ b/rpc.cpp @@ -247,7 +247,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("hashespersec", gethashespersec(params, false))); - obj.push_back(Pair("status", strWarning)); + obj.push_back(Pair("errors", GetWarnings("statusbar"))); return obj; } @@ -975,8 +975,9 @@ void ThreadRPCServer2(void* parg) printf("ThreadRPCServer method=%s\n", strMethod.c_str()); // Observe lockdown - if (IsLockdown() && !mapArgs.count("-overridesafety") && strMethod != "help" && strMethod != "stop" && strMethod != "getgenerate" && strMethod != "setgenerate") - throw runtime_error("WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."); + string strWarning = GetWarnings("rpc"); + if (strWarning != "" && !mapArgs.count("-overridesafety") && strMethod != "getinfo" && strMethod != "help" && strMethod != "stop" && strMethod != "getgenerate" && strMethod != "setgenerate") + throw runtime_error(strWarning); // Execute map::iterator mi = mapCallTable.find(strMethod); diff --git a/serialize.h b/serialize.h index e029312f..37971597 100644 --- a/serialize.h +++ b/serialize.h @@ -19,8 +19,11 @@ class CScript; class CDataStream; class CAutoFile; -static const int VERSION = 310; -static const char* pszSubVer = ".5"; +static const unsigned int MAX_SIZE = 0x02000000; + +static const int VERSION = 311; +static const char* pszSubVer = ".0"; + @@ -224,7 +227,7 @@ uint64 ReadCompactSize(Stream& is) READDATA(is, nSize); nSizeRet = nSize; } - if (nSizeRet > (uint64)INT_MAX) + if (nSizeRet > (uint64)MAX_SIZE) throw std::ios_base::failure("ReadCompactSize() : size too large"); return nSizeRet; } diff --git a/ui.cpp b/ui.cpp index 478ae83b..179b22d6 100644 --- a/ui.cpp +++ b/ui.cpp @@ -196,7 +196,7 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* pa void CalledSetStatusBar(const string& strText, int nField) { - if (nField == 0 && IsLockdown()) + if (nField == 0 && GetWarnings("statusbar") != "") return; if (pframeMain && pframeMain->m_statusBar) pframeMain->m_statusBar->SetStatusText(strText, nField); @@ -1013,12 +1013,13 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) RefreshStatusColumn(); // Update status bar - static bool fPrevLockdown; - if (IsLockdown()) - m_statusBar->SetStatusText(string(" ") + _("WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."), 0); - else if (fPrevLockdown) + static string strPrevWarning; + string strWarning = GetWarnings("statusbar"); + if (strWarning != "") + m_statusBar->SetStatusText(string(" ") + _(strWarning), 0); + else if (strPrevWarning != "") m_statusBar->SetStatusText("", 0); - fPrevLockdown = IsLockdown(); + strPrevWarning = strWarning; string strGen = ""; if (fGenerateBitcoins) diff --git a/util.cpp b/util.cpp index 2cfd5602..2a3e964a 100644 --- a/util.cpp +++ b/util.cpp @@ -14,7 +14,7 @@ char pszSetDataDir[MAX_PATH] = ""; bool fShutdown = false; bool fDaemon = false; bool fCommandLine = false; -string strWarning; +string strMiscWarning; @@ -104,12 +104,8 @@ void RandAddSeedPerfmon() RegCloseKey(HKEY_PERFORMANCE_DATA); if (ret == ERROR_SUCCESS) { - uint256 hash; - SHA256(pdata, nSize, (unsigned char*)&hash); - RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash))); - hash = 0; + RAND_add(pdata, nSize, nSize/100.0); memset(pdata, 0, nSize); - printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize); } #endif @@ -371,11 +367,6 @@ bool ParseMoney(const char* pszIn, int64& nRet) vector ParseHex(const char* psz) { - vector vch; - while (isspace(*psz)) - psz++; - vch.reserve((strlen(psz)+1)/3); - static char phexdigit[256] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, @@ -394,24 +385,22 @@ vector ParseHex(const char* psz) -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; - while (*psz) + // convert hex dump to vector + vector vch; + loop { + while (isspace(*psz)) + psz++; char c = phexdigit[(unsigned char)*psz++]; if (c == -1) break; unsigned char n = (c << 4); - if (*psz) - { - char c = phexdigit[(unsigned char)*psz++]; - if (c == -1) - break; - n |= c; - vch.push_back(n); - } - while (isspace(*psz)) - psz++; + c = phexdigit[(unsigned char)*psz++]; + if (c == -1) + break; + n |= c; + vch.push_back(n); } - return vch; } @@ -761,7 +750,7 @@ void AddTimeData(unsigned int ip, int64 nTime) { fDone = true; string strMessage = _("Warning: Check your system date and time, you may not be able to generate or receive the most recent blocks!"); - strWarning = strMessage; + strMiscWarning = strMessage; printf("*** %s\n", strMessage.c_str()); boost::thread(bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1)); } diff --git a/util.h b/util.h index 79692fce..56b13c0b 100644 --- a/util.h +++ b/util.h @@ -143,7 +143,7 @@ extern char pszSetDataDir[MAX_PATH]; extern bool fShutdown; extern bool fDaemon; extern bool fCommandLine; -extern string strWarning; +extern string strMiscWarning; void RandAddSeed(); void RandAddSeedPerfmon(); @@ -307,6 +307,8 @@ inline int64 abs64(int64 n) template string HexStr(const T itbegin, const T itend, bool fSpaces=true) { + if (itbegin == itend) + return ""; const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); string str; @@ -323,6 +325,8 @@ inline string HexStr(vector vch, bool fSpaces=true) template string HexNumStr(const T itbegin, const T itend, bool f0x=true) { + if (itbegin == itend) + return ""; const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); string str = (f0x ? "0x" : "");