diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index a71f55dd2..048d298f0 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -132,7 +132,7 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { return true; } -bool EvalScript(vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags) +bool EvalScript(vector >& stack, const CScript& script, unsigned int flags, const SignatureChecker& checker) { CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); @@ -675,7 +675,7 @@ bool EvalScript(vector >& stack, const CScript& script, co scriptCode.FindAndDelete(CScript(vchSig)); bool fSuccess = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && - CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, flags); + checker.CheckSig(vchSig, vchPubKey, scriptCode, flags); popstack(stack); popstack(stack); @@ -736,7 +736,7 @@ bool EvalScript(vector >& stack, const CScript& script, co // Check signature bool fOk = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && - CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, flags); + checker.CheckSig(vchSig, vchPubKey, scriptCode, flags); if (fOk) { isig++; @@ -897,7 +897,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); @@ -976,7 +976,7 @@ public: } }; -bool CheckSig(vector vchSig, const vector& vchPubKey, const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int flags) +bool SignatureChecker::CheckSig(const vector& vchSigIn, const vector& vchPubKey, const CScript& scriptCode, int flags) const { static CSignatureCache signatureCache; @@ -985,6 +985,7 @@ bool CheckSig(vector vchSig, const vector& vchPubK return false; // Hash type is one byte tacked on to the end of the signature + vector vchSig(vchSigIn); if (vchSig.empty()) return false; int nHashType = vchSig.back(); @@ -1004,14 +1005,14 @@ bool CheckSig(vector vchSig, const vector& vchPubK 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 SignatureChecker& checker) { vector > 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; @@ -1034,7 +1035,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 adca2142a..f3fd49a3b 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -38,8 +38,30 @@ bool IsCanonicalPubKey(const std::vector &vchPubKey, unsigned int bool IsCanonicalSignature(const std::vector &vchSig, unsigned int flags); uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); -bool CheckSig(std::vector vchSig, const std::vector &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int flags); -bool EvalScript(std::vector >& 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 SignatureChecker +{ +private: + const CTransaction& txTo; + unsigned int nIn; + +public: + SignatureChecker(const CTransaction& txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {} + bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, int nFlags) const; +}; + +bool EvalScript(std::vector >& stack, const CScript& script, unsigned int flags, const SignatureChecker& checker); +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const SignatureChecker& checker); + +// Wrappers using a default SignatureChecker. +bool inline EvalScript(std::vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags) +{ + return EvalScript(stack, script, flags, SignatureChecker(txTo, nIn)); +} + +bool inline VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags) +{ + return VerifyScript(scriptSig, scriptPubKey, flags, SignatureChecker(txTo, nIn)); +} #endif // H_BITCOIN_SCRIPT_INTERPRETER diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 8abd8d221..a17fb5878 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -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, 0)) { sigs[pubkey] = sig; break; diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 7f09b3daa..992f32cc4 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -89,7 +89,7 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CTr void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message) { - BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)), 0, flags) == expect, message); + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, SignatureChecker(BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)), 0)) == expect, message); } namespace