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