validation_tests.cpp
1 // Copyright (c) 2014-present 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, BasicTestingSetup) 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(block_subsidy_test) 49 { 50 const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN); 51 TestBlockSubsidyHalvings(chainParams->GetConsensus()); // As in main 52 TestBlockSubsidyHalvings(150); // As in regtest 53 TestBlockSubsidyHalvings(1000); // Just another interval 54 } 55 56 BOOST_AUTO_TEST_CASE(subsidy_limit_test) 57 { 58 const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN); 59 CAmount nSum = 0; 60 for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) { 61 CAmount nSubsidy = GetBlockSubsidy(nHeight, chainParams->GetConsensus()); 62 BOOST_CHECK(nSubsidy <= 50 * COIN); 63 nSum += nSubsidy * 1000; 64 BOOST_CHECK(MoneyRange(nSum)); 65 } 66 BOOST_CHECK_EQUAL(nSum, CAmount{2099999997690000}); 67 } 68 69 BOOST_AUTO_TEST_CASE(signet_parse_tests) 70 { 71 ArgsManager signet_argsman; 72 signet_argsman.ForceSetArg("-signetchallenge", "51"); // set challenge to OP_TRUE 73 const auto signet_params = CreateChainParams(signet_argsman, ChainType::SIGNET); 74 CBlock block; 75 BOOST_CHECK(signet_params->GetConsensus().signet_challenge == std::vector<uint8_t>{OP_TRUE}); 76 CScript challenge{OP_TRUE}; 77 78 // empty block is invalid 79 BOOST_CHECK(!SignetTxs::Create(block, challenge)); 80 BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus())); 81 82 // no witness commitment 83 CMutableTransaction cb; 84 cb.vout.emplace_back(0, CScript{}); 85 block.vtx.push_back(MakeTransactionRef(cb)); 86 block.vtx.push_back(MakeTransactionRef(cb)); // Add dummy tx to exercise merkle root code 87 BOOST_CHECK(!SignetTxs::Create(block, challenge)); 88 BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus())); 89 90 // no header is treated valid 91 std::vector<uint8_t> witness_commitment_section_141{0xaa, 0x21, 0xa9, 0xed}; 92 for (int i = 0; i < 32; ++i) { 93 witness_commitment_section_141.push_back(0xff); 94 } 95 cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141; 96 block.vtx.at(0) = MakeTransactionRef(cb); 97 BOOST_CHECK(SignetTxs::Create(block, challenge)); 98 BOOST_CHECK(CheckSignetBlockSolution(block, signet_params->GetConsensus())); 99 100 // no data after header, valid 101 std::vector<uint8_t> witness_commitment_section_325{0xec, 0xc7, 0xda, 0xa2}; 102 cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141 << witness_commitment_section_325; 103 block.vtx.at(0) = MakeTransactionRef(cb); 104 BOOST_CHECK(SignetTxs::Create(block, challenge)); 105 BOOST_CHECK(CheckSignetBlockSolution(block, signet_params->GetConsensus())); 106 107 // Premature end of data, invalid 108 witness_commitment_section_325.push_back(0x01); 109 witness_commitment_section_325.push_back(0x51); 110 cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141 << witness_commitment_section_325; 111 block.vtx.at(0) = MakeTransactionRef(cb); 112 BOOST_CHECK(!SignetTxs::Create(block, challenge)); 113 BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus())); 114 115 // has data, valid 116 witness_commitment_section_325.push_back(0x00); 117 cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141 << witness_commitment_section_325; 118 block.vtx.at(0) = MakeTransactionRef(cb); 119 BOOST_CHECK(SignetTxs::Create(block, challenge)); 120 BOOST_CHECK(CheckSignetBlockSolution(block, signet_params->GetConsensus())); 121 122 // Extraneous data, invalid 123 witness_commitment_section_325.push_back(0x00); 124 cb.vout.at(0).scriptPubKey = CScript{} << OP_RETURN << witness_commitment_section_141 << witness_commitment_section_325; 125 block.vtx.at(0) = MakeTransactionRef(cb); 126 BOOST_CHECK(!SignetTxs::Create(block, challenge)); 127 BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus())); 128 } 129 130 //! Test retrieval of valid assumeutxo values. 131 BOOST_AUTO_TEST_CASE(test_assumeutxo) 132 { 133 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 std::vector<int> bad_heights{0, 100, 111, 115, 209, 211}; 138 139 for (auto empty : bad_heights) { 140 const auto out = params->AssumeutxoForHeight(empty); 141 BOOST_CHECK(!out); 142 } 143 144 const auto out110 = *params->AssumeutxoForHeight(110); 145 BOOST_CHECK_EQUAL(out110.hash_serialized.ToString(), "b952555c8ab81fec46f3d4253b7af256d766ceb39fb7752b9d18cdf4a0141327"); 146 BOOST_CHECK_EQUAL(out110.m_chain_tx_count, 111U); 147 148 const auto out110_2 = *params->AssumeutxoForBlockhash(uint256{"6affe030b7965ab538f820a56ef56c8149b7dc1d1c144af57113be080db7c397"}); 149 BOOST_CHECK_EQUAL(out110_2.hash_serialized.ToString(), "b952555c8ab81fec46f3d4253b7af256d766ceb39fb7752b9d18cdf4a0141327"); 150 BOOST_CHECK_EQUAL(out110_2.m_chain_tx_count, 111U); 151 } 152 153 BOOST_AUTO_TEST_CASE(block_malleation) 154 { 155 // Test utilities that calls `IsBlockMutated` and then clears the validity 156 // cache flags on `CBlock`. 157 auto is_mutated = [](CBlock& block, bool check_witness_root) { 158 bool mutated{IsBlockMutated(block, check_witness_root)}; 159 block.fChecked = false; 160 block.m_checked_witness_commitment = false; 161 block.m_checked_merkle_root = false; 162 return mutated; 163 }; 164 auto is_not_mutated = [&is_mutated](CBlock& block, bool check_witness_root) { 165 return !is_mutated(block, check_witness_root); 166 }; 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 auto create_coinbase_tx = [](bool include_witness = false) { 175 CMutableTransaction coinbase; 176 coinbase.vin.resize(1); 177 if (include_witness) { 178 coinbase.vin[0].scriptWitness.stack.resize(1); 179 coinbase.vin[0].scriptWitness.stack[0] = std::vector<unsigned char>(32, 0x00); 180 } 181 182 coinbase.vout.resize(1); 183 coinbase.vout[0].scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT); 184 coinbase.vout[0].scriptPubKey[0] = OP_RETURN; 185 coinbase.vout[0].scriptPubKey[1] = 0x24; 186 coinbase.vout[0].scriptPubKey[2] = 0xaa; 187 coinbase.vout[0].scriptPubKey[3] = 0x21; 188 coinbase.vout[0].scriptPubKey[4] = 0xa9; 189 coinbase.vout[0].scriptPubKey[5] = 0xed; 190 191 auto tx = MakeTransactionRef(coinbase); 192 assert(tx->IsCoinBase()); 193 return tx; 194 }; 195 auto insert_witness_commitment = [](CBlock& block, uint256 commitment) { 196 assert(!block.vtx.empty() && block.vtx[0]->IsCoinBase() && !block.vtx[0]->vout.empty()); 197 198 CMutableTransaction mtx{*block.vtx[0]}; 199 CHash256().Write(commitment).Write(std::vector<unsigned char>(32, 0x00)).Finalize(commitment); 200 memcpy(&mtx.vout[0].scriptPubKey[6], commitment.begin(), 32); 201 block.vtx[0] = MakeTransactionRef(mtx); 202 }; 203 204 { 205 CBlock block; 206 207 // Empty block is expected to have merkle root of 0x0. 208 BOOST_CHECK(block.vtx.empty()); 209 block.hashMerkleRoot = uint256{1}; 210 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false)); 211 block.hashMerkleRoot = uint256{}; 212 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 block.vtx.push_back(create_coinbase_tx()); 217 BOOST_CHECK(block.vtx[0]->GetHash().ToUint256() != block.hashMerkleRoot); 218 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false)); 219 block.hashMerkleRoot = block.vtx[0]->GetHash().ToUint256(); 220 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 block.vtx.push_back(MakeTransactionRef(CMutableTransaction{})); 226 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false)); 227 HashWriter hasher; 228 hasher.write(block.vtx[0]->GetHash()); 229 hasher.write(block.vtx[1]->GetHash()); 230 block.hashMerkleRoot = hasher.GetHash(); 231 BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/false)); 232 233 // Block with two transactions is mutated if any node is duplicate. 234 { 235 block.vtx[1] = block.vtx[0]; 236 HashWriter hasher; 237 hasher.write(block.vtx[0]->GetHash()); 238 hasher.write(block.vtx[1]->GetHash()); 239 block.hashMerkleRoot = hasher.GetHash(); 240 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false)); 241 } 242 243 // Blocks with 64-byte coinbase transactions are not considered mutated 244 block.vtx.clear(); 245 { 246 CMutableTransaction mtx; 247 mtx.vin.resize(1); 248 mtx.vout.resize(1); 249 mtx.vout[0].scriptPubKey.resize(4); 250 block.vtx.push_back(MakeTransactionRef(mtx)); 251 block.hashMerkleRoot = block.vtx.back()->GetHash().ToUint256(); 252 assert(block.vtx.back()->IsCoinBase()); 253 assert(GetSerializeSize(TX_NO_WITNESS(block.vtx.back())) == 64); 254 } 255 BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/false)); 256 } 257 258 { 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 CMutableTransaction tx1; 278 BOOST_CHECK(DecodeHexTx(tx1, "ff204bd0000000000000", /*try_no_witness=*/true, /*try_witness=*/false)); 279 CMutableTransaction tx2; 280 BOOST_CHECK(DecodeHexTx(tx2, "8ae53c92000000000000", /*try_no_witness=*/true, /*try_witness=*/false)); 281 CMutableTransaction tx3; 282 BOOST_CHECK(DecodeHexTx(tx3, "cdaf22d00002c6a7f848f8ae4d30054e61dcf3303d6fe01d282163341f06feecc10032b3160fcab87bdfe3ecfb769206ef2d991b92f8a268e423a6ef4d485f06", /*try_no_witness=*/true, /*try_witness=*/false)); 283 { 284 // Verify that double_sha256(txid1||txid2) == txid3 285 HashWriter hasher; 286 hasher.write(tx1.GetHash()); 287 hasher.write(tx2.GetHash()); 288 assert(hasher.GetHash() == tx3.GetHash().ToUint256()); 289 // Verify that tx3 is 64 bytes in size (without witness). 290 assert(GetSerializeSize(TX_NO_WITNESS(tx3)) == 64); 291 } 292 293 CBlock block; 294 block.vtx.push_back(MakeTransactionRef(tx1)); 295 block.vtx.push_back(MakeTransactionRef(tx2)); 296 uint256 merkle_root = block.hashMerkleRoot = BlockMerkleRoot(block); 297 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 block.vtx.clear(); 303 block.vtx.push_back(MakeTransactionRef(tx3)); 304 BOOST_CHECK(!block.vtx.back()->IsCoinBase()); 305 BOOST_CHECK(BlockMerkleRoot(block) == merkle_root); 306 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false)); 307 } 308 309 { 310 CBlock block; 311 block.vtx.push_back(create_coinbase_tx(/*include_witness=*/true)); 312 { 313 CMutableTransaction mtx; 314 mtx.vin.resize(1); 315 mtx.vin[0].scriptWitness.stack.resize(1); 316 mtx.vin[0].scriptWitness.stack[0] = {0}; 317 block.vtx.push_back(MakeTransactionRef(mtx)); 318 } 319 block.hashMerkleRoot = BlockMerkleRoot(block); 320 // Block with witnesses is considered mutated if the witness commitment 321 // is not validated. 322 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false)); 323 // Block with invalid witness commitment is considered mutated. 324 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/true)); 325 326 // Block with valid commitment is not mutated 327 { 328 auto commitment{BlockWitnessMerkleRoot(block)}; 329 insert_witness_commitment(block, commitment); 330 block.hashMerkleRoot = BlockMerkleRoot(block); 331 } 332 BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/true)); 333 334 // Malleating witnesses should be caught by `IsBlockMutated`. 335 { 336 CMutableTransaction mtx{*block.vtx[1]}; 337 assert(!mtx.vin[0].scriptWitness.stack[0].empty()); 338 ++mtx.vin[0].scriptWitness.stack[0][0]; 339 block.vtx[1] = MakeTransactionRef(mtx); 340 } 341 // Without also updating the witness commitment, the merkle root should 342 // not change when changing one of the witnesses. 343 BOOST_CHECK(block.hashMerkleRoot == BlockMerkleRoot(block)); 344 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/true)); 345 { 346 auto commitment{BlockWitnessMerkleRoot(block)}; 347 insert_witness_commitment(block, commitment); 348 block.hashMerkleRoot = BlockMerkleRoot(block); 349 } 350 BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/true)); 351 352 // Test malleating the coinbase witness reserved value 353 { 354 CMutableTransaction mtx{*block.vtx[0]}; 355 mtx.vin[0].scriptWitness.stack.resize(0); 356 block.vtx[0] = MakeTransactionRef(mtx); 357 block.hashMerkleRoot = BlockMerkleRoot(block); 358 } 359 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/true)); 360 } 361 } 362 363 BOOST_AUTO_TEST_SUITE_END()