pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);\r
}\r
\r
-bool IsLockdown()\r
-{\r
- if (!pindexBest)\r
- return false;\r
- return (bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6);\r
-}\r
-\r
-void Lockdown(CBlockIndex* pindexNew)\r
+void InvalidChainFound(CBlockIndex* pindexNew)\r
{\r
if (pindexNew->bnChainWork > bnBestInvalidWork)\r
{\r
CTxDB().WriteBestInvalidWork(bnBestInvalidWork);\r
MainFrameRepaint();\r
}\r
- 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());\r
- printf("Lockdown: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());\r
- printf("Lockdown: IsLockdown()=%d\n", (IsLockdown() ? 1 : 0));\r
- if (IsLockdown())\r
- printf("Lockdown: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");\r
+ 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());\r
+ printf("InvalidChainFound: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());\r
+ if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6)\r
+ printf("InvalidChainFound: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");\r
}\r
\r
\r
\r
\r
\r
+\r
+\r
+\r
bool CTransaction::DisconnectInputs(CTxDB& txdb)\r
{\r
// Relinquish previous transactions' spent pointers\r
if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))\r
{\r
txdb.TxnAbort();\r
- Lockdown(pindexNew);\r
+ InvalidChainFound(pindexNew);\r
return error("SetBestChain() : ConnectBlock failed");\r
}\r
txdb.TxnCommit();\r
if (!Reorganize(txdb, pindexNew))\r
{\r
txdb.TxnAbort();\r
- Lockdown(pindexNew);\r
+ InvalidChainFound(pindexNew);\r
return error("SetBestChain() : Reorganize failed");\r
}\r
}\r
}\r
}\r
\r
-bool CheckDiskSpace(int64 nAdditionalBytes)\r
+bool CheckDiskSpace(uint64 nAdditionalBytes)\r
{\r
uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available;\r
\r
// Check for 15MB because database could create another 10MB log file at any time\r
- if (nFreeBytesAvailable < (int64)15000000 + nAdditionalBytes)\r
+ if (nFreeBytesAvailable < (uint64)15000000 + nAdditionalBytes)\r
{\r
fShutdown = true;\r
string strMessage = _("Warning: Disk space is low ");\r
- strWarning = strMessage;\r
+ strMiscWarning = strMessage;\r
printf("*** %s\n", strMessage.c_str());\r
ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION);\r
CreateThread(Shutdown, NULL);\r
if (!fAllowNew)\r
return false;\r
\r
-\r
// Genesis Block:\r
- // GetHash() = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f\r
- // hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b\r
- // txNew.vin[0].scriptSig = 486604799 4 0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854\r
- // txNew.vout[0].nValue = 5000000000\r
- // txNew.vout[0].scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG\r
- // block.nVersion = 1\r
- // block.nTime = 1231006505\r
- // block.nBits = 0x1d00ffff\r
- // block.nNonce = 2083236893\r
// CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)\r
// CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)\r
// CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)\r
txNew.vout.resize(1);\r
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));\r
txNew.vout[0].nValue = 50 * COIN;\r
- CBigNum bnPubKey;\r
- bnPubKey.SetHex("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704");\r
- txNew.vout[0].scriptPubKey = CScript() << bnPubKey << OP_CHECKSIG;\r
+ txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;\r
CBlock block;\r
block.vtx.push_back(txNew);\r
block.hashPrevBlock = 0;\r
\r
//// debug print\r
printf("%s\n", block.GetHash().ToString().c_str());\r
- printf("%s\n", block.hashMerkleRoot.ToString().c_str());\r
printf("%s\n", hashGenesisBlock.ToString().c_str());\r
- txNew.vout[0].scriptPubKey.print();\r
- block.print();\r
+ printf("%s\n", block.hashMerkleRoot.ToString().c_str());\r
assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));\r
+ block.print();\r
\r
assert(block.GetHash() == hashGenesisBlock);\r
\r
\r
//////////////////////////////////////////////////////////////////////////////\r
//\r
+// CAlert\r
+//\r
+\r
+map<uint256, CAlert> mapAlerts;\r
+CCriticalSection cs_mapAlerts;\r
+\r
+string GetWarnings(string strFor)\r
+{\r
+ int nPriority = 0;\r
+ string strStatusBar;\r
+ string strRPC;\r
+\r
+ // Misc warnings like out of disk space and clock is wrong\r
+ if (strMiscWarning != "")\r
+ {\r
+ nPriority = 1000;\r
+ strStatusBar = strMiscWarning;\r
+ }\r
+\r
+ // Longer invalid proof-of-work chain\r
+ if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6)\r
+ {\r
+ nPriority = 2000;\r
+ strStatusBar = strRPC = "WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.";\r
+ }\r
+\r
+ // Alerts\r
+ CRITICAL_BLOCK(cs_mapAlerts)\r
+ {\r
+ foreach(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)\r
+ {\r
+ const CAlert& alert = item.second;\r
+ if (alert.AppliesToMe() && alert.nPriority > nPriority)\r
+ {\r
+ nPriority = alert.nPriority;\r
+ strStatusBar = alert.strStatusBar;\r
+ strRPC = alert.strRPCError;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (strFor == "statusbar")\r
+ return strStatusBar;\r
+ else if (strFor == "rpc")\r
+ return strRPC;\r
+ assert(("GetWarnings() : invalid parameter", false));\r
+ return "error";\r
+}\r
+\r
+bool CAlert::ProcessAlert()\r
+{\r
+ if (!CheckSignature())\r
+ return false;\r
+ if (!IsInEffect())\r
+ return false;\r
+\r
+ CRITICAL_BLOCK(cs_mapAlerts)\r
+ {\r
+ // Cancel previous alerts\r
+ for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)\r
+ {\r
+ const CAlert& alert = (*mi).second;\r
+ if (Cancels(alert))\r
+ {\r
+ printf("cancelling alert %d\n", alert.nID);\r
+ mapAlerts.erase(mi++);\r
+ }\r
+ else if (!alert.IsInEffect())\r
+ {\r
+ printf("expiring alert %d\n", alert.nID);\r
+ mapAlerts.erase(mi++);\r
+ }\r
+ else\r
+ mi++;\r
+ }\r
+\r
+ // Check if this alert has been cancelled\r
+ foreach(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)\r
+ {\r
+ const CAlert& alert = item.second;\r
+ if (alert.Cancels(*this))\r
+ {\r
+ printf("alert already cancelled by %d\n", alert.nID);\r
+ return false;\r
+ }\r
+ }\r
+\r
+ // Add to mapAlerts\r
+ mapAlerts.insert(make_pair(GetHash(), *this));\r
+ }\r
+\r
+ printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());\r
+ MainFrameRepaint();\r
+ return true;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////////////\r
+//\r
// Messages\r
//\r
\r
if (vRecv.empty())\r
return true;\r
//if (fDebug)\r
- // printf("ProcessMessages(%d bytes)\n", vRecv.size());\r
+ // printf("ProcessMessages(%u bytes)\n", vRecv.size());\r
\r
//\r
// Message format\r
\r
// Message size\r
unsigned int nMessageSize = hdr.nMessageSize;\r
+ if (nMessageSize > MAX_SIZE)\r
+ {\r
+ printf("ProcessMessage(%s, %u bytes) : nMessageSize > MAX_SIZE\n", strCommand.c_str(), nMessageSize);\r
+ continue;\r
+ }\r
if (nMessageSize > vRecv.size())\r
{\r
// Rewind and wait for rest of message\r
memcpy(&nChecksum, &hash, sizeof(nChecksum));\r
if (nChecksum != hdr.nChecksum)\r
{\r
- printf("ProcessMessage(%s, %d bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",\r
+ printf("ProcessMessage(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",\r
strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);\r
continue;\r
}\r
}\r
catch (std::ios_base::failure& e)\r
{\r
- if (strstr(e.what(), "CDataStream::read() : end of data"))\r
+ if (strstr(e.what(), "end of data"))\r
{\r
// Allow exceptions from underlength message on vRecv\r
- 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());\r
+ 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());\r
}\r
- else if (strstr(e.what(), ": size too large"))\r
+ else if (strstr(e.what(), "size too large"))\r
{\r
// Allow exceptions from overlong size\r
- printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());\r
+ printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());\r
}\r
else\r
{\r
}\r
\r
if (!fRet)\r
- printf("ProcessMessage(%s, %d bytes) FAILED\n", strCommand.c_str(), nMessageSize);\r
+ printf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize);\r
}\r
\r
vRecv.Compact();\r
CAddress addrMe;\r
CAddress addrFrom;\r
uint64 nNonce = 1;\r
- string strSubVer;\r
vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;\r
if (pfrom->nVersion == 10300)\r
pfrom->nVersion = 300;\r
if (pfrom->nVersion >= 106 && !vRecv.empty())\r
vRecv >> addrFrom >> nNonce;\r
if (pfrom->nVersion >= 106 && !vRecv.empty())\r
- vRecv >> strSubVer;\r
+ vRecv >> pfrom->strSubVer;\r
if (pfrom->nVersion >= 209 && !vRecv.empty())\r
vRecv >> pfrom->nStartingHeight;\r
\r
pfrom->PushGetBlocks(pindexBest, uint256(0));\r
}\r
\r
+ // Relay alerts\r
+ CRITICAL_BLOCK(cs_mapAlerts)\r
+ foreach(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)\r
+ item.second.RelayTo(pfrom);\r
+\r
pfrom->fSuccessfullyConnected = true;\r
\r
printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight);\r
}\r
\r
\r
+ else if (strCommand == "alert")\r
+ {\r
+ CAlert alert;\r
+ vRecv >> alert;\r
+\r
+ if (alert.ProcessAlert())\r
+ {\r
+ // Relay\r
+ pfrom->setKnown.insert(alert.GetHash());\r
+ CRITICAL_BLOCK(cs_vNodes)\r
+ foreach(CNode* pnode, vNodes)\r
+ alert.RelayTo(pnode);\r
+ }\r
+ }\r
+\r
+\r
else\r
{\r
// Ignore unknown commands for extensibility\r
map<uint256, CTxIndex> mapTestPool;\r
vector<char> vfAlreadyAdded(mapTransactions.size());\r
bool fFoundSomething = true;\r
- unsigned int nBlockSize = 0;\r
+ uint64 nBlockSize = 0;\r
while (fFoundSomething && nBlockSize < MAX_SIZE/2)\r
{\r
fFoundSomething = false;\r
class CWalletTx;\r
class CKeyItem;\r
\r
-static const unsigned int MAX_SIZE = 0x02000000;\r
static const unsigned int MAX_BLOCK_SIZE = 1000000;\r
static const int64 COIN = 100000000;\r
static const int64 CENT = 1000000;\r
\r
\r
\r
-bool CheckDiskSpace(int64 nAdditionalBytes=0);\r
+bool CheckDiskSpace(uint64 nAdditionalBytes=0);\r
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");\r
FILE* AppendBlockFile(unsigned int& nFileRet);\r
bool AddKey(const CKey& key);\r
void BitcoinMiner();\r
bool CheckProofOfWork(uint256 hash, unsigned int nBits);\r
bool IsInitialBlockDownload();\r
-bool IsLockdown();\r
+string GetWarnings(string strFor);\r
\r
\r
\r
int64 nValue;\r
CScript scriptPubKey;\r
\r
-public:\r
CTxOut()\r
{\r
SetNull();\r
if (vin.empty() || vout.empty())\r
return error("CTransaction::CheckTransaction() : vin or vout empty");\r
\r
+ // Size limits\r
+ if (::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)\r
+ return error("CTransaction::CheckTransaction() : size limits failed");\r
+\r
// Check for negative or overflow output values\r
int64 nValueOut = 0;\r
foreach(const CTxOut& txout, vout)\r
\r
\r
\r
+//\r
+// Alert messages are broadcast as a vector of signed data. Unserializing may\r
+// not read the entire buffer if the alert is for a newer version, but older\r
+// versions can still relay the original data.\r
+//\r
+class CUnsignedAlert\r
+{\r
+public:\r
+ int nVersion;\r
+ int64 nRelayUntil; // when newer nodes stop relaying to newer nodes\r
+ int64 nExpiration;\r
+ int nID;\r
+ int nCancel;\r
+ set<int> setCancel;\r
+ int nMinVer; // lowest version inclusive\r
+ int nMaxVer; // highest version inclusive\r
+ set<string> setSubVer; // empty matches all\r
+ int nPriority;\r
+\r
+ // Actions\r
+ string strComment;\r
+ string strStatusBar;\r
+ string strRPCError;\r
+\r
+ IMPLEMENT_SERIALIZE\r
+ (\r
+ READWRITE(this->nVersion);\r
+ nVersion = this->nVersion;\r
+ READWRITE(nRelayUntil);\r
+ READWRITE(nExpiration);\r
+ READWRITE(nID);\r
+ READWRITE(nCancel);\r
+ READWRITE(setCancel);\r
+ READWRITE(nMinVer);\r
+ READWRITE(nMaxVer);\r
+ READWRITE(setSubVer);\r
+ READWRITE(nPriority);\r
+\r
+ READWRITE(strComment);\r
+ READWRITE(strStatusBar);\r
+ READWRITE(strRPCError);\r
+ )\r
+\r
+ void SetNull()\r
+ {\r
+ nVersion = 1;\r
+ nRelayUntil = 0;\r
+ nExpiration = 0;\r
+ nID = 0;\r
+ nCancel = 0;\r
+ setCancel.clear();\r
+ nMinVer = 0;\r
+ nMaxVer = 0;\r
+ setSubVer.clear();\r
+ nPriority = 0;\r
+\r
+ strComment.clear();\r
+ strStatusBar.clear();\r
+ strRPCError.clear();\r
+ }\r
+\r
+ string ToString() const\r
+ {\r
+ string strSetCancel;\r
+ foreach(int n, setCancel)\r
+ strSetCancel += strprintf("%d ", n);\r
+ string strSetSubVer;\r
+ foreach(string str, setSubVer)\r
+ strSetSubVer += "\"" + str + "\" ";\r
+ return strprintf(\r
+ "CAlert(\n"\r
+ " nVersion = %d\n"\r
+ " nRelayUntil = %"PRI64d"\n"\r
+ " nExpiration = %"PRI64d"\n"\r
+ " nID = %d\n"\r
+ " nCancel = %d\n"\r
+ " setCancel = %s\n"\r
+ " nMinVer = %d\n"\r
+ " nMaxVer = %d\n"\r
+ " setSubVer = %s\n"\r
+ " nPriority = %d\n"\r
+ " strComment = \"%s\"\n"\r
+ " strStatusBar = \"%s\"\n"\r
+ " strRPCError = \"%s\"\n"\r
+ ")\n",\r
+ nVersion,\r
+ nRelayUntil,\r
+ nExpiration,\r
+ nID,\r
+ nCancel,\r
+ strSetCancel.c_str(),\r
+ nMinVer,\r
+ nMaxVer,\r
+ strSetSubVer.c_str(),\r
+ nPriority,\r
+ strComment.c_str(),\r
+ strStatusBar.c_str(),\r
+ strRPCError.c_str());\r
+ }\r
+\r
+ void print() const\r
+ {\r
+ printf("%s", ToString().c_str());\r
+ }\r
+};\r
+\r
+class CAlert : public CUnsignedAlert\r
+{\r
+public:\r
+ vector<unsigned char> vchMsg;\r
+ vector<unsigned char> vchSig;\r
+\r
+ CAlert()\r
+ {\r
+ SetNull();\r
+ }\r
+\r
+ IMPLEMENT_SERIALIZE\r
+ (\r
+ READWRITE(vchMsg);\r
+ READWRITE(vchSig);\r
+ )\r
+\r
+ void SetNull()\r
+ {\r
+ CUnsignedAlert::SetNull();\r
+ vchMsg.clear();\r
+ vchSig.clear();\r
+ }\r
+\r
+ bool IsNull() const\r
+ {\r
+ return (nExpiration == 0);\r
+ }\r
+\r
+ uint256 GetHash() const\r
+ {\r
+ return SerializeHash(*this);\r
+ }\r
+\r
+ bool IsInEffect() const\r
+ {\r
+ return (GetAdjustedTime() < nExpiration);\r
+ }\r
+\r
+ bool Cancels(const CAlert& alert) const\r
+ {\r
+ if (!IsInEffect())\r
+ false;\r
+ return (alert.nID <= nCancel || setCancel.count(alert.nID));\r
+ }\r
+\r
+ bool AppliesTo(int nVersion, string strSubVerIn) const\r
+ {\r
+ return (IsInEffect() &&\r
+ nMinVer <= nVersion && nVersion <= nMaxVer &&\r
+ (setSubVer.empty() || setSubVer.count(strSubVerIn)));\r
+ }\r
+\r
+ bool AppliesToMe() const\r
+ {\r
+ return AppliesTo(VERSION, ::pszSubVer);\r
+ }\r
+\r
+ bool RelayTo(CNode* pnode) const\r
+ {\r
+ if (!IsInEffect())\r
+ return false;\r
+ // returns true if wasn't already contained in the set\r
+ if (pnode->setKnown.insert(GetHash()).second)\r
+ {\r
+ if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||\r
+ AppliesToMe() ||\r
+ GetAdjustedTime() < nRelayUntil)\r
+ {\r
+ pnode->PushMessage("alert", *this);\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ bool CheckSignature()\r
+ {\r
+ CKey key;\r
+ if (!key.SetPubKey(ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284")))\r
+ return error("CAlert::CheckSignature() : SetPubKey failed");\r
+ if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))\r
+ return error("CAlert::CheckSignature() : verify signature failed");\r
+\r
+ // Now unserialize the data\r
+ CDataStream sMsg(vchMsg);\r
+ sMsg >> *(CUnsignedAlert*)this;\r
+ return true;\r
+ }\r
+\r
+ bool ProcessAlert();\r
+};\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
extern map<uint256, CTransaction> mapTransactions;\r
extern map<uint256, CWalletTx> mapWallet;\r
extern vector<uint256> vWalletUpdated;\r
unsigned int nMessageStart;\r
CAddress addr;\r
int nVersion;\r
+ string strSubVer;\r
bool fClient;\r
bool fInbound;\r
bool fNetworkNode;\r
uint256 hashLastGetBlocksEnd;\r
int nStartingHeight;\r
\r
- // flood\r
+ // flood relay\r
vector<CAddress> vAddrToSend;\r
set<CAddress> setAddrKnown;\r
bool fGetAddr;\r
+ set<uint256> setKnown;\r
\r
// inventory based relay\r
set<CInv> setInventoryKnown;\r
nMessageStart = -1;\r
addr = addrIn;\r
nVersion = 0;\r
+ strSubVer = "";\r
fClient = false; // set by version message\r
fInbound = fInboundIn;\r
fNetworkNode = false;\r
obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));\r
obj.push_back(Pair("difficulty", (double)GetDifficulty()));\r
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));\r
- obj.push_back(Pair("status", strWarning));\r
+ obj.push_back(Pair("errors", GetWarnings("statusbar")));\r
return obj;\r
}\r
\r
printf("ThreadRPCServer method=%s\n", strMethod.c_str());\r
\r
// Observe lockdown\r
- if (IsLockdown() && !mapArgs.count("-overridesafety") && strMethod != "help" && strMethod != "stop" && strMethod != "getgenerate" && strMethod != "setgenerate")\r
- throw runtime_error("WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.");\r
+ string strWarning = GetWarnings("rpc");\r
+ if (strWarning != "" && !mapArgs.count("-overridesafety") && strMethod != "getinfo" && strMethod != "help" && strMethod != "stop" && strMethod != "getgenerate" && strMethod != "setgenerate")\r
+ throw runtime_error(strWarning);\r
\r
// Execute\r
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);\r
class CDataStream;\r
class CAutoFile;\r
\r
-static const int VERSION = 310;\r
-static const char* pszSubVer = ".5";\r
+static const unsigned int MAX_SIZE = 0x02000000;\r
+\r
+static const int VERSION = 311;\r
+static const char* pszSubVer = ".0";\r
+\r
\r
\r
\r
READDATA(is, nSize);\r
nSizeRet = nSize;\r
}\r
- if (nSizeRet > (uint64)INT_MAX)\r
+ if (nSizeRet > (uint64)MAX_SIZE)\r
throw std::ios_base::failure("ReadCompactSize() : size too large");\r
return nSizeRet;\r
}\r
\r
void CalledSetStatusBar(const string& strText, int nField)\r
{\r
- if (nField == 0 && IsLockdown())\r
+ if (nField == 0 && GetWarnings("statusbar") != "")\r
return;\r
if (pframeMain && pframeMain->m_statusBar)\r
pframeMain->m_statusBar->SetStatusText(strText, nField);\r
RefreshStatusColumn();\r
\r
// Update status bar\r
- static bool fPrevLockdown;\r
- if (IsLockdown())\r
- m_statusBar->SetStatusText(string(" ") + _("WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."), 0);\r
- else if (fPrevLockdown)\r
+ static string strPrevWarning;\r
+ string strWarning = GetWarnings("statusbar");\r
+ if (strWarning != "")\r
+ m_statusBar->SetStatusText(string(" ") + _(strWarning), 0);\r
+ else if (strPrevWarning != "")\r
m_statusBar->SetStatusText("", 0);\r
- fPrevLockdown = IsLockdown();\r
+ strPrevWarning = strWarning;\r
\r
string strGen = "";\r
if (fGenerateBitcoins)\r
bool fShutdown = false;\r
bool fDaemon = false;\r
bool fCommandLine = false;\r
-string strWarning;\r
+string strMiscWarning;\r
\r
\r
\r
RegCloseKey(HKEY_PERFORMANCE_DATA);\r
if (ret == ERROR_SUCCESS)\r
{\r
- uint256 hash;\r
- SHA256(pdata, nSize, (unsigned char*)&hash);\r
- RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash)));\r
- hash = 0;\r
+ RAND_add(pdata, nSize, nSize/100.0);\r
memset(pdata, 0, nSize);\r
-\r
printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);\r
}\r
#endif\r
\r
vector<unsigned char> ParseHex(const char* psz)\r
{\r
- vector<unsigned char> vch;\r
- while (isspace(*psz))\r
- psz++;\r
- vch.reserve((strlen(psz)+1)/3);\r
-\r
static char phexdigit[256] =\r
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\r
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\r
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\r
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };\r
\r
- while (*psz)\r
+ // convert hex dump to vector\r
+ vector<unsigned char> vch;\r
+ loop\r
{\r
+ while (isspace(*psz))\r
+ psz++;\r
char c = phexdigit[(unsigned char)*psz++];\r
if (c == -1)\r
break;\r
unsigned char n = (c << 4);\r
- if (*psz)\r
- {\r
- char c = phexdigit[(unsigned char)*psz++];\r
- if (c == -1)\r
- break;\r
- n |= c;\r
- vch.push_back(n);\r
- }\r
- while (isspace(*psz))\r
- psz++;\r
+ c = phexdigit[(unsigned char)*psz++];\r
+ if (c == -1)\r
+ break;\r
+ n |= c;\r
+ vch.push_back(n);\r
}\r
-\r
return vch;\r
}\r
\r
{\r
fDone = true;\r
string strMessage = _("Warning: Check your system date and time, you may not be able to generate or receive the most recent blocks!");\r
- strWarning = strMessage;\r
+ strMiscWarning = strMessage;\r
printf("*** %s\n", strMessage.c_str());\r
boost::thread(bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));\r
}\r
extern bool fShutdown;\r
extern bool fDaemon;\r
extern bool fCommandLine;\r
-extern string strWarning;\r
+extern string strMiscWarning;\r
\r
void RandAddSeed();\r
void RandAddSeedPerfmon();\r
template<typename T>\r
string HexStr(const T itbegin, const T itend, bool fSpaces=true)\r
{\r
+ if (itbegin == itend)\r
+ return "";\r
const unsigned char* pbegin = (const unsigned char*)&itbegin[0];\r
const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);\r
string str;\r
template<typename T>\r
string HexNumStr(const T itbegin, const T itend, bool f0x=true)\r
{\r
+ if (itbegin == itend)\r
+ return "";\r
const unsigned char* pbegin = (const unsigned char*)&itbegin[0];\r
const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);\r
string str = (f0x ? "0x" : "");\r