LCOV - code coverage report
Current view: top level - src/test - validation_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 97.8 % 229 224
Test Date: 2024-11-04 05:10:19 Functions: 100.0 % 14 14
Branches: 50.5 % 986 498

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2014-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 <chainparams.h>
       6                 :             : #include <consensus/amount.h>
       7                 :             : #include <consensus/merkle.h>
       8                 :             : #include <core_io.h>
       9                 :             : #include <hash.h>
      10                 :             : #include <net.h>
      11                 :             : #include <signet.h>
      12                 :             : #include <uint256.h>
      13                 :             : #include <util/chaintype.h>
      14                 :             : #include <validation.h>
      15                 :             : 
      16                 :             : #include <string>
      17                 :             : 
      18                 :             : #include <test/util/setup_common.h>
      19                 :             : 
      20                 :             : #include <boost/test/unit_test.hpp>
      21                 :             : 
      22                 :             : BOOST_FIXTURE_TEST_SUITE(validation_tests, TestingSetup)
      23                 :             : 
      24                 :           3 : static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams)
      25                 :             : {
      26                 :           3 :     int maxHalvings = 64;
      27                 :           3 :     CAmount nInitialSubsidy = 50 * COIN;
      28                 :             : 
      29                 :           3 :     CAmount nPreviousSubsidy = nInitialSubsidy * 2; // for height == 0
      30         [ +  - ]:           3 :     BOOST_CHECK_EQUAL(nPreviousSubsidy, nInitialSubsidy * 2);
      31         [ +  + ]:         195 :     for (int nHalvings = 0; nHalvings < maxHalvings; nHalvings++) {
      32                 :         192 :         int nHeight = nHalvings * consensusParams.nSubsidyHalvingInterval;
      33                 :         192 :         CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
      34         [ +  - ]:         384 :         BOOST_CHECK(nSubsidy <= nInitialSubsidy);
      35         [ +  - ]:         192 :         BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2);
      36                 :         192 :         nPreviousSubsidy = nSubsidy;
      37                 :             :     }
      38         [ +  - ]:           3 :     BOOST_CHECK_EQUAL(GetBlockSubsidy(maxHalvings * consensusParams.nSubsidyHalvingInterval, consensusParams), 0);
      39                 :           3 : }
      40                 :             : 
      41                 :           2 : static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval)
      42                 :             : {
      43                 :           2 :     Consensus::Params consensusParams;
      44                 :           2 :     consensusParams.nSubsidyHalvingInterval = nSubsidyHalvingInterval;
      45         [ +  - ]:           2 :     TestBlockSubsidyHalvings(consensusParams);
      46                 :           2 : }
      47                 :             : 
      48   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(block_subsidy_test)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      49                 :             : {
      50                 :           1 :     const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN);
      51         [ +  - ]:           1 :     TestBlockSubsidyHalvings(chainParams->GetConsensus()); // As in main
      52         [ +  - ]:           1 :     TestBlockSubsidyHalvings(150); // As in regtest
      53         [ +  - ]:           1 :     TestBlockSubsidyHalvings(1000); // Just another interval
      54                 :           1 : }
      55                 :             : 
      56   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(subsidy_limit_test)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      57                 :             : {
      58                 :           1 :     const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN);
      59                 :           1 :     CAmount nSum = 0;
      60         [ +  + ]:       14001 :     for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) {
      61         [ +  - ]:       14000 :         CAmount nSubsidy = GetBlockSubsidy(nHeight, chainParams->GetConsensus());
      62   [ +  -  +  -  :       28000 :         BOOST_CHECK(nSubsidy <= 50 * COIN);
                   +  - ]
      63                 :       14000 :         nSum += nSubsidy * 1000;
      64   [ +  -  +  - ]:       28000 :         BOOST_CHECK(MoneyRange(nSum));
      65                 :             :     }
      66   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(nSum, CAmount{2099999997690000});
      67                 :           1 : }
      68                 :             : 
      69   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(signet_parse_tests)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      70                 :             : {
      71                 :           1 :     ArgsManager signet_argsman;
      72   [ +  -  +  -  :           2 :     signet_argsman.ForceSetArg("-signetchallenge", "51"); // set challenge to OP_TRUE
                   +  - ]
      73         [ +  - ]:           1 :     const auto signet_params = CreateChainParams(signet_argsman, ChainType::SIGNET);
      74                 :           1 :     CBlock block;
      75   [ +  -  +  -  :           2 :     BOOST_CHECK(signet_params->GetConsensus().signet_challenge == std::vector<uint8_t>{OP_TRUE});
             +  -  +  - ]
      76         [ +  - ]:           1 :     CScript challenge{OP_TRUE};
      77                 :             : 
      78                 :             :     // empty block is invalid
      79   [ +  -  +  -  :           2 :     BOOST_CHECK(!SignetTxs::Create(block, challenge));
             +  -  +  - ]
      80   [ +  -  +  -  :           2 :     BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus()));
             +  -  +  - ]
      81                 :             : 
      82                 :             :     // no witness commitment
      83         [ +  - ]:           1 :     CMutableTransaction cb;
      84         [ +  - ]:           1 :     cb.vout.emplace_back(0, CScript{});
      85   [ +  -  +  -  :           2 :     block.vtx.push_back(MakeTransactionRef(cb));
                   -  + ]
      86   [ +  -  +  -  :           2 :     block.vtx.push_back(MakeTransactionRef(cb)); // Add dummy tx to exercise merkle root code
                   -  + ]
      87   [ +  -  +  -  :           2 :     BOOST_CHECK(!SignetTxs::Create(block, challenge));
             +  -  +  - ]
      88   [ +  -  +  -  :           2 :     BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus()));
             +  -  +  - ]
      89                 :             : 
      90                 :             :     // no header is treated valid
      91         [ +  - ]:           1 :     std::vector<uint8_t> witness_commitment_section_141{0xaa, 0x21, 0xa9, 0xed};
      92         [ +  + ]:          33 :     for (int i = 0; i < 32; ++i) {
      93         [ +  - ]:          32 :         witness_commitment_section_141.push_back(0xff);
      94                 :             :     }
      95   [ +  -  +  - ]:           1 :     cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141;
      96   [ +  -  +  -  :           2 :     block.vtx.at(0) = MakeTransactionRef(cb);
                   -  + ]
      97   [ +  -  +  -  :           2 :     BOOST_CHECK(SignetTxs::Create(block, challenge));
             +  -  +  - ]
      98   [ +  -  +  -  :           2 :     BOOST_CHECK(CheckSignetBlockSolution(block, signet_params->GetConsensus()));
             +  -  +  - ]
      99                 :             : 
     100                 :             :     // no data after header, valid
     101         [ +  - ]:           1 :     std::vector<uint8_t> witness_commitment_section_325{0xec, 0xc7, 0xda, 0xa2};
     102   [ +  -  +  - ]:           1 :     cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141 << witness_commitment_section_325;
     103   [ +  -  +  -  :           2 :     block.vtx.at(0) = MakeTransactionRef(cb);
                   -  + ]
     104   [ +  -  +  -  :           2 :     BOOST_CHECK(SignetTxs::Create(block, challenge));
             +  -  +  - ]
     105   [ +  -  +  -  :           2 :     BOOST_CHECK(CheckSignetBlockSolution(block, signet_params->GetConsensus()));
             +  -  +  - ]
     106                 :             : 
     107                 :             :     // Premature end of data, invalid
     108         [ +  - ]:           1 :     witness_commitment_section_325.push_back(0x01);
     109         [ +  - ]:           1 :     witness_commitment_section_325.push_back(0x51);
     110   [ +  -  +  - ]:           1 :     cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141 << witness_commitment_section_325;
     111   [ +  -  +  -  :           2 :     block.vtx.at(0) = MakeTransactionRef(cb);
                   -  + ]
     112   [ +  -  +  -  :           2 :     BOOST_CHECK(!SignetTxs::Create(block, challenge));
             +  -  +  - ]
     113   [ +  -  +  -  :           2 :     BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus()));
             +  -  +  - ]
     114                 :             : 
     115                 :             :     // has data, valid
     116         [ +  - ]:           1 :     witness_commitment_section_325.push_back(0x00);
     117   [ +  -  +  - ]:           1 :     cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141 << witness_commitment_section_325;
     118   [ +  -  +  -  :           2 :     block.vtx.at(0) = MakeTransactionRef(cb);
                   -  + ]
     119   [ +  -  +  -  :           2 :     BOOST_CHECK(SignetTxs::Create(block, challenge));
             +  -  +  - ]
     120   [ +  -  +  -  :           2 :     BOOST_CHECK(CheckSignetBlockSolution(block, signet_params->GetConsensus()));
             +  -  +  - ]
     121                 :             : 
     122                 :             :     // Extraneous data, invalid
     123         [ +  - ]:           1 :     witness_commitment_section_325.push_back(0x00);
     124   [ +  -  +  - ]:           1 :     cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141 << witness_commitment_section_325;
     125   [ +  -  +  -  :           2 :     block.vtx.at(0) = MakeTransactionRef(cb);
                   -  + ]
     126   [ +  -  +  -  :           2 :     BOOST_CHECK(!SignetTxs::Create(block, challenge));
             +  -  +  - ]
     127   [ +  -  +  -  :           2 :     BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus()));
                   +  - ]
     128                 :           2 : }
     129                 :             : 
     130                 :             : //! Test retrieval of valid assumeutxo values.
     131   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(test_assumeutxo)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     132                 :             : {
     133                 :           1 :     const auto params = CreateChainParams(*m_node.args, ChainType::REGTEST);
     134                 :             : 
     135                 :             :     // These heights don't have assumeutxo configurations associated, per the contents
     136                 :             :     // of kernel/chainparams.cpp.
     137         [ +  - ]:           1 :     std::vector<int> bad_heights{0, 100, 111, 115, 209, 211};
     138                 :             : 
     139         [ +  + ]:           7 :     for (auto empty : bad_heights) {
     140                 :           6 :         const auto out = params->AssumeutxoForHeight(empty);
     141   [ +  -  +  - ]:          12 :         BOOST_CHECK(!out);
     142                 :             :     }
     143                 :             : 
     144         [ +  - ]:           1 :     const auto out110 = *params->AssumeutxoForHeight(110);
     145   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(out110.hash_serialized.ToString(), "6657b736d4fe4db0cbc796789e812d5dba7f5c143764b1b6905612f1830609d1");
                   +  - ]
     146   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(out110.m_chain_tx_count, 111U);
     147                 :             : 
     148         [ +  - ]:           1 :     const auto out110_2 = *params->AssumeutxoForBlockhash(uint256{"696e92821f65549c7ee134edceeeeaaa4105647a3c4fd9f298c0aec0ab50425c"});
     149   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(out110_2.hash_serialized.ToString(), "6657b736d4fe4db0cbc796789e812d5dba7f5c143764b1b6905612f1830609d1");
                   +  - ]
     150   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(out110_2.m_chain_tx_count, 111U);
     151                 :           1 : }
     152                 :             : 
     153   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(block_malleation)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     154                 :             : {
     155                 :             :     // Test utilities that calls `IsBlockMutated` and then clears the validity
     156                 :             :     // cache flags on `CBlock`.
     157                 :          17 :     auto is_mutated = [](CBlock& block, bool check_witness_root) {
     158   [ +  -  +  -  :           9 :         bool mutated{IsBlockMutated(block, check_witness_root)};
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     159                 :          16 :         block.fChecked = false;
     160                 :          16 :         block.m_checked_witness_commitment = false;
     161                 :          16 :         block.m_checked_merkle_root = false;
     162                 :          16 :         return mutated;
     163                 :             :     };
     164                 :           8 :     auto is_not_mutated = [&is_mutated](CBlock& block, bool check_witness_root) {
     165   [ +  -  +  -  :           7 :         return !is_mutated(block, check_witness_root);
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     166                 :           1 :     };
     167                 :             : 
     168                 :             :     // Test utilities to create coinbase transactions and insert witness
     169                 :             :     // commitments.
     170                 :             :     //
     171                 :             :     // Note: this will not include the witness stack by default to avoid
     172                 :             :     // triggering the "no witnesses allowed for blocks that don't commit to
     173                 :             :     // witnesses" rule when testing other malleation vectors.
     174                 :           3 :     auto create_coinbase_tx = [](bool include_witness = false) {
     175                 :           2 :         CMutableTransaction coinbase;
     176         [ +  - ]:           2 :         coinbase.vin.resize(1);
     177         [ +  + ]:           2 :         if (include_witness) {
     178         [ +  - ]:           1 :             coinbase.vin[0].scriptWitness.stack.resize(1);
     179         [ +  - ]:           1 :             coinbase.vin[0].scriptWitness.stack[0] = std::vector<unsigned char>(32, 0x00);
     180                 :             :         }
     181                 :             : 
     182         [ +  - ]:           2 :         coinbase.vout.resize(1);
     183                 :           2 :         coinbase.vout[0].scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT);
     184         [ -  + ]:           2 :         coinbase.vout[0].scriptPubKey[0] = OP_RETURN;
     185         [ -  + ]:           2 :         coinbase.vout[0].scriptPubKey[1] = 0x24;
     186         [ -  + ]:           2 :         coinbase.vout[0].scriptPubKey[2] = 0xaa;
     187         [ -  + ]:           2 :         coinbase.vout[0].scriptPubKey[3] = 0x21;
     188         [ -  + ]:           2 :         coinbase.vout[0].scriptPubKey[4] = 0xa9;
     189         [ -  + ]:           2 :         coinbase.vout[0].scriptPubKey[5] = 0xed;
     190                 :             : 
     191         [ +  - ]:           2 :         auto tx = MakeTransactionRef(coinbase);
     192         [ -  + ]:           2 :         assert(tx->IsCoinBase());
     193                 :           2 :         return tx;
     194                 :           2 :     };
     195                 :           3 :     auto insert_witness_commitment = [](CBlock& block, uint256 commitment) {
     196   [ +  -  +  -  :           2 :         assert(!block.vtx.empty() && block.vtx[0]->IsCoinBase() && !block.vtx[0]->vout.empty());
                   -  + ]
     197                 :             : 
     198                 :           2 :         CMutableTransaction mtx{*block.vtx[0]};
     199   [ +  -  +  -  :           4 :         CHash256().Write(commitment).Write(std::vector<unsigned char>(32, 0x00)).Finalize(commitment);
          +  -  +  -  +  
                -  -  + ]
     200   [ -  +  +  - ]:           4 :         memcpy(&mtx.vout[0].scriptPubKey[6], commitment.begin(), 32);
     201   [ +  -  -  + ]:           4 :         block.vtx[0] = MakeTransactionRef(mtx);
     202                 :           2 :     };
     203                 :             : 
     204                 :           1 :     {
     205                 :           1 :         CBlock block;
     206                 :             : 
     207                 :             :         // Empty block is expected to have merkle root of 0x0.
     208   [ +  -  +  -  :           2 :         BOOST_CHECK(block.vtx.empty());
                   +  - ]
     209         [ +  - ]:           1 :         block.hashMerkleRoot = uint256{1};
     210   [ +  -  +  -  :           2 :         BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false));
             +  -  +  - ]
     211         [ +  - ]:           1 :         block.hashMerkleRoot = uint256{};
     212   [ +  -  +  -  :           2 :         BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/false));
             +  -  +  - ]
     213                 :             : 
     214                 :             :         // Block with a single coinbase tx is mutated if the merkle root is not
     215                 :             :         // equal to the coinbase tx's hash.
     216   [ +  -  -  + ]:           2 :         block.vtx.push_back(create_coinbase_tx());
     217   [ +  -  +  -  :           2 :         BOOST_CHECK(block.vtx[0]->GetHash() != block.hashMerkleRoot);
                   +  - ]
     218   [ +  -  +  -  :           2 :         BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false));
             +  -  +  - ]
     219         [ +  - ]:           1 :         block.hashMerkleRoot = block.vtx[0]->GetHash();
     220   [ +  -  +  -  :           2 :         BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/false));
             +  -  +  - ]
     221                 :             : 
     222                 :             :         // Block with two transactions is mutated if the merkle root does not
     223                 :             :         // match the double sha256 of the concatenation of the two transaction
     224                 :             :         // hashes.
     225   [ +  -  +  -  :           2 :         block.vtx.push_back(MakeTransactionRef(CMutableTransaction{}));
                   -  + ]
     226   [ +  -  +  -  :           2 :         BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false));
             +  -  +  - ]
     227         [ +  - ]:           1 :         HashWriter hasher;
     228         [ +  - ]:           1 :         hasher.write(block.vtx[0]->GetHash());
     229         [ +  - ]:           1 :         hasher.write(block.vtx[1]->GetHash());
     230         [ +  - ]:           1 :         block.hashMerkleRoot = hasher.GetHash();
     231   [ +  -  +  -  :           2 :         BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/false));
                   +  - ]
     232                 :             : 
     233                 :             :         // Block with two transactions is mutated if any node is duplicate.
     234                 :           1 :         {
     235                 :           1 :             block.vtx[1] = block.vtx[0];
     236         [ +  - ]:           1 :             HashWriter hasher;
     237         [ +  - ]:           1 :             hasher.write(block.vtx[0]->GetHash());
     238         [ +  - ]:           1 :             hasher.write(block.vtx[1]->GetHash());
     239         [ +  - ]:           1 :             block.hashMerkleRoot = hasher.GetHash();
     240   [ +  -  +  -  :           2 :             BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false));
                   +  - ]
     241                 :             :         }
     242                 :             : 
     243                 :             :         // Blocks with 64-byte coinbase transactions are not considered mutated
     244                 :           1 :         block.vtx.clear();
     245                 :           1 :         {
     246         [ +  - ]:           1 :             CMutableTransaction mtx;
     247         [ +  - ]:           1 :             mtx.vin.resize(1);
     248         [ +  - ]:           1 :             mtx.vout.resize(1);
     249                 :           1 :             mtx.vout[0].scriptPubKey.resize(4);
     250   [ +  -  +  -  :           2 :             block.vtx.push_back(MakeTransactionRef(mtx));
                   -  + ]
     251         [ -  + ]:           1 :             block.hashMerkleRoot = block.vtx.back()->GetHash();
     252         [ -  + ]:           1 :             assert(block.vtx.back()->IsCoinBase());
     253         [ -  + ]:           1 :             assert(GetSerializeSize(TX_NO_WITNESS(block.vtx.back())) == 64);
     254                 :           0 :         }
     255   [ +  -  +  -  :           2 :         BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/false));
                   +  - ]
     256                 :           0 :     }
     257                 :             : 
     258                 :           1 :     {
     259                 :             :         // Test merkle root malleation
     260                 :             : 
     261                 :             :         // Pseudo code to mine transactions tx{1,2,3}:
     262                 :             :         //
     263                 :             :         // ```
     264                 :             :         // loop {
     265                 :             :         //   tx1 = random_tx()
     266                 :             :         //   tx2 = random_tx()
     267                 :             :         //   tx3 = deserialize_tx(txid(tx1) || txid(tx2));
     268                 :             :         //   if serialized_size_without_witness(tx3) == 64 {
     269                 :             :         //     print(hex(tx3))
     270                 :             :         //     break
     271                 :             :         //   }
     272                 :             :         // }
     273                 :             :         // ```
     274                 :             :         //
     275                 :             :         // The `random_tx` function used to mine the txs below simply created
     276                 :             :         // empty transactions with a random version field.
     277                 :           1 :         CMutableTransaction tx1;
     278   [ +  -  +  -  :           2 :         BOOST_CHECK(DecodeHexTx(tx1, "ff204bd0000000000000", /*try_no_witness=*/true, /*try_witness=*/false));
          +  -  +  -  +  
                      - ]
     279         [ +  - ]:           1 :         CMutableTransaction tx2;
     280   [ +  -  +  -  :           2 :         BOOST_CHECK(DecodeHexTx(tx2, "8ae53c92000000000000", /*try_no_witness=*/true, /*try_witness=*/false));
          +  -  +  -  +  
                      - ]
     281         [ +  - ]:           1 :         CMutableTransaction tx3;
     282   [ +  -  +  -  :           2 :         BOOST_CHECK(DecodeHexTx(tx3, "cdaf22d00002c6a7f848f8ae4d30054e61dcf3303d6fe01d282163341f06feecc10032b3160fcab87bdfe3ecfb769206ef2d991b92f8a268e423a6ef4d485f06", /*try_no_witness=*/true, /*try_witness=*/false));
          +  -  +  -  +  
                      - ]
     283                 :           1 :         {
     284                 :             :             // Verify that double_sha256(txid1||txid2) == txid3
     285         [ +  - ]:           1 :             HashWriter hasher;
     286   [ +  -  +  - ]:           1 :             hasher.write(tx1.GetHash());
     287   [ +  -  +  - ]:           1 :             hasher.write(tx2.GetHash());
     288   [ +  -  +  -  :           1 :             assert(hasher.GetHash() == tx3.GetHash());
                   -  + ]
     289                 :             :             // Verify that tx3 is 64 bytes in size (without witness).
     290         [ -  + ]:           1 :             assert(GetSerializeSize(TX_NO_WITNESS(tx3)) == 64);
     291                 :             :         }
     292                 :             : 
     293                 :           1 :         CBlock block;
     294   [ +  -  +  -  :           2 :         block.vtx.push_back(MakeTransactionRef(tx1));
                   -  + ]
     295   [ +  -  +  -  :           2 :         block.vtx.push_back(MakeTransactionRef(tx2));
                   -  + ]
     296         [ +  - ]:           1 :         uint256 merkle_root = block.hashMerkleRoot = BlockMerkleRoot(block);
     297   [ +  -  +  -  :           2 :         BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/false));
                   +  - ]
     298                 :             : 
     299                 :             :         // Mutate the block by replacing the two transactions with one 64-byte
     300                 :             :         // transaction that serializes into the concatenation of the txids of
     301                 :             :         // the transactions in the unmutated block.
     302                 :           1 :         block.vtx.clear();
     303   [ +  -  +  -  :           2 :         block.vtx.push_back(MakeTransactionRef(tx3));
                   -  + ]
     304   [ +  -  +  -  :           2 :         BOOST_CHECK(!block.vtx.back()->IsCoinBase());
                   +  - ]
     305   [ +  -  +  -  :           2 :         BOOST_CHECK(BlockMerkleRoot(block) == merkle_root);
             +  -  +  - ]
     306   [ +  -  +  -  :           2 :         BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false));
                   +  - ]
     307                 :           3 :     }
     308                 :             : 
     309                 :           1 :     {
     310                 :           1 :         CBlock block;
     311   [ +  -  -  + ]:           2 :         block.vtx.push_back(create_coinbase_tx(/*include_witness=*/true));
     312                 :           1 :         {
     313         [ +  - ]:           1 :             CMutableTransaction mtx;
     314         [ +  - ]:           1 :             mtx.vin.resize(1);
     315         [ +  - ]:           1 :             mtx.vin[0].scriptWitness.stack.resize(1);
     316         [ +  - ]:           1 :             mtx.vin[0].scriptWitness.stack[0] = {0};
     317   [ +  -  +  -  :           2 :             block.vtx.push_back(MakeTransactionRef(mtx));
                   -  + ]
     318                 :           0 :         }
     319         [ +  - ]:           1 :         block.hashMerkleRoot = BlockMerkleRoot(block);
     320                 :             :         // Block with witnesses is considered mutated if the witness commitment
     321                 :             :         // is not validated.
     322   [ +  -  +  -  :           2 :         BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false));
             +  -  +  - ]
     323                 :             :         // Block with invalid witness commitment is considered mutated.
     324   [ +  -  +  -  :           2 :         BOOST_CHECK(is_mutated(block, /*check_witness_root=*/true));
             +  -  +  - ]
     325                 :             : 
     326                 :             :         // Block with valid commitment is not mutated
     327                 :           1 :         {
     328         [ +  - ]:           1 :             auto commitment{BlockWitnessMerkleRoot(block)};
     329         [ +  - ]:           1 :             insert_witness_commitment(block, commitment);
     330         [ +  - ]:           1 :             block.hashMerkleRoot = BlockMerkleRoot(block);
     331                 :             :         }
     332   [ +  -  +  -  :           2 :         BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/true));
             +  -  +  - ]
     333                 :             : 
     334                 :             :         // Malleating witnesses should be caught by `IsBlockMutated`.
     335                 :           1 :         {
     336         [ +  - ]:           1 :             CMutableTransaction mtx{*block.vtx[1]};
     337         [ -  + ]:           1 :             assert(!mtx.vin[0].scriptWitness.stack[0].empty());
     338         [ +  - ]:           1 :             ++mtx.vin[0].scriptWitness.stack[0][0];
     339   [ +  -  -  + ]:           2 :             block.vtx[1] = MakeTransactionRef(mtx);
     340                 :           0 :         }
     341                 :             :         // Without also updating the witness commitment, the merkle root should
     342                 :             :         // not change when changing one of the witnesses.
     343   [ +  -  +  -  :           2 :         BOOST_CHECK(block.hashMerkleRoot == BlockMerkleRoot(block));
             +  -  +  - ]
     344   [ +  -  +  -  :           2 :         BOOST_CHECK(is_mutated(block, /*check_witness_root=*/true));
             +  -  +  - ]
     345                 :           1 :         {
     346         [ +  - ]:           1 :             auto commitment{BlockWitnessMerkleRoot(block)};
     347         [ +  - ]:           1 :             insert_witness_commitment(block, commitment);
     348         [ +  - ]:           1 :             block.hashMerkleRoot = BlockMerkleRoot(block);
     349                 :             :         }
     350   [ +  -  +  -  :           2 :         BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/true));
             +  -  +  - ]
     351                 :             : 
     352                 :             :         // Test malleating the coinbase witness reserved value
     353                 :           1 :         {
     354         [ +  - ]:           1 :             CMutableTransaction mtx{*block.vtx[0]};
     355         [ +  - ]:           1 :             mtx.vin[0].scriptWitness.stack.resize(0);
     356   [ +  -  -  + ]:           2 :             block.vtx[0] = MakeTransactionRef(mtx);
     357         [ +  - ]:           1 :             block.hashMerkleRoot = BlockMerkleRoot(block);
     358                 :           0 :         }
     359   [ +  -  +  -  :           2 :         BOOST_CHECK(is_mutated(block, /*check_witness_root=*/true));
                   +  - ]
     360                 :           1 :     }
     361                 :           1 : }
     362                 :             : 
     363                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1