Branch data Line data Source code
# 1 : : // Copyright (c) 2011-2021 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : #include <consensus/validation.h>
# 6 : : #include <key.h>
# 7 : : #include <script/sign.h>
# 8 : : #include <script/signingprovider.h>
# 9 : : #include <script/standard.h>
# 10 : : #include <test/util/setup_common.h>
# 11 : : #include <txmempool.h>
# 12 : : #include <validation.h>
# 13 : :
# 14 : : #include <boost/test/unit_test.hpp>
# 15 : :
# 16 : : struct Dersig100Setup : public TestChain100Setup {
# 17 : : Dersig100Setup()
# 18 : 4 : : TestChain100Setup{{"-testactivationheight=dersig@102"}} {}
# 19 : : };
# 20 : :
# 21 : : bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
# 22 : : const CCoinsViewCache& inputs, unsigned int flags, bool cacheSigStore,
# 23 : : bool cacheFullScriptStore, PrecomputedTransactionData& txdata,
# 24 : : std::vector<CScriptCheck>* pvChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
# 25 : :
# 26 : : BOOST_AUTO_TEST_SUITE(txvalidationcache_tests)
# 27 : :
# 28 : : BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)
# 29 : 2 : {
# 30 : : // Make sure skipping validation of transactions that were
# 31 : : // validated going into the memory pool does not allow
# 32 : : // double-spends in blocks to pass validation when they should not.
# 33 : :
# 34 : 2 : CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
# 35 : :
# 36 : 6 : const auto ToMemPool = [this](const CMutableTransaction& tx) {
# 37 : 6 : LOCK(cs_main);
# 38 : :
# 39 : 6 : const MempoolAcceptResult result = m_node.chainman->ProcessTransaction(MakeTransactionRef(tx));
# 40 : 6 : return result.m_result_type == MempoolAcceptResult::ResultType::VALID;
# 41 : 6 : };
# 42 : :
# 43 : : // Create a double-spend of mature coinbase txn:
# 44 : 2 : std::vector<CMutableTransaction> spends;
# 45 : 2 : spends.resize(2);
# 46 [ + + ]: 6 : for (int i = 0; i < 2; i++)
# 47 : 4 : {
# 48 : 4 : spends[i].nVersion = 1;
# 49 : 4 : spends[i].vin.resize(1);
# 50 : 4 : spends[i].vin[0].prevout.hash = m_coinbase_txns[0]->GetHash();
# 51 : 4 : spends[i].vin[0].prevout.n = 0;
# 52 : 4 : spends[i].vout.resize(1);
# 53 : 4 : spends[i].vout[0].nValue = 11*CENT;
# 54 : 4 : spends[i].vout[0].scriptPubKey = scriptPubKey;
# 55 : :
# 56 : : // Sign:
# 57 : 4 : std::vector<unsigned char> vchSig;
# 58 : 4 : uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SigVersion::BASE);
# 59 : 4 : BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
# 60 : 4 : vchSig.push_back((unsigned char)SIGHASH_ALL);
# 61 : 4 : spends[i].vin[0].scriptSig << vchSig;
# 62 : 4 : }
# 63 : :
# 64 : 2 : CBlock block;
# 65 : :
# 66 : : // Test 1: block with both of those transactions should be rejected.
# 67 : 2 : block = CreateAndProcessBlock(spends, scriptPubKey);
# 68 : 2 : {
# 69 : 2 : LOCK(cs_main);
# 70 : 2 : BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash());
# 71 : 2 : }
# 72 : :
# 73 : : // Test 2: ... and should be rejected if spend1 is in the memory pool
# 74 : 2 : BOOST_CHECK(ToMemPool(spends[0]));
# 75 : 2 : block = CreateAndProcessBlock(spends, scriptPubKey);
# 76 : 2 : {
# 77 : 2 : LOCK(cs_main);
# 78 : 2 : BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash());
# 79 : 2 : }
# 80 : 2 : m_node.mempool->clear();
# 81 : :
# 82 : : // Test 3: ... and should be rejected if spend2 is in the memory pool
# 83 : 2 : BOOST_CHECK(ToMemPool(spends[1]));
# 84 : 2 : block = CreateAndProcessBlock(spends, scriptPubKey);
# 85 : 2 : {
# 86 : 2 : LOCK(cs_main);
# 87 : 2 : BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash());
# 88 : 2 : }
# 89 : 2 : m_node.mempool->clear();
# 90 : :
# 91 : : // Final sanity test: first spend in *m_node.mempool, second in block, that's OK:
# 92 : 2 : std::vector<CMutableTransaction> oneSpend;
# 93 : 2 : oneSpend.push_back(spends[0]);
# 94 : 2 : BOOST_CHECK(ToMemPool(spends[1]));
# 95 : 2 : block = CreateAndProcessBlock(oneSpend, scriptPubKey);
# 96 : 2 : {
# 97 : 2 : LOCK(cs_main);
# 98 : 2 : BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() == block.GetHash());
# 99 : 2 : }
# 100 : : // spends[1] should have been removed from the mempool when the
# 101 : : // block with spends[0] is accepted:
# 102 : 2 : BOOST_CHECK_EQUAL(m_node.mempool->size(), 0U);
# 103 : 2 : }
# 104 : :
# 105 : : // Run CheckInputScripts (using CoinsTip()) on the given transaction, for all script
# 106 : : // flags. Test that CheckInputScripts passes for all flags that don't overlap with
# 107 : : // the failing_flags argument, but otherwise fails.
# 108 : : // CHECKLOCKTIMEVERIFY and CHECKSEQUENCEVERIFY (and future NOP codes that may
# 109 : : // get reassigned) have an interaction with DISCOURAGE_UPGRADABLE_NOPS: if
# 110 : : // the script flags used contain DISCOURAGE_UPGRADABLE_NOPS but don't contain
# 111 : : // CHECKLOCKTIMEVERIFY (or CHECKSEQUENCEVERIFY), but the script does contain
# 112 : : // OP_CHECKLOCKTIMEVERIFY (or OP_CHECKSEQUENCEVERIFY), then script execution
# 113 : : // should fail.
# 114 : : // Capture this interaction with the upgraded_nop argument: set it when evaluating
# 115 : : // any script flag that is implemented as an upgraded NOP code.
# 116 : : static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache, CCoinsViewCache& active_coins_tip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
# 117 : 14 : {
# 118 : 14 : PrecomputedTransactionData txdata;
# 119 : :
# 120 : 14 : FastRandomContext insecure_rand(true);
# 121 : :
# 122 [ + + ]: 140014 : for (int count = 0; count < 10000; ++count) {
# 123 : 140000 : TxValidationState state;
# 124 : :
# 125 : : // Randomly selects flag combinations
# 126 : 140000 : uint32_t test_flags = (uint32_t) insecure_rand.randrange((SCRIPT_VERIFY_END_MARKER - 1) << 1);
# 127 : :
# 128 : : // Filter out incompatible flag choices
# 129 [ + + ]: 140000 : if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) {
# 130 : : // CLEANSTACK requires P2SH and WITNESS, see VerifyScript() in
# 131 : : // script/interpreter.cpp
# 132 : 70588 : test_flags |= SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS;
# 133 : 70588 : }
# 134 [ + + ]: 140000 : if ((test_flags & SCRIPT_VERIFY_WITNESS)) {
# 135 : : // WITNESS requires P2SH
# 136 : 105154 : test_flags |= SCRIPT_VERIFY_P2SH;
# 137 : 105154 : }
# 138 : 140000 : bool ret = CheckInputScripts(tx, state, &active_coins_tip, test_flags, true, add_to_cache, txdata, nullptr);
# 139 : : // CheckInputScripts should succeed iff test_flags doesn't intersect with
# 140 : : // failing_flags
# 141 : 140000 : bool expected_return_value = !(test_flags & failing_flags);
# 142 : 140000 : BOOST_CHECK_EQUAL(ret, expected_return_value);
# 143 : :
# 144 : : // Test the caching
# 145 [ + + ][ + + ]: 140000 : if (ret && add_to_cache) {
# 146 : : // Check that we get a cache hit if the tx was valid
# 147 : 67524 : std::vector<CScriptCheck> scriptchecks;
# 148 : 67524 : BOOST_CHECK(CheckInputScripts(tx, state, &active_coins_tip, test_flags, true, add_to_cache, txdata, &scriptchecks));
# 149 : 67524 : BOOST_CHECK(scriptchecks.empty());
# 150 : 72476 : } else {
# 151 : : // Check that we get script executions to check, if the transaction
# 152 : : // was invalid, or we didn't add to cache.
# 153 : 72476 : std::vector<CScriptCheck> scriptchecks;
# 154 : 72476 : BOOST_CHECK(CheckInputScripts(tx, state, &active_coins_tip, test_flags, true, add_to_cache, txdata, &scriptchecks));
# 155 : 72476 : BOOST_CHECK_EQUAL(scriptchecks.size(), tx.vin.size());
# 156 : 72476 : }
# 157 : 140000 : }
# 158 : 14 : }
# 159 : :
# 160 : : BOOST_FIXTURE_TEST_CASE(checkinputs_test, Dersig100Setup)
# 161 : 2 : {
# 162 : : // Test that passing CheckInputScripts with one set of script flags doesn't imply
# 163 : : // that we would pass again with a different set of flags.
# 164 : 2 : {
# 165 : 2 : LOCK(cs_main);
# 166 : 2 : InitScriptExecutionCache();
# 167 : 2 : }
# 168 : :
# 169 : 2 : CScript p2pk_scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
# 170 : 2 : CScript p2sh_scriptPubKey = GetScriptForDestination(ScriptHash(p2pk_scriptPubKey));
# 171 : 2 : CScript p2pkh_scriptPubKey = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()));
# 172 : 2 : CScript p2wpkh_scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(coinbaseKey.GetPubKey()));
# 173 : :
# 174 : 2 : FillableSigningProvider keystore;
# 175 : 2 : BOOST_CHECK(keystore.AddKey(coinbaseKey));
# 176 : 2 : BOOST_CHECK(keystore.AddCScript(p2pk_scriptPubKey));
# 177 : :
# 178 : : // flags to test: SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, SCRIPT_VERIFY_CHECKSEQUENCE_VERIFY, SCRIPT_VERIFY_NULLDUMMY, uncompressed pubkey thing
# 179 : :
# 180 : : // Create 2 outputs that match the three scripts above, spending the first
# 181 : : // coinbase tx.
# 182 : 2 : CMutableTransaction spend_tx;
# 183 : :
# 184 : 2 : spend_tx.nVersion = 1;
# 185 : 2 : spend_tx.vin.resize(1);
# 186 : 2 : spend_tx.vin[0].prevout.hash = m_coinbase_txns[0]->GetHash();
# 187 : 2 : spend_tx.vin[0].prevout.n = 0;
# 188 : 2 : spend_tx.vout.resize(4);
# 189 : 2 : spend_tx.vout[0].nValue = 11*CENT;
# 190 : 2 : spend_tx.vout[0].scriptPubKey = p2sh_scriptPubKey;
# 191 : 2 : spend_tx.vout[1].nValue = 11*CENT;
# 192 : 2 : spend_tx.vout[1].scriptPubKey = p2wpkh_scriptPubKey;
# 193 : 2 : spend_tx.vout[2].nValue = 11*CENT;
# 194 : 2 : spend_tx.vout[2].scriptPubKey = CScript() << OP_CHECKLOCKTIMEVERIFY << OP_DROP << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
# 195 : 2 : spend_tx.vout[3].nValue = 11*CENT;
# 196 : 2 : spend_tx.vout[3].scriptPubKey = CScript() << OP_CHECKSEQUENCEVERIFY << OP_DROP << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
# 197 : :
# 198 : : // Sign, with a non-DER signature
# 199 : 2 : {
# 200 : 2 : std::vector<unsigned char> vchSig;
# 201 : 2 : uint256 hash = SignatureHash(p2pk_scriptPubKey, spend_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE);
# 202 : 2 : BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
# 203 : 2 : vchSig.push_back((unsigned char) 0); // padding byte makes this non-DER
# 204 : 2 : vchSig.push_back((unsigned char)SIGHASH_ALL);
# 205 : 2 : spend_tx.vin[0].scriptSig << vchSig;
# 206 : 2 : }
# 207 : :
# 208 : : // Test that invalidity under a set of flags doesn't preclude validity
# 209 : : // under other (eg consensus) flags.
# 210 : : // spend_tx is invalid according to DERSIG
# 211 : 2 : {
# 212 : 2 : LOCK(cs_main);
# 213 : :
# 214 : 2 : TxValidationState state;
# 215 : 2 : PrecomputedTransactionData ptd_spend_tx;
# 216 : :
# 217 : 2 : BOOST_CHECK(!CheckInputScripts(CTransaction(spend_tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
# 218 : :
# 219 : : // If we call again asking for scriptchecks (as happens in
# 220 : : // ConnectBlock), we should add a script check object for this -- we're
# 221 : : // not caching invalidity (if that changes, delete this test case).
# 222 : 2 : std::vector<CScriptCheck> scriptchecks;
# 223 : 2 : BOOST_CHECK(CheckInputScripts(CTransaction(spend_tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks));
# 224 : 2 : BOOST_CHECK_EQUAL(scriptchecks.size(), 1U);
# 225 : :
# 226 : : // Test that CheckInputScripts returns true iff DERSIG-enforcing flags are
# 227 : : // not present. Don't add these checks to the cache, so that we can
# 228 : : // test later that block validation works fine in the absence of cached
# 229 : : // successes.
# 230 : 2 : ValidateCheckInputsForAllFlags(CTransaction(spend_tx), SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false, m_node.chainman->ActiveChainstate().CoinsTip());
# 231 : 2 : }
# 232 : :
# 233 : : // And if we produce a block with this tx, it should be valid (DERSIG not
# 234 : : // enabled yet), even though there's no cache entry.
# 235 : 2 : CBlock block;
# 236 : :
# 237 : 2 : block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey);
# 238 : 2 : LOCK(cs_main);
# 239 : 2 : BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() == block.GetHash());
# 240 : 2 : BOOST_CHECK(m_node.chainman->ActiveChainstate().CoinsTip().GetBestBlock() == block.GetHash());
# 241 : :
# 242 : : // Test P2SH: construct a transaction that is valid without P2SH, and
# 243 : : // then test validity with P2SH.
# 244 : 2 : {
# 245 : 2 : CMutableTransaction invalid_under_p2sh_tx;
# 246 : 2 : invalid_under_p2sh_tx.nVersion = 1;
# 247 : 2 : invalid_under_p2sh_tx.vin.resize(1);
# 248 : 2 : invalid_under_p2sh_tx.vin[0].prevout.hash = spend_tx.GetHash();
# 249 : 2 : invalid_under_p2sh_tx.vin[0].prevout.n = 0;
# 250 : 2 : invalid_under_p2sh_tx.vout.resize(1);
# 251 : 2 : invalid_under_p2sh_tx.vout[0].nValue = 11*CENT;
# 252 : 2 : invalid_under_p2sh_tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
# 253 : 2 : std::vector<unsigned char> vchSig2(p2pk_scriptPubKey.begin(), p2pk_scriptPubKey.end());
# 254 : 2 : invalid_under_p2sh_tx.vin[0].scriptSig << vchSig2;
# 255 : :
# 256 : 2 : ValidateCheckInputsForAllFlags(CTransaction(invalid_under_p2sh_tx), SCRIPT_VERIFY_P2SH, true, m_node.chainman->ActiveChainstate().CoinsTip());
# 257 : 2 : }
# 258 : :
# 259 : : // Test CHECKLOCKTIMEVERIFY
# 260 : 2 : {
# 261 : 2 : CMutableTransaction invalid_with_cltv_tx;
# 262 : 2 : invalid_with_cltv_tx.nVersion = 1;
# 263 : 2 : invalid_with_cltv_tx.nLockTime = 100;
# 264 : 2 : invalid_with_cltv_tx.vin.resize(1);
# 265 : 2 : invalid_with_cltv_tx.vin[0].prevout.hash = spend_tx.GetHash();
# 266 : 2 : invalid_with_cltv_tx.vin[0].prevout.n = 2;
# 267 : 2 : invalid_with_cltv_tx.vin[0].nSequence = 0;
# 268 : 2 : invalid_with_cltv_tx.vout.resize(1);
# 269 : 2 : invalid_with_cltv_tx.vout[0].nValue = 11*CENT;
# 270 : 2 : invalid_with_cltv_tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
# 271 : :
# 272 : : // Sign
# 273 : 2 : std::vector<unsigned char> vchSig;
# 274 : 2 : uint256 hash = SignatureHash(spend_tx.vout[2].scriptPubKey, invalid_with_cltv_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE);
# 275 : 2 : BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
# 276 : 2 : vchSig.push_back((unsigned char)SIGHASH_ALL);
# 277 : 2 : invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
# 278 : :
# 279 : 2 : ValidateCheckInputsForAllFlags(CTransaction(invalid_with_cltv_tx), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, m_node.chainman->ActiveChainstate().CoinsTip());
# 280 : :
# 281 : : // Make it valid, and check again
# 282 : 2 : invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
# 283 : 2 : TxValidationState state;
# 284 : 2 : PrecomputedTransactionData txdata;
# 285 : 2 : BOOST_CHECK(CheckInputScripts(CTransaction(invalid_with_cltv_tx), state, m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
# 286 : 2 : }
# 287 : :
# 288 : : // TEST CHECKSEQUENCEVERIFY
# 289 : 2 : {
# 290 : 2 : CMutableTransaction invalid_with_csv_tx;
# 291 : 2 : invalid_with_csv_tx.nVersion = 2;
# 292 : 2 : invalid_with_csv_tx.vin.resize(1);
# 293 : 2 : invalid_with_csv_tx.vin[0].prevout.hash = spend_tx.GetHash();
# 294 : 2 : invalid_with_csv_tx.vin[0].prevout.n = 3;
# 295 : 2 : invalid_with_csv_tx.vin[0].nSequence = 100;
# 296 : 2 : invalid_with_csv_tx.vout.resize(1);
# 297 : 2 : invalid_with_csv_tx.vout[0].nValue = 11*CENT;
# 298 : 2 : invalid_with_csv_tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
# 299 : :
# 300 : : // Sign
# 301 : 2 : std::vector<unsigned char> vchSig;
# 302 : 2 : uint256 hash = SignatureHash(spend_tx.vout[3].scriptPubKey, invalid_with_csv_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE);
# 303 : 2 : BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
# 304 : 2 : vchSig.push_back((unsigned char)SIGHASH_ALL);
# 305 : 2 : invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
# 306 : :
# 307 : 2 : ValidateCheckInputsForAllFlags(CTransaction(invalid_with_csv_tx), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, m_node.chainman->ActiveChainstate().CoinsTip());
# 308 : :
# 309 : : // Make it valid, and check again
# 310 : 2 : invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
# 311 : 2 : TxValidationState state;
# 312 : 2 : PrecomputedTransactionData txdata;
# 313 : 2 : BOOST_CHECK(CheckInputScripts(CTransaction(invalid_with_csv_tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
# 314 : 2 : }
# 315 : :
# 316 : : // TODO: add tests for remaining script flags
# 317 : :
# 318 : : // Test that passing CheckInputScripts with a valid witness doesn't imply success
# 319 : : // for the same tx with a different witness.
# 320 : 2 : {
# 321 : 2 : CMutableTransaction valid_with_witness_tx;
# 322 : 2 : valid_with_witness_tx.nVersion = 1;
# 323 : 2 : valid_with_witness_tx.vin.resize(1);
# 324 : 2 : valid_with_witness_tx.vin[0].prevout.hash = spend_tx.GetHash();
# 325 : 2 : valid_with_witness_tx.vin[0].prevout.n = 1;
# 326 : 2 : valid_with_witness_tx.vout.resize(1);
# 327 : 2 : valid_with_witness_tx.vout[0].nValue = 11*CENT;
# 328 : 2 : valid_with_witness_tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
# 329 : :
# 330 : : // Sign
# 331 : 2 : SignatureData sigdata;
# 332 : 2 : BOOST_CHECK(ProduceSignature(keystore, MutableTransactionSignatureCreator(&valid_with_witness_tx, 0, 11*CENT, SIGHASH_ALL), spend_tx.vout[1].scriptPubKey, sigdata));
# 333 : 2 : UpdateInput(valid_with_witness_tx.vin[0], sigdata);
# 334 : :
# 335 : : // This should be valid under all script flags.
# 336 : 2 : ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), 0, true, m_node.chainman->ActiveChainstate().CoinsTip());
# 337 : :
# 338 : : // Remove the witness, and check that it is now invalid.
# 339 : 2 : valid_with_witness_tx.vin[0].scriptWitness.SetNull();
# 340 : 2 : ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), SCRIPT_VERIFY_WITNESS, true, m_node.chainman->ActiveChainstate().CoinsTip());
# 341 : 2 : }
# 342 : :
# 343 : 2 : {
# 344 : : // Test a transaction with multiple inputs.
# 345 : 2 : CMutableTransaction tx;
# 346 : :
# 347 : 2 : tx.nVersion = 1;
# 348 : 2 : tx.vin.resize(2);
# 349 : 2 : tx.vin[0].prevout.hash = spend_tx.GetHash();
# 350 : 2 : tx.vin[0].prevout.n = 0;
# 351 : 2 : tx.vin[1].prevout.hash = spend_tx.GetHash();
# 352 : 2 : tx.vin[1].prevout.n = 1;
# 353 : 2 : tx.vout.resize(1);
# 354 : 2 : tx.vout[0].nValue = 22*CENT;
# 355 : 2 : tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
# 356 : :
# 357 : : // Sign
# 358 [ + + ]: 6 : for (int i=0; i<2; ++i) {
# 359 : 4 : SignatureData sigdata;
# 360 : 4 : BOOST_CHECK(ProduceSignature(keystore, MutableTransactionSignatureCreator(&tx, i, 11*CENT, SIGHASH_ALL), spend_tx.vout[i].scriptPubKey, sigdata));
# 361 : 4 : UpdateInput(tx.vin[i], sigdata);
# 362 : 4 : }
# 363 : :
# 364 : : // This should be valid under all script flags
# 365 : 2 : ValidateCheckInputsForAllFlags(CTransaction(tx), 0, true, m_node.chainman->ActiveChainstate().CoinsTip());
# 366 : :
# 367 : : // Check that if the second input is invalid, but the first input is
# 368 : : // valid, the transaction is not cached.
# 369 : : // Invalidate vin[1]
# 370 : 2 : tx.vin[1].scriptWitness.SetNull();
# 371 : :
# 372 : 2 : TxValidationState state;
# 373 : 2 : PrecomputedTransactionData txdata;
# 374 : : // This transaction is now invalid under segwit, because of the second input.
# 375 : 2 : BOOST_CHECK(!CheckInputScripts(CTransaction(tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
# 376 : :
# 377 : 2 : std::vector<CScriptCheck> scriptchecks;
# 378 : : // Make sure this transaction was not cached (ie because the first
# 379 : : // input was valid)
# 380 : 2 : BOOST_CHECK(CheckInputScripts(CTransaction(tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks));
# 381 : : // Should get 2 script checks back -- caching is on a whole-transaction basis.
# 382 : 2 : BOOST_CHECK_EQUAL(scriptchecks.size(), 2U);
# 383 : 2 : }
# 384 : 2 : }
# 385 : :
# 386 : : BOOST_AUTO_TEST_SUITE_END()
|