alert system
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Wed, 25 Aug 2010 00:05:37 +0000 (00:05 +0000)
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Wed, 25 Aug 2010 00:05:37 +0000 (00:05 +0000)
-- version 0.3.11

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@142 1a98c847-1fd6-4fd8-948a-caf3550aa51b

main.cpp
main.h
net.h
rpc.cpp
serialize.h
ui.cpp
util.cpp
util.h

index aa1d67a..0171f14 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -898,14 +898,7 @@ bool IsInitialBlockDownload()
             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
@@ -913,11 +906,10 @@ void Lockdown(CBlockIndex* pindexNew)
         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
@@ -927,6 +919,9 @@ void Lockdown(CBlockIndex* pindexNew)
 \r
 \r
 \r
+\r
+\r
+\r
 bool CTransaction::DisconnectInputs(CTxDB& txdb)\r
 {\r
     // Relinquish previous transactions' spent pointers\r
@@ -1282,7 +1277,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
         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
@@ -1298,7 +1293,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
         if (!Reorganize(txdb, pindexNew))\r
         {\r
             txdb.TxnAbort();\r
-            Lockdown(pindexNew);\r
+            InvalidChainFound(pindexNew);\r
             return error("SetBestChain() : Reorganize failed");\r
         }\r
     }\r
@@ -1571,16 +1566,16 @@ bool ScanMessageStart(Stream& s)
     }\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
@@ -1648,17 +1643,7 @@ bool LoadBlockIndex(bool fAllowNew)
         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
@@ -1672,9 +1657,7 @@ bool LoadBlockIndex(bool fAllowNew)
         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
@@ -1686,11 +1669,10 @@ bool LoadBlockIndex(bool fAllowNew)
 \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
@@ -1800,6 +1782,111 @@ void PrintBlockTree()
 \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
@@ -1827,7 +1914,7 @@ bool ProcessMessages(CNode* pfrom)
     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
@@ -1869,6 +1956,11 @@ bool ProcessMessages(CNode* pfrom)
 \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
@@ -1889,7 +1981,7 @@ bool ProcessMessages(CNode* pfrom)
             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
@@ -1906,15 +1998,15 @@ bool ProcessMessages(CNode* pfrom)
         }\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
@@ -1928,7 +2020,7 @@ bool ProcessMessages(CNode* pfrom)
         }\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
@@ -1965,14 +2057,13 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         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
@@ -2010,6 +2101,11 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
             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
@@ -2362,6 +2458,22 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
     }\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
@@ -2695,7 +2807,7 @@ void BitcoinMiner()
             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
diff --git a/main.h b/main.h
index 474080c..b7b7c56 100644 (file)
--- a/main.h
+++ b/main.h
@@ -14,7 +14,6 @@ class CBlockIndex;
 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
@@ -61,7 +60,7 @@ extern int fMinimizeOnClose;
 \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
@@ -85,7 +84,7 @@ void ThreadBitcoinMiner(void* parg);
 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
@@ -298,7 +297,6 @@ public:
     int64 nValue;\r
     CScript scriptPubKey;\r
 \r
-public:\r
     CTxOut()\r
     {\r
         SetNull();\r
@@ -475,6 +473,10 @@ public:
         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
@@ -1469,6 +1471,214 @@ public:
 \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
diff --git a/net.h b/net.h
index 3e98835..cf6bc94 100644 (file)
--- a/net.h
+++ b/net.h
@@ -504,6 +504,7 @@ public:
     unsigned int nMessageStart;\r
     CAddress addr;\r
     int nVersion;\r
+    string strSubVer;\r
     bool fClient;\r
     bool fInbound;\r
     bool fNetworkNode;\r
@@ -520,10 +521,11 @@ public:
     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
@@ -557,6 +559,7 @@ public:
         nMessageStart = -1;\r
         addr = addrIn;\r
         nVersion = 0;\r
+        strSubVer = "";\r
         fClient = false; // set by version message\r
         fInbound = fInboundIn;\r
         fNetworkNode = false;\r
diff --git a/rpc.cpp b/rpc.cpp
index a93a6bc..541a8b8 100644 (file)
--- 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)));\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
@@ -975,8 +975,9 @@ void ThreadRPCServer2(void* parg)
                 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
index 2cc9ab3..d1dcea2 100644 (file)
@@ -19,8 +19,11 @@ class CScript;
 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
@@ -224,7 +227,7 @@ uint64 ReadCompactSize(Stream& is)
         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
diff --git a/ui.cpp b/ui.cpp
index b8f50b4..d7a0eb0 100644 (file)
--- a/ui.cpp
+++ b/ui.cpp
@@ -196,7 +196,7 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* pa
 \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
@@ -1013,12 +1013,13 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
     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
index 2be841d..2068e8a 100644 (file)
--- a/util.cpp
+++ b/util.cpp
@@ -14,7 +14,7 @@ char pszSetDataDir[MAX_PATH] = "";
 bool fShutdown = false;\r
 bool fDaemon = false;\r
 bool fCommandLine = false;\r
-string strWarning;\r
+string strMiscWarning;\r
 \r
 \r
 \r
@@ -104,12 +104,8 @@ void RandAddSeedPerfmon()
     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
@@ -371,11 +367,6 @@ bool ParseMoney(const char* pszIn, int64& nRet)
 \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
@@ -394,24 +385,22 @@ vector<unsigned char> ParseHex(const char* psz)
       -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
@@ -761,7 +750,7 @@ void AddTimeData(unsigned int ip, int64 nTime)
             {\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
diff --git a/util.h b/util.h
index f61896f..ba941bf 100644 (file)
--- a/util.h
+++ b/util.h
@@ -143,7 +143,7 @@ extern char pszSetDataDir[MAX_PATH];
 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
@@ -307,6 +307,8 @@ inline int64 abs64(int64 n)
 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
@@ -323,6 +325,8 @@ inline string HexStr(vector<unsigned char> vch, bool fSpaces=true)
 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