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