X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fscript.cpp;h=ad31b76feedac081b3a8378018b4be950a797783;hb=HEAD;hp=040c90698eb070b7c97ad905ceb6679739d7ddfb;hpb=5af8418fee23af1be2065382dda14a97034fdf56;p=novacoin.git diff --git a/src/script.cpp b/src/script.cpp index 040c906..5447ba0 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -2,21 +2,18 @@ // Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include -#include - -using namespace std; -using namespace boost; #include "script.h" #include "keystore.h" -#include "bignum.h" #include "key.h" #include "main.h" -#include "sync.h" +#include "random.h" #include "util.h" +#include "base58.h" + +#include -bool CheckSig(vector vchSig, const vector &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags); +bool CheckSig(std::vector vchSig, const std::vector &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags); static const valtype vchFalse(0); static const valtype vchZero(0); @@ -31,7 +28,7 @@ static const size_t nMaxNumSize = 4; CBigNum CastToBigNum(const valtype& vch) { if (vch.size() > nMaxNumSize) - throw runtime_error("CastToBigNum() : overflow"); + throw std::runtime_error("CastToBigNum() : overflow"); // Get rid of extra leading zeros return CBigNum(CBigNum(vch).getvch()); } @@ -85,10 +82,10 @@ void MakeSameSize(valtype& vch1, valtype& vch2) // #define stacktop(i) (stack.at(stack.size()+(i))) #define altstacktop(i) (altstack.at(altstack.size()+(i))) -static inline void popstack(vector& stack) +static inline void popstack(std::vector& stack) { if (stack.empty()) - throw runtime_error("popstack() : stack empty"); + throw std::runtime_error("popstack() : stack empty"); stack.pop_back(); } @@ -415,7 +412,7 @@ bool CheckSequence(const int64_t& nSequence, const CTransaction &txTo, unsigned return true; } -bool EvalScript(vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType) +bool EvalScript(std::vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType) { CAutoBN_CTX pctx; CScript::const_iterator pc = script.begin(); @@ -423,8 +420,8 @@ bool EvalScript(vector >& stack, const CScript& script, co CScript::const_iterator pbegincodehash = script.begin(); opcodetype opcode; valtype vchPushValue; - vector vfExec; - vector altstack; + std::vector vfExec; + std::vector altstack; if (script.size() > 10000) return false; int nOpCount = 0; @@ -1231,15 +1228,15 @@ class CSignatureCache { private: // sigdata_type is (signature hash, signature, public key): - typedef boost::tuple, CPubKey > sigdata_type; - std::set< sigdata_type> setValid; - boost::shared_mutex cs_sigcache; + using sigdata_type = std::tuple, CPubKey>; + std::set setValid; + std::shared_mutex cs_sigcache; public: bool Get(const uint256 &hash, const std::vector& vchSig, const CPubKey& pubKey) { - boost::shared_lock lock(cs_sigcache); + std::shared_lock lock(cs_sigcache); sigdata_type k(hash, vchSig, pubKey); std::set::iterator mi = setValid.find(k); @@ -1257,7 +1254,7 @@ public: int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000); if (nMaxCacheSize <= 0) return; - boost::shared_lock lock(cs_sigcache); + std::shared_lock lock(cs_sigcache); while (static_cast(setValid.size()) > nMaxCacheSize) { @@ -1279,15 +1276,12 @@ public: } }; -bool CheckSig(vector vchSig, const vector &vchPubKey, const CScript &scriptCode, +bool CheckSig(std::vector vchSig, const std::vector &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags) { static CSignatureCache signatureCache; - CKey key; - if (!key.SetPubKey(vchPubKey)) - return false; - CPubKey pubkey = key.GetPubKey(); + CPubKey pubkey(vchPubKey); if (!pubkey.IsValid()) return false; @@ -1305,7 +1299,7 @@ bool CheckSig(vector vchSig, const vector &vchPubK if (signatureCache.Get(sighash, vchSig, pubkey)) return true; - if (!key.Verify(sighash, vchSig)) + if (!pubkey.Verify(sighash, vchSig)) return false; if (!(flags & SCRIPT_VERIFY_NOCACHE)) @@ -1315,29 +1309,20 @@ bool CheckSig(vector vchSig, const vector &vchPubK } - - - - - - // // Return public keys or hashes from scriptPubKey, for 'standard' transaction types. // -bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector >& vSolutionsRet) +bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet) { // Templates - static map mTemplates; + static std::map mTemplates; if (mTemplates.empty()) { // Standard tx, sender provides pubkey, receiver adds signature mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG)); - if (fTestNet || GetTime() > SMALLDATA_SWITCH_TIME) - { - // Malleable pubkey tx hack, sender provides generated pubkey combined with R parameter. The R parameter is dropped before checking a signature. - mTemplates.insert(make_pair(TX_PUBKEY_DROP, CScript() << OP_PUBKEY << OP_PUBKEY << OP_DROP << OP_CHECKSIG)); - } + // Malleable pubkey tx hack, sender provides generated pubkey combined with R parameter. The R parameter is dropped before checking a signature. + mTemplates.insert(make_pair(TX_PUBKEY_DROP, CScript() << OP_PUBKEY << OP_PUBKEY << OP_DROP << OP_CHECKSIG)); // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG)); @@ -1356,7 +1341,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22); + std::vector hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22); vSolutionsRet.push_back(hashBytes); return true; } @@ -1373,18 +1358,18 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector vch1, vch2; + std::vector vch1, vch2; // Compare CScript::const_iterator pc1 = script1.begin(); CScript::const_iterator pc2 = script2.begin(); - while (true) + for ( ; ; ) { if (pc1 == script1.end() && pc2 == script2.end()) { @@ -1460,7 +1445,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector (GetTime() > SMALLDATA_SWITCH_TIME ? 1024 : 80)) + if (vch1.size() > 1024) break; } else if (opcode1 != opcode2 || vch1 != vch2) @@ -1483,7 +1468,7 @@ bool Sign1(const CKeyID& address, const CKeyStore& keystore, const uint256& hash if (!keystore.GetKey(address, key)) return false; - vector vchSig; + std::vector vchSig; if (!key.Sign(hash, vchSig)) return false; vchSig.push_back((unsigned char)nHashType); @@ -1498,7 +1483,7 @@ bool SignR(const CPubKey& pubKey, const CPubKey& R, const CKeyStore& keystore, c if (!keystore.CreatePrivKey(pubKey, R, key)) return false; - vector vchSig; + std::vector vchSig; if (!key.Sign(hash, vchSig)) return false; vchSig.push_back((unsigned char)nHashType); @@ -1507,7 +1492,7 @@ bool SignR(const CPubKey& pubKey, const CPubKey& R, const CKeyStore& keystore, c return true; } -bool SignN(const vector& multisigdata, const CKeyStore& keystore, const uint256& hash, int nHashType, CScript& scriptSigRet) +bool SignN(const std::vector& multisigdata, const CKeyStore& keystore, const uint256& hash, int nHashType, CScript& scriptSigRet) { int nSigned = 0; int nRequired = multisigdata.front()[0]; @@ -1532,7 +1517,7 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, const uint25 { scriptSigRet.clear(); - vector vSolutions; + std::vector vSolutions; if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) return false; @@ -1597,7 +1582,7 @@ int ScriptSigArgsExpected(txnouttype t, const std::vector vSolutions; + std::vector vSolutions; if (!Solver(scriptPubKey, whichType, vSolutions)) return false; @@ -1616,10 +1601,10 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) } -unsigned int HaveKeys(const vector& pubkeys, const CKeyStore& keystore) +unsigned int HaveKeys(const std::vector& pubkeys, const CKeyStore& keystore) { unsigned int nResult = 0; - BOOST_FOREACH(const valtype& pubkey, pubkeys) + for (const valtype& pubkey : pubkeys) { CKeyID keyID = CPubKey(pubkey).GetID(); if (keystore.HaveKey(keyID)) @@ -1629,7 +1614,7 @@ unsigned int HaveKeys(const vector& pubkeys, const CKeyStore& keystore) } -class CKeyStoreIsMineVisitor : public boost::static_visitor +class CKeyStoreIsMineVisitor { private: const CKeyStore *keystore; @@ -1640,16 +1625,24 @@ public: bool operator()(const CScriptID &scriptID) const { return keystore->HaveCScript(scriptID); } }; +/* isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest) { CScript script; script.SetDestination(dest); return IsMine(keystore, script); +}*/ + +isminetype IsMine(const CKeyStore &keystore, const CBitcoinAddress& dest) +{ + CScript script; + script.SetAddress(dest); + return IsMine(keystore, script); } isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) { - vector vSolutions; + std::vector vSolutions; txnouttype whichType; if (!Solver(scriptPubKey, whichType, vSolutions)) { if (keystore.HaveWatchOnly(scriptPubKey)) @@ -1699,7 +1692,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) // partially owned (somebody else has a key that can spend // them) enable spend-out-from-under-you attacks, especially // in shared-wallet situations. - vector keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); + std::vector keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); if (HaveKeys(keys, keystore) == keys.size()) return MINE_SPENDABLE; break; @@ -1713,7 +1706,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) { - vector vSolutions; + std::vector vSolutions; txnouttype whichType; if (!Solver(scriptPubKey, whichType, vSolutions)) return false; @@ -1737,7 +1730,43 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) return false; } -class CAffectedKeysVisitor : public boost::static_visitor { +bool ExtractAddress(const CKeyStore &keystore, const CScript& scriptPubKey, CBitcoinAddress& addressRet) +{ + std::vector vSolutions; + txnouttype whichType; + if (!Solver(scriptPubKey, whichType, vSolutions)) + return false; + + if (whichType == TX_PUBKEY) + { + addressRet = CBitcoinAddress(CPubKey(vSolutions[0]).GetID()); + return true; + } + if (whichType == TX_PUBKEY_DROP) + { + // Pay-to-Pubkey-R + CMalleableKeyView view; + if (!keystore.CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view)) + return false; + + addressRet = CBitcoinAddress(view.GetMalleablePubKey()); + return true; + } + else if (whichType == TX_PUBKEYHASH) + { + addressRet = CBitcoinAddress(CKeyID(uint160(vSolutions[0]))); + return true; + } + else if (whichType == TX_SCRIPTHASH) + { + addressRet = CBitcoinAddress(CScriptID(uint160(vSolutions[0]))); + return true; + } + // Multisig txns have more than one address... + return false; +} + +class CAffectedKeysVisitor { private: const CKeyStore &keystore; CAffectedKeysVisitor& operator=(CAffectedKeysVisitor const&); @@ -1751,8 +1780,8 @@ public: std::vector vDest; int nRequired; if (ExtractDestinations(script, type, vDest, nRequired)) { - BOOST_FOREACH(const CTxDestination &dest, vDest) - boost::apply_visitor(*this, dest); + for (const CTxDestination &dest : vDest) + std::visit(*this, dest); } } @@ -1775,11 +1804,11 @@ void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, CAffectedKeysVisitor(keystore, vKeys).Process(scriptPubKey); } -bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector& addressRet, int& nRequiredRet) +bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet) { addressRet.clear(); typeRet = TX_NONSTANDARD; - vector vSolutions; + std::vector vSolutions; if (!Solver(scriptPubKey, typeRet, vSolutions)) return false; if (typeRet == TX_NULL_DATA) @@ -1814,7 +1843,7 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType) { - vector > stack, stackCopy; + std::vector > stack, stackCopy; if (!EvalScript(stack, scriptSig, txTo, nIn, flags, nHashType)) return false; if (flags & SCRIPT_VERIFY_P2SH) @@ -1898,26 +1927,26 @@ bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTrans return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType); } -static CScript PushAll(const vector& values) +static CScript PushAll(const std::vector& values) { CScript result; - BOOST_FOREACH(const valtype& v, values) + for (const valtype& v : values) result << v; return result; } static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, - const vector& vSolutions, - vector& sigs1, vector& sigs2) + const std::vector& vSolutions, + std::vector& sigs1, std::vector& sigs2) { // Combine all the signatures we've got: - set allsigs; - BOOST_FOREACH(const valtype& v, sigs1) + std::set allsigs; + for (const valtype& v : sigs1) { if (!v.empty()) allsigs.insert(v); } - BOOST_FOREACH(const valtype& v, sigs2) + for (const valtype& v : sigs2) { if (!v.empty()) allsigs.insert(v); @@ -1927,8 +1956,8 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction& assert(vSolutions.size() > 1); unsigned int nSigsRequired = vSolutions.front()[0]; unsigned int nPubKeys = (unsigned int)(vSolutions.size()-2); - map sigs; - BOOST_FOREACH(const valtype& sig, allsigs) + std::map sigs; + for (const valtype& sig : allsigs) { for (unsigned int i = 0; i < nPubKeys; i++) { @@ -1962,8 +1991,8 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction& } static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, - const txnouttype txType, const vector& vSolutions, - vector& sigs1, vector& sigs2) + const txnouttype txType, const std::vector& vSolutions, + std::vector& sigs1, std::vector& sigs2) { switch (txType) { @@ -1992,7 +2021,7 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction CScript pubKey2(spk.begin(), spk.end()); txnouttype txType2; - vector > vSolutions2; + std::vector > vSolutions2; Solver(pubKey2, txType2, vSolutions2); sigs1.pop_back(); sigs2.pop_back(); @@ -2011,12 +2040,12 @@ CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, const CScript& scriptSig1, const CScript& scriptSig2) { txnouttype txType; - vector > vSolutions; + std::vector > vSolutions; Solver(scriptPubKey, txType, vSolutions); - vector stack1; + std::vector stack1; EvalScript(stack1, scriptSig1, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC, 0); - vector stack2; + std::vector stack2; EvalScript(stack2, scriptSig2, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC, 0); return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2); @@ -2106,7 +2135,7 @@ bool CScript::HasCanonicalPushes() const return true; } -class CScriptVisitor : public boost::static_visitor +class CScriptVisitor { private: CScript *script; @@ -2133,22 +2162,39 @@ public: void CScript::SetDestination(const CTxDestination& dest) { - boost::apply_visitor(CScriptVisitor(this), dest); + std::visit(CScriptVisitor(this), dest); } -void CScript::SetDestination(const CPubKey& R, CPubKey& pubKeyVariant) +void CScript::SetAddress(const CBitcoinAddress& dest) { this->clear(); - *this << pubKeyVariant << R << OP_DROP << OP_CHECKSIG; + if (dest.IsScript()) + *this << OP_HASH160 << dest.GetData() << OP_EQUAL; + else if (dest.IsPubKey()) + *this << OP_DUP << OP_HASH160 << dest.GetData() << OP_EQUALVERIFY << OP_CHECKSIG; + else if (dest.IsPair()) { + // Pubkey pair address, going to generate + // new one-time public key. + CMalleablePubKey mpk; + if (!mpk.setvch(dest.GetData())) + return; + CPubKey R, pubKeyVariant; + mpk.GetVariant(R, pubKeyVariant); + *this << pubKeyVariant << R << OP_DROP << OP_CHECKSIG; + } } - -void CScript::SetMultisig(int nRequired, const std::vector& keys) +void CScript::SetMultisig(int nRequired, const std::vector& keys) { this->clear(); *this << EncodeOP_N(nRequired); - BOOST_FOREACH(const CKey& key, keys) - *this << key.GetPubKey(); + for (const CPubKey& key : keys) + *this << key; *this << EncodeOP_N((int)(keys.size())) << OP_CHECKMULTISIG; } + +CScriptID CScript::GetID() const +{ + return CScriptID(Hash160(*this)); +}