diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -361,7 +361,7 @@ : hashPrevouts(txdata.hashPrevouts), hashSequence(txdata.hashSequence), hashOutputs(txdata.hashOutputs) {} - explicit PrecomputedTransactionData(const CTransaction &tx); + template explicit PrecomputedTransactionData(const T &tx); }; #endif // BITCOIN_PRIMITIVES_TRANSACTION_H diff --git a/src/script/interpreter.h b/src/script/interpreter.h --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -21,7 +21,8 @@ class CTransaction; class uint256; -uint256 SignatureHash(const CScript &scriptCode, const CTransaction &txTo, +template +uint256 SignatureHash(const CScript &scriptCode, const T &txTo, unsigned int nIn, SigHashType sigHashType, const Amount amount, const PrecomputedTransactionData *cache = nullptr, @@ -50,20 +51,21 @@ virtual ~BaseSignatureChecker() {} }; -class TransactionSignatureChecker : public BaseSignatureChecker { +template +class GenericTransactionSignatureChecker : public BaseSignatureChecker { private: - const CTransaction *txTo; + const T *txTo; unsigned int nIn; const Amount amount; const PrecomputedTransactionData *txdata; public: - TransactionSignatureChecker(const CTransaction *txToIn, unsigned int nInIn, - const Amount amountIn) + GenericTransactionSignatureChecker(const T *txToIn, unsigned int nInIn, + const Amount &amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(nullptr) {} - TransactionSignatureChecker(const CTransaction *txToIn, unsigned int nInIn, - const Amount amountIn, - const PrecomputedTransactionData &txdataIn) + GenericTransactionSignatureChecker( + const T *txToIn, unsigned int nInIn, const Amount &amountIn, + const PrecomputedTransactionData &txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {} // The overridden functions are now final. @@ -75,16 +77,10 @@ bool CheckSequence(const CScriptNum &nSequence) const final override; }; -class MutableTransactionSignatureChecker : public TransactionSignatureChecker { -private: - const CTransaction txTo; - -public: - MutableTransactionSignatureChecker(const CMutableTransaction *txToIn, - unsigned int nInIn, - const Amount amountIn) - : TransactionSignatureChecker(&txTo, nInIn, amountIn), txTo(*txToIn) {} -}; +using TransactionSignatureChecker = + GenericTransactionSignatureChecker; +using MutableTransactionSignatureChecker = + GenericTransactionSignatureChecker; bool EvalScript(std::vector> &stack, const CScript &script, uint32_t flags, const BaseSignatureChecker &checker, diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1331,10 +1331,10 @@ * Wrapper that serializes like CTransaction, but with the modifications * required for the signature hash done in-place */ -class CTransactionSignatureSerializer { +template class CTransactionSignatureSerializer { private: //!< reference to the spending transaction (the one being serialized) - const CTransaction &txTo; + const T &txTo; //!< output script being consumed const CScript &scriptCode; //!< input index of txTo being signed @@ -1343,7 +1343,7 @@ const SigHashType sigHashType; public: - CTransactionSignatureSerializer(const CTransaction &txToIn, + CTransactionSignatureSerializer(const T &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, SigHashType sigHashTypeIn) @@ -1440,7 +1440,7 @@ } }; -uint256 GetPrevoutHash(const CTransaction &txTo) { +template uint256 GetPrevoutHash(const T &txTo) { CHashWriter ss(SER_GETHASH, 0); for (const auto &txin : txTo.vin) { ss << txin.prevout; @@ -1448,7 +1448,7 @@ return ss.GetHash(); } -uint256 GetSequenceHash(const CTransaction &txTo) { +template uint256 GetSequenceHash(const T &txTo) { CHashWriter ss(SER_GETHASH, 0); for (const auto &txin : txTo.vin) { ss << txin.nSequence; @@ -1456,7 +1456,7 @@ return ss.GetHash(); } -uint256 GetOutputsHash(const CTransaction &txTo) { +template uint256 GetOutputsHash(const T &txTo) { CHashWriter ss(SER_GETHASH, 0); for (const auto &txout : txTo.vout) { ss << txout; @@ -1466,14 +1466,21 @@ } // namespace -PrecomputedTransactionData::PrecomputedTransactionData( - const CTransaction &txTo) { +template +PrecomputedTransactionData::PrecomputedTransactionData(const T &txTo) { hashPrevouts = GetPrevoutHash(txTo); hashSequence = GetSequenceHash(txTo); hashOutputs = GetOutputsHash(txTo); } -uint256 SignatureHash(const CScript &scriptCode, const CTransaction &txTo, +// explicit instantiation +template PrecomputedTransactionData::PrecomputedTransactionData( + const CTransaction &txTo); +template PrecomputedTransactionData::PrecomputedTransactionData( + const CMutableTransaction &txTo); + +template +uint256 SignatureHash(const CScript &scriptCode, const T &txTo, unsigned int nIn, SigHashType sigHashType, const Amount amount, const PrecomputedTransactionData *cache, uint32_t flags) { @@ -1547,7 +1554,8 @@ // Wrapper to serialize only the necessary parts of the transaction being // signed - CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, sigHashType); + CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, + sigHashType); // Serialize and hash CHashWriter ss(SER_GETHASH, 0); @@ -1565,7 +1573,8 @@ } } -bool TransactionSignatureChecker::CheckSig( +template +bool GenericTransactionSignatureChecker::CheckSig( const std::vector &vchSigIn, const std::vector &vchPubKey, const CScript &scriptCode, uint32_t flags) const { CPubKey pubkey(vchPubKey); @@ -1591,7 +1600,8 @@ return true; } -bool TransactionSignatureChecker::CheckLockTime( +template +bool GenericTransactionSignatureChecker::CheckLockTime( const CScriptNum &nLockTime) const { // There are two kinds of nLockTime: lock-by-blockheight and // lock-by-blocktime, distinguished by whether nLockTime < @@ -1629,7 +1639,8 @@ return true; } -bool TransactionSignatureChecker::CheckSequence( +template +bool GenericTransactionSignatureChecker::CheckSequence( const CScriptNum &nSequence) const { // Relative lock times are supported by comparing the passed in operand to // the sequence number of the input. @@ -1679,6 +1690,10 @@ return true; } +// explicit instantiation +template class GenericTransactionSignatureChecker; +template class GenericTransactionSignatureChecker; + bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, uint32_t flags, const BaseSignatureChecker &checker, ScriptError *serror) { diff --git a/src/script/sign.h b/src/script/sign.h --- a/src/script/sign.h +++ b/src/script/sign.h @@ -39,35 +39,23 @@ }; /** A signature creator for transactions. */ -class TransactionSignatureCreator : public BaseSignatureCreator { - const CTransaction *txTo; +class MutableTransactionSignatureCreator : public BaseSignatureCreator { + const CMutableTransaction *txTo; unsigned int nIn; Amount amount; SigHashType sigHashType; - const TransactionSignatureChecker checker; + const MutableTransactionSignatureChecker checker; public: - TransactionSignatureCreator(const CTransaction *txToIn, unsigned int nInIn, - const Amount amountIn, - SigHashType sigHashTypeIn = SigHashType()); + MutableTransactionSignatureCreator( + const CMutableTransaction *txToIn, unsigned int nInIn, + const Amount &amountIn, SigHashType sigHashTypeIn = SigHashType()); const BaseSignatureChecker &Checker() const override { return checker; } bool CreateSig(const SigningProvider &provider, std::vector &vchSig, const CKeyID &keyid, const CScript &scriptCode) const override; }; -class MutableTransactionSignatureCreator : public TransactionSignatureCreator { - CTransaction tx; - -public: - MutableTransactionSignatureCreator(const CMutableTransaction *txToIn, - unsigned int nInIn, - const Amount amountIn, - SigHashType sigHashTypeIn) - : TransactionSignatureCreator(&tx, nInIn, amountIn, sigHashTypeIn), - tx(*txToIn) {} -}; - /** A signature creator that just produces 72-byte empty signatures. */ extern const BaseSignatureCreator &DUMMY_SIGNATURE_CREATOR; diff --git a/src/script/sign.cpp b/src/script/sign.cpp --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -13,16 +13,15 @@ typedef std::vector valtype; -TransactionSignatureCreator::TransactionSignatureCreator( - const CTransaction *txToIn, unsigned int nInIn, const Amount amountIn, - SigHashType sigHashTypeIn) +MutableTransactionSignatureCreator::MutableTransactionSignatureCreator( + const CMutableTransaction *txToIn, unsigned int nInIn, + const Amount &amountIn, SigHashType sigHashTypeIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), sigHashType(sigHashTypeIn), checker(txTo, nIn, amountIn) {} -bool TransactionSignatureCreator::CreateSig(const SigningProvider &provider, - std::vector &vchSig, - const CKeyID &address, - const CScript &scriptCode) const { +bool MutableTransactionSignatureCreator::CreateSig( + const SigningProvider &provider, std::vector &vchSig, + const CKeyID &address, const CScript &scriptCode) const { CKey key; if (!provider.GetKey(address, key)) { return false; @@ -177,8 +176,7 @@ const Amount amount, SigHashType sigHashType) { assert(nIn < txTo.vin.size()); - CTransaction txToConst(txTo); - TransactionSignatureCreator creator(&txToConst, nIn, amount, sigHashType); + MutableTransactionSignatureCreator creator(&txTo, nIn, amount, sigHashType); SignatureData sigdata; bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2787,7 +2787,6 @@ bool CWallet::SignTransaction(CMutableTransaction &tx) { // sign the new tx - CTransaction txNewConst(tx); int nIn = 0; for (const auto &input : tx.vin) { auto mi = mapWallet.find(input.prevout.GetTxId()); @@ -2801,8 +2800,8 @@ SignatureData sigdata; SigHashType sigHashType = SigHashType().withForkId(); if (!ProduceSignature(*this, - TransactionSignatureCreator(&txNewConst, nIn, - amount, sigHashType), + MutableTransactionSignatureCreator( + &tx, nIn, amount, sigHashType), scriptPubKey, sigdata)) { return false; } @@ -3253,7 +3252,6 @@ if (sign) { SigHashType sigHashType = SigHashType().withForkId(); - CTransaction txNewConst(txNew); int nIn = 0; for (const auto &coin : selected_coins) { const CScript &scriptPubKey = coin.txout.scriptPubKey; @@ -3261,8 +3259,8 @@ if (!ProduceSignature( *this, - TransactionSignatureCreator( - &txNewConst, nIn, coin.txout.nValue, sigHashType), + MutableTransactionSignatureCreator( + &txNew, nIn, coin.txout.nValue, sigHashType), scriptPubKey, sigdata)) { strFailReason = _("Signing transaction failed"); return false;