From 5ed0a2b839d4654c252e63b86352c7b1bcbb69ab Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Sat, 10 Jan 2015 11:02:49 +0000 Subject: [PATCH] Add redeemScript size sanity checkings. See #107 for additional info. --- src/keystore.cpp | 3 +++ src/rpcrawtransaction.cpp | 4 ++++ src/rpcwallet.cpp | 5 +++++ src/wallet.cpp | 17 +++++++++++++++++ src/wallet.h | 2 +- 5 files changed, 30 insertions(+), 1 deletions(-) diff --git a/src/keystore.cpp b/src/keystore.cpp index 5f07bb1..fb85da1 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -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; diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index ba80b01..14b0705 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -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); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 1575f3a..046c190 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -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); diff --git a/src/wallet.cpp b/src/wallet.cpp index 1b6d0c5..5990978 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -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)) diff --git a/src/wallet.h b/src/wallet.h index 6075118..ce5f205 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -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 &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); -- 1.7.1