Bitcoin Core 28.99.0
P2P Digital Currency
validation_tests.cpp
Go to the documentation of this file.
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
19
20#include <boost/test/unit_test.hpp>
21
23
24static 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
41static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval)
42{
43 Consensus::Params consensusParams;
44 consensusParams.nSubsidyHalvingInterval = nSubsidyHalvingInterval;
45 TestBlockSubsidyHalvings(consensusParams);
46}
47
48BOOST_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
56BOOST_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;
65 }
66 BOOST_CHECK_EQUAL(nSum, CAmount{2099999997690000});
67}
68
69BOOST_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
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
131BOOST_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);
142 }
143
144 const auto out110 = *params->AssumeutxoForHeight(110);
145 BOOST_CHECK_EQUAL(out110.hash_serialized.ToString(), "6657b736d4fe4db0cbc796789e812d5dba7f5c143764b1b6905612f1830609d1");
146 BOOST_CHECK_EQUAL(out110.m_chain_tx_count, 111U);
147
148 const auto out110_2 = *params->AssumeutxoForBlockhash(uint256{"696e92821f65549c7ee134edceeeeaaa4105647a3c4fd9f298c0aec0ab50425c"});
149 BOOST_CHECK_EQUAL(out110_2.hash_serialized.ToString(), "6657b736d4fe4db0cbc796789e812d5dba7f5c143764b1b6905612f1830609d1");
150 BOOST_CHECK_EQUAL(out110_2.m_chain_tx_count, 111U);
151}
152
153BOOST_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() != block.hashMerkleRoot);
218 BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false));
219 block.hashMerkleRoot = block.vtx[0]->GetHash();
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 {
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();
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.
278 BOOST_CHECK(DecodeHexTx(tx1, "ff204bd0000000000000", /*try_no_witness=*/true, /*try_witness=*/false));
280 BOOST_CHECK(DecodeHexTx(tx2, "8ae53c92000000000000", /*try_no_witness=*/true, /*try_witness=*/false));
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());
289 // Verify that tx3 is 64 bytes in size (without witness).
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 {
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.
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
bool MoneyRange(const CAmount &nValue)
Definition: amount.h:27
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
static constexpr CAmount COIN
The amount of satoshis in one BTC.
Definition: amount.h:15
node::NodeContext m_node
Definition: bitcoin-gui.cpp:42
std::unique_ptr< const CChainParams > CreateChainParams(const ArgsManager &args, const ChainType chain)
Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
const CChainParams & Params()
Return the currently selected parameters.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: args.cpp:546
uint256 hashMerkleRoot
Definition: block.h:27
Definition: block.h:69
bool m_checked_merkle_root
Definition: block.h:77
std::vector< CTransactionRef > vtx
Definition: block.h:72
bool m_checked_witness_commitment
Definition: block.h:76
bool fChecked
Definition: block.h:75
A hasher class for Bitcoin's 256-bit hash (double SHA-256).
Definition: hash.h:24
void Finalize(Span< unsigned char > output)
Definition: hash.h:30
CHash256 & Write(Span< const unsigned char > input)
Definition: hash.h:37
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:415
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:101
void write(Span< const std::byte > src)
Definition: hash.h:106
uint256 GetHash()
Compute the double-SHA256 hash of all data written to this object.
Definition: hash.h:115
static std::optional< SignetTxs > Create(const CBlock &block, const CScript &challenge)
Definition: signet.cpp:69
256-bit opaque blob.
Definition: uint256.h:190
static constexpr size_t MINIMUM_WITNESS_COMMITMENT
Minimum size of a witness commitment structure.
Definition: validation.h:18
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
Definition: core_read.cpp:196
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
unsigned int nHeight
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
Definition: merkle.cpp:66
uint256 BlockWitnessMerkleRoot(const CBlock &block, bool *mutated)
Definition: merkle.cpp:76
Transaction validation functions.
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
static constexpr TransactionSerParams TX_NO_WITNESS
Definition: transaction.h:196
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:424
@ OP_TRUE
Definition: script.h:84
@ OP_RETURN
Definition: script.h:111
size_t GetSerializeSize(const T &t)
Definition: serialize.h:1101
bool CheckSignetBlockSolution(const CBlock &block, const Consensus::Params &consensusParams)
Extract signature and check whether a block has a valid solution.
Definition: signet.cpp:125
A mutable version of CTransaction.
Definition: transaction.h:378
std::vector< CTxOut > vout
Definition: transaction.h:380
Txid GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:69
std::vector< CTxIn > vin
Definition: transaction.h:379
Parameters that influence chain consensus.
Definition: params.h:74
int nSubsidyHalvingInterval
Definition: params.h:76
Testing setup that configures a complete environment.
Definition: setup_common.h:120
ArgsManager * args
Definition: context.h:74
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams)
assert(!tx.IsCoinBase())
static void TestBlockSubsidyHalvings(const Consensus::Params &consensusParams)
BOOST_AUTO_TEST_CASE(block_subsidy_test)