diff options
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/interpreter.cpp | 176 | ||||
-rw-r--r-- | src/script/interpreter.h | 58 | ||||
-rw-r--r-- | src/script/script.h | 6 | ||||
-rw-r--r-- | src/script/sigcache.cpp | 88 | ||||
-rw-r--r-- | src/script/sigcache.h | 26 | ||||
-rw-r--r-- | src/script/sign.cpp | 8 | ||||
-rw-r--r-- | src/script/standard.cpp | 15 |
7 files changed, 255 insertions, 122 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index fd3e4f1ff7..ae66217b7c 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -9,14 +9,10 @@ #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha2.h" -#include "random.h" #include "script/script.h" #include "uint256.h" #include "util.h" -#include <boost/thread.hpp> -#include <boost/tuple/tuple_comparison.hpp> - using namespace std; typedef vector<unsigned char> valtype; @@ -56,10 +52,7 @@ static inline void popstack(vector<valtype>& stack) stack.pop_back(); } -bool IsCanonicalPubKey(const valtype &vchPubKey, unsigned int flags) { - if (!(flags & SCRIPT_VERIFY_STRICTENC)) - return true; - +bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { if (vchPubKey.size() < 33) return error("Non-canonical public key: too short"); if (vchPubKey[0] == 0x04) { @@ -74,10 +67,7 @@ bool IsCanonicalPubKey(const valtype &vchPubKey, unsigned int flags) { return true; } -bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { - if (!(flags & SCRIPT_VERIFY_STRICTENC)) - return true; - +bool static IsDERSignature(const valtype &vchSig) { // See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 // A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype> // Where R and S are not negative (their first byte has its highest bit not set), and not @@ -87,9 +77,6 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { return error("Non-canonical signature: too short"); if (vchSig.size() > 73) return error("Non-canonical signature: too long"); - unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY)); - if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE) - return error("Non-canonical signature: unknown hashtype byte"); if (vchSig[0] != 0x30) return error("Non-canonical signature: wrong type"); if (vchSig[1] != vchSig.size()-3) @@ -121,18 +108,55 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) return error("Non-canonical signature: S value excessively padded"); - if (flags & SCRIPT_VERIFY_LOW_S) { - // If the S value is above the order of the curve divided by two, its - // complement modulo the order could have been used instead, which is - // one byte shorter when encoded correctly. - if (!CKey::CheckSignatureElement(S, nLenS, true)) - return error("Non-canonical signature: S value is unnecessarily high"); + return true; +} + +bool static IsLowDERSignature(const valtype &vchSig) { + if (!IsDERSignature(vchSig)) { + return false; } + unsigned int nLenR = vchSig[3]; + unsigned int nLenS = vchSig[5+nLenR]; + const unsigned char *S = &vchSig[6+nLenR]; + // If the S value is above the order of the curve divided by two, its + // complement modulo the order could have been used instead, which is + // one byte shorter when encoded correctly. + if (!CKey::CheckSignatureElement(S, nLenS, true)) + return error("Non-canonical signature: S value is unnecessarily high"); + + return true; +} + +bool static IsDefinedHashtypeSignature(const valtype &vchSig) { + if (vchSig.size() == 0) { + return false; + } + unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY)); + if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE) + return error("Non-canonical signature: unknown hashtype byte"); + + return true; +} + +bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags) { + if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsDERSignature(vchSig)) { + return false; + } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig)) { + return false; + } else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature(vchSig)) { + return false; + } + return true; +} +bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags) { + if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchSig)) { + return false; + } return true; } -bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags) +bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker) { CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); @@ -637,19 +661,19 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co valtype& vch = stacktop(-1); valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32); if (opcode == OP_RIPEMD160) - CRIPEMD160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CRIPEMD160().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_SHA1) - CSHA1().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CSHA1().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_SHA256) - CSHA256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CSHA256().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_HASH160) - CHash160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CHash160().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_HASH256) - CHash256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); + CHash256().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); popstack(stack); stack.push_back(vchHash); } - break; + break; case OP_CODESEPARATOR: { @@ -674,8 +698,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co // Drop the signature, since there's no way for a signature to sign itself scriptCode.FindAndDelete(CScript(vchSig)); - bool fSuccess = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && - CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, flags); + if (!CheckSignatureEncoding(vchSig, flags)) { + return false; + } + + bool fSuccess = CheckPubKeyEncoding(vchPubKey, flags) && checker.CheckSig(vchSig, vchPubKey, scriptCode); popstack(stack); popstack(stack); @@ -734,9 +761,12 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co valtype& vchSig = stacktop(-isig); valtype& vchPubKey = stacktop(-ikey); + if (!CheckSignatureEncoding(vchSig, flags)) { + return false; + } + // Check signature - bool fOk = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && - CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, flags); + bool fOk = CheckPubKeyEncoding(vchPubKey, flags) && checker.CheckSig(vchSig, vchPubKey, scriptCode); if (fOk) { isig++; @@ -839,7 +869,8 @@ public: itBegin = it; } } - s.write((char*)&itBegin[0], it-itBegin); + if (itBegin != scriptCode.end()) + s.write((char*)&itBegin[0], it-itBegin); } /** Serialize an input of txTo */ @@ -896,7 +927,7 @@ public: } // anon namespace -uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) +uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) { if (nIn >= txTo.vin.size()) { LogPrintf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn); @@ -920,70 +951,19 @@ uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsig return ss.GetHash(); } -// Valid signature cache, to avoid doing expensive ECDSA signature checking -// twice for every transaction (once when accepted into memory pool, and -// again when accepted into the block chain) -class CSignatureCache +bool SignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const { -private: - // sigdata_type is (signature hash, signature, public key): - typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type; - std::set< sigdata_type> setValid; - boost::shared_mutex cs_sigcache; - -public: - bool - Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) - { - boost::shared_lock<boost::shared_mutex> lock(cs_sigcache); - - sigdata_type k(hash, vchSig, pubKey); - std::set<sigdata_type>::iterator mi = setValid.find(k); - if (mi != setValid.end()) - return true; - return false; - } - - void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) - { - // DoS prevention: limit cache size to less than 10MB - // (~200 bytes per cache entry times 50,000 entries) - // Since there are a maximum of 20,000 signature operations per block - // 50,000 is a reasonable default. - int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000); - if (nMaxCacheSize <= 0) return; - - boost::unique_lock<boost::shared_mutex> lock(cs_sigcache); - - while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize) - { - // Evict a random entry. Random because that helps - // foil would-be DoS attackers who might try to pre-generate - // and re-use a set of valid signatures just-slightly-greater - // than our cache size. - uint256 randomHash = GetRandHash(); - std::vector<unsigned char> unused; - std::set<sigdata_type>::iterator it = - setValid.lower_bound(sigdata_type(randomHash, unused, unused)); - if (it == setValid.end()) - it = setValid.begin(); - setValid.erase(*it); - } - - sigdata_type k(hash, vchSig, pubKey); - setValid.insert(k); - } -}; + return pubkey.Verify(sighash, vchSig); +} -bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int flags) +bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const { - static CSignatureCache signatureCache; - CPubKey pubkey(vchPubKey); if (!pubkey.IsValid()) return false; // Hash type is one byte tacked on to the end of the signature + vector<unsigned char> vchSig(vchSigIn); if (vchSig.empty()) return false; int nHashType = vchSig.back(); @@ -991,26 +971,20 @@ bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char>& vchPubK uint256 sighash = SignatureHash(scriptCode, txTo, nIn, nHashType); - if (signatureCache.Get(sighash, vchSig, pubkey)) - return true; - - if (!pubkey.Verify(sighash, vchSig)) + if (!VerifySignature(vchSig, pubkey, sighash)) return false; - if (!(flags & SCRIPT_VERIFY_NOCACHE)) - signatureCache.Set(sighash, vchSig, pubkey); - return true; } -bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags) +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker) { vector<vector<unsigned char> > stack, stackCopy; - if (!EvalScript(stack, scriptSig, txTo, nIn, flags)) + if (!EvalScript(stack, scriptSig, flags, checker)) return false; if (flags & SCRIPT_VERIFY_P2SH) stackCopy = stack; - if (!EvalScript(stack, scriptPubKey, txTo, nIn, flags)) + if (!EvalScript(stack, scriptPubKey, flags, checker)) return false; if (stack.empty()) return false; @@ -1033,7 +1007,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); popstack(stackCopy); - if (!EvalScript(stackCopy, pubKey2, txTo, nIn, flags)) + if (!EvalScript(stackCopy, pubKey2, flags, checker)) return false; if (stackCopy.empty()) return false; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index adca2142ac..de5ce2ced1 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -10,6 +10,7 @@ #include <stdint.h> #include <string> +class CPubKey; class CScript; class CTransaction; class uint256; @@ -27,19 +28,54 @@ enum enum { SCRIPT_VERIFY_NONE = 0, - SCRIPT_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts - SCRIPT_VERIFY_STRICTENC = (1U << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys - SCRIPT_VERIFY_LOW_S = (1U << 2), // enforce low S values (<n/2) in signatures (depends on STRICTENC) - SCRIPT_VERIFY_NOCACHE = (1U << 3), // do not store results in signature cache (but do query it) - SCRIPT_VERIFY_NULLDUMMY = (1U << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length -}; -bool IsCanonicalPubKey(const std::vector<unsigned char> &vchPubKey, unsigned int flags); -bool IsCanonicalSignature(const std::vector<unsigned char> &vchSig, unsigned int flags); + // Evaluate P2SH subscripts (softfork safe, BIP16). + SCRIPT_VERIFY_P2SH = (1U << 0), + + // Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure. + // Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be + // skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT). + SCRIPT_VERIFY_STRICTENC = (1U << 1), + + // Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1) + SCRIPT_VERIFY_DERSIG = (1U << 2), + + // Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure + // (softfork safe, BIP62 rule 5). + SCRIPT_VERIFY_LOW_S = (1U << 3), + + // verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7). + SCRIPT_VERIFY_NULLDUMMY = (1U << 4), +}; uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); -bool CheckSig(std::vector<unsigned char> vchSig, const std::vector<unsigned char> &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int flags); -bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags); -bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags); + +class BaseSignatureChecker +{ +public: + virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const + { + return false; + } + + virtual ~BaseSignatureChecker() {} +}; + +class SignatureChecker : public BaseSignatureChecker +{ +private: + const CTransaction& txTo; + unsigned int nIn; + +protected: + virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; + +public: + SignatureChecker(const CTransaction& txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {} + bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const; +}; + +bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker); +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker); #endif // H_BITCOIN_SCRIPT_INTERPRETER diff --git a/src/script/script.h b/src/script/script.h index 07a4229f85..caf176476f 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -304,7 +304,7 @@ private: // If the input vector's most significant byte is 0x80, remove it from // the result's msb and return a negative. if (vch.back() & 0x80) - return -(result & ~(0x80ULL << (8 * (vch.size() - 1)))); + return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1))))); return result; } @@ -340,9 +340,7 @@ public: CScript() { } CScript(const CScript& b) : std::vector<unsigned char>(b.begin(), b.end()) { } CScript(const_iterator pbegin, const_iterator pend) : std::vector<unsigned char>(pbegin, pend) { } -#ifndef _MSC_VER CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector<unsigned char>(pbegin, pend) { } -#endif CScript& operator+=(const CScript& b) { @@ -546,7 +544,7 @@ public: { while (end() - pc >= (long)b.size() && memcmp(&pc[0], &b[0], b.size()) == 0) { - erase(pc, pc + b.size()); + pc = erase(pc, pc + b.size()); ++nFound; } } diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp new file mode 100644 index 0000000000..ab366898d8 --- /dev/null +++ b/src/script/sigcache.cpp @@ -0,0 +1,88 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "sigcache.h" + +#include "key.h" +#include "random.h" +#include "uint256.h" +#include "util.h" + +#include <boost/thread.hpp> +#include <boost/tuple/tuple_comparison.hpp> + +namespace { + +// Valid signature cache, to avoid doing expensive ECDSA signature checking +// twice for every transaction (once when accepted into memory pool, and +// again when accepted into the block chain) +class CSignatureCache +{ +private: + // sigdata_type is (signature hash, signature, public key): + typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type; + std::set< sigdata_type> setValid; + boost::shared_mutex cs_sigcache; + +public: + bool + Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) + { + boost::shared_lock<boost::shared_mutex> lock(cs_sigcache); + + sigdata_type k(hash, vchSig, pubKey); + std::set<sigdata_type>::iterator mi = setValid.find(k); + if (mi != setValid.end()) + return true; + return false; + } + + void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) + { + // DoS prevention: limit cache size to less than 10MB + // (~200 bytes per cache entry times 50,000 entries) + // Since there are a maximum of 20,000 signature operations per block + // 50,000 is a reasonable default. + int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000); + if (nMaxCacheSize <= 0) return; + + boost::unique_lock<boost::shared_mutex> lock(cs_sigcache); + + while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize) + { + // Evict a random entry. Random because that helps + // foil would-be DoS attackers who might try to pre-generate + // and re-use a set of valid signatures just-slightly-greater + // than our cache size. + uint256 randomHash = GetRandHash(); + std::vector<unsigned char> unused; + std::set<sigdata_type>::iterator it = + setValid.lower_bound(sigdata_type(randomHash, unused, unused)); + if (it == setValid.end()) + it = setValid.begin(); + setValid.erase(*it); + } + + sigdata_type k(hash, vchSig, pubKey); + setValid.insert(k); + } +}; + +} + +bool CachingSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const +{ + static CSignatureCache signatureCache; + + if (signatureCache.Get(sighash, vchSig, pubkey)) + return true; + + if (!SignatureChecker::VerifySignature(vchSig, pubkey, sighash)) + return false; + + if (store) + signatureCache.Set(sighash, vchSig, pubkey); + return true; +} diff --git a/src/script/sigcache.h b/src/script/sigcache.h new file mode 100644 index 0000000000..46b8f4d335 --- /dev/null +++ b/src/script/sigcache.h @@ -0,0 +1,26 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef H_BITCOIN_SCRIPT_SIGCACHE +#define H_BITCOIN_SCRIPT_SIGCACHE + +#include "script/interpreter.h" + +#include <vector> + +class CPubKey; + +class CachingSignatureChecker : public SignatureChecker +{ +private: + bool store; + +public: + CachingSignatureChecker(const CTransaction& txToIn, unsigned int nInIn, bool storeIn=true) : SignatureChecker(txToIn, nInIn), store(storeIn) {} + + bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; +}; + +#endif // H_BITCOIN_SCRIPT_SIGCACHE diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 8abd8d221d..da77e7d1f1 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -123,7 +123,7 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutabl } // Test solution - return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS); + return VerifyScript(txin.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, SignatureChecker(txTo, nIn)); } bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType) @@ -174,7 +174,7 @@ static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& if (sigs.count(pubkey)) continue; // Already got a sig for this pubkey - if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0)) + if (SignatureChecker(txTo, nIn).CheckSig(sig, pubkey, scriptPubKey)) { sigs[pubkey] = sig; break; @@ -252,9 +252,9 @@ CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsign Solver(scriptPubKey, txType, vSolutions); vector<valtype> stack1; - EvalScript(stack1, scriptSig1, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC); + EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker()); vector<valtype> stack2; - EvalScript(stack2, scriptSig2, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC); + EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker()); return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2); } diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 407baf621d..53ae254d59 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -203,7 +203,11 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) if (whichType == TX_PUBKEY) { - addressRet = CPubKey(vSolutions[0]).GetID(); + CPubKey pubKey(vSolutions[0]); + if (!pubKey.IsValid()) + return false; + + addressRet = pubKey.GetID(); return true; } else if (whichType == TX_PUBKEYHASH) @@ -237,9 +241,16 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto nRequiredRet = vSolutions.front()[0]; for (unsigned int i = 1; i < vSolutions.size()-1; i++) { - CTxDestination address = CPubKey(vSolutions[i]).GetID(); + CPubKey pubKey(vSolutions[i]); + if (!pubKey.IsValid()) + continue; + + CTxDestination address = pubKey.GetID(); addressRet.push_back(address); } + + if (addressRet.empty()) + return false; } else { |