diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -669,8 +669,9 @@ // Only sign SIGHASH_SINGLE if there's a corresponding output: if ((sigHashType.getBaseType() != BaseSigHashType::SINGLE) || (i < mergedTx.vout.size())) { - ProduceSignature(MutableTransactionSignatureCreator( - &keystore, &mergedTx, i, amount, sigHashType), + ProduceSignature(keystore, + MutableTransactionSignatureCreator( + &mergedTx, i, amount, sigHashType), prevPubKey, sigdata); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -983,8 +983,9 @@ // Only sign SIGHASH_SINGLE if there's a corresponding output: if ((sigHashType.getBaseType() != BaseSigHashType::SINGLE) || (i < mtx.vout.size())) { - ProduceSignature(MutableTransactionSignatureCreator( - keystore, &mtx, i, amount, sigHashType), + ProduceSignature(*keystore, + MutableTransactionSignatureCreator(&mtx, i, amount, + sigHashType), prevPubKey, sigdata); } sigdata = CombineSignatures( diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp --- a/src/script/ismine.cpp +++ b/src/script/ismine.cpp @@ -96,7 +96,7 @@ // TODO: This could be optimized some by doing some work after the above // solver SignatureData sigs; - return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, + return ProduceSignature(keystore, DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE; diff --git a/src/script/sign.h b/src/script/sign.h --- a/src/script/sign.h +++ b/src/script/sign.h @@ -26,20 +26,15 @@ virtual bool GetKey(const CKeyID &address, CKey &key) const = 0; }; -/** Virtual base class for signature creators. */ +/** Interface for signature creators. */ class BaseSignatureCreator { -protected: - const SigningProvider *m_provider; - public: - explicit BaseSignatureCreator(const SigningProvider *provider) - : m_provider(provider) {} - const SigningProvider &Provider() const { return *m_provider; } virtual ~BaseSignatureCreator() {} virtual const BaseSignatureChecker &Checker() const = 0; /** Create a singular (non-script) signature. */ - virtual bool CreateSig(std::vector &vchSig, const CKeyID &keyid, + virtual bool CreateSig(const SigningProvider &provider, + std::vector &vchSig, const CKeyID &keyid, const CScript &scriptCode) const = 0; }; @@ -52,12 +47,12 @@ const TransactionSignatureChecker checker; public: - TransactionSignatureCreator(const SigningProvider *provider, - const CTransaction *txToIn, unsigned int nInIn, + TransactionSignatureCreator(const CTransaction *txToIn, unsigned int nInIn, const Amount amountIn, SigHashType sigHashTypeIn = SigHashType()); const BaseSignatureChecker &Checker() const override { return checker; } - bool CreateSig(std::vector &vchSig, const CKeyID &keyid, + bool CreateSig(const SigningProvider &provider, + std::vector &vchSig, const CKeyID &keyid, const CScript &scriptCode) const override; }; @@ -65,25 +60,16 @@ CTransaction tx; public: - MutableTransactionSignatureCreator(const SigningProvider *provider, - const CMutableTransaction *txToIn, + MutableTransactionSignatureCreator(const CMutableTransaction *txToIn, unsigned int nInIn, const Amount amountIn, SigHashType sigHashTypeIn) - : TransactionSignatureCreator(provider, &tx, nInIn, amountIn, - sigHashTypeIn), + : TransactionSignatureCreator(&tx, nInIn, amountIn, sigHashTypeIn), tx(*txToIn) {} }; /** A signature creator that just produces 72-byte empty signatures. */ -class DummySignatureCreator : public BaseSignatureCreator { -public: - explicit DummySignatureCreator(const SigningProvider *provider) - : BaseSignatureCreator(provider) {} - const BaseSignatureChecker &Checker() const override; - bool CreateSig(std::vector &vchSig, const CKeyID &keyid, - const CScript &scriptCode) const override; -}; +extern const BaseSignatureCreator &DUMMY_SIGNATURE_CREATOR; struct SignatureData { CScript scriptSig; @@ -93,7 +79,8 @@ }; /** Produce a script signature using a generic signature creator. */ -bool ProduceSignature(const BaseSignatureCreator &creator, +bool ProduceSignature(const SigningProvider &provider, + const BaseSignatureCreator &creator, const CScript &scriptPubKey, SignatureData &sigdata); /** Produce a script signature for a transaction. */ diff --git a/src/script/sign.cpp b/src/script/sign.cpp --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -14,17 +14,17 @@ typedef std::vector valtype; TransactionSignatureCreator::TransactionSignatureCreator( - const SigningProvider *provider, const CTransaction *txToIn, - unsigned int nInIn, const Amount amountIn, SigHashType sigHashTypeIn) - : BaseSignatureCreator(provider), txTo(txToIn), nIn(nInIn), - amount(amountIn), sigHashType(sigHashTypeIn), + const CTransaction *txToIn, unsigned int nInIn, const Amount amountIn, + SigHashType sigHashTypeIn) + : txTo(txToIn), nIn(nInIn), amount(amountIn), sigHashType(sigHashTypeIn), checker(txTo, nIn, amountIn) {} -bool TransactionSignatureCreator::CreateSig(std::vector &vchSig, +bool TransactionSignatureCreator::CreateSig(const SigningProvider &provider, + std::vector &vchSig, const CKeyID &address, const CScript &scriptCode) const { CKey key; - if (!m_provider->GetKey(address, key)) { + if (!provider.GetKey(address, key)) { return false; } @@ -37,10 +37,11 @@ return true; } -static bool Sign1(const CKeyID &address, const BaseSignatureCreator &creator, +static bool Sign1(const SigningProvider &provider, const CKeyID &address, + const BaseSignatureCreator &creator, const CScript &scriptCode, std::vector &ret) { std::vector vchSig; - if (!creator.CreateSig(vchSig, address, scriptCode)) { + if (!creator.CreateSig(provider, vchSig, address, scriptCode)) { return false; } @@ -48,7 +49,8 @@ return true; } -static bool SignN(const std::vector &multisigdata, +static bool SignN(const SigningProvider &provider, + const std::vector &multisigdata, const BaseSignatureCreator &creator, const CScript &scriptCode, std::vector &ret) { int nSigned = 0; @@ -57,7 +59,7 @@ i++) { const valtype &pubkey = multisigdata[i]; CKeyID keyID = CPubKey(pubkey).GetID(); - if (Sign1(keyID, creator, scriptCode, ret)) { + if (Sign1(provider, keyID, creator, scriptCode, ret)) { ++nSigned; } } @@ -72,7 +74,8 @@ * scriptSigRet is the redemption script. * Returns false if scriptPubKey could not be completely satisfied. */ -static bool SignStep(const BaseSignatureCreator &creator, +static bool SignStep(const SigningProvider &provider, + const BaseSignatureCreator &creator, const CScript &scriptPubKey, std::vector &ret, txnouttype &whichTypeRet) { CScript scriptRet; @@ -91,21 +94,20 @@ return false; case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); - return Sign1(keyID, creator, scriptPubKey, ret); + return Sign1(provider, keyID, creator, scriptPubKey, ret); case TX_PUBKEYHASH: { keyID = CKeyID(uint160(vSolutions[0])); - if (!Sign1(keyID, creator, scriptPubKey, ret)) { + if (!Sign1(provider, keyID, creator, scriptPubKey, ret)) { return false; } CPubKey vch; - creator.Provider().GetPubKey(keyID, vch); + provider.GetPubKey(keyID, vch); ret.push_back(ToByteVector(vch)); return true; } case TX_SCRIPTHASH: - if (creator.Provider().GetCScript(uint160(vSolutions[0]), - scriptRet)) { + if (provider.GetCScript(uint160(vSolutions[0]), scriptRet)) { ret.push_back( std::vector(scriptRet.begin(), scriptRet.end())); return true; @@ -114,7 +116,7 @@ case TX_MULTISIG: // workaround CHECKMULTISIG bug ret.push_back(valtype()); - return (SignN(vSolutions, creator, scriptPubKey, ret)); + return (SignN(provider, vSolutions, creator, scriptPubKey, ret)); default: return false; } @@ -135,11 +137,12 @@ return result; } -bool ProduceSignature(const BaseSignatureCreator &creator, +bool ProduceSignature(const SigningProvider &provider, + const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata) { std::vector result; txnouttype whichType; - bool solved = SignStep(creator, fromPubKey, result, whichType); + bool solved = SignStep(provider, creator, fromPubKey, result, whichType); CScript subscript; if (solved && whichType == TX_SCRIPTHASH) { @@ -147,7 +150,8 @@ // scriptSig is the signatures from that and then the serialized // subscript: subscript = CScript(result[0].begin(), result[0].end()); - solved = solved && SignStep(creator, subscript, result, whichType) && + solved = solved && + SignStep(provider, creator, subscript, result, whichType) && whichType != TX_SCRIPTHASH; result.push_back( std::vector(subscript.begin(), subscript.end())); @@ -185,11 +189,10 @@ assert(nIn < txTo.vin.size()); CTransaction txToConst(txTo); - TransactionSignatureCreator creator(&provider, &txToConst, nIn, amount, - sigHashType); + TransactionSignatureCreator creator(&txToConst, nIn, amount, sigHashType); SignatureData sigdata; - bool ret = ProduceSignature(creator, fromPubKey, sigdata); + bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata); UpdateTransaction(txTo, nIn, sigdata); return ret; } @@ -352,36 +355,40 @@ namespace { /** Dummy signature checker which accepts all signatures. */ -class DummySignatureChecker : public BaseSignatureChecker { +class DummySignatureChecker final : public BaseSignatureChecker { public: DummySignatureChecker() {} - bool CheckSig(const std::vector &scriptSig, const std::vector &vchPubKey, const CScript &scriptCode, uint32_t flags) const override { return true; } }; -const DummySignatureChecker dummyChecker; -} // namespace +const DummySignatureChecker DUMMY_CHECKER; -const BaseSignatureChecker &DummySignatureCreator::Checker() const { - return dummyChecker; -} +class DummySignatureCreator final : public BaseSignatureCreator { +public: + DummySignatureCreator() {} + const BaseSignatureChecker &Checker() const override { + return DUMMY_CHECKER; + } + bool CreateSig(const SigningProvider &provider, + std::vector &vchSig, const CKeyID &keyid, + const CScript &scriptCode) const { + // Create a dummy signature that is a valid DER-encoding + vchSig.assign(72, '\000'); + vchSig[0] = 0x30; + vchSig[1] = 69; + vchSig[2] = 0x02; + vchSig[3] = 33; + vchSig[4] = 0x01; + vchSig[4 + 33] = 0x02; + vchSig[5 + 33] = 32; + vchSig[6 + 33] = 0x01; + vchSig[6 + 33 + 32] = SIGHASH_ALL | SIGHASH_FORKID; + return true; + } +}; +} // namespace -bool DummySignatureCreator::CreateSig(std::vector &vchSig, - const CKeyID &keyid, - const CScript &scriptCode) const { - // Create a dummy signature that is a valid DER-encoding - vchSig.assign(72, '\000'); - vchSig[0] = 0x30; - vchSig[1] = 69; - vchSig[2] = 0x02; - vchSig[3] = 33; - vchSig[4] = 0x01; - vchSig[4 + 33] = 0x02; - vchSig[5 + 33] = 32; - vchSig[6 + 33] = 0x01; - vchSig[6 + 33 + 32] = SIGHASH_ALL | SIGHASH_FORKID; - return true; -} +const BaseSignatureCreator &DUMMY_SIGNATURE_CREATOR = DummySignatureCreator(); diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -394,15 +394,15 @@ // Sign SignatureData sigdata; - ProduceSignature( - MutableTransactionSignatureCreator(&keystore, &tx, 0, 11 * CENT, - SigHashType().withForkId()), - spend_tx.vout[0].scriptPubKey, sigdata); + ProduceSignature(keystore, + MutableTransactionSignatureCreator( + &tx, 0, 11 * CENT, SigHashType().withForkId()), + spend_tx.vout[0].scriptPubKey, sigdata); UpdateTransaction(tx, 0, sigdata); - ProduceSignature( - MutableTransactionSignatureCreator(&keystore, &tx, 1, 11 * CENT, - SigHashType().withForkId()), - spend_tx.vout[3].scriptPubKey, sigdata); + ProduceSignature(keystore, + MutableTransactionSignatureCreator( + &tx, 1, 11 * CENT, SigHashType().withForkId()), + spend_tx.vout[3].scriptPubKey, sigdata); UpdateTransaction(tx, 1, sigdata); // This should be valid under all script flags diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1618,7 +1618,8 @@ const CScript &scriptPubKey = txout.scriptPubKey; SignatureData sigdata; - if (!ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata)) { + if (!ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, scriptPubKey, + sigdata)) { return false; } @@ -2807,8 +2808,9 @@ const Amount amount = mi->second.tx->vout[input.prevout.GetN()].nValue; SignatureData sigdata; SigHashType sigHashType = SigHashType().withForkId(); - if (!ProduceSignature(TransactionSignatureCreator( - this, &txNewConst, nIn, amount, sigHashType), + if (!ProduceSignature(*this, + TransactionSignatureCreator(&txNewConst, nIn, + amount, sigHashType), scriptPubKey, sigdata)) { return false; } @@ -3276,10 +3278,11 @@ const CScript &scriptPubKey = coin.txout.scriptPubKey; SignatureData sigdata; - if (!ProduceSignature(TransactionSignatureCreator( - this, &txNewConst, nIn, - coin.txout.nValue, sigHashType), - scriptPubKey, sigdata)) { + if (!ProduceSignature( + *this, + TransactionSignatureCreator( + &txNewConst, nIn, coin.txout.nValue, sigHashType), + scriptPubKey, sigdata)) { strFailReason = _("Signing transaction failed"); return false; }