From 066e2a1403fe306787a2ce0c8571aa9de57386cf Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 24 Sep 2014 22:24:46 -0400 Subject: [PATCH] script: move CScriptID to standard.h and add a ctor for creating them from CScripts This allows for a reversal of the current behavior. This: CScript foo; CScriptID bar(foo.GetID()); Becomes: CScript foo; CScriptID bar(foo); This way, CScript is no longer dependent on CScriptID or Hash(); --- src/crypter.cpp | 1 + src/key.h | 8 -------- src/keystore.cpp | 3 ++- src/keystore.h | 1 + src/rpcmisc.cpp | 2 +- src/rpcrawtransaction.cpp | 2 +- src/rpcwallet.cpp | 2 +- src/script/compressor.cpp | 1 + src/script/compressor.h | 2 ++ src/script/script.h | 6 ------ src/script/standard.cpp | 2 ++ src/script/standard.h | 9 +++++++++ src/test/miner_tests.cpp | 2 +- src/test/script_P2SH_tests.cpp | 20 ++++++++++---------- src/test/script_tests.cpp | 4 ++-- src/test/sigopcount_tests.cpp | 4 ++-- src/wallet.cpp | 2 +- 17 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/crypter.cpp b/src/crypter.cpp index a872df702..756538836 100644 --- a/src/crypter.cpp +++ b/src/crypter.cpp @@ -5,6 +5,7 @@ #include "crypter.h" #include "script/script.h" +#include "script/standard.h" #include "util.h" #include diff --git a/src/key.h b/src/key.h index f6f6d35d3..48b165253 100644 --- a/src/key.h +++ b/src/key.h @@ -30,14 +30,6 @@ public: CKeyID(const uint160& in) : uint160(in) {} }; -/** A reference to a CScript: the Hash160 of its serialization (see script.h) */ -class CScriptID : public uint160 -{ -public: - CScriptID() : uint160(0) {} - CScriptID(const uint160& in) : uint160(in) {} -}; - /** An encapsulated public key. */ class CPubKey { diff --git a/src/keystore.cpp b/src/keystore.cpp index 755defa26..039c69062 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -8,6 +8,7 @@ #include "crypter.h" #include "key.h" #include "script/script.h" +#include "script/standard.h" #include "util.h" #include @@ -38,7 +39,7 @@ bool CBasicKeyStore::AddCScript(const CScript& redeemScript) return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE); LOCK(cs_KeyStore); - mapScripts[redeemScript.GetID()] = redeemScript; + mapScripts[CScriptID(redeemScript)] = redeemScript; return true; } diff --git a/src/keystore.h b/src/keystore.h index d3478f767..4f8189c8f 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -13,6 +13,7 @@ #include class CScript; +class CScriptID; /** A virtual base class for key stores */ class CKeyStore diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 8be14b567..92ed1c3e2 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -292,7 +292,7 @@ Value createmultisig(const Array& params, bool fHelp) // Construct using pay-to-script-hash: CScript inner = _createmultisig_redeemScript(params); - CScriptID innerID = inner.GetID(); + CScriptID innerID(inner); CBitcoinAddress address(innerID); Object result; diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 78372da68..fdfcb59ee 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -480,7 +480,7 @@ Value decodescript(const Array& params, bool fHelp) } ScriptPubKeyToJSON(script, r, false); - r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString())); + r.push_back(Pair("p2sh", CBitcoinAddress(CScriptID(script)).ToString())); return r; } diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index d11455e38..68bb4068b 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -918,7 +918,7 @@ Value addmultisigaddress(const Array& params, bool fHelp) // Construct using pay-to-script-hash: CScript inner = _createmultisig_redeemScript(params); - CScriptID innerID = inner.GetID(); + CScriptID innerID(inner); pwalletMain->AddCScript(inner); pwalletMain->SetAddressBook(innerID, strAccount, "send"); diff --git a/src/script/compressor.cpp b/src/script/compressor.cpp index 51a3cf602..dbb4df8b7 100644 --- a/src/script/compressor.cpp +++ b/src/script/compressor.cpp @@ -4,6 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "compressor.h" +#include "script/standard.h" bool CScriptCompressor::IsToKeyID(CKeyID &hash) const { diff --git a/src/script/compressor.h b/src/script/compressor.h index 53c6bf3ec..f48ecf500 100644 --- a/src/script/compressor.h +++ b/src/script/compressor.h @@ -8,6 +8,8 @@ #include "script/script.h" +class CScriptID; + /** Compact serializer for scripts. * * It detects common cases and encodes them much more efficiently. diff --git a/src/script/script.h b/src/script/script.h index caf176476..4d685f559 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -610,12 +610,6 @@ public: } return str; } - - CScriptID GetID() const - { - return CScriptID(Hash160(*this)); - } - void clear() { // The default std::vector::clear() does not release memory. diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 53ae254d5..adbec01f2 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -14,6 +14,8 @@ using namespace std; typedef vector valtype; +CScriptID::CScriptID(const CScript& in) : uint160(in.size() ? Hash160(in.begin(), in.end()) : 0) {} + const char* GetTxnOutputType(txnouttype t) { switch (t) diff --git a/src/script/standard.h b/src/script/standard.h index ead79b82a..38d0b5988 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -13,6 +13,15 @@ class CScript; +/** A reference to a CScript: the Hash160 of its serialization (see script.h) */ +class CScriptID : public uint160 +{ +public: + CScriptID() : uint160(0) {} + CScriptID(const CScript& in); + CScriptID(const uint160& in) : uint160(in) {} +}; + static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes // Mandatory script verification flags that all new blocks must comply with for diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index bad5c13ac..93b7fe189 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -170,7 +170,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].scriptSig = CScript() << OP_1; tx.vout[0].nValue = 4900000000LL; script = CScript() << OP_0; - tx.vout[0].scriptPubKey = GetScriptForDestination(script.GetID()); + tx.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(script)); hash = tx.GetHash(); mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11)); tx.vin[0].prevout.hash = hash; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index f8361a0dc..a23792a4f 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(sign) for (int i = 0; i < 4; i++) { keystore.AddCScript(standardScripts[i]); - evalScripts[i] = GetScriptForDestination(standardScripts[i].GetID()); + evalScripts[i] = GetScriptForDestination(CScriptID(standardScripts[i])); } CMutableTransaction txFrom; // Funding transaction: @@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE(norecurse) CScript invalidAsScript; invalidAsScript << OP_INVALIDOPCODE << OP_INVALIDOPCODE; - CScript p2sh = GetScriptForDestination(invalidAsScript.GetID()); + CScript p2sh = GetScriptForDestination(CScriptID(invalidAsScript)); CScript scriptSig; scriptSig << Serialize(invalidAsScript); @@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(norecurse) // Try to recur, and verification should succeed because // the inner HASH160 <> EQUAL should only check the hash: - CScript p2sh2 = GetScriptForDestination(p2sh.GetID()); + CScript p2sh2 = GetScriptForDestination(CScriptID(p2sh)); CScript scriptSig2; scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh); @@ -169,7 +169,7 @@ BOOST_AUTO_TEST_CASE(set) CScript outer[4]; for (int i = 0; i < 4; i++) { - outer[i] = GetScriptForDestination(inner[i].GetID()); + outer[i] = GetScriptForDestination(CScriptID(inner[i])); keystore.AddCScript(inner[i]); } @@ -242,7 +242,7 @@ BOOST_AUTO_TEST_CASE(switchover) CScript scriptSig; scriptSig << Serialize(notValid); - CScript fund = GetScriptForDestination(notValid.GetID()); + CScript fund = GetScriptForDestination(CScriptID(notValid)); // Validation should succeed under old rules (hash is correct): @@ -275,7 +275,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) keystore.AddCScript(pay1); CScript pay1of3 = GetScriptForMultisig(1, keys); - txFrom.vout[0].scriptPubKey = GetScriptForDestination(pay1.GetID()); // P2SH (OP_CHECKSIG) + txFrom.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(pay1)); // P2SH (OP_CHECKSIG) txFrom.vout[0].nValue = 1000; txFrom.vout[1].scriptPubKey = pay1; // ordinary OP_CHECKSIG txFrom.vout[1].nValue = 2000; @@ -290,7 +290,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) oneAndTwo << OP_2 << key[3].GetPubKey() << key[4].GetPubKey() << key[5].GetPubKey(); oneAndTwo << OP_3 << OP_CHECKMULTISIG; keystore.AddCScript(oneAndTwo); - txFrom.vout[3].scriptPubKey = GetScriptForDestination(oneAndTwo.GetID()); + txFrom.vout[3].scriptPubKey = GetScriptForDestination(CScriptID(oneAndTwo)); txFrom.vout[3].nValue = 4000; // vout[4] is max sigops: @@ -299,17 +299,17 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) fifteenSigops << key[i%3].GetPubKey(); fifteenSigops << OP_15 << OP_CHECKMULTISIG; keystore.AddCScript(fifteenSigops); - txFrom.vout[4].scriptPubKey = GetScriptForDestination(fifteenSigops.GetID()); + txFrom.vout[4].scriptPubKey = GetScriptForDestination(CScriptID(fifteenSigops)); txFrom.vout[4].nValue = 5000; // vout[5/6] are non-standard because they exceed MAX_P2SH_SIGOPS CScript sixteenSigops; sixteenSigops << OP_16 << OP_CHECKMULTISIG; keystore.AddCScript(sixteenSigops); - txFrom.vout[5].scriptPubKey = GetScriptForDestination(fifteenSigops.GetID()); + txFrom.vout[5].scriptPubKey = GetScriptForDestination(CScriptID(fifteenSigops)); txFrom.vout[5].nValue = 5000; CScript twentySigops; twentySigops << OP_CHECKMULTISIG; keystore.AddCScript(twentySigops); - txFrom.vout[6].scriptPubKey = GetScriptForDestination(twentySigops.GetID()); + txFrom.vout[6].scriptPubKey = GetScriptForDestination(CScriptID(twentySigops)); txFrom.vout[6].nValue = 6000; coins.ModifyCoins(txFrom.GetHash())->FromTx(txFrom, 0); diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index a4b021249..cfb4fa6e7 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -162,7 +162,7 @@ public: TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_) { if (P2SH) { - creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << redeemScript.GetID() << OP_EQUAL); + creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << CScriptID(redeemScript) << OP_EQUAL); } else { creditTx = BuildCreditingTransaction(redeemScript); } @@ -697,7 +697,7 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) // P2SH, single-signature case: CScript pkSingle; pkSingle << keys[0].GetPubKey() << OP_CHECKSIG; keystore.AddCScript(pkSingle); - scriptPubKey = GetScriptForDestination(pkSingle.GetID()); + scriptPubKey = GetScriptForDestination(CScriptID(pkSingle)); SignSignature(keystore, txFrom, txTo, 0); combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); BOOST_CHECK(combined == scriptSig); diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 62a6cd63d..4ce2c87a0 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount) BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3U); BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21U); - CScript p2sh = GetScriptForDestination(s1.GetID()); + CScript p2sh = GetScriptForDestination(CScriptID(s1)); CScript scriptSig; scriptSig << OP_0 << Serialize(s1); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3U); @@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount) BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3U); BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20U); - p2sh = GetScriptForDestination(s2.GetID()); + p2sh = GetScriptForDestination(CScriptID(s2)); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0U); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0U); CScript scriptSig2; diff --git a/src/wallet.cpp b/src/wallet.cpp index 19e43f6ec..65944587f 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -158,7 +158,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript) * these. Do not add them to the wallet and warn. */ if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) { - std::string strAddr = CBitcoinAddress(redeemScript.GetID()).ToString(); + std::string strAddr = CBitcoinAddress(CScriptID(redeemScript)).ToString(); LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr); return true;