diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -485,7 +485,7 @@ static const struct { const char *flagStr; int flags; -} sighashOptions[N_SIGHASH_OPTS] = { +} sigHashOptions[N_SIGHASH_OPTS] = { {"ALL", SIGHASH_ALL}, {"NONE", SIGHASH_NONE}, {"SINGLE", SIGHASH_SINGLE}, @@ -503,12 +503,13 @@ SIGHASH_SINGLE | SIGHASH_FORKID | SIGHASH_ANYONECANPAY}, }; -static bool findSighashFlags(int &flags, const std::string &flagStr) { - flags = 0; +static bool findSigHashFlags(SigHashType &sigHashType, + const std::string &flagStr) { + sigHashType = SigHashType(); for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) { - if (flagStr == sighashOptions[i].flagStr) { - flags = sighashOptions[i].flags; + if (flagStr == sigHashOptions[i].flagStr) { + sigHashType = SigHashType(sigHashOptions[i].flags); return true; } } @@ -553,9 +554,9 @@ } static void MutateTxSign(CMutableTransaction &tx, const std::string &flagStr) { - int nHashType = SIGHASH_ALL | SIGHASH_FORKID; + SigHashType sigHashType = SigHashType().withForkId(true); - if ((flagStr.size() > 0) && !findSighashFlags(nHashType, flagStr)) { + if ((flagStr.size() > 0) && !findSigHashFlags(sigHashType, flagStr)) { throw std::runtime_error("unknown sighash flag/sign option"); } @@ -657,10 +658,6 @@ const CKeyStore &keystore = tempKeystore; - bool fHashSingle = - ((nHashType & ~(SIGHASH_ANYONECANPAY | SIGHASH_FORKID)) == - SIGHASH_SINGLE); - // Sign what we can: for (size_t i = 0; i < mergedTx.vin.size(); i++) { CTxIn &txin = mergedTx.vin[i]; @@ -675,9 +672,10 @@ SignatureData sigdata; // Only sign SIGHASH_SINGLE if there's a corresponding output: - if (!fHashSingle || (i < mergedTx.vout.size())) { + if ((sigHashType.getBaseSigHashType() != BaseSigHashType::SINGLE) || + (i < mergedTx.vout.size())) { ProduceSignature(MutableTransactionSignatureCreator( - &keystore, &mergedTx, i, amount, nHashType), + &keystore, &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 @@ -1032,8 +1032,7 @@ if ((sigHashType.getBaseSigHashType() != BaseSigHashType::SINGLE) || (i < mergedTx.vout.size())) { ProduceSignature(MutableTransactionSignatureCreator( - &keystore, &mergedTx, i, amount, - sigHashType.getRawSigHashType()), + &keystore, &mergedTx, i, amount, sigHashType), prevPubKey, sigdata); } diff --git a/src/script/sign.h b/src/script/sign.h --- a/src/script/sign.h +++ b/src/script/sign.h @@ -7,6 +7,7 @@ #define BITCOIN_SCRIPT_SIGN_H #include "script/interpreter.h" +#include "script/sighashtype.h" class CKeyID; class CKeyStore; @@ -35,14 +36,14 @@ const CTransaction *txTo; unsigned int nIn; Amount amount; - uint32_t nHashType; + SigHashType sigHashType; const TransactionSignatureChecker checker; public: TransactionSignatureCreator(const CKeyStore *keystoreIn, const CTransaction *txToIn, unsigned int nInIn, const Amount amountIn, - uint32_t nHashTypeIn = SIGHASH_ALL); + SigHashType sigHashTypeIn = SigHashType()); const BaseSignatureChecker &Checker() const override { return checker; } bool CreateSig(std::vector &vchSig, const CKeyID &keyid, const CScript &scriptCode) const override; @@ -55,9 +56,9 @@ MutableTransactionSignatureCreator(const CKeyStore *keystoreIn, const CMutableTransaction *txToIn, unsigned int nInIn, const Amount amount, - uint32_t nHashTypeIn) + SigHashType sigHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, - nHashTypeIn), + sigHashTypeIn), tx(*txToIn) {} }; @@ -85,10 +86,10 @@ /** Produce a script signature for a transaction. */ bool SignSignature(const CKeyStore &keystore, const CScript &fromPubKey, CMutableTransaction &txTo, unsigned int nIn, - const Amount amount, uint32_t nHashType); + const Amount amount, SigHashType sigHashType); bool SignSignature(const CKeyStore &keystore, const CTransaction &txFrom, CMutableTransaction &txTo, unsigned int nIn, - uint32_t nHashType); + SigHashType sigHashType); /** Combine two script signatures using a generic signature checker, * intelligently, possibly with OP_0 placeholders. */ diff --git a/src/script/sign.cpp b/src/script/sign.cpp --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -16,9 +16,10 @@ TransactionSignatureCreator::TransactionSignatureCreator( const CKeyStore *keystoreIn, const CTransaction *txToIn, unsigned int nInIn, - const Amount amountIn, uint32_t nHashTypeIn) + const Amount amountIn, SigHashType sigHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), - amount(amountIn), nHashType(nHashTypeIn), checker(txTo, nIn, amountIn) {} + amount(amountIn), sigHashType(sigHashTypeIn), + checker(txTo, nIn, amountIn) {} bool TransactionSignatureCreator::CreateSig(std::vector &vchSig, const CKeyID &address, @@ -28,12 +29,13 @@ return false; } - uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount); + uint256 hash = SignatureHash(scriptCode, *txTo, nIn, + sigHashType.getRawSigHashType(), amount); if (!key.Sign(hash, vchSig)) { return false; } - vchSig.push_back(uint8_t(nHashType)); + vchSig.push_back(uint8_t(sigHashType.getRawSigHashType())); return true; } @@ -182,12 +184,12 @@ bool SignSignature(const CKeyStore &keystore, const CScript &fromPubKey, CMutableTransaction &txTo, unsigned int nIn, - const Amount amount, uint32_t nHashType) { + const Amount amount, SigHashType sigHashType) { assert(nIn < txTo.vin.size()); CTransaction txToConst(txTo); TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, - nHashType); + sigHashType); SignatureData sigdata; bool ret = ProduceSignature(creator, fromPubKey, sigdata); @@ -197,14 +199,14 @@ bool SignSignature(const CKeyStore &keystore, const CTransaction &txFrom, CMutableTransaction &txTo, unsigned int nIn, - uint32_t nHashType) { + SigHashType sigHashType) { assert(nIn < txTo.vin.size()); CTxIn &txin = txTo.vin[nIn]; assert(txin.prevout.n < txFrom.vout.size()); const CTxOut &txout = txFrom.vout[txin.prevout.n]; return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, - nHashType); + sigHashType); } static std::vector CombineMultisig( diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -174,7 +174,7 @@ tx.vout[0].nValue = 1 * CENT; tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); - SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL); + SignSignature(keystore, *txPrev, tx, 0, SigHashType()); AddOrphanTx(MakeTransactionRef(tx), i); } @@ -193,7 +193,7 @@ tx.vin[j].prevout.n = j; tx.vin[j].prevout.hash = txPrev->GetId(); } - SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL); + SignSignature(keystore, *txPrev, tx, 0, SigHashType()); // Re-use same signature for other inputs // (they don't have to be valid for this test) for (unsigned int j = 1; j < tx.vin.size(); j++) diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -351,7 +351,7 @@ for (int i = 0; i < 3; i++) { BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, - SIGHASH_ALL | SIGHASH_FORKID), + SigHashType().withForkId(true)), strprintf("SignSignature %d", i)); } } diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -99,7 +99,7 @@ } for (int i = 0; i < 8; i++) { BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, - SIGHASH_ALL | SIGHASH_FORKID), + SigHashType().withForkId(true)), strprintf("SignSignature %d", i)); } // All of the above should be OK, and the txTos have valid signatures @@ -205,7 +205,7 @@ } for (int i = 0; i < 4; i++) { BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, - SIGHASH_ALL | SIGHASH_FORKID), + SigHashType().withForkId(true)), strprintf("SignSignature %d", i)); BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i)); @@ -390,12 +390,12 @@ txTo.vin[i].prevout.n = i; txTo.vin[i].prevout.hash = txFrom.GetId(); } - BOOST_CHECK( - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL | SIGHASH_FORKID)); - BOOST_CHECK( - SignSignature(keystore, txFrom, txTo, 1, SIGHASH_ALL | SIGHASH_FORKID)); - BOOST_CHECK( - SignSignature(keystore, txFrom, txTo, 2, SIGHASH_ALL | SIGHASH_FORKID)); + BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, + SigHashType().withForkId(true))); + BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, + SigHashType().withForkId(true))); + BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, + SigHashType().withForkId(true))); // SignSignature doesn't know how to sign these. We're not testing // validating signatures, so just create dummy signatures that DO include // the correct P2SH scripts: diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1357,7 +1357,8 @@ BOOST_CHECK(combined.scriptSig.empty()); // Single signature case: - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); // changes scriptSig + SignSignature(keystore, txFrom, txTo, 0, + SigHashType()); // changes scriptSig combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); @@ -1368,7 +1369,7 @@ BOOST_CHECK(combined.scriptSig == scriptSig); CScript scriptSigCopy = scriptSig; // Signing again will give a different, valid signature: - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); + SignSignature(keystore, txFrom, txTo, 0, SigHashType()); combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); @@ -1380,7 +1381,7 @@ pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG; keystore.AddCScript(pkSingle); scriptPubKey = GetScriptForDestination(CScriptID(pkSingle)); - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); + SignSignature(keystore, txFrom, txTo, 0, SigHashType()); combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); @@ -1390,7 +1391,7 @@ empty, SignatureData(scriptSig)); BOOST_CHECK(combined.scriptSig == scriptSig); scriptSigCopy = scriptSig; - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); + SignSignature(keystore, txFrom, txTo, 0, SigHashType()); combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); @@ -1412,7 +1413,7 @@ // Hardest case: Multisig 2-of-3 scriptPubKey = GetScriptForMultisig(2, pubkeys); keystore.AddCScript(scriptPubKey); - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); + SignSignature(keystore, txFrom, txTo, 0, SigHashType()); combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -346,7 +346,7 @@ inputm.vout[0].nValue = Amount(1); inputm.vout[0].scriptPubKey = CScript(); bool ret = SignSignature(keystore, *output, inputm, 0, - SIGHASH_ALL | SIGHASH_FORKID); + SigHashType().withForkId(true)); BOOST_CHECK_EQUAL(ret, success); CDataStream ssin(SER_NETWORK, PROTOCOL_VERSION); ssin << inputm; 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 @@ -347,12 +347,12 @@ SignatureData sigdata; ProduceSignature( MutableTransactionSignatureCreator(&keystore, &tx, 0, 11 * CENT, - SIGHASH_ALL | SIGHASH_FORKID), + SigHashType().withForkId(true)), spend_tx.vout[0].scriptPubKey, sigdata); UpdateTransaction(tx, 0, sigdata); ProduceSignature( MutableTransactionSignatureCreator(&keystore, &tx, 1, 11 * CENT, - SIGHASH_ALL | SIGHASH_FORKID), + SigHashType().withForkId(true)), spend_tx.vout[3].scriptPubKey, sigdata); UpdateTransaction(tx, 1, sigdata); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2976,7 +2976,7 @@ TransactionSignatureCreator( this, &txNewConst, nIn, coin.first->tx->vout[coin.second].nValue, - sigHashType.getRawSigHashType()), + sigHashType), scriptPubKey, sigdata)) { strFailReason = _("Signing transaction failed"); return false;