Browse Source

BIP143: Verification logic

Includes simplifications by Eric Lombrozo.

Edited for Zcash merge by Ariel Gabizon.
metaverse
Pieter Wuille 7 years ago
committed by Jack Grigg
parent
commit
c86a1cb86e
No known key found for this signature in database GPG Key ID: 665DBCD284F7DAFF
  1. 2
      src/bitcoin-tx.cpp
  2. 2
      src/gtest/test_checktransaction.cpp
  3. 4
      src/main.cpp
  4. 2
      src/rpcrawtransaction.cpp
  5. 76
      src/script/interpreter.cpp
  6. 19
      src/script/interpreter.h
  7. 17
      src/script/sign.cpp
  8. 5
      src/script/sign.h
  9. 2
      src/test/multisig_tests.cpp
  10. 57
      src/test/script_tests.cpp
  11. 6
      src/test/sighash_tests.cpp
  12. 2
      src/test/transaction_tests.cpp
  13. 6
      src/utiltest.cpp
  14. 2
      src/wallet/asyncrpcoperation_sendmany.cpp
  15. 2
      src/wallet/asyncrpcoperation_shieldcoinbase.cpp
  16. 2
      src/wallet/rpcwallet.cpp

2
src/bitcoin-tx.cpp

@ -430,7 +430,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
// ... and merge in other signatures:
BOOST_FOREACH(const CTransaction& txv, txVariants) {
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, amount, txin.scriptSig, txv.vin[i].scriptSig);
}
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount)))
fComplete = false;

2
src/gtest/test_checktransaction.cpp

@ -74,7 +74,7 @@ CMutableTransaction GetValidTransaction() {
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
if (dataToBeSigned == one) {
throw std::runtime_error("SignatureHash failed");
}

4
src/main.cpp

@ -784,7 +784,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
// IsStandardTx() will have already returned false
// and this method isn't called.
vector<vector<unsigned char> > stack;
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker()))
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE))
return false;
if (whichType == TX_SCRIPTHASH)
@ -1088,7 +1088,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
CScript scriptCode;
uint256 dataToBeSigned;
try {
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL);
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
} catch (std::logic_error ex) {
return state.DoS(100, error("CheckTransaction(): error computing signature hash"),
REJECT_INVALID, "error-computing-signature-hash");

2
src/rpcrawtransaction.cpp

@ -859,7 +859,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
// ... and merge in other signatures:
BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, txin.scriptSig, txv.vin[i].scriptSig);
txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, amount, txin.scriptSig, txv.vin[i].scriptSig);
}
ScriptError serror = SCRIPT_ERR_OK;
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {

76
src/script/interpreter.cpp

@ -232,7 +232,7 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
return true;
}
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
{
static const CScriptNum bnZero(0);
static const CScriptNum bnOne(1);
@ -828,7 +828,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
//serror is set
return false;
}
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script);
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script, sigversion);
popstack(stack);
popstack(stack);
@ -886,7 +886,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
}
// Check signature
bool fOk = checker.CheckSig(vchSig, vchPubKey, script);
bool fOk = checker.CheckSig(vchSig, vchPubKey, script, sigversion);
if (fOk) {
isig++;
@ -1052,13 +1052,71 @@ 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, const CAmount& amount, SigVersion sigversion)
{
if (nIn >= txTo.vin.size() && nIn != NOT_AN_INPUT) {
// nIn out of range
throw logic_error("input index is out of range");
}
if (sigversion == SIGVERSION_WITNESS_V0) {
uint256 hashPrevouts;
uint256 hashSequence;
uint256 hashOutputs;
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
CHashWriter ss(SER_GETHASH, 0);
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
ss << txTo.vin[n].prevout;
}
hashPrevouts = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
}
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
CHashWriter ss(SER_GETHASH, 0);
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
ss << txTo.vin[n].nSequence;
}
hashSequence = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
}
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
CHashWriter ss(SER_GETHASH, 0);
for (unsigned int n = 0; n < txTo.vout.size(); n++) {
ss << txTo.vout[n];
}
hashOutputs = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
CHashWriter ss(SER_GETHASH, 0);
ss << txTo.vout[nIn];
hashOutputs = ss.GetHash();
}
CHashWriter ss(SER_GETHASH, 0);
// Version
ss << txTo.nVersion;
// Input prevouts/nSequence (none/all, depending on flags)
ss << hashPrevouts;
ss << hashSequence;
// The input being signed (replacing the scriptSig with scriptCode + amount)
// The prevout may already be contained in hashPrevout, and the nSequence
// may already be contained in hashSequence.
if (nIn != NOT_AN_INPUT)
ss << txTo.vin[nIn].prevout;
ss << scriptCode;
ss << amount;
if (nIn != NOT_AN_INPUT)
ss << txTo.vin[nIn].nSequence;
// Outputs (none/one/all, depending on flags)
ss << hashOutputs;
// Locktime
ss << txTo.nLockTime;
// Sighash type
ss << nHashType;
return ss.GetHash();
}
// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
@ -1081,7 +1139,7 @@ bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned cha
return pubkey.Verify(sighash, vchSig);
}
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
@ -1096,7 +1154,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
uint256 sighash;
try {
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
} catch (logic_error ex) {
return false;
}
@ -1153,12 +1211,12 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
}
vector<vector<unsigned char> > stack, stackCopy;
if (!EvalScript(stack, scriptSig, flags, checker, serror))
if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
if (flags & SCRIPT_VERIFY_P2SH)
stackCopy = stack;
if (!EvalScript(stack, scriptPubKey, flags, checker, serror))
if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
if (stack.empty())
@ -1185,7 +1243,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
popstack(stack);
if (!EvalScript(stack, pubKey2, flags, checker, serror))
if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
if (stack.empty())

19
src/script/interpreter.h

@ -88,12 +88,18 @@ enum
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9),
};
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
enum SigVersion
{
SIGVERSION_BASE = 0,
SIGVERSION_WITNESS_V0 = 1,
};
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion);
class BaseSignatureChecker
{
public:
virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
return false;
}
@ -111,13 +117,14 @@ class TransactionSignatureChecker : public BaseSignatureChecker
private:
const CTransaction* txTo;
unsigned int nIn;
const CAmount amount;
protected:
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
public:
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : txTo(txToIn), nIn(nInIn) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const;
bool CheckLockTime(const CScriptNum& nLockTime) const;
};
@ -130,7 +137,7 @@ public:
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
};
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = NULL);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = NULL);
#endif // BITCOIN_SCRIPT_INTERPRETER_H

17
src/script/sign.cpp

@ -17,8 +17,7 @@ using namespace std;
typedef vector<unsigned char> valtype;
static const CAmount amountZero = 0;
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn, amountZero) {}
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode) const
{
@ -28,7 +27,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
uint256 hash;
try {
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, SIGVERSION_BASE);
} catch (logic_error ex) {
return false;
}
@ -191,7 +190,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC
if (sigs.count(pubkey))
continue; // Already got a sig for this pubkey
if (checker.CheckSig(sig, pubkey, scriptPubKey))
if (checker.CheckSig(sig, pubkey, scriptPubKey, SIGVERSION_BASE))
{
sigs[pubkey] = sig;
break;
@ -261,10 +260,10 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatur
return CScript();
}
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CAmount& amount,
const CScript& scriptSig1, const CScript& scriptSig2)
{
TransactionSignatureChecker checker(&txTo, nIn, amountZero);
TransactionSignatureChecker checker(&txTo, nIn, amount);
return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2);
}
@ -276,9 +275,9 @@ CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecke
Solver(scriptPubKey, txType, vSolutions);
vector<valtype> stack1;
EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
vector<valtype> stack2;
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2);
}
@ -290,7 +289,7 @@ class DummySignatureChecker : public BaseSignatureChecker
public:
DummySignatureChecker() {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
return true;
}

5
src/script/sign.h

@ -35,10 +35,11 @@ class TransactionSignatureCreator : public BaseSignatureCreator {
const CTransaction* txTo;
unsigned int nIn;
int nHashType;
CAmount amount;
const TransactionSignatureChecker checker;
public:
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn=SIGHASH_ALL);
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
const BaseSignatureChecker& Checker() const { return checker; }
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const;
};
@ -62,6 +63,6 @@ bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutab
CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const CScript& scriptSig1, const CScript& scriptSig2);
/** Combine two script signatures on transactions. */
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2);
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CAmount& amount, const CScript& scriptSig1, const CScript& scriptSig2);
#endif // BITCOIN_SCRIPT_SIGN_H

2
src/test/multisig_tests.cpp

@ -28,7 +28,7 @@ BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
CScript
sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn)
{
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL);
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SIGVERSION_BASE);
CScript result;
result << OP_0; // CHECKMULTISIG bug workaround

57
src/test/script_tests.cpp

@ -237,7 +237,7 @@ public:
TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32)
{
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType);
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType, 0, SIGVERSION_BASE);
std::vector<unsigned char> vchSig, r, s;
uint32_t iter = 0;
do {
@ -640,21 +640,21 @@ BOOST_AUTO_TEST_CASE(script_PushData)
ScriptError err;
vector<vector<unsigned char> > directStack;
BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata1Stack;
BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
BOOST_CHECK(pushdata1Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata2Stack;
BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
BOOST_CHECK(pushdata2Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata4Stack;
BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
BOOST_CHECK(pushdata4Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
@ -662,7 +662,7 @@ BOOST_AUTO_TEST_CASE(script_PushData)
CScript
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction)
{
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL);
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
CScript result;
//
@ -793,6 +793,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
BOOST_AUTO_TEST_CASE(script_combineSigs)
{
// Test the CombineSignatures function
CAmount amount;
CBasicKeyStore keystore;
vector<CKey> keys;
vector<CPubKey> pubkeys;
@ -811,19 +812,19 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
CScript& scriptSig = txTo.vin[0].scriptSig;
CScript empty;
CScript combined = CombineSignatures(scriptPubKey, txTo, 0, empty, empty);
CScript combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, empty);
BOOST_CHECK(combined.empty());
// Single signature case:
SignSignature(keystore, txFrom, txTo, 0); // changes scriptSig
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty);
BOOST_CHECK(combined == scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig);
BOOST_CHECK(combined == scriptSig);
CScript scriptSigCopy = scriptSig;
// Signing again will give a different, valid signature:
SignSignature(keystore, txFrom, txTo, 0);
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig);
BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
// P2SH, single-signature case:
@ -831,41 +832,41 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
keystore.AddCScript(pkSingle);
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
SignSignature(keystore, txFrom, txTo, 0);
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty);
BOOST_CHECK(combined == scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig);
BOOST_CHECK(combined == scriptSig);
scriptSigCopy = scriptSig;
SignSignature(keystore, txFrom, txTo, 0);
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig);
BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
// dummy scriptSigCopy with placeholder, should always choose non-placeholder:
scriptSigCopy = CScript() << OP_0 << static_cast<vector<unsigned char> >(pkSingle);
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig);
BOOST_CHECK(combined == scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, scriptSigCopy);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, scriptSigCopy);
BOOST_CHECK(combined == scriptSig);
// Hardest case: Multisig 2-of-3
scriptPubKey = GetScriptForMultisig(2, pubkeys);
keystore.AddCScript(scriptPubKey);
SignSignature(keystore, txFrom, txTo, 0);
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty);
BOOST_CHECK(combined == scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig);
BOOST_CHECK(combined == scriptSig);
// A couple of partially-signed versions:
vector<unsigned char> sig1;
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL);
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
BOOST_CHECK(keys[0].Sign(hash1, sig1));
sig1.push_back(SIGHASH_ALL);
vector<unsigned char> sig2;
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE);
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, SIGVERSION_BASE);
BOOST_CHECK(keys[1].Sign(hash2, sig2));
sig2.push_back(SIGHASH_NONE);
vector<unsigned char> sig3;
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE);
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, SIGVERSION_BASE);
BOOST_CHECK(keys[2].Sign(hash3, sig3));
sig3.push_back(SIGHASH_SINGLE);
@ -881,21 +882,21 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
CScript complete13 = CScript() << OP_0 << sig1 << sig3;
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1a, partial1b);
BOOST_CHECK(combined == partial1a);
combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1a, partial2a);
BOOST_CHECK(combined == complete12);
combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial1a);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial2a, partial1a);
BOOST_CHECK(combined == complete12);
combined = CombineSignatures(scriptPubKey, txTo, 0, partial1b, partial2b);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1b, partial2b);
BOOST_CHECK(combined == complete12);
combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial1b);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial1b);
BOOST_CHECK(combined == complete13);
combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial3a);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial2a, partial3a);
BOOST_CHECK(combined == complete23);
combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial2b);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial2b);
BOOST_CHECK(combined == complete23);
combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial3a);
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial3a);
BOOST_CHECK(combined == partial3c);
}

6
src/test/sighash_tests.cpp

@ -160,7 +160,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
// Empty output script.
CScript scriptCode;
CTransaction signTx(tx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
assert(crypto_sign_detached(&tx.joinSplitSig[0], NULL,
dataToBeSigned.begin(), 32,
@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(sighash_test)
uint256 sh, sho;
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
sh = SignatureHash(scriptCode, txTo, nIn, nHashType);
sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SIGVERSION_BASE);
#if defined(PRINT_SIGHASH_JSON)
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << txTo;
@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
continue;
}
sh = SignatureHash(scriptCode, tx, nIn, nHashType);
sh = SignatureHash(scriptCode, tx, nIn, nHashType, 0, SIGVERSION_BASE);
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
}
}

2
src/test/transaction_tests.cpp

@ -424,7 +424,7 @@ BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
// Empty output script.
CScript scriptCode;
CTransaction signTx(newTx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
assert(crypto_sign_detached(&newTx.joinSplitSig[0], NULL,
dataToBeSigned.begin(), 32,

6
src/utiltest.cpp

@ -47,7 +47,9 @@ CWalletTx GetValidReceive(ZCJoinSplit& params,
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
//fifth parameter amount will not be used for joinsplit signing, value arbitrary, also arbitrary decision what to use for sigverion
//This is just to get this merge commit to compile later will remove sigversion parameter as choosing sigversion by block height
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL,0, SIGVERSION_BASE);
// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
@ -131,7 +133,7 @@ CWalletTx GetValidSpend(ZCJoinSplit& params,
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL,0,SIGVERSION_BASE);
// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,

2
src/wallet/asyncrpcoperation_sendmany.cpp

@ -994,7 +994,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
// Add the signature
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,

2
src/wallet/asyncrpcoperation_shieldcoinbase.cpp

@ -369,7 +369,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
// Add the signature
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,

2
src/wallet/rpcwallet.cpp

@ -2840,7 +2840,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,

Loading…
Cancel
Save