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