Add redeemScript size sanity checkings.
authorCryptoManiac <balthazar@yandex.ru>
Sat, 10 Jan 2015 11:02:49 +0000 (11:02 +0000)
committerCryptoManiac <balthazar@yandex.ru>
Sat, 10 Jan 2015 11:02:49 +0000 (11:02 +0000)
See #107 for additional info.

src/keystore.cpp
src/rpcrawtransaction.cpp
src/rpcwallet.cpp
src/wallet.cpp
src/wallet.h

index 5f07bb1..fb85da1 100644 (file)
@@ -31,6 +31,9 @@ bool CBasicKeyStore::AddKey(const CKey& key)
 
 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
 {
+    if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
+        return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
+
     {
         LOCK(cs_KeyStore);
         mapScripts[redeemScript.GetID()] = redeemScript;
index ba80b01..14b0705 100644 (file)
@@ -650,6 +650,10 @@ Value createmultisig(const Array& params, bool fHelp)
     CScript inner;
     inner.SetMultisig(nRequired, pubkeys);
 
+    if (inner.size() > MAX_SCRIPT_ELEMENT_SIZE)
+        throw runtime_error(
+            strprintf("redeemScript exceeds size limit: %" PRIszu " > %d", inner.size(), MAX_SCRIPT_ELEMENT_SIZE));
+
     CScriptID innerID = inner.GetID();
     CBitcoinAddress address(innerID);
 
index 1575f3a..046c190 100644 (file)
@@ -847,6 +847,11 @@ Value addmultisigaddress(const Array& params, bool fHelp)
     // Construct using pay-to-script-hash:
     CScript inner;
     inner.SetMultisig(nRequired, pubkeys);
+
+    if (inner.size() > MAX_SCRIPT_ELEMENT_SIZE)
+    throw runtime_error(
+        strprintf("redeemScript exceeds size limit: %" PRIszu " > %d", inner.size(), MAX_SCRIPT_ELEMENT_SIZE));
+
     CScriptID innerID = inner.GetID();
     pwalletMain->AddCScript(inner);
 
index 1b6d0c5..5990978 100644 (file)
@@ -113,6 +113,23 @@ bool CWallet::AddCScript(const CScript& redeemScript)
     return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
 }
 
+bool CWallet::LoadCScript(const CScript& redeemScript)
+{
+    /* A sanity check was added in pull #3843 to avoid adding redeemScripts
+     * that never can be redeemed. However, old wallets may still contain
+     * these. Do not add them to the wallet and warn. */
+    if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
+    {
+        std::string strAddr = CBitcoinAddress(redeemScript.GetID()).ToString();
+        printf("LoadCScript() : Warning: This wallet contains a redeemScript of size %" PRIszu " which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
+          redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr.c_str());
+          return true;
+    }
+
+    return CCryptoKeyStore::AddCScript(redeemScript);
+}
+
+
 bool CWallet::AddWatchOnly(const CScript &dest)
 {
     if (!CCryptoKeyStore::AddWatchOnly(dest))
index 6075118..ce5f205 100644 (file)
@@ -159,7 +159,7 @@ public:
     // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
     bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
     bool AddCScript(const CScript& redeemScript);
-    bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); }
+    bool LoadCScript(const CScript& redeemScript);
 
     // Adds a watch-only address to the store, and saves it to disk.
     bool AddWatchOnly(const CScript &dest);