Michael Witrant  committed 66213cc

Warn the user on unknown protocol received

If 20% of the last 2000 blocks have a protocol version vote above the
latest protocol version known by the client, a warning is displayed in
the status bar and the "errors" field of the getinfo RPC.

Comments (0)

Files changed (5)

File src/bitcoinrpc.cpp Modified

View file
  • Ignore whitespace
  • Hide word diff
     return wtx.GetHash().ToString();
 }
 
+int nForcedVersionVote = -1;
+Value setversionvote(const Array& params, bool fHelp)
+{
+    if (fHelp || params.size() != 1)
+        throw runtime_error(
+            "setversionvote <version>\n"
+            );
+
+    nForcedVersionVote = params[0].get_int();
+    return Value::null;
+}
 
 #endif
 
     { "shutdown",               &shutdown,               true },
     { "timetravel",             &timetravel,             true },
     { "manualunpark",           &manualunpark,           true },
+    { "setversionvote",         &setversionvote,         true },
 #endif
 };
 
     if (strMethod == "burn"                    && n > 0) ConvertTo<double>(params[0]);
 #ifdef TESTING
     if (strMethod == "timetravel"              && n > 0) ConvertTo<boost::int64_t>(params[0]);
+    if (strMethod == "setversionvote"          && n > 0) ConvertTo<boost::int64_t>(params[0]);
 #endif
 
     if (strMethod == "signmessage"             && n == 1)

File src/main.cpp Modified

View file
  • Ignore whitespace
  • Hide word diff
 // Settings
 int64 nSplitShareOutputs = MIN_COINSTAKE_VALUE;
 
+static string strProtocolWarningMessage = _("Unknown protocol vote received. You may need to upgrade your client.");
+string strProtocolWarning = "";
+
 
 
 //////////////////////////////////////////////////////////////////////////////
     // The new chain may have changed some stake modifiers
     ClearStakeModifierCache();
 
+    strProtocolWarning.clear();
+    if (pindexBest->vote.nVersionVote > PROTOCOL_VERSION)
+    {
+#ifdef TESTING
+        const int nCheckedBlocks = 10;
+#else
+        const int nCheckedBlocks = 2000;
+#endif
+        const CBlockIndex* pi = pindexBest;
+        int nCount = 0;
+        for (int i = 0; pi && i < nCheckedBlocks; i++, pi = pi->pprev)
+        {
+            if (pi->vote.nVersionVote > PROTOCOL_VERSION)
+            {
+                nCount++;
+                if (nCount >= nCheckedBlocks * 20 / 100)
+                {
+                    strProtocolWarning = strProtocolWarningMessage;
+                    break;
+                }
+            }
+        }
+    }
+
     return true;
 }
 
     if (GetBoolArg("-testsafemode"))
         strRPC = "test";
 
+    if (strProtocolWarning.size())
+    {
+        nPriority = 0;
+        strStatusBar = strProtocolWarning;
+    }
+
     if (strDataFeedError != "")
     {
         nPriority = 0;

File src/test/features/step_definitions/unknown_protocol_warning.rb Added

View file
  • Ignore whitespace
  • Hide word diff
+Given(/^node "(.*?)" votes for a protocol version above the current protocol$/) do |arg1|
+  @nodes[arg1].rpc("setversionvote", 99999999)
+end
+
+Then(/^node "(.*?)" should have no error$/) do |arg1|
+  expect(@nodes[arg1].info["errors"]).to eq("")
+end
+
+Then(/^node "(.*?)" should have a warning about the unknown protocol$/) do |arg1|
+  expect(@nodes[arg1].info["errors"]).to eq("Unknown protocol vote received. You may need to upgrade your client.")
+end
+

File src/test/features/unknown_protocol_warning.feature Added

View file
  • Ignore whitespace
  • Hide word diff
+Feature: Users should be warned if their client receive votes for an unknown protocol. It probably means there's a protocol upgrade to install.
+  Scenario:
+    Given a network with nodes "Alice" and "Bob"
+    And node "Alice" votes for a protocol version above the current protocol
+    When node "Alice" finds 1 block received by all other nodes
+    Then node "Bob" should have no error
+
+    When node "Alice" finds 1 block received by all other nodes
+    Then node "Bob" should have a warning about the unknown protocol

File src/wallet.cpp Modified

View file
  • Ignore whitespace
  • Hide word diff
 static map<const CWalletTx*, CBlock> mapTxBlock;
 static map<const CWalletTx*, int64> mapTxLastUse;
 
+#ifdef TESTING
+extern int nForcedVersionVote;
+#endif
+
 // ppcoin: create coin stake transaction
 bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64 nSearchInterval, CTransaction& txNew, CBlockIndex* pindexprev)
 {
     if (!blockVote.IsValidInBlock(nProtocolVersion))
         return error("CreateCoinStake : generated vote is invalid");
 
+#ifdef TESTING
+    if (nForcedVersionVote != -1)
+        blockVote.nVersionVote = nForcedVersionVote;
+#endif
+
     txNew.vout.push_back(CTxOut(0, blockVote.ToScript(nProtocolVersion)));
 
     // nubit: The result of the vote is stored in the CoinStake transaction