LCOV - code coverage report
Current view: top level - src/test - txvalidationcache_tests.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 228 228 100.0 %
Date: 2022-04-21 14:51:19 Functions: 5 5 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 14 14 100.0 %

           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()

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a