Bitcoin Core  27.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 
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(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
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 
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(), "6657b736d4fe4db0cbc796789e812d5dba7f5c143764b1b6905612f1830609d1");
146  BOOST_CHECK_EQUAL(out110.nChainTx, 111U);
147 
148  const auto out110_2 = *params->AssumeutxoForBlockhash(uint256S("0x696e92821f65549c7ee134edceeeeaaa4105647a3c4fd9f298c0aec0ab50425c"));
149  BOOST_CHECK_EQUAL(out110_2.hash_serialized.ToString(), "6657b736d4fe4db0cbc796789e812d5dba7f5c143764b1b6905612f1830609d1");
150  BOOST_CHECK_EQUAL(out110_2.nChainTx, 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() != 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.
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 
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:37
const CChainParams & Params()
Return the currently selected parameters.
std::unique_ptr< const CChainParams > CreateChainParams(const ArgsManager &args, const ChainType chain)
Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: args.cpp:544
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
CHash256 & Write(Span< const unsigned char > input)
Definition: hash.h:37
void Finalize(Span< unsigned char > output)
Definition: hash.h:30
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:414
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:68
256-bit opaque blob.
Definition: uint256.h:106
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:194
BOOST_AUTO_TEST_SUITE_END()
unsigned int nHeight
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
Definition: merkle.cpp:65
uint256 BlockWitnessMerkleRoot(const CBlock &block, bool *mutated)
Definition: merkle.cpp:75
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:83
@ OP_RETURN
Definition: script.h:110
size_t GetSerializeSize(const T &t)
Definition: serialize.h:1116
bool CheckSignetBlockSolution(const CBlock &block, const Consensus::Params &consensusParams)
Extract signature and check whether a block has a valid solution.
Definition: signet.cpp:124
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:83
ArgsManager * args
Definition: context.h:64
uint256 uint256S(const char *str)
Definition: uint256.h:119
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)