diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp --- a/src/bench/ccoins_caching.cpp +++ b/src/bench/ccoins_caching.cpp @@ -36,7 +36,7 @@ dummyTransactions[0].vout[1].nValue = 50 * CENT; dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG; - AddCoins(coinsRet, dummyTransactions[0], 0); + AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0); dummyTransactions[1].vout.resize(2); dummyTransactions[1].vout[0].nValue = 21 * CENT; @@ -45,7 +45,7 @@ dummyTransactions[1].vout[1].nValue = 22 * CENT; dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID()); - AddCoins(coinsRet, dummyTransactions[1], 0); + AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0); return dummyTransactions; } @@ -82,9 +82,10 @@ // Benchmark. while (state.KeepRunning()) { - bool success = AreInputsStandard(t1, coins); + CTransaction t(t1); + bool success = AreInputsStandard(t, coins); assert(success); - Amount value = coins.GetValueIn(t1); + Amount value = coins.GetValueIn(t); assert(value == (50 + 21 + 22) * CENT); } } diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -99,16 +99,24 @@ CTxMemPool pool(CFeeRate(Amount(1000))); + CTransaction t1(tx1); + CTransaction t2(tx2); + CTransaction t3(tx3); + CTransaction t4(tx4); + CTransaction t5(tx5); + CTransaction t6(tx6); + CTransaction t7(tx1); + while (state.KeepRunning()) { - AddTx(tx1, Amount(10000LL), pool); - AddTx(tx2, Amount(5000LL), pool); - AddTx(tx3, Amount(20000LL), pool); - AddTx(tx4, Amount(7000LL), pool); - AddTx(tx5, Amount(1000LL), pool); - AddTx(tx6, Amount(1100LL), pool); - AddTx(tx7, Amount(9000LL), pool); + AddTx(t1, Amount(10000LL), pool); + AddTx(t2, Amount(5000LL), pool); + AddTx(t3, Amount(20000LL), pool); + AddTx(t4, Amount(7000LL), pool); + AddTx(t5, Amount(1000LL), pool); + AddTx(t6, Amount(1100LL), pool); + AddTx(t7, Amount(9000LL), pool); pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); - pool.TrimToSize(CTransaction(tx1).GetTotalSize()); + pool.TrimToSize(t1.GetTotalSize()); } } diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -562,7 +562,7 @@ } std::vector txVariants; - txVariants.push_back(tx); + txVariants.push_back(CTransaction(tx)); // mergedTx will end up with all the signatures; it starts as a clone of the // raw tx: @@ -854,7 +854,7 @@ MutateTx(tx, key, value); } - OutputTx(tx); + OutputTx(CTransaction(tx)); } catch (const boost::thread_interrupted &) { diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -277,8 +277,8 @@ CTransaction(); /** Convert a CMutableTransaction into a CTransaction. */ - CTransaction(const CMutableTransaction &tx); - CTransaction(CMutableTransaction &&tx); + explicit CTransaction(const CMutableTransaction &tx); + explicit CTransaction(CMutableTransaction &&tx); template inline void Serialize(Stream &s) const { SerializeTransaction(*this, s); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -570,7 +570,7 @@ } } - return EncodeHexTx(rawTx); + return EncodeHexTx(CTransaction(rawTx)); } static UniValue decoderawtransaction(const Config &config, @@ -1071,7 +1071,7 @@ bool fComplete = vErrors.empty(); UniValue result(UniValue::VOBJ); - result.push_back(Pair("hex", EncodeHexTx(mergedTx))); + result.push_back(Pair("hex", EncodeHexTx(CTransaction(mergedTx)))); result.push_back(Pair("complete", fComplete)); if (!vErrors.empty()) { result.push_back(Pair("errors", vErrors)); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -386,7 +386,7 @@ // Call UpdateCoins on the top cache CTxUndo undo; - UpdateCoins(tx, *(stack.back()), undo, height); + UpdateCoins(CTransaction(tx), *(stack.back()), undo, height); // Update the utxo set for future spends utxoset.insert(outpoint); diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -52,13 +52,13 @@ // Nothing in pool, remove should do nothing: unsigned int poolSize = testPool.size(); - testPool.removeRecursive(txParent); + testPool.removeRecursive(CTransaction(txParent)); BOOST_CHECK_EQUAL(testPool.size(), poolSize); // Just the parent: testPool.addUnchecked(txParent.GetId(), entry.FromTx(txParent)); poolSize = testPool.size(); - testPool.removeRecursive(txParent); + testPool.removeRecursive(CTransaction(txParent)); BOOST_CHECK_EQUAL(testPool.size(), poolSize - 1); // Parent, children, grandchildren: @@ -70,18 +70,18 @@ } // Remove Child[0], GrandChild[0] should be removed: poolSize = testPool.size(); - testPool.removeRecursive(txChild[0]); + testPool.removeRecursive(CTransaction(txChild[0])); BOOST_CHECK_EQUAL(testPool.size(), poolSize - 2); // ... make sure grandchild and child are gone: poolSize = testPool.size(); - testPool.removeRecursive(txGrandChild[0]); + testPool.removeRecursive(CTransaction(txGrandChild[0])); BOOST_CHECK_EQUAL(testPool.size(), poolSize); poolSize = testPool.size(); - testPool.removeRecursive(txChild[0]); + testPool.removeRecursive(CTransaction(txChild[0])); BOOST_CHECK_EQUAL(testPool.size(), poolSize); // Remove parent, all children/grandchildren should go: poolSize = testPool.size(); - testPool.removeRecursive(txParent); + testPool.removeRecursive(CTransaction(txParent)); BOOST_CHECK_EQUAL(testPool.size(), poolSize - 5); BOOST_CHECK_EQUAL(testPool.size(), 0UL); @@ -96,7 +96,7 @@ // Now remove the parent, as might happen if a block-re-org occurs but the // parent cannot be put into the mempool (maybe because it is non-standard): poolSize = testPool.size(); - testPool.removeRecursive(txParent); + testPool.removeRecursive(CTransaction(txParent)); BOOST_CHECK_EQUAL(testPool.size(), poolSize - 6); BOOST_CHECK_EQUAL(testPool.size(), 0UL); } diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -160,7 +160,7 @@ // Test that packages above the min relay fee do get included, even if one // of the transactions is below the min relay fee. Remove the low fee // transaction and replace with a higher fee transaction - mempool.removeRecursive(tx); + mempool.removeRecursive(CTransaction(tx)); // Now we should be just over the min relay fee. tx.vout[0].nValue -= Amount(2); hashLowFeeTx = tx.GetId(); @@ -532,15 +532,15 @@ // Locktime passes. GlobalConfig config; CValidationState state; - BOOST_CHECK(ContextualCheckTransactionForCurrentBlock(config, tx, state, - flags)); + BOOST_CHECK(ContextualCheckTransactionForCurrentBlock( + config, CTransaction(tx), state, flags)); } // Sequence locks fail. - BOOST_CHECK(!TestSequenceLocks(tx, flags)); + BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass on 2nd block. BOOST_CHECK( - SequenceLocks(tx, flags, &prevheights, + SequenceLocks(CTransaction(tx), flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 2))); // Relative time locked. @@ -559,12 +559,12 @@ // Locktime passes. GlobalConfig config; CValidationState state; - BOOST_CHECK(ContextualCheckTransactionForCurrentBlock(config, tx, state, - flags)); + BOOST_CHECK(ContextualCheckTransactionForCurrentBlock( + config, CTransaction(tx), state, flags)); } // Sequence locks fail. - BOOST_CHECK(!TestSequenceLocks(tx, flags)); + BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++) { // Trick the MedianTimePast. @@ -573,7 +573,7 @@ } // Sequence locks pass 512 seconds later. BOOST_CHECK( - SequenceLocks(tx, flags, &prevheights, + SequenceLocks(CTransaction(tx), flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 1))); for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++) { // Undo tricked MTP. @@ -593,20 +593,20 @@ // Locktime fails. GlobalConfig config; CValidationState state; - BOOST_CHECK(!ContextualCheckTransactionForCurrentBlock(config, tx, - state, flags)); + BOOST_CHECK(!ContextualCheckTransactionForCurrentBlock( + config, CTransaction(tx), state, flags)); BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-txns-nonfinal"); } // Sequence locks pass. - BOOST_CHECK(TestSequenceLocks(tx, flags)); + BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); { // Locktime passes on 2nd block. GlobalConfig config; CValidationState state; BOOST_CHECK(ContextualCheckTransaction( - config, tx, state, chainActive.Tip()->nHeight + 2, + config, CTransaction(tx), state, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast())); } @@ -622,20 +622,20 @@ // Locktime fails. GlobalConfig config; CValidationState state; - BOOST_CHECK(!ContextualCheckTransactionForCurrentBlock(config, tx, - state, flags)); + BOOST_CHECK(!ContextualCheckTransactionForCurrentBlock( + config, CTransaction(tx), state, flags)); BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-txns-nonfinal"); } // Sequence locks pass. - BOOST_CHECK(TestSequenceLocks(tx, flags)); + BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); { // Locktime passes 1 second later. GlobalConfig config; CValidationState state; BOOST_CHECK(ContextualCheckTransaction( - config, tx, state, chainActive.Tip()->nHeight + 1, + config, CTransaction(tx), state, chainActive.Tip()->nHeight + 1, chainActive.Tip()->GetMedianTimePast() + 1)); } @@ -649,21 +649,21 @@ // Locktime passes. GlobalConfig config; CValidationState state; - BOOST_CHECK(ContextualCheckTransactionForCurrentBlock(config, tx, state, - flags)); + BOOST_CHECK(ContextualCheckTransactionForCurrentBlock( + config, CTransaction(tx), state, flags)); } // Sequence locks pass. - BOOST_CHECK(TestSequenceLocks(tx, flags)); + BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); tx.vin[0].nSequence = 1; // Sequence locks fail. - BOOST_CHECK(!TestSequenceLocks(tx, flags)); + BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG; // Sequence locks pass. - BOOST_CHECK(TestSequenceLocks(tx, flags)); + BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1; // Sequence locks fail. - BOOST_CHECK(!TestSequenceLocks(tx, flags)); + BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); BOOST_CHECK(pblocktemplate = BlockAssembler(config).CreateNewBlock(scriptPubKey)); 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 @@ -21,9 +21,9 @@ BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup) CScript sign_multisig(CScript scriptPubKey, std::vector keys, - CTransaction transaction, int whichIn) { - uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, - SigHashType(), Amount(0)); + CMutableTransaction mutableTransaction, int whichIn) { + uint256 hash = SignatureHash(scriptPubKey, CTransaction(mutableTransaction), + whichIn, SigHashType(), Amount(0)); CScript result; // CHECKMULTISIG bug workaround @@ -351,7 +351,8 @@ } for (int i = 0; i < 3; i++) { - BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, + BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), + txTo[i], 0, 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 @@ -85,7 +85,7 @@ txFrom.vout[i + 4].scriptPubKey = standardScripts[i]; txFrom.vout[i + 4].nValue = COIN; } - BOOST_CHECK(IsStandardTx(txFrom, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(txFrom), reason)); CMutableTransaction txTo[8]; // Spending transactions for (int i = 0; i < 8; i++) { @@ -98,7 +98,8 @@ strprintf("IsMine %d", i)); } for (int i = 0; i < 8; i++) { - BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, + BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), + txTo[i], 0, SigHashType().withForkId(true)), strprintf("SignSignature %d", i)); } @@ -106,16 +107,16 @@ // Check to make sure signature verification fails if we use the wrong // ScriptSig: for (int i = 0; i < 8; i++) { - PrecomputedTransactionData txdata(txTo[i]); + PrecomputedTransactionData txdata(CTransaction(txTo[i])); for (int j = 0; j < 8; j++) { CScript sigSave = txTo[i].vin[0].scriptSig; txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; const CTxOut &output = txFrom.vout[txTo[i].vin[0].prevout.n]; - bool sigOK = - CScriptCheck(output.scriptPubKey, output.nValue, txTo[i], 0, - SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC | - SCRIPT_ENABLE_SIGHASH_FORKID, - false, txdata)(); + bool sigOK = CScriptCheck( + output.scriptPubKey, output.nValue, CTransaction(txTo[i]), 0, + SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC | + SCRIPT_ENABLE_SIGHASH_FORKID, + false, txdata)(); if (i == j) { BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); @@ -189,7 +190,7 @@ txFrom.vout[i].scriptPubKey = outer[i]; txFrom.vout[i].nValue = CENT; } - BOOST_CHECK(IsStandardTx(txFrom, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(txFrom), reason)); // Spending transactions CMutableTransaction txTo[4]; @@ -204,10 +205,11 @@ strprintf("IsMine %d", i)); } for (int i = 0; i < 4; i++) { - BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, + BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), + txTo[i], 0, SigHashType().withForkId(true)), strprintf("SignSignature %d", i)); - BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), + BOOST_CHECK_MESSAGE(IsStandardTx(CTransaction(txTo[i]), reason), strprintf("txTo[%d].IsStandard", i)); } } @@ -378,7 +380,7 @@ GetScriptForDestination(CScriptID(twentySigops)); txFrom.vout[6].nValue = Amount(6000); - AddCoins(coins, txFrom, 0); + AddCoins(coins, CTransaction(txFrom), 0); CMutableTransaction txTo; txTo.vout.resize(1); @@ -390,11 +392,11 @@ txTo.vin[i].prevout.n = i; txTo.vin[i].prevout.hash = txFrom.GetId(); } - BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType().withForkId(true))); - BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 1, SigHashType().withForkId(true))); - BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, + BOOST_CHECK(SignSignature(keystore, CTransaction(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 @@ -405,9 +407,9 @@ txTo.vin[4].scriptSig << std::vector(fifteenSigops.begin(), fifteenSigops.end()); - BOOST_CHECK(::AreInputsStandard(txTo, coins)); + BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins)); // 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4] - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txTo), coins), 22U); CMutableTransaction txToNonStd1; txToNonStd1.vout.resize(1); @@ -420,8 +422,8 @@ txToNonStd1.vin[0].scriptSig << std::vector(sixteenSigops.begin(), sixteenSigops.end()); - BOOST_CHECK(!::AreInputsStandard(txToNonStd1, coins)); - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd1, coins), 16U); + BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins)); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd1), coins), 16U); CMutableTransaction txToNonStd2; txToNonStd2.vout.resize(1); @@ -434,8 +436,8 @@ txToNonStd2.vin[0].scriptSig << std::vector(twentySigops.begin(), twentySigops.end()); - BOOST_CHECK(!::AreInputsStandard(txToNonStd2, coins)); - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd2, coins), 20U); + BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins)); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2), coins), 20U); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/script_antireplay_tests.cpp b/src/test/script_antireplay_tests.cpp --- a/src/test/script_antireplay_tests.cpp +++ b/src/test/script_antireplay_tests.cpp @@ -91,22 +91,24 @@ { // Base transaction is valid. CValidationState state; - BOOST_CHECK(ContextualCheckTransaction(config, tx, state, nSunsetHeight, - nUAHFStartTime)); + BOOST_CHECK(ContextualCheckTransaction(config, CTransaction(tx), state, + nSunsetHeight, nUAHFStartTime)); } { // Base transaction is still valid after sunset. CValidationState state; - BOOST_CHECK(ContextualCheckTransaction( - config, tx, state, nSunsetHeight + 1, nUAHFStartTime)); + BOOST_CHECK(ContextualCheckTransaction(config, CTransaction(tx), state, + nSunsetHeight + 1, + nUAHFStartTime)); } { // Base transaction is valid before the fork. CValidationState state; - BOOST_CHECK(ContextualCheckTransaction( - config, tx, state, nUAHFHeight - 1, nUAHFStartTime - 1)); + BOOST_CHECK(ContextualCheckTransaction(config, CTransaction(tx), state, + nUAHFHeight - 1, + nUAHFStartTime - 1)); } tx.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_0; @@ -114,8 +116,8 @@ { // Wrong commitment, still valid. CValidationState state; - BOOST_CHECK(ContextualCheckTransaction(config, tx, state, nSunsetHeight, - nUAHFStartTime)); + BOOST_CHECK(ContextualCheckTransaction(config, CTransaction(tx), state, + nSunsetHeight, nUAHFStartTime)); } tx.vout[0].scriptPubKey = CScript() << OP_RETURN @@ -124,15 +126,15 @@ { // Anti replay commitment, not valid anymore. CValidationState state; - BOOST_CHECK(!ContextualCheckTransaction(config, tx, state, nUAHFHeight, - nUAHFStartTime)); + BOOST_CHECK(!ContextualCheckTransaction(config, CTransaction(tx), state, + nUAHFHeight, nUAHFStartTime)); BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-txn-replay"); } { // Anti replay commitment, not valid anymore. CValidationState state; - BOOST_CHECK(!ContextualCheckTransaction(config, tx, state, + BOOST_CHECK(!ContextualCheckTransaction(config, CTransaction(tx), state, nSunsetHeight, nUAHFStartTime)); BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-txn-replay"); } @@ -141,14 +143,15 @@ // Anti replay commitment, disabled before start time. CValidationState state; BOOST_CHECK(ContextualCheckTransaction( - config, tx, state, nUAHFHeight - 1, nUAHFStartTime)); + config, CTransaction(tx), state, nUAHFHeight - 1, nUAHFStartTime)); } { // Anti replay commitment, disabled after sunset. CValidationState state; - BOOST_CHECK(ContextualCheckTransaction( - config, tx, state, nSunsetHeight + 1, nUAHFStartTime)); + BOOST_CHECK(ContextualCheckTransaction(config, CTransaction(tx), state, + nSunsetHeight + 1, + nUAHFStartTime)); } } 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 @@ -313,7 +313,8 @@ SigHashType sigHashType = SigHashType(), unsigned int lenR = 32, unsigned int lenS = 32, Amount amount = Amount(0)) { - uint256 hash = SignatureHash(script, spendTx, 0, sigHashType, amount); + uint256 hash = SignatureHash(script, CTransaction(spendTx), 0, + sigHashType, amount); std::vector vchSig, r, s; uint32_t iter = 0; do { @@ -1196,7 +1197,8 @@ BuildCreditingTransaction(scriptPubKey12, Amount(0)); CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12); - CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); + CScript goodsig1 = + sign_multisig(scriptPubKey12, key1, CTransaction(txTo12)); BOOST_CHECK(VerifyScript( goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), @@ -1209,14 +1211,15 @@ &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); - CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); + CScript goodsig2 = + sign_multisig(scriptPubKey12, key2, CTransaction(txTo12)); BOOST_CHECK(VerifyScript( goodsig2, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); - CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); + CScript badsig1 = sign_multisig(scriptPubKey12, key3, CTransaction(txTo12)); BOOST_CHECK(!VerifyScript( badsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), @@ -1240,7 +1243,15 @@ CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23, Amount(0)); - CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), txFrom23); + CMutableTransaction mutableTxTo23 = + BuildSpendingTransaction(CScript(), txFrom23); + + // after it has been set up, mutableTxTo23 does not change in this test, + // so we can convert it to readonly transaction and use + // TransactionSignatureChecker + // instead of MutableTransactionSignatureChecker + + const CTransaction txTo23(mutableTxTo23); std::vector keys; keys.push_back(key1); @@ -1248,7 +1259,7 @@ CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(VerifyScript( goodsig1, scriptPubKey23, flags, - MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), + TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); @@ -1258,7 +1269,7 @@ CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(VerifyScript( goodsig2, scriptPubKey23, flags, - MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), + TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); @@ -1268,7 +1279,7 @@ CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(VerifyScript( goodsig3, scriptPubKey23, flags, - MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), + TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); @@ -1278,7 +1289,7 @@ CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(!VerifyScript( badsig1, scriptPubKey23, flags, - MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), + TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); @@ -1288,7 +1299,7 @@ CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(!VerifyScript( badsig2, scriptPubKey23, flags, - MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), + TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); @@ -1298,7 +1309,7 @@ CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(!VerifyScript( badsig3, scriptPubKey23, flags, - MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), + TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); @@ -1308,7 +1319,7 @@ CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(!VerifyScript( badsig4, scriptPubKey23, flags, - MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), + TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); @@ -1318,7 +1329,7 @@ CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(!VerifyScript( badsig5, scriptPubKey23, flags, - MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), + TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); @@ -1326,7 +1337,7 @@ CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(!VerifyScript( badsig6, scriptPubKey23, flags, - MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), + TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); @@ -1352,6 +1363,14 @@ CScript &scriptPubKey = txFrom.vout[0].scriptPubKey; CScript &scriptSig = txTo.vin[0].scriptSig; + // Although it looks like CMutableTransaction is not modified after it’s + // been set up (it is not passed as parameter to any non-const function), + // it is actually modified when new value is assigned to scriptPubKey, + // which points to mutableTxFrom.vout[0].scriptPubKey. Therefore we can + // not use single instance of CTransaction in this test. + // CTransaction creates a copy of CMutableTransaction and is not modified + // when scriptPubKey is assigned to. + SignatureData empty; SignatureData combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), @@ -1359,7 +1378,7 @@ BOOST_CHECK(combined.scriptSig.empty()); // Single signature case: - SignSignature(keystore, txFrom, txTo, 0, + SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); // changes scriptSig combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), @@ -1371,7 +1390,7 @@ BOOST_CHECK(combined.scriptSig == scriptSig); CScript scriptSigCopy = scriptSig; // Signing again will give a different, valid signature: - SignSignature(keystore, txFrom, txTo, 0, SigHashType()); + SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); @@ -1383,7 +1402,7 @@ pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG; keystore.AddCScript(pkSingle); scriptPubKey = GetScriptForDestination(CScriptID(pkSingle)); - SignSignature(keystore, txFrom, txTo, 0, SigHashType()); + SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); @@ -1393,7 +1412,7 @@ empty, SignatureData(scriptSig)); BOOST_CHECK(combined.scriptSig == scriptSig); scriptSigCopy = scriptSig; - SignSignature(keystore, txFrom, txTo, 0, SigHashType()); + SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); @@ -1415,7 +1434,7 @@ // Hardest case: Multisig 2-of-3 scriptPubKey = GetScriptForMultisig(2, pubkeys); keystore.AddCScript(scriptPubKey); - SignSignature(keystore, txFrom, txTo, 0, SigHashType()); + SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); combined = CombineSignatures( scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); @@ -1427,19 +1446,19 @@ // A couple of partially-signed versions: std::vector sig1; - uint256 hash1 = - SignatureHash(scriptPubKey, txTo, 0, SigHashType(), Amount(0)); + uint256 hash1 = SignatureHash(scriptPubKey, CTransaction(txTo), 0, + SigHashType(), Amount(0)); BOOST_CHECK(keys[0].Sign(hash1, sig1)); sig1.push_back(SIGHASH_ALL); std::vector sig2; uint256 hash2 = SignatureHash( - scriptPubKey, txTo, 0, + scriptPubKey, CTransaction(txTo), 0, SigHashType().withBaseSigHash(BaseSigHashType::NONE), Amount(0)); BOOST_CHECK(keys[1].Sign(hash2, sig2)); sig2.push_back(SIGHASH_NONE); std::vector sig3; uint256 hash3 = SignatureHash( - scriptPubKey, txTo, 0, + scriptPubKey, CTransaction(txTo), 0, SigHashType().withBaseSigHash(BaseSigHashType::SINGLE), Amount(0)); BOOST_CHECK(keys[2].Sign(hash3, sig3)); sig3.push_back(SIGHASH_SINGLE); diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -407,9 +407,9 @@ const char *charstrval("testing charstr"); CMutableTransaction txval; CSerializeMethodsTestSingle methodtest1(intval, boolval, stringval, - charstrval, txval); + charstrval, CTransaction(txval)); CSerializeMethodsTestMany methodtest2(intval, boolval, stringval, - charstrval, txval); + charstrval, CTransaction(txval)); CSerializeMethodsTestSingle methodtest3; CSerializeMethodsTestMany methodtest4; CDataStream ss(SER_DISK, PROTOCOL_VERSION); diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -144,8 +144,9 @@ int nIn = InsecureRandRange(txTo.vin.size()); uint256 sh, sho; - sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType); - sh = SignatureHash(scriptCode, txTo, nIn, sigHashType, Amount(0)); + sho = SignatureHashOld(scriptCode, CTransaction(txTo), nIn, nHashType); + sh = SignatureHash(scriptCode, CTransaction(txTo), nIn, sigHashType, + Amount(0)); #if defined(PRINT_SIGHASH_JSON) CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << txTo; diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -104,7 +104,7 @@ spendingTx.vout[0].nValue = Amount(1); spendingTx.vout[0].scriptPubKey = CScript(); - AddCoins(coins, creationTx, 0); + AddCoins(coins, CTransaction(creationTx), 0); } BOOST_AUTO_TEST_CASE(GetTxSigOpCost) { @@ -133,6 +133,7 @@ CScript scriptSig = CScript() << OP_0 << OP_0; BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig); + // Legacy counting only includes signature operations in scriptSigs and // scriptPubKeys of a transaction and does not take the actual executed // sig operations into account. spendingTx in itself does not contain a @@ -145,7 +146,7 @@ flags) == MAX_PUBKEYS_PER_MULTISIG); // Sanity check: script verification fails because of an invalid // signature. - assert(VerifyWithFlag(creationTx, spendingTx, flags) == + assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); } @@ -161,7 +162,7 @@ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig); assert(GetTransactionSigOpCount(CTransaction(spendingTx), coins, flags) == 2); - assert(VerifyWithFlag(creationTx, spendingTx, flags) == + assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); } } @@ -198,7 +199,7 @@ { CValidationState state; - BOOST_CHECK(CheckRegularTransaction(tx, state, false)); + BOOST_CHECK(CheckRegularTransaction(CTransaction(tx), state, false)); } // Get just before the limit. @@ -208,7 +209,7 @@ { CValidationState state; - BOOST_CHECK(CheckRegularTransaction(tx, state, false)); + BOOST_CHECK(CheckRegularTransaction(CTransaction(tx), state, false)); } // And go over. @@ -216,7 +217,7 @@ { CValidationState state; - BOOST_CHECK(!CheckRegularTransaction(tx, state, false)); + BOOST_CHECK(!CheckRegularTransaction(CTransaction(tx), state, false)); BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-txn-sigops"); } } 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 @@ -241,12 +241,14 @@ CMutableTransaction tx; stream >> tx; CValidationState state; - BOOST_CHECK_MESSAGE(CheckRegularTransaction(tx, state) && state.IsValid(), + BOOST_CHECK_MESSAGE(CheckRegularTransaction(CTransaction(tx), state) && + state.IsValid(), "Simple deserialized transaction should be valid."); // Check that duplicate txins fail tx.vin.push_back(tx.vin[0]); - BOOST_CHECK_MESSAGE(!CheckRegularTransaction(tx, state) || !state.IsValid(), + BOOST_CHECK_MESSAGE(!CheckRegularTransaction(CTransaction(tx), state) || + !state.IsValid(), "Transaction with duplicate txins should be invalid."); } @@ -276,7 +278,7 @@ dummyTransactions[0].vout[1].nValue = 50 * CENT; dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG; - AddCoins(coinsRet, dummyTransactions[0], 0); + AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0); dummyTransactions[1].vout.resize(2); dummyTransactions[1].vout[0].nValue = 21 * CENT; @@ -285,7 +287,7 @@ dummyTransactions[1].vout[1].nValue = 22 * CENT; dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID()); - AddCoins(coinsRet, dummyTransactions[1], 0); + AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0); return dummyTransactions; } @@ -314,8 +316,9 @@ t1.vout[0].nValue = 90 * CENT; t1.vout[0].scriptPubKey << OP_1; - BOOST_CHECK(AreInputsStandard(t1, coins)); - BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50 + 21 + 22) * CENT); + BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins)); + BOOST_CHECK_EQUAL(coins.GetValueIn(CTransaction(t1)), + (50 + 21 + 22) * CENT); } void CreateCreditAndSpend(const CKeyStore &keystore, const CScript &outscript, @@ -538,31 +541,31 @@ t.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); std::string reason; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // Check dust with default relay fee: Amount nDustThreshold = 3 * 182 * dustRelayFee.GetFeePerK() / 1000; BOOST_CHECK_EQUAL(nDustThreshold, Amount(546)); // dust: t.vout[0].nValue = nDustThreshold - Amount(1); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // not dust: t.vout[0].nValue = nDustThreshold; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // Check dust with odd relay fee to verify rounding: // nDustThreshold = 182 * 1234 / 1000 * 3 dustRelayFee = CFeeRate(Amount(1234)); // dust: t.vout[0].nValue = Amount(672 - 1); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // not dust: t.vout[0].nValue = Amount(672); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE); t.vout[0].scriptPubKey = CScript() << OP_1; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // MAX_OP_RETURN_RELAY-byte TX_NULL_DATA (standard) t.vout[0].scriptPubKey = @@ -572,7 +575,7 @@ "271967f1a67130b7105cd6a828e03909a67962e0ea1f61de" "b649f6bc3f4cef38"); BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size()); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // MAX_OP_RETURN_RELAY+1-byte TX_NULL_DATA (non-standard) t.vout[0].scriptPubKey = @@ -582,34 +585,34 @@ "271967f1a67130b7105cd6a828e03909a67962e0ea1f61de" "b649f6bc3f4cef3800"); BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size()); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // Data payload can be encoded in any way... t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex(""); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("00") << ParseHex("01"); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // OP_RESERVED *is* considered to be a PUSHDATA type opcode by IsPushOnly()! t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RESERVED << -1 << 0 << ParseHex("01") << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12 << 13 << 14 << 15 << 16; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); t.vout[0].scriptPubKey = CScript() << OP_RETURN << 0 << ParseHex("01") << 2 << ParseHex("fffffffffffffffffffffffffffffffffffff" "fffffffffffffffffffffffffffffffffff"); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // ...so long as it only contains PUSHDATA's t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // TX_NULL_DATA w/o PUSHDATA t.vout.resize(1); t.vout[0].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // Only one TX_NULL_DATA permitted in all cases t.vout.resize(2); @@ -621,18 +624,18 @@ CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909" "a67962e0ea1f61deb649f6bc3f4cef38"); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909" "a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[1].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); t.vout[0].scriptPubKey = CScript() << OP_RETURN; t.vout[1].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); } BOOST_AUTO_TEST_SUITE_END() 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 @@ -53,7 +53,7 @@ // Sign: std::vector vchSig; - uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, + uint256 hash = SignatureHash(scriptPubKey, CTransaction(spends[i]), 0, SigHashType().withForkId(true), coinbaseTxns[0].vout[0].nValue); BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); @@ -101,9 +101,10 @@ // should fail. // Capture this interaction with the upgraded_nop argument: set it when // evaluating any script flag that is implemented as an upgraded NOP code. -void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, +void ValidateCheckInputsForAllFlags(const CMutableTransaction &mutableTx, uint32_t failing_flags, bool add_to_cache, bool upgraded_nop) { + const CTransaction tx(mutableTx); PrecomputedTransactionData txdata(tx); // If we add many more flags, this loop can get too expensive, but we can // rewrite in the future to randomly pick a set of flags to evaluate. @@ -168,37 +169,39 @@ // Create 2 outputs that match the three scripts above, spending the first // coinbase tx. - CMutableTransaction spend_tx; - - spend_tx.nVersion = 1; - spend_tx.vin.resize(1); - spend_tx.vin[0].prevout.hash = coinbaseTxns[0].GetId(); - spend_tx.vin[0].prevout.n = 0; - spend_tx.vout.resize(4); - spend_tx.vout[0].nValue = 11 * CENT; - spend_tx.vout[0].scriptPubKey = p2sh_scriptPubKey; - spend_tx.vout[1].nValue = 11 * CENT; - spend_tx.vout[1].scriptPubKey = + CMutableTransaction mutableSpend_tx; + + mutableSpend_tx.nVersion = 1; + mutableSpend_tx.vin.resize(1); + mutableSpend_tx.vin[0].prevout.hash = coinbaseTxns[0].GetId(); + mutableSpend_tx.vin[0].prevout.n = 0; + mutableSpend_tx.vout.resize(4); + mutableSpend_tx.vout[0].nValue = 11 * CENT; + mutableSpend_tx.vout[0].scriptPubKey = p2sh_scriptPubKey; + mutableSpend_tx.vout[1].nValue = 11 * CENT; + mutableSpend_tx.vout[1].scriptPubKey = CScript() << OP_CHECKLOCKTIMEVERIFY << OP_DROP << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; - spend_tx.vout[2].nValue = 11 * CENT; - spend_tx.vout[2].scriptPubKey = + mutableSpend_tx.vout[2].nValue = 11 * CENT; + mutableSpend_tx.vout[2].scriptPubKey = CScript() << OP_CHECKSEQUENCEVERIFY << OP_DROP << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; - spend_tx.vout[3].nValue = 11 * CENT; - spend_tx.vout[3].scriptPubKey = p2sh_scriptPubKey; + mutableSpend_tx.vout[3].nValue = 11 * CENT; + mutableSpend_tx.vout[3].scriptPubKey = p2sh_scriptPubKey; // Sign, and push an extra element on the stack. { std::vector vchSig; - uint256 hash = SignatureHash(p2pk_scriptPubKey, spend_tx, 0, - SigHashType().withForkId(true), - coinbaseTxns[0].vout[0].nValue); + uint256 hash = SignatureHash( + p2pk_scriptPubKey, CTransaction(mutableSpend_tx), 0, + SigHashType().withForkId(true), coinbaseTxns[0].vout[0].nValue); BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); vchSig.push_back(uint8_t(SIGHASH_ALL | SIGHASH_FORKID)); - spend_tx.vin[0].scriptSig << OP_TRUE << vchSig; + mutableSpend_tx.vin[0].scriptSig << OP_TRUE << vchSig; } + const CTransaction spend_tx(mutableSpend_tx); + LOCK(cs_main); // Test that invalidity under a set of flags doesn't preclude validity under @@ -274,8 +277,8 @@ // Sign std::vector vchSig; uint256 hash = SignatureHash( - spend_tx.vout[1].scriptPubKey, invalid_with_cltv_tx, 0, - SigHashType().withForkId(true), spend_tx.vout[1].nValue); + spend_tx.vout[1].scriptPubKey, CTransaction(invalid_with_cltv_tx), + 0, SigHashType().withForkId(true), spend_tx.vout[1].nValue); BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); vchSig.push_back(uint8_t(SIGHASH_ALL | SIGHASH_FORKID)); invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101; @@ -287,8 +290,11 @@ // Make it valid, and check again invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100; CValidationState state; - PrecomputedTransactionData txdata(invalid_with_cltv_tx); - BOOST_CHECK(CheckInputs(invalid_with_cltv_tx, state, pcoinsTip, true, + + CTransaction transaction(invalid_with_cltv_tx); + PrecomputedTransactionData txdata(transaction); + + BOOST_CHECK(CheckInputs(transaction, state, pcoinsTip, true, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr)); @@ -309,7 +315,7 @@ // Sign std::vector vchSig; uint256 hash = SignatureHash( - spend_tx.vout[2].scriptPubKey, invalid_with_csv_tx, 0, + spend_tx.vout[2].scriptPubKey, CTransaction(invalid_with_csv_tx), 0, SigHashType().withForkId(true), spend_tx.vout[2].nValue); BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); vchSig.push_back(uint8_t(SIGHASH_ALL | SIGHASH_FORKID)); @@ -321,8 +327,11 @@ // Make it valid, and check again invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100; CValidationState state; - PrecomputedTransactionData txdata(invalid_with_csv_tx); - BOOST_CHECK(CheckInputs(invalid_with_csv_tx, state, pcoinsTip, true, + + CTransaction transaction(invalid_with_csv_tx); + PrecomputedTransactionData txdata(transaction); + + BOOST_CHECK(CheckInputs(transaction, state, pcoinsTip, true, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr)); @@ -366,18 +375,19 @@ tx.vin[1].scriptSig = CScript(); CValidationState state; - PrecomputedTransactionData txdata(tx); + CTransaction transaction(tx); + PrecomputedTransactionData txdata(transaction); // This transaction is now invalid because the second signature is // missing. - BOOST_CHECK(!CheckInputs(tx, state, pcoinsTip, true, + BOOST_CHECK(!CheckInputs(transaction, state, pcoinsTip, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, true, txdata, nullptr)); // Make sure this transaction was not cached (ie becausethe first input // was valid) std::vector scriptchecks; - BOOST_CHECK(CheckInputs(tx, state, pcoinsTip, true, + BOOST_CHECK(CheckInputs(transaction, state, pcoinsTip, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, true, txdata, &scriptchecks)); // Should get 2 script checks back -- caching is on a whole-transaction diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3408,7 +3408,7 @@ } UniValue result(UniValue::VOBJ); - result.push_back(Pair("hex", EncodeHexTx(tx))); + result.push_back(Pair("hex", EncodeHexTx(CTransaction(tx)))); result.push_back(Pair("changepos", changePosition)); result.push_back(Pair("fee", ValueFromAmount(nFeeOut))); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2916,9 +2916,8 @@ return false; } - unsigned int nBytes = CTransaction(txNew).GetTotalSize(); - CTransaction txNewConst(txNew); + unsigned int nBytes = txNewConst.GetTotalSize(); dPriority = txNewConst.ComputePriority(dPriority, nBytes); // Remove scriptSigs to eliminate the fee calculation dummy