diff --git a/src/script/interpreter.h b/src/script/interpreter.h --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -29,9 +29,24 @@ class BaseSignatureChecker { public: + /** + * Declare which flags absolutely do not affect VerifySignature() result. + * The caching code in sighash.cpp uses this to reduce the number of + * duplicated entries. + */ + static const uint32_t invariantFlagsVerifySignature = + SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_DERSIG | + SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_NULLDUMMY | + SCRIPT_VERIFY_SIGPUSHONLY | SCRIPT_VERIFY_MINIMALDATA | + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | SCRIPT_VERIFY_CLEANSTACK | + SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKSEQUENCEVERIFY | + SCRIPT_VERIFY_MINIMALIF | SCRIPT_VERIFY_NULLFAIL | + SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE | SCRIPT_ENABLE_SIGHASH_FORKID | + SCRIPT_ENABLE_REPLAY_PROTECTION | SCRIPT_ENABLE_CHECKDATASIG; + virtual bool VerifySignature(const std::vector &vchSig, const CPubKey &vchPubKey, - const uint256 &sighash) const; + const uint256 &sighash, uint32_t flags) const; virtual bool CheckSig(const std::vector &vchSigIn, const std::vector &vchPubKey, diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -942,7 +942,8 @@ .Write(vchMessage.data(), vchMessage.size()) .Finalize(vchHash.data()); fSuccess = checker.VerifySignature( - vchSig, CPubKey(vchPubKey), uint256(vchHash)); + vchSig, CPubKey(vchPubKey), uint256(vchHash), + flags); } if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && @@ -1464,7 +1465,8 @@ bool BaseSignatureChecker::VerifySignature(const std::vector &vchSig, const CPubKey &pubkey, - const uint256 &sighash) const { + const uint256 &sighash, + uint32_t flags) const { return pubkey.VerifyECDSA(sighash, vchSig); } @@ -1487,7 +1489,7 @@ uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, sigHashType, amount, this->txdata, flags); - if (!VerifySignature(vchSig, pubkey, sighash)) { + if (!VerifySignature(vchSig, pubkey, sighash, flags)) { return false; } diff --git a/src/script/sigcache.h b/src/script/sigcache.h --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -52,8 +52,8 @@ store(storeIn) {} bool VerifySignature(const std::vector &vchSig, - const CPubKey &vchPubKey, - const uint256 &sighash) const override; + const CPubKey &vchPubKey, const uint256 &sighash, + uint32_t flags) const override; }; void InitSignatureCache(); diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -23,7 +23,8 @@ */ class CSignatureCache { private: - //! Entries are SHA256(nonce || signature hash || public key || signature): + //! Entries are SHA256(nonce || signature || public key || signature hash || + //! flags): uint256 nonce; typedef CuckooCache::cache map_type; map_type setValid; @@ -32,14 +33,17 @@ public: CSignatureCache() { GetRandBytes(nonce.begin(), 32); } - void ComputeEntry(uint256 &entry, const uint256 &hash, - const std::vector &vchSig, - const CPubKey &pubkey) { + void ComputeEntry(uint256 &entry, const std::vector &vchSig, + const CPubKey &pubkey, const uint256 &hash, + uint32_t flags) { + flags &= + ~CachingTransactionSignatureChecker::invariantFlagsVerifySignature; CSHA256() .Write(nonce.begin(), 32) - .Write(hash.begin(), 32) - .Write(&pubkey[0], pubkey.size()) .Write(&vchSig[0], vchSig.size()) + .Write(&pubkey[0], pubkey.size()) + .Write(hash.begin(), 32) + .Write(reinterpret_cast(&flags), sizeof(flags)) .Finalize(entry.begin()); } @@ -82,14 +86,14 @@ bool CachingTransactionSignatureChecker::VerifySignature( const std::vector &vchSig, const CPubKey &pubkey, - const uint256 &sighash) const { + const uint256 &sighash, uint32_t flags) const { uint256 entry; - signatureCache.ComputeEntry(entry, sighash, vchSig, pubkey); + signatureCache.ComputeEntry(entry, vchSig, pubkey, sighash, flags); if (signatureCache.Get(entry, !store)) { return true; } - if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, - sighash)) { + if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, sighash, + flags)) { return false; } if (store) {