validation_tests.cpp raw

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