feature_block.py raw
1 #!/usr/bin/env python3
2 # Copyright (c) 2015-2022 The Limenka developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 """Test block processing."""
6 import copy
7 import time
8
9 from test_framework.blocktools import (
10 create_block,
11 create_coinbase,
12 create_tx_with_script,
13 get_legacy_sigopcount_block,
14 MAX_BLOCK_SIGOPS,
15 REGTEST_N_BITS,
16 )
17 from test_framework.messages import (
18 CBlock,
19 COIN,
20 COutPoint,
21 CTransaction,
22 CTxIn,
23 CTxOut,
24 MAX_BLOCK_WEIGHT,
25 SEQUENCE_FINAL,
26 uint256_from_compact,
27 uint256_from_str,
28 )
29 from test_framework.p2p import P2PDataStore
30 from test_framework.script import (
31 CScript,
32 MAX_SCRIPT_ELEMENT_SIZE,
33 OP_2DUP,
34 OP_CHECKMULTISIG,
35 OP_CHECKMULTISIGVERIFY,
36 OP_CHECKSIG,
37 OP_CHECKSIGVERIFY,
38 OP_ELSE,
39 OP_ENDIF,
40 OP_DROP,
41 OP_FALSE,
42 OP_IF,
43 OP_INVALIDOPCODE,
44 OP_RETURN,
45 OP_TRUE,
46 sign_input_legacy,
47 )
48 from test_framework.script_util import (
49 script_to_p2sh_script,
50 )
51 from test_framework.test_framework import LimenkaTestFramework
52 from test_framework.util import (
53 assert_equal,
54 assert_greater_than,
55 )
56 from test_framework.wallet_util import generate_keypair
57 from data import invalid_txs
58
59
60 # Use this class for tests that require behavior other than normal p2p behavior.
61 # For now, it is used to serialize a bloated varint (b64).
62 class CBrokenBlock(CBlock):
63 def initialize(self, base_block):
64 self.vtx = copy.deepcopy(base_block.vtx)
65 self.hashMerkleRoot = self.calc_merkle_root()
66
67 def serialize(self, with_witness=False):
68 r = b""
69 r += super(CBlock, self).serialize()
70 r += (255).to_bytes(1, "little") + len(self.vtx).to_bytes(8, "little")
71 for tx in self.vtx:
72 if with_witness:
73 r += tx.serialize_with_witness()
74 else:
75 r += tx.serialize_without_witness()
76 return r
77
78 def normal_serialize(self):
79 return super().serialize()
80
81
82 DUPLICATE_COINBASE_SCRIPT_SIG = b'\x01\x78' # Valid for block at height 120
83
84
85 class FullBlockTest(LimenkaTestFramework):
86 def set_test_params(self):
87 self.num_nodes = 1
88 self.setup_clean_chain = True
89 self.extra_args = [[
90 '-acceptnonstdtxn=1', # This is a consensus block test, we don't care about tx policy
91 '-testactivationheight=bip34@2',
92 ]]
93
94 def run_test(self):
95 node = self.nodes[0] # convenience reference to the node
96
97 self.bootstrap_p2p() # Add one p2p connection to the node
98
99 self.block_heights = {}
100 self.coinbase_key, self.coinbase_pubkey = generate_keypair()
101 self.tip = None
102 self.blocks = {}
103 self.genesis_hash = int(self.nodes[0].getbestblockhash(), 16)
104 self.block_heights[self.genesis_hash] = 0
105 self.spendable_outputs = []
106
107 # Create a new block
108 b_dup_cb = self.next_block('dup_cb')
109 b_dup_cb.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG
110 b_dup_cb.vtx[0].rehash()
111 duplicate_tx = b_dup_cb.vtx[0]
112 b_dup_cb = self.update_block('dup_cb', [])
113 self.send_blocks([b_dup_cb])
114
115 b0 = self.next_block(0)
116 self.save_spendable_output()
117 self.send_blocks([b0])
118
119 # These constants chosen specifically to trigger an immature coinbase spend
120 # at a certain time below.
121 NUM_BUFFER_BLOCKS_TO_GENERATE = 99
122 NUM_OUTPUTS_TO_COLLECT = 33
123
124 # Allow the block to mature
125 blocks = []
126 for i in range(NUM_BUFFER_BLOCKS_TO_GENERATE):
127 blocks.append(self.next_block(f"maturitybuffer.{i}"))
128 self.save_spendable_output()
129 self.send_blocks(blocks)
130
131 # collect spendable outputs now to avoid cluttering the code later on
132 out = []
133 for _ in range(NUM_OUTPUTS_TO_COLLECT):
134 out.append(self.get_spendable_output())
135
136 # Start by building a couple of blocks on top (which output is spent is
137 # in parentheses):
138 # genesis -> b1 (0) -> b2 (1)
139 b1 = self.next_block(1, spend=out[0])
140 self.save_spendable_output()
141
142 b2 = self.next_block(2, spend=out[1])
143 self.save_spendable_output()
144
145 self.send_blocks([b1, b2], timeout=4)
146
147 # Select a txn with an output eligible for spending. This won't actually be spent,
148 # since we're testing submission of a series of blocks with invalid txns.
149 attempt_spend_tx = out[2]
150
151 # Submit blocks for rejection, each of which contains a single transaction
152 # (aside from coinbase) which should be considered invalid.
153 for TxTemplate in invalid_txs.iter_all_templates():
154 template = TxTemplate(spend_tx=attempt_spend_tx)
155
156 if template.valid_in_block:
157 continue
158
159 self.log.info(f"Reject block with invalid tx: {TxTemplate.__name__}")
160 blockname = f"for_invalid.{TxTemplate.__name__}"
161 self.next_block(blockname)
162 badtx = template.get_tx()
163 if TxTemplate != invalid_txs.InputMissing:
164 self.sign_tx(badtx, attempt_spend_tx)
165 badtx.rehash()
166 badblock = self.update_block(blockname, [badtx])
167 reject_reason = (template.block_reject_reason or template.reject_reason)
168 if reject_reason and reject_reason.startswith("mempool-script-verify-flag-failed"):
169 reject_reason = "mandatory-script-verify-flag-failed" + reject_reason[33:]
170 self.send_blocks(
171 [badblock], success=False,
172 reject_reason=reject_reason,
173 reconnect=True, timeout=2)
174
175 self.move_tip(2)
176
177 # Fork like this:
178 #
179 # genesis -> b1 (0) -> b2 (1)
180 # \-> b3 (1)
181 #
182 # Nothing should happen at this point. We saw b2 first so it takes priority.
183 self.log.info("Don't reorg to a chain of the same length")
184 self.move_tip(1)
185 b3 = self.next_block(3, spend=out[1])
186 txout_b3 = b3.vtx[1]
187 self.send_blocks([b3], False)
188
189 # Now we add another block to make the alternative chain longer.
190 #
191 # genesis -> b1 (0) -> b2 (1)
192 # \-> b3 (1) -> b4 (2)
193 self.log.info("Reorg to a longer chain")
194 b4 = self.next_block(4, spend=out[2])
195 self.send_blocks([b4])
196
197 # ... and back to the first chain.
198 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
199 # \-> b3 (1) -> b4 (2)
200 self.move_tip(2)
201 b5 = self.next_block(5, spend=out[2])
202 self.save_spendable_output()
203 self.send_blocks([b5], False)
204
205 self.log.info("Reorg back to the original chain")
206 b6 = self.next_block(6, spend=out[3])
207 self.send_blocks([b6], True)
208
209 # Try to create a fork that double-spends
210 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
211 # \-> b7 (2) -> b8 (4)
212 # \-> b3 (1) -> b4 (2)
213 self.log.info("Reject a chain with a double spend, even if it is longer")
214 self.move_tip(5)
215 b7 = self.next_block(7, spend=out[2])
216 self.send_blocks([b7], False)
217
218 b8 = self.next_block(8, spend=out[4])
219 self.send_blocks([b8], False, reconnect=True)
220
221 # Try to create a block that has too much fee
222 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
223 # \-> b9 (4)
224 # \-> b3 (1) -> b4 (2)
225 self.log.info("Reject a block where the miner creates too much coinbase reward")
226 self.move_tip(6)
227 b9 = self.next_block(9, spend=out[4], additional_coinbase_value=1)
228 self.send_blocks([b9], success=False, reject_reason='bad-cb-amount', reconnect=True)
229
230 # Create a fork that ends in a block with too much fee (the one that causes the reorg)
231 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
232 # \-> b10 (3) -> b11 (4)
233 # \-> b3 (1) -> b4 (2)
234 self.log.info("Reject a chain where the miner creates too much coinbase reward, even if the chain is longer")
235 self.move_tip(5)
236 b10 = self.next_block(10, spend=out[3])
237 self.send_blocks([b10], False)
238
239 b11 = self.next_block(11, spend=out[4], additional_coinbase_value=1)
240 self.send_blocks([b11], success=False, reject_reason='bad-cb-amount', reconnect=True)
241
242 # Try again, but with a valid fork first
243 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
244 # \-> b12 (3) -> b13 (4) -> b14 (5)
245 # \-> b3 (1) -> b4 (2)
246 self.log.info("Reject a chain where the miner creates too much coinbase reward, even if the chain is longer (on a forked chain)")
247 self.move_tip(5)
248 b12 = self.next_block(12, spend=out[3])
249 self.save_spendable_output()
250 b13 = self.next_block(13, spend=out[4])
251 self.save_spendable_output()
252 b14 = self.next_block(14, spend=out[5], additional_coinbase_value=1)
253 self.send_blocks([b12, b13, b14], success=False, reject_reason='bad-cb-amount', reconnect=True)
254
255 # New tip should be b13.
256 assert_equal(node.getbestblockhash(), b13.hash)
257
258 # Add a block with MAX_BLOCK_SIGOPS and one with one more sigop
259 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
260 # \-> b12 (3) -> b13 (4) -> b15 (5) -> b16 (6)
261 # \-> b3 (1) -> b4 (2)
262 self.log.info("Accept a block with lots of checksigs")
263 lots_of_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS - 1))
264 self.move_tip(13)
265 b15 = self.next_block(15, spend=out[5], script=lots_of_checksigs)
266 self.save_spendable_output()
267 self.send_blocks([b15], True)
268
269 self.log.info("Reject a block with too many checksigs")
270 too_many_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
271 b16 = self.next_block(16, spend=out[6], script=too_many_checksigs)
272 self.send_blocks([b16], success=False, reject_reason='bad-blk-sigops', reconnect=True)
273
274 # Attempt to spend a transaction created on a different fork
275 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
276 # \-> b12 (3) -> b13 (4) -> b15 (5) -> b17 (b3.vtx[1])
277 # \-> b3 (1) -> b4 (2)
278 self.log.info("Reject a block with a spend from a re-org'ed out tx")
279 self.move_tip(15)
280 b17 = self.next_block(17, spend=txout_b3)
281 self.send_blocks([b17], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
282
283 # Attempt to spend a transaction created on a different fork (on a fork this time)
284 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
285 # \-> b12 (3) -> b13 (4) -> b15 (5)
286 # \-> b18 (b3.vtx[1]) -> b19 (6)
287 # \-> b3 (1) -> b4 (2)
288 self.log.info("Reject a block with a spend from a re-org'ed out tx (on a forked chain)")
289 self.move_tip(13)
290 b18 = self.next_block(18, spend=txout_b3)
291 self.send_blocks([b18], False)
292
293 b19 = self.next_block(19, spend=out[6])
294 self.send_blocks([b19], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
295
296 # Attempt to spend a coinbase at depth too low
297 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
298 # \-> b12 (3) -> b13 (4) -> b15 (5) -> b20 (7)
299 # \-> b3 (1) -> b4 (2)
300 self.log.info("Reject a block spending an immature coinbase.")
301 self.move_tip(15)
302 b20 = self.next_block(20, spend=out[7])
303 self.send_blocks([b20], success=False, reject_reason='bad-txns-premature-spend-of-coinbase', reconnect=True)
304
305 # Attempt to spend a coinbase at depth too low (on a fork this time)
306 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
307 # \-> b12 (3) -> b13 (4) -> b15 (5)
308 # \-> b21 (6) -> b22 (5)
309 # \-> b3 (1) -> b4 (2)
310 self.log.info("Reject a block spending an immature coinbase (on a forked chain)")
311 self.move_tip(13)
312 b21 = self.next_block(21, spend=out[6])
313 self.send_blocks([b21], False)
314
315 b22 = self.next_block(22, spend=out[5])
316 self.send_blocks([b22], success=False, reject_reason='bad-txns-premature-spend-of-coinbase', reconnect=True)
317
318 # Create a block on either side of MAX_BLOCK_WEIGHT and make sure its accepted/rejected
319 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
320 # \-> b12 (3) -> b13 (4) -> b15 (5) -> b23 (6)
321 # \-> b24 (6) -> b25 (7)
322 # \-> b3 (1) -> b4 (2)
323 self.log.info("Accept a block of weight MAX_BLOCK_WEIGHT")
324 self.move_tip(15)
325 b23 = self.next_block(23, spend=out[6])
326 tx = CTransaction()
327 script_length = (MAX_BLOCK_WEIGHT - b23.get_weight() - 276) // 4
328 script_output = CScript([b'\x00' * script_length])
329 tx.vout.append(CTxOut(0, script_output))
330 tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 0)))
331 b23 = self.update_block(23, [tx])
332 # Make sure the math above worked out to produce a max-weighted block
333 assert_equal(b23.get_weight(), MAX_BLOCK_WEIGHT)
334 self.send_blocks([b23], True)
335 self.save_spendable_output()
336
337 self.log.info("Reject a block of weight MAX_BLOCK_WEIGHT + 4")
338 self.move_tip(15)
339 b24 = self.next_block(24, spend=out[6])
340 script_length = (MAX_BLOCK_WEIGHT - b24.get_weight() - 276) // 4
341 script_output = CScript([b'\x00' * (script_length + 1)])
342 tx.vout = [CTxOut(0, script_output)]
343 b24 = self.update_block(24, [tx])
344 assert_equal(b24.get_weight(), MAX_BLOCK_WEIGHT + 1 * 4)
345 self.send_blocks([b24], success=False, reject_reason='bad-blk-length', reconnect=True)
346
347 b25 = self.next_block(25, spend=out[7])
348 self.send_blocks([b25], False)
349
350 # Create blocks with a coinbase input script size out of range
351 # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
352 # \-> b12 (3) -> b13 (4) -> b15 (5) -> b23 (6) -> b30 (7)
353 # \-> ... (6) -> ... (7)
354 # \-> b3 (1) -> b4 (2)
355 self.log.info("Reject a block with coinbase input script size out of range")
356 self.move_tip(15)
357 b26 = self.next_block(26, spend=out[6])
358 b26.vtx[0].vin[0].scriptSig = b'\x00'
359 b26.vtx[0].rehash()
360 # update_block causes the merkle root to get updated, even with no new
361 # transactions, and updates the required state.
362 b26 = self.update_block(26, [])
363 self.send_blocks([b26], success=False, reject_reason='bad-cb-length', reconnect=True)
364
365 # Extend the b26 chain to make sure limenkad isn't accepting b26
366 b27 = self.next_block(27, spend=out[7])
367 self.send_blocks([b27], False)
368
369 # Now try a too-large-coinbase script
370 self.move_tip(15)
371 b28 = self.next_block(28, spend=out[6])
372 b28.vtx[0].vin[0].scriptSig = b'\x00' * 101
373 b28.vtx[0].rehash()
374 b28 = self.update_block(28, [])
375 self.send_blocks([b28], success=False, reject_reason='bad-cb-length', reconnect=True)
376
377 # Extend the b28 chain to make sure limenkad isn't accepting b28
378 b29 = self.next_block(29, spend=out[7])
379 self.send_blocks([b29], False)
380
381 # b30 has a max-sized coinbase scriptSig.
382 self.move_tip(23)
383 b30 = self.next_block(30)
384 b30.vtx[0].vin[0].scriptSig = bytes(b30.vtx[0].vin[0].scriptSig) # Convert CScript to raw bytes
385 b30.vtx[0].vin[0].scriptSig += b'\x00' * (100 - len(b30.vtx[0].vin[0].scriptSig)) # Fill with 0s
386 assert_equal(len(b30.vtx[0].vin[0].scriptSig), 100)
387 b30.vtx[0].rehash()
388 b30 = self.update_block(30, [])
389 self.send_blocks([b30], True)
390 self.save_spendable_output()
391
392 # b31 - b35 - check sigops of OP_CHECKMULTISIG / OP_CHECKMULTISIGVERIFY / OP_CHECKSIGVERIFY
393 #
394 # genesis -> ... -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10)
395 # \-> b36 (11)
396 # \-> b34 (10)
397 # \-> b32 (9)
398 #
399
400 # MULTISIG: each op code counts as 20 sigops. To create the edge case, pack another 19 sigops at the end.
401 self.log.info("Accept a block with the max number of OP_CHECKMULTISIG sigops")
402 lots_of_multisigs = CScript([OP_CHECKMULTISIG] * ((MAX_BLOCK_SIGOPS - 1) // 20) + [OP_CHECKSIG] * 19)
403 b31 = self.next_block(31, spend=out[8], script=lots_of_multisigs)
404 assert_equal(get_legacy_sigopcount_block(b31), MAX_BLOCK_SIGOPS)
405 self.send_blocks([b31], True)
406 self.save_spendable_output()
407
408 # this goes over the limit because the coinbase has one sigop
409 self.log.info("Reject a block with too many OP_CHECKMULTISIG sigops")
410 too_many_multisigs = CScript([OP_CHECKMULTISIG] * (MAX_BLOCK_SIGOPS // 20))
411 b32 = self.next_block(32, spend=out[9], script=too_many_multisigs)
412 assert_equal(get_legacy_sigopcount_block(b32), MAX_BLOCK_SIGOPS + 1)
413 self.send_blocks([b32], success=False, reject_reason='bad-blk-sigops', reconnect=True)
414
415 # CHECKMULTISIGVERIFY
416 self.log.info("Accept a block with the max number of OP_CHECKMULTISIGVERIFY sigops")
417 self.move_tip(31)
418 lots_of_multisigs = CScript([OP_CHECKMULTISIGVERIFY] * ((MAX_BLOCK_SIGOPS - 1) // 20) + [OP_CHECKSIG] * 19)
419 b33 = self.next_block(33, spend=out[9], script=lots_of_multisigs)
420 self.send_blocks([b33], True)
421 self.save_spendable_output()
422
423 self.log.info("Reject a block with too many OP_CHECKMULTISIGVERIFY sigops")
424 too_many_multisigs = CScript([OP_CHECKMULTISIGVERIFY] * (MAX_BLOCK_SIGOPS // 20))
425 b34 = self.next_block(34, spend=out[10], script=too_many_multisigs)
426 self.send_blocks([b34], success=False, reject_reason='bad-blk-sigops', reconnect=True)
427
428 # CHECKSIGVERIFY
429 self.log.info("Accept a block with the max number of OP_CHECKSIGVERIFY sigops")
430 self.move_tip(33)
431 lots_of_checksigs = CScript([OP_CHECKSIGVERIFY] * (MAX_BLOCK_SIGOPS - 1))
432 b35 = self.next_block(35, spend=out[10], script=lots_of_checksigs)
433 self.send_blocks([b35], True)
434 self.save_spendable_output()
435
436 self.log.info("Reject a block with too many OP_CHECKSIGVERIFY sigops")
437 too_many_checksigs = CScript([OP_CHECKSIGVERIFY] * (MAX_BLOCK_SIGOPS))
438 b36 = self.next_block(36, spend=out[11], script=too_many_checksigs)
439 self.send_blocks([b36], success=False, reject_reason='bad-blk-sigops', reconnect=True)
440
441 # Check spending of a transaction in a block which failed to connect
442 #
443 # b6 (3)
444 # b12 (3) -> b13 (4) -> b15 (5) -> b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10)
445 # \-> b37 (11)
446 # \-> b38 (11/37)
447 #
448
449 # save 37's spendable output, but then double-spend out11 to invalidate the block
450 self.log.info("Reject a block spending transaction from a block which failed to connect")
451 self.move_tip(35)
452 b37 = self.next_block(37, spend=out[11])
453 txout_b37 = b37.vtx[1]
454 tx = self.create_and_sign_transaction(out[11], 0)
455 b37 = self.update_block(37, [tx])
456 self.send_blocks([b37], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
457
458 # attempt to spend b37's first non-coinbase tx, at which point b37 was still considered valid
459 self.move_tip(35)
460 b38 = self.next_block(38, spend=txout_b37)
461 self.send_blocks([b38], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
462
463 # Check P2SH SigOp counting
464 #
465 #
466 # 13 (4) -> b15 (5) -> b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b41 (12)
467 # \-> b40 (12)
468 #
469 # b39 - create some P2SH outputs that will require 6 sigops to spend:
470 #
471 # redeem_script = COINBASE_PUBKEY, (OP_2DUP+OP_CHECKSIGVERIFY) * 5, OP_CHECKSIG
472 # p2sh_script = OP_HASH160, ripemd160(sha256(script)), OP_EQUAL
473 #
474 self.log.info("Check P2SH SIGOPS are correctly counted")
475 self.move_tip(35)
476 self.next_block(39)
477 b39_outputs = 0
478 b39_sigops_per_output = 6
479
480 # Build the redeem script, hash it, use hash to create the p2sh script
481 redeem_script = CScript([self.coinbase_pubkey] + [OP_2DUP, OP_CHECKSIGVERIFY] * 5 + [OP_CHECKSIG])
482 p2sh_script = script_to_p2sh_script(redeem_script)
483
484 # Create a transaction that spends one satoshi to the p2sh_script, the rest to OP_TRUE
485 # This must be signed because it is spending a coinbase
486 spend = out[11]
487 tx = self.create_tx(spend, 0, 1, p2sh_script)
488 tx.vout.append(CTxOut(spend.vout[0].nValue - 1, CScript([OP_TRUE])))
489 self.sign_tx(tx, spend)
490 tx.rehash()
491 b39 = self.update_block(39, [tx])
492 b39_outputs += 1
493
494 # Until block is full, add tx's with 1 satoshi to p2sh_script, the rest to OP_TRUE
495 tx_new = None
496 tx_last = tx
497 total_weight = b39.get_weight()
498 while total_weight < MAX_BLOCK_WEIGHT:
499 tx_new = self.create_tx(tx_last, 1, 1, p2sh_script)
500 tx_new.vout.append(CTxOut(tx_last.vout[1].nValue - 1, CScript([OP_TRUE])))
501 tx_new.rehash()
502 total_weight += tx_new.get_weight()
503 if total_weight >= MAX_BLOCK_WEIGHT:
504 break
505 b39.vtx.append(tx_new) # add tx to block
506 tx_last = tx_new
507 b39_outputs += 1
508
509 # The accounting in the loop above can be off, because it misses the
510 # compact size encoding of the number of transactions in the block.
511 # Make sure we didn't accidentally make too big a block. Note that the
512 # size of the block has non-determinism due to the ECDSA signature in
513 # the first transaction.
514 while b39.get_weight() >= MAX_BLOCK_WEIGHT:
515 del b39.vtx[-1]
516
517 b39 = self.update_block(39, [])
518 self.send_blocks([b39], True)
519 self.save_spendable_output()
520
521 # Test sigops in P2SH redeem scripts
522 #
523 # b40 creates 3333 tx's spending the 6-sigop P2SH outputs from b39 for a total of 19998 sigops.
524 # The first tx has one sigop and then at the end we add 2 more to put us just over the max.
525 #
526 # b41 does the same, less one, so it has the maximum sigops permitted.
527 #
528 self.log.info("Reject a block with too many P2SH sigops")
529 self.move_tip(39)
530 b40 = self.next_block(40, spend=out[12])
531 sigops = get_legacy_sigopcount_block(b40)
532 numTxes = (MAX_BLOCK_SIGOPS - sigops) // b39_sigops_per_output
533 assert_equal(numTxes <= b39_outputs, True)
534
535 lastOutpoint = COutPoint(b40.vtx[1].sha256, 0)
536 new_txs = []
537 for i in range(1, numTxes + 1):
538 tx = CTransaction()
539 tx.vout.append(CTxOut(1, CScript([OP_TRUE])))
540 tx.vin.append(CTxIn(lastOutpoint, b''))
541 # second input is corresponding P2SH output from b39
542 tx.vin.append(CTxIn(COutPoint(b39.vtx[i].sha256, 0), b''))
543 # Note: must pass the redeem_script (not p2sh_script) to the signature hash function
544 tx.vin[1].scriptSig = CScript([redeem_script])
545 sign_input_legacy(tx, 1, redeem_script, self.coinbase_key)
546 new_txs.append(tx)
547 lastOutpoint = COutPoint(tx.sha256, 0)
548
549 b40_sigops_to_fill = MAX_BLOCK_SIGOPS - (numTxes * b39_sigops_per_output + sigops) + 1
550 tx = CTransaction()
551 tx.vin.append(CTxIn(lastOutpoint, b''))
552 tx.vout.append(CTxOut(1, CScript([OP_CHECKSIG] * b40_sigops_to_fill)))
553 tx.rehash()
554 new_txs.append(tx)
555 self.update_block(40, new_txs)
556 self.send_blocks([b40], success=False, reject_reason='bad-blk-sigops', reconnect=True)
557
558 # same as b40, but one less sigop
559 self.log.info("Accept a block with the max number of P2SH sigops")
560 self.move_tip(39)
561 b41 = self.next_block(41, spend=None)
562 self.update_block(41, b40.vtx[1:-1])
563 b41_sigops_to_fill = b40_sigops_to_fill - 1
564 tx = CTransaction()
565 tx.vin.append(CTxIn(lastOutpoint, b''))
566 tx.vout.append(CTxOut(1, CScript([OP_CHECKSIG] * b41_sigops_to_fill)))
567 tx.rehash()
568 self.update_block(41, [tx])
569 self.send_blocks([b41], True)
570
571 # Fork off of b39 to create a constant base again
572 #
573 # b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13)
574 # \-> b41 (12)
575 #
576 self.move_tip(39)
577 b42 = self.next_block(42, spend=out[12])
578 self.save_spendable_output()
579
580 b43 = self.next_block(43, spend=out[13])
581 self.save_spendable_output()
582 self.send_blocks([b42, b43], True)
583
584 # Test a number of really invalid scenarios
585 #
586 # -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b44 (14)
587 # \-> ??? (15)
588
589 # The next few blocks are going to be created "by hand" since they'll do funky things, such as having
590 # the first transaction be non-coinbase, etc. The purpose of b44 is to make sure this works.
591 self.log.info("Build block 44 manually")
592 height = self.block_heights[self.tip.sha256] + 1
593 coinbase = create_coinbase(height, self.coinbase_pubkey)
594 b44 = CBlock()
595 b44.nTime = self.tip.nTime + 1
596 b44.hashPrevBlock = self.tip.sha256
597 b44.nBits = REGTEST_N_BITS
598 b44.vtx.append(coinbase)
599 tx = self.create_and_sign_transaction(out[14], 1)
600 b44.vtx.append(tx)
601 b44.hashMerkleRoot = b44.calc_merkle_root()
602 b44.solve()
603 self.tip = b44
604 self.block_heights[b44.sha256] = height
605 self.blocks[44] = b44
606 self.send_blocks([b44], True)
607
608 self.log.info("Reject a block with a non-coinbase as the first tx")
609 non_coinbase = self.create_tx(out[15], 0, 1)
610 b45 = CBlock()
611 b45.nTime = self.tip.nTime + 1
612 b45.hashPrevBlock = self.tip.sha256
613 b45.nBits = REGTEST_N_BITS
614 b45.vtx.append(non_coinbase)
615 b45.hashMerkleRoot = b45.calc_merkle_root()
616 b45.solve()
617 self.block_heights[b45.sha256] = self.block_heights[self.tip.sha256] + 1
618 self.tip = b45
619 self.blocks[45] = b45
620 self.send_blocks([b45], success=False, reject_reason='bad-cb-missing', reconnect=True)
621
622 self.log.info("Reject a block with no transactions")
623 self.move_tip(44)
624 b46 = CBlock()
625 b46.nTime = b44.nTime + 1
626 b46.hashPrevBlock = b44.sha256
627 b46.nBits = REGTEST_N_BITS
628 b46.vtx = []
629 b46.hashMerkleRoot = 0
630 b46.solve()
631 self.block_heights[b46.sha256] = self.block_heights[b44.sha256] + 1
632 self.tip = b46
633 assert 46 not in self.blocks
634 self.blocks[46] = b46
635 self.send_blocks([b46], success=False, reject_reason='bad-blk-length', reconnect=True)
636
637 self.log.info("Reject a block with invalid work")
638 self.move_tip(44)
639 b47 = self.next_block(47)
640 target = uint256_from_compact(b47.nBits)
641 while b47.sha256 <= target:
642 # Rehash nonces until an invalid too-high-hash block is found.
643 b47.nNonce += 1
644 b47.rehash()
645 self.send_blocks([b47], False, force_send=True, reject_reason='high-hash', reconnect=True)
646
647 self.log.info("Reject a block with a timestamp >2 hours in the future")
648 self.move_tip(44)
649 b48 = self.next_block(48)
650 b48.nTime = int(time.time()) + 60 * 60 * 3
651 # Header timestamp has changed. Re-solve the block.
652 b48.solve()
653 self.send_blocks([b48], False, force_send=True, reject_reason='time-too-new')
654
655 self.log.info("Reject a block with invalid merkle hash")
656 self.move_tip(44)
657 b49 = self.next_block(49)
658 b49.hashMerkleRoot += 1
659 b49.solve()
660 self.send_blocks([b49], success=False, reject_reason='bad-txnmrklroot', reconnect=True)
661
662 self.log.info("Reject a block with incorrect POW limit")
663 self.move_tip(44)
664 b50 = self.next_block(50)
665 b50.nBits = b50.nBits - 1
666 b50.solve()
667 self.send_blocks([b50], False, force_send=True, reject_reason='bad-diffbits', reconnect=True)
668
669 self.log.info("Reject a block with two coinbase transactions")
670 self.move_tip(44)
671 self.next_block(51)
672 cb2 = create_coinbase(51, self.coinbase_pubkey)
673 b51 = self.update_block(51, [cb2])
674 self.send_blocks([b51], success=False, reject_reason='bad-cb-multiple', reconnect=True)
675
676 self.log.info("Reject a block with duplicate transactions")
677 # Note: txns have to be in the right position in the merkle tree to trigger this error
678 self.move_tip(44)
679 b52 = self.next_block(52, spend=out[15])
680 tx = self.create_tx(b52.vtx[1], 0, 1)
681 b52 = self.update_block(52, [tx, tx])
682 self.send_blocks([b52], success=False, reject_reason='bad-txns-duplicate', reconnect=True)
683
684 # Test block timestamps
685 # -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15)
686 # \-> b54 (15)
687 # -> b44 (14)\-> b48 ()
688 self.move_tip(43)
689 b53 = self.next_block(53, spend=out[14])
690 self.send_blocks([b53], False)
691 self.save_spendable_output()
692
693 self.log.info("Reject a block with timestamp before MedianTimePast")
694 b54 = self.next_block(54, spend=out[15])
695 b54.nTime = b35.nTime - 1
696 b54.solve()
697 self.send_blocks([b54], False, force_send=True, reject_reason='time-too-old', reconnect=True)
698
699 # valid timestamp
700 self.move_tip(53)
701 b55 = self.next_block(55, spend=out[15])
702 b55.nTime = b35.nTime
703 self.update_block(55, [])
704 self.send_blocks([b55], True)
705 self.save_spendable_output()
706
707 # The block which was previously rejected because of being "too far(3 hours)" must be accepted 2 hours later.
708 # The new block is only 1 hour into future now and we must reorg onto to the new longer chain.
709 # The new bestblock b48p is invalidated manually.
710 # -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15)
711 # \-> b54 (15)
712 # -> b44 (14)\-> b48 () -> b48p ()
713 self.log.info("Accept a previously rejected future block at a later time")
714 node.setmocktime(int(time.time()) + 2*60*60)
715 self.move_tip(48)
716 self.block_heights[b48.sha256] = self.block_heights[b44.sha256] + 1 # b48 is a parent of b44
717 b48p = self.next_block("48p")
718 self.send_blocks([b48, b48p], success=True) # Reorg to the longer chain
719 node.invalidateblock(b48p.hash) # mark b48p as invalid
720 node.setmocktime(0)
721
722 # Test Merkle tree malleability
723 #
724 # -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57p2 (16)
725 # \-> b57 (16)
726 # \-> b56p2 (16)
727 # \-> b56 (16)
728 #
729 # Merkle tree malleability (CVE-2012-2459): repeating sequences of transactions in a block without
730 # affecting the merkle root of a block, while still invalidating it.
731 # See: src/consensus/merkle.h
732 #
733 # b57 has three txns: coinbase, tx, tx1. The merkle root computation will duplicate tx.
734 # Result: OK
735 #
736 # b56 copies b57 but duplicates tx1 and does not recalculate the block hash. So it has a valid merkle
737 # root but duplicate transactions.
738 # Result: Fails
739 #
740 # b57p2 has six transactions in its merkle tree:
741 # - coinbase, tx, tx1, tx2, tx3, tx4
742 # Merkle root calculation will duplicate as necessary.
743 # Result: OK.
744 #
745 # b56p2 copies b57p2 but adds both tx3 and tx4. The purpose of the test is to make sure the code catches
746 # duplicate txns that are not next to one another with the "bad-txns-duplicate" error (which indicates
747 # that the error was caught early, avoiding a DOS vulnerability.)
748
749 # b57 - a good block with 2 txs, don't submit until end
750 self.move_tip(55)
751 self.next_block(57)
752 tx = self.create_and_sign_transaction(out[16], 1)
753 tx1 = self.create_tx(tx, 0, 1)
754 b57 = self.update_block(57, [tx, tx1])
755
756 # b56 - copy b57, add a duplicate tx
757 self.log.info("Reject a block with a duplicate transaction in the Merkle Tree (but with a valid Merkle Root)")
758 self.move_tip(55)
759 b56 = copy.deepcopy(b57)
760 self.blocks[56] = b56
761 assert_equal(len(b56.vtx), 3)
762 b56 = self.update_block(56, [tx1])
763 assert_equal(b56.hash, b57.hash)
764 self.send_blocks([b56], success=False, reject_reason='bad-txns-duplicate', reconnect=True)
765
766 # b57p2 - a good block with 6 tx'es, don't submit until end
767 self.move_tip(55)
768 self.next_block("57p2")
769 tx = self.create_and_sign_transaction(out[16], 1)
770 tx1 = self.create_tx(tx, 0, 1)
771 tx2 = self.create_tx(tx1, 0, 1)
772 tx3 = self.create_tx(tx2, 0, 1)
773 tx4 = self.create_tx(tx3, 0, 1)
774 b57p2 = self.update_block("57p2", [tx, tx1, tx2, tx3, tx4])
775
776 # b56p2 - copy b57p2, duplicate two non-consecutive tx's
777 self.log.info("Reject a block with two duplicate transactions in the Merkle Tree (but with a valid Merkle Root)")
778 self.move_tip(55)
779 b56p2 = copy.deepcopy(b57p2)
780 self.blocks["b56p2"] = b56p2
781 assert_equal(b56p2.hash, b57p2.hash)
782 assert_equal(len(b56p2.vtx), 6)
783 b56p2 = self.update_block("b56p2", [tx3, tx4])
784 self.send_blocks([b56p2], success=False, reject_reason='bad-txns-duplicate', reconnect=True)
785
786 self.move_tip("57p2")
787 self.send_blocks([b57p2], True)
788
789 self.move_tip(57)
790 self.send_blocks([b57], False) # The tip is not updated because 57p2 seen first
791 self.save_spendable_output()
792
793 # Test a few invalid tx types
794 #
795 # -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 ()
796 # \-> ??? (17)
797 #
798
799 # tx with prevout.n out of range
800 self.log.info("Reject a block with a transaction with prevout.n out of range")
801 self.move_tip(57)
802 self.next_block(58, spend=out[17])
803 tx = CTransaction()
804 assert len(out[17].vout) < 42
805 tx.vin.append(CTxIn(COutPoint(out[17].sha256, 42), CScript([OP_TRUE]), SEQUENCE_FINAL))
806 tx.vout.append(CTxOut(0, b""))
807 tx.calc_sha256()
808 b58 = self.update_block(58, [tx])
809 self.send_blocks([b58], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
810
811 # tx with output value > input value
812 self.log.info("Reject a block with a transaction with outputs > inputs")
813 self.move_tip(57)
814 self.next_block(59)
815 tx = self.create_and_sign_transaction(out[17], 51 * COIN)
816 b59 = self.update_block(59, [tx])
817 self.send_blocks([b59], success=False, reject_reason='bad-txns-in-belowout', reconnect=True)
818
819 # reset to good chain
820 self.move_tip(57)
821 b60 = self.next_block(60)
822 self.send_blocks([b60], True)
823 self.save_spendable_output()
824
825 # Test BIP30 (reject duplicate)
826 #
827 # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 ()
828 # \-> b61 ()
829 #
830 # Blocks are not allowed to contain a transaction whose id matches that of an earlier,
831 # not-fully-spent transaction in the same chain. To test, make identical coinbases;
832 # the second one should be rejected. See also CVE-2012-1909.
833 #
834 self.log.info("Reject a block with a transaction with a duplicate hash of a previous transaction (BIP30)")
835 self.move_tip(60)
836 b61 = self.next_block(61)
837 b61.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG
838 b61.vtx[0].rehash()
839 b61 = self.update_block(61, [])
840 assert_equal(duplicate_tx.serialize(), b61.vtx[0].serialize())
841 # BIP30 is always checked on regtest, regardless of the BIP34 activation height
842 self.send_blocks([b61], success=False, reject_reason='bad-txns-BIP30', reconnect=True)
843
844 # Test BIP30 (allow duplicate if spent)
845 #
846 # -> b57 (16) -> b60 ()
847 # \-> b_spend_dup_cb (b_dup_cb) -> b_dup_2 ()
848 #
849 self.move_tip(57)
850 self.next_block('spend_dup_cb')
851 tx = CTransaction()
852 tx.vin.append(CTxIn(COutPoint(duplicate_tx.sha256, 0)))
853 tx.vout.append(CTxOut(0, CScript([OP_TRUE])))
854 self.sign_tx(tx, duplicate_tx)
855 tx.rehash()
856 b_spend_dup_cb = self.update_block('spend_dup_cb', [tx])
857
858 b_dup_2 = self.next_block('dup_2')
859 b_dup_2.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG
860 b_dup_2.vtx[0].rehash()
861 b_dup_2 = self.update_block('dup_2', [])
862 assert_equal(duplicate_tx.serialize(), b_dup_2.vtx[0].serialize())
863 assert_equal(self.nodes[0].gettxout(txid=duplicate_tx.hash, n=0)['confirmations'], 119)
864 self.send_blocks([b_spend_dup_cb, b_dup_2], success=True)
865 # The duplicate has less confirmations
866 assert_equal(self.nodes[0].gettxout(txid=duplicate_tx.hash, n=0)['confirmations'], 1)
867
868 # Test tx.isFinal is properly rejected (not an exhaustive tx.isFinal test, that should be in data-driven transaction tests)
869 #
870 # -> b_spend_dup_cb (b_dup_cb) -> b_dup_2 ()
871 # \-> b62 (18)
872 #
873 self.log.info("Reject a block with a transaction with a nonfinal locktime")
874 self.move_tip('dup_2')
875 self.next_block(62)
876 tx = CTransaction()
877 tx.nLockTime = 0xffffffff # this locktime is non-final
878 tx.vin.append(CTxIn(COutPoint(out[18].sha256, 0))) # don't set nSequence
879 tx.vout.append(CTxOut(0, CScript([OP_TRUE])))
880 assert_greater_than(SEQUENCE_FINAL, tx.vin[0].nSequence)
881 tx.calc_sha256()
882 b62 = self.update_block(62, [tx])
883 self.send_blocks([b62], success=False, reject_reason='bad-txns-nonfinal', reconnect=True)
884
885 # Test a non-final coinbase is also rejected
886 #
887 # -> b_spend_dup_cb (b_dup_cb) -> b_dup_2 ()
888 # \-> b63 (-)
889 #
890 self.log.info("Reject a block with a coinbase transaction with a nonfinal locktime")
891 self.move_tip('dup_2')
892 b63 = self.next_block(63)
893 b63.vtx[0].nLockTime = 0xffffffff
894 b63.vtx[0].vin[0].nSequence = 0xDEADBEEF
895 b63.vtx[0].rehash()
896 b63 = self.update_block(63, [])
897 self.send_blocks([b63], success=False, reject_reason='bad-txns-nonfinal', reconnect=True)
898
899 # This checks that a block with a bloated VARINT between the block_header and the array of tx such that
900 # the block is > MAX_BLOCK_WEIGHT with the bloated varint, but <= MAX_BLOCK_WEIGHT without the bloated varint,
901 # does not cause a subsequent, identical block with canonical encoding to be rejected. The test does not
902 # care whether the bloated block is accepted or rejected; it only cares that the second block is accepted.
903 #
904 # What matters is that the receiving node should not reject the bloated block, and then reject the canonical
905 # block on the basis that it's the same as an already-rejected block (which would be a consensus failure.)
906 #
907 # -> b_spend_dup_cb (b_dup_cb) -> b_dup_2 () -> b64 (18)
908 # \
909 # b64a (18)
910 # b64a is a bloated block (non-canonical varint)
911 # b64 is a good block (same as b64 but w/ canonical varint)
912 #
913 self.log.info("Accept a valid block even if a bloated version of the block has previously been sent")
914 self.move_tip('dup_2')
915 regular_block = self.next_block("64a", spend=out[18])
916
917 # make it a "broken_block," with non-canonical serialization
918 b64a = CBrokenBlock(regular_block)
919 b64a.initialize(regular_block)
920 self.blocks["64a"] = b64a
921 self.tip = b64a
922 tx = CTransaction()
923
924 # use canonical serialization to calculate size
925 script_length = (MAX_BLOCK_WEIGHT - 4 * len(b64a.normal_serialize()) - 276) // 4
926 script_output = CScript([b'\x00' * script_length])
927 tx.vout.append(CTxOut(0, script_output))
928 tx.vin.append(CTxIn(COutPoint(b64a.vtx[1].sha256, 0)))
929 b64a = self.update_block("64a", [tx])
930 assert_equal(b64a.get_weight(), MAX_BLOCK_WEIGHT + 8 * 4)
931 self.send_blocks([b64a], success=False, reject_reason='non-canonical ReadCompactSize()')
932
933 # limenkad doesn't disconnect us for sending a bloated block, but if we subsequently
934 # resend the header message, it won't send us the getdata message again. Just
935 # disconnect and reconnect and then call sync_blocks.
936 # TODO: improve this test to be less dependent on P2P DOS behaviour.
937 node.disconnect_p2ps()
938 self.reconnect_p2p()
939
940 self.move_tip('dup_2')
941 b64 = CBlock(b64a)
942 b64.vtx = copy.deepcopy(b64a.vtx)
943 assert_equal(b64.hash, b64a.hash)
944 assert_equal(b64.get_weight(), MAX_BLOCK_WEIGHT)
945 self.blocks[64] = b64
946 b64 = self.update_block(64, [])
947 self.send_blocks([b64], True)
948 self.save_spendable_output()
949
950 # Spend an output created in the block itself
951 #
952 # -> b_dup_2 () -> b64 (18) -> b65 (19)
953 #
954 self.log.info("Accept a block with a transaction spending an output created in the same block")
955 self.move_tip(64)
956 self.next_block(65)
957 tx1 = self.create_and_sign_transaction(out[19], out[19].vout[0].nValue)
958 tx2 = self.create_and_sign_transaction(tx1, 0)
959 b65 = self.update_block(65, [tx1, tx2])
960 self.send_blocks([b65], True)
961 self.save_spendable_output()
962
963 # Attempt to spend an output created later in the same block
964 #
965 # -> b64 (18) -> b65 (19)
966 # \-> b66 (20)
967 self.log.info("Reject a block with a transaction spending an output created later in the same block")
968 self.move_tip(65)
969 self.next_block(66)
970 tx1 = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue)
971 tx2 = self.create_and_sign_transaction(tx1, 1)
972 b66 = self.update_block(66, [tx2, tx1])
973 self.send_blocks([b66], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
974
975 # Attempt to double-spend a transaction created in a block
976 #
977 # -> b64 (18) -> b65 (19)
978 # \-> b67 (20)
979 #
980 #
981 self.log.info("Reject a block with a transaction double spending a transaction created in the same block")
982 self.move_tip(65)
983 self.next_block(67)
984 tx1 = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue)
985 tx2 = self.create_and_sign_transaction(tx1, 1)
986 tx3 = self.create_and_sign_transaction(tx1, 2)
987 b67 = self.update_block(67, [tx1, tx2, tx3])
988 self.send_blocks([b67], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
989
990 # More tests of block subsidy
991 #
992 # -> b64 (18) -> b65 (19) -> b69 (20)
993 # \-> b68 (20)
994 #
995 # b68 - coinbase with an extra 10 satoshis,
996 # creates a tx that has 9 satoshis from out[20] go to fees
997 # this fails because the coinbase is trying to claim 1 satoshi too much in fees
998 #
999 # b69 - coinbase with extra 10 satoshis, and a tx that gives a 10 satoshi fee
1000 # this succeeds
1001 #
1002 self.log.info("Reject a block trying to claim too much subsidy in the coinbase transaction")
1003 self.move_tip(65)
1004 self.next_block(68, additional_coinbase_value=10)
1005 tx = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue - 9)
1006 b68 = self.update_block(68, [tx])
1007 self.send_blocks([b68], success=False, reject_reason='bad-cb-amount', reconnect=True)
1008
1009 self.log.info("Accept a block claiming the correct subsidy in the coinbase transaction")
1010 self.move_tip(65)
1011 b69 = self.next_block(69, additional_coinbase_value=10)
1012 tx = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue - 10)
1013 self.update_block(69, [tx])
1014 self.send_blocks([b69], True)
1015 self.save_spendable_output()
1016
1017 # Test spending the outpoint of a non-existent transaction
1018 #
1019 # -> b65 (19) -> b69 (20)
1020 # \-> b70 (21)
1021 #
1022 self.log.info("Reject a block containing a transaction spending from a non-existent input")
1023 self.move_tip(69)
1024 self.next_block(70, spend=out[21])
1025 bogus_tx = CTransaction()
1026 bogus_tx.sha256 = uint256_from_str(b"23c70ed7c0506e9178fc1a987f40a33946d4ad4c962b5ae3a52546da53af0c5c")
1027 tx = CTransaction()
1028 tx.vin.append(CTxIn(COutPoint(bogus_tx.sha256, 0), b"", SEQUENCE_FINAL))
1029 tx.vout.append(CTxOut(1, b""))
1030 b70 = self.update_block(70, [tx])
1031 self.send_blocks([b70], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
1032
1033 # Test accepting an invalid block which has the same hash as a valid one (via merkle tree tricks)
1034 #
1035 # -> b65 (19) -> b69 (20) -> b72 (21)
1036 # \-> b71 (21)
1037 #
1038 # b72 is a good block.
1039 # b71 is a copy of 72, but re-adds one of its transactions. However, it has the same hash as b72.
1040 self.log.info("Reject a block containing a duplicate transaction but with the same Merkle root (Merkle tree malleability")
1041 self.move_tip(69)
1042 self.next_block(72)
1043 tx1 = self.create_and_sign_transaction(out[21], 2)
1044 tx2 = self.create_and_sign_transaction(tx1, 1)
1045 b72 = self.update_block(72, [tx1, tx2]) # now tip is 72
1046 b71 = copy.deepcopy(b72)
1047 b71.vtx.append(tx2) # add duplicate tx2
1048 self.block_heights[b71.sha256] = self.block_heights[b69.sha256] + 1 # b71 builds off b69
1049 self.blocks[71] = b71
1050
1051 assert_equal(len(b71.vtx), 4)
1052 assert_equal(len(b72.vtx), 3)
1053 assert_equal(b72.sha256, b71.sha256)
1054
1055 self.move_tip(71)
1056 self.send_blocks([b71], success=False, reject_reason='bad-txns-duplicate', reconnect=True)
1057
1058 self.move_tip(72)
1059 self.send_blocks([b72], True)
1060 self.save_spendable_output()
1061
1062 # Test some invalid scripts and MAX_BLOCK_SIGOPS
1063 #
1064 # -> b69 (20) -> b72 (21)
1065 # \-> b** (22)
1066 #
1067
1068 # b73 - tx with excessive sigops that are placed after an excessively large script element.
1069 # The purpose of the test is to make sure those sigops are counted.
1070 #
1071 # script is a bytearray of size 20,526
1072 #
1073 # bytearray[0-19,998] : OP_CHECKSIG
1074 # bytearray[19,999] : OP_PUSHDATA4
1075 # bytearray[20,000-20,003]: 521 (max_script_element_size+1, in little-endian format)
1076 # bytearray[20,004-20,525]: unread data (script_element)
1077 # bytearray[20,526] : OP_CHECKSIG (this puts us over the limit)
1078 self.log.info("Reject a block containing too many sigops after a large script element")
1079 self.move_tip(72)
1080 self.next_block(73)
1081 size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 1 + 5 + 1
1082 a = bytearray([OP_CHECKSIG] * size)
1083 a[MAX_BLOCK_SIGOPS - 1] = int("4e", 16) # OP_PUSHDATA4
1084
1085 element_size = MAX_SCRIPT_ELEMENT_SIZE + 1
1086 a[MAX_BLOCK_SIGOPS] = element_size % 256
1087 a[MAX_BLOCK_SIGOPS + 1] = element_size // 256
1088 a[MAX_BLOCK_SIGOPS + 2] = 0
1089 a[MAX_BLOCK_SIGOPS + 3] = 0
1090
1091 tx = self.create_and_sign_transaction(out[22], 1, CScript(a))
1092 b73 = self.update_block(73, [tx])
1093 assert_equal(get_legacy_sigopcount_block(b73), MAX_BLOCK_SIGOPS + 1)
1094 self.send_blocks([b73], success=False, reject_reason='bad-blk-sigops', reconnect=True)
1095
1096 # b74/75 - if we push an invalid script element, all previous sigops are counted,
1097 # but sigops after the element are not counted.
1098 #
1099 # The invalid script element is that the push_data indicates that
1100 # there will be a large amount of data (0xffffff bytes), but we only
1101 # provide a much smaller number. These bytes are CHECKSIGS so they would
1102 # cause b75 to fail for excessive sigops, if those bytes were counted.
1103 #
1104 # b74 fails because we put MAX_BLOCK_SIGOPS+1 before the element
1105 # b75 succeeds because we put MAX_BLOCK_SIGOPS before the element
1106 self.log.info("Check sigops are counted correctly after an invalid script element")
1107 self.move_tip(72)
1108 self.next_block(74)
1109 size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 42 # total = 20,561
1110 a = bytearray([OP_CHECKSIG] * size)
1111 a[MAX_BLOCK_SIGOPS] = 0x4e
1112 a[MAX_BLOCK_SIGOPS + 1] = 0xfe
1113 a[MAX_BLOCK_SIGOPS + 2] = 0xff
1114 a[MAX_BLOCK_SIGOPS + 3] = 0xff
1115 a[MAX_BLOCK_SIGOPS + 4] = 0xff
1116 tx = self.create_and_sign_transaction(out[22], 1, CScript(a))
1117 b74 = self.update_block(74, [tx])
1118 self.send_blocks([b74], success=False, reject_reason='bad-blk-sigops', reconnect=True)
1119
1120 self.move_tip(72)
1121 self.next_block(75)
1122 size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 42
1123 a = bytearray([OP_CHECKSIG] * size)
1124 a[MAX_BLOCK_SIGOPS - 1] = 0x4e
1125 a[MAX_BLOCK_SIGOPS] = 0xff
1126 a[MAX_BLOCK_SIGOPS + 1] = 0xff
1127 a[MAX_BLOCK_SIGOPS + 2] = 0xff
1128 a[MAX_BLOCK_SIGOPS + 3] = 0xff
1129 tx = self.create_and_sign_transaction(out[22], 1, CScript(a))
1130 b75 = self.update_block(75, [tx])
1131 self.send_blocks([b75], True)
1132 self.save_spendable_output()
1133
1134 # Check that if we push an element filled with CHECKSIGs, they are not counted
1135 self.move_tip(75)
1136 self.next_block(76)
1137 size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 1 + 5
1138 a = bytearray([OP_CHECKSIG] * size)
1139 a[MAX_BLOCK_SIGOPS - 1] = 0x4e # PUSHDATA4, but leave the following bytes as just checksigs
1140 tx = self.create_and_sign_transaction(out[23], 1, CScript(a))
1141 b76 = self.update_block(76, [tx])
1142 self.send_blocks([b76], True)
1143 self.save_spendable_output()
1144
1145 # Test transaction resurrection
1146 #
1147 # -> b77 (24) -> b78 (25) -> b79 (26)
1148 # \-> b80 (25) -> b81 (26) -> b82 (27)
1149 #
1150 # b78 creates a tx, which is spent in b79. After b82, both should be in mempool
1151 #
1152 # The tx'es must be unsigned and pass the node's mempool policy. It is unsigned for the
1153 # rather obscure reason that the Python signature code does not distinguish between
1154 # Low-S and High-S values (whereas the limenka code has custom code which does so);
1155 # as a result of which, the odds are 50% that the python code will use the right
1156 # value and the transaction will be accepted into the mempool. Until we modify the
1157 # test framework to support low-S signing, we are out of luck.
1158 #
1159 # To get around this issue, we construct transactions which are not signed and which
1160 # spend to OP_TRUE. If the standard-ness rules change, this test would need to be
1161 # updated. (Perhaps to spend to a P2SH OP_TRUE script)
1162 self.log.info("Test transaction resurrection during a re-org")
1163 self.move_tip(76)
1164 self.next_block(77)
1165 tx77 = self.create_and_sign_transaction(out[24], 10 * COIN)
1166 b77 = self.update_block(77, [tx77])
1167 self.send_blocks([b77], True)
1168 self.save_spendable_output()
1169
1170 self.next_block(78)
1171 tx78 = self.create_tx(tx77, 0, 9 * COIN)
1172 b78 = self.update_block(78, [tx78])
1173 self.send_blocks([b78], True)
1174
1175 self.next_block(79)
1176 tx79 = self.create_tx(tx78, 0, 8 * COIN)
1177 b79 = self.update_block(79, [tx79])
1178 self.send_blocks([b79], True)
1179
1180 # mempool should be empty
1181 assert_equal(len(self.nodes[0].getrawmempool()), 0)
1182
1183 self.move_tip(77)
1184 b80 = self.next_block(80, spend=out[25])
1185 self.send_blocks([b80], False, force_send=True)
1186 self.save_spendable_output()
1187
1188 b81 = self.next_block(81, spend=out[26])
1189 self.send_blocks([b81], False, force_send=True) # other chain is same length
1190 self.save_spendable_output()
1191
1192 b82 = self.next_block(82, spend=out[27])
1193 self.send_blocks([b82], True) # now this chain is longer, triggers re-org
1194 self.save_spendable_output()
1195
1196 # now check that tx78 and tx79 have been put back into the peer's mempool
1197 mempool = self.nodes[0].getrawmempool()
1198 assert_equal(len(mempool), 2)
1199 assert tx78.hash in mempool
1200 assert tx79.hash in mempool
1201
1202 # Test invalid opcodes in dead execution paths.
1203 #
1204 # -> b81 (26) -> b82 (27) -> b83 (28)
1205 #
1206 self.log.info("Accept a block with invalid opcodes in dead execution paths")
1207 self.next_block(83)
1208 op_codes = [OP_IF, OP_INVALIDOPCODE, OP_ELSE, OP_TRUE, OP_ENDIF]
1209 script = CScript(op_codes)
1210 tx1 = self.create_and_sign_transaction(out[28], out[28].vout[0].nValue, script)
1211
1212 tx2 = self.create_and_sign_transaction(tx1, 0, CScript([OP_TRUE]))
1213 tx2.vin[0].scriptSig = CScript([OP_FALSE])
1214 tx2.rehash()
1215
1216 b83 = self.update_block(83, [tx1, tx2])
1217 self.send_blocks([b83], True)
1218 self.save_spendable_output()
1219
1220 # Reorg on/off blocks that have OP_RETURN in them (and try to spend them)
1221 #
1222 # -> b81 (26) -> b82 (27) -> b83 (28) -> b84 (29) -> b87 (30) -> b88 (31)
1223 # \-> b85 (29) -> b86 (30) \-> b89a (32)
1224 #
1225 self.log.info("Test re-orging blocks with OP_RETURN in them")
1226 self.next_block(84)
1227 tx1 = self.create_tx(out[29], 0, 0, CScript([OP_RETURN]))
1228 tx1.vout.append(CTxOut(0, CScript([OP_TRUE])))
1229 tx1.vout.append(CTxOut(0, CScript([OP_TRUE])))
1230 tx1.vout.append(CTxOut(0, CScript([OP_TRUE])))
1231 tx1.vout.append(CTxOut(0, CScript([OP_TRUE])))
1232 tx1.calc_sha256()
1233 self.sign_tx(tx1, out[29])
1234 tx1.rehash()
1235 tx2 = self.create_tx(tx1, 1, 0, CScript([OP_RETURN]))
1236 tx2.vout.append(CTxOut(0, CScript([OP_RETURN])))
1237 tx3 = self.create_tx(tx1, 2, 0, CScript([OP_RETURN]))
1238 tx3.vout.append(CTxOut(0, CScript([OP_TRUE])))
1239 tx4 = self.create_tx(tx1, 3, 0, CScript([OP_TRUE]))
1240 tx4.vout.append(CTxOut(0, CScript([OP_RETURN])))
1241 tx5 = self.create_tx(tx1, 4, 0, CScript([OP_RETURN]))
1242
1243 b84 = self.update_block(84, [tx1, tx2, tx3, tx4, tx5])
1244 self.send_blocks([b84], True)
1245 self.save_spendable_output()
1246
1247 self.move_tip(83)
1248 b85 = self.next_block(85, spend=out[29])
1249 self.send_blocks([b85], False) # other chain is same length
1250
1251 b86 = self.next_block(86, spend=out[30])
1252 self.send_blocks([b86], True)
1253
1254 self.move_tip(84)
1255 b87 = self.next_block(87, spend=out[30])
1256 self.send_blocks([b87], False) # other chain is same length
1257 self.save_spendable_output()
1258
1259 b88 = self.next_block(88, spend=out[31])
1260 self.send_blocks([b88], True)
1261 self.save_spendable_output()
1262
1263 # trying to spend the OP_RETURN output is rejected
1264 self.next_block("89a", spend=out[32])
1265 tx = self.create_tx(tx1, 0, 0, CScript([OP_TRUE]))
1266 b89a = self.update_block("89a", [tx])
1267 self.send_blocks([b89a], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
1268
1269 # Don't use v2transport for the large reorg, which is too slow with the unoptimized python ChaCha20 implementation
1270 if self.options.v2transport:
1271 self.nodes[0].disconnect_p2ps()
1272 self.helper_peer = self.nodes[0].add_outbound_p2p_connection(P2PDataStore(), supports_v2_p2p=False, advertise_v2_p2p=False, p2p_idx=0)
1273 self.log.info("Test a re-org of one week's worth of blocks (1088 blocks)")
1274
1275 self.move_tip(88)
1276 LARGE_REORG_SIZE = 1088
1277 blocks = []
1278 spend = out[32]
1279 for i in range(89, LARGE_REORG_SIZE + 89):
1280 b = self.next_block(i, spend)
1281 tx = CTransaction()
1282 script_length = (MAX_BLOCK_WEIGHT - b.get_weight() - 276) // 4
1283 script_output = CScript([b'\x00' * script_length])
1284 tx.vout.append(CTxOut(0, script_output))
1285 tx.vin.append(CTxIn(COutPoint(b.vtx[1].sha256, 0)))
1286 b = self.update_block(i, [tx])
1287 assert_equal(b.get_weight(), MAX_BLOCK_WEIGHT)
1288 blocks.append(b)
1289 self.save_spendable_output()
1290 spend = self.get_spendable_output()
1291
1292 self.send_blocks(blocks, True, timeout=2440)
1293 chain1_tip = i
1294
1295 # now create alt chain of same length
1296 self.move_tip(88)
1297 blocks2 = []
1298 for i in range(89, LARGE_REORG_SIZE + 89):
1299 blocks2.append(self.next_block("alt" + str(i)))
1300 self.send_blocks(blocks2, False, force_send=False)
1301
1302 # extend alt chain to trigger re-org
1303 block = self.next_block("alt" + str(chain1_tip + 1))
1304 self.send_blocks([block], True, timeout=2440)
1305
1306 # ... and re-org back to the first chain
1307 self.move_tip(chain1_tip)
1308 block = self.next_block(chain1_tip + 1)
1309 self.send_blocks([block], False, force_send=True)
1310 block = self.next_block(chain1_tip + 2)
1311 self.send_blocks([block], True, timeout=2440)
1312
1313 self.log.info("Reject a block with an invalid block header version")
1314 b_v1 = self.next_block('b_v1', version=1)
1315 self.send_blocks([b_v1], success=False, force_send=True, reject_reason='bad-version(0x00000001)', reconnect=True)
1316
1317 self.move_tip(chain1_tip + 2)
1318 b_cb34 = self.next_block('b_cb34')
1319 b_cb34.vtx[0].vin[0].scriptSig = b_cb34.vtx[0].vin[0].scriptSig[:-1]
1320 b_cb34.vtx[0].rehash()
1321 b_cb34.hashMerkleRoot = b_cb34.calc_merkle_root()
1322 b_cb34.solve()
1323 self.send_blocks([b_cb34], success=False, reject_reason='bad-cb-height', reconnect=True)
1324
1325 # Helper methods
1326 ################
1327
1328 def add_transactions_to_block(self, block, tx_list):
1329 [tx.rehash() for tx in tx_list]
1330 block.vtx.extend(tx_list)
1331
1332 # this is a little handier to use than the version in blocktools.py
1333 def create_tx(self, spend_tx, n, value, output_script=None):
1334 if output_script is None:
1335 output_script = CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])
1336 return create_tx_with_script(spend_tx, n, amount=value, output_script=output_script)
1337
1338 # sign a transaction, using the key we know about
1339 # this signs input 0 in tx, which is assumed to be spending output 0 in spend_tx
1340 def sign_tx(self, tx, spend_tx):
1341 scriptPubKey = bytearray(spend_tx.vout[0].scriptPubKey)
1342 if (scriptPubKey[0] == OP_TRUE): # an anyone-can-spend
1343 tx.vin[0].scriptSig = CScript()
1344 return
1345 sign_input_legacy(tx, 0, spend_tx.vout[0].scriptPubKey, self.coinbase_key)
1346
1347 def create_and_sign_transaction(self, spend_tx, value, output_script=None):
1348 if output_script is None:
1349 output_script = CScript([OP_TRUE])
1350 tx = self.create_tx(spend_tx, 0, value, output_script=output_script)
1351 self.sign_tx(tx, spend_tx)
1352 tx.rehash()
1353 return tx
1354
1355 def next_block(self, number, spend=None, additional_coinbase_value=0, *, script=None, version=4):
1356 if script is None:
1357 script = CScript([OP_TRUE])
1358 if self.tip is None:
1359 base_block_hash = self.genesis_hash
1360 block_time = int(time.time()) + 1
1361 else:
1362 base_block_hash = self.tip.sha256
1363 block_time = self.tip.nTime + 1
1364 # First create the coinbase
1365 height = self.block_heights[base_block_hash] + 1
1366 coinbase = create_coinbase(height, self.coinbase_pubkey)
1367 coinbase.vout[0].nValue += additional_coinbase_value
1368 coinbase.rehash()
1369 if spend is None:
1370 block = create_block(base_block_hash, coinbase, block_time, version=version)
1371 else:
1372 coinbase.vout[0].nValue += spend.vout[0].nValue - 1 # all but one satoshi to fees
1373 coinbase.rehash()
1374 tx = self.create_tx(spend, 0, 1, output_script=script) # spend 1 satoshi
1375 self.sign_tx(tx, spend)
1376 tx.rehash()
1377 block = create_block(base_block_hash, coinbase, block_time, version=version, txlist=[tx])
1378 # Block is created. Find a valid nonce.
1379 block.solve()
1380 self.tip = block
1381 self.block_heights[block.sha256] = height
1382 assert number not in self.blocks
1383 self.blocks[number] = block
1384 return block
1385
1386 # save the current tip so it can be spent by a later block
1387 def save_spendable_output(self):
1388 self.log.debug(f"saving spendable output {self.tip.vtx[0]}")
1389 self.spendable_outputs.append(self.tip)
1390
1391 # get an output that we previously marked as spendable
1392 def get_spendable_output(self):
1393 self.log.debug(f"getting spendable output {self.spendable_outputs[0].vtx[0]}")
1394 return self.spendable_outputs.pop(0).vtx[0]
1395
1396 # move the tip back to a previous block
1397 def move_tip(self, number):
1398 self.tip = self.blocks[number]
1399
1400 # adds transactions to the block and updates state
1401 def update_block(self, block_number, new_transactions):
1402 block = self.blocks[block_number]
1403 self.add_transactions_to_block(block, new_transactions)
1404 old_sha256 = block.sha256
1405 block.hashMerkleRoot = block.calc_merkle_root()
1406 block.solve()
1407 # Update the internal state just like in next_block
1408 self.tip = block
1409 if block.sha256 != old_sha256:
1410 self.block_heights[block.sha256] = self.block_heights[old_sha256]
1411 del self.block_heights[old_sha256]
1412 self.blocks[block_number] = block
1413 return block
1414
1415 def bootstrap_p2p(self, timeout=10):
1416 """Add a P2P connection to the node.
1417
1418 Helper to connect and wait for version handshake."""
1419 self.helper_peer = self.nodes[0].add_outbound_p2p_connection(P2PDataStore(), p2p_idx=0)
1420 # We need to wait for the initial getheaders from the peer before we
1421 # start populating our blockstore. If we don't, then we may run ahead
1422 # to the next subtest before we receive the getheaders. We'd then send
1423 # an INV for the next block and receive two getheaders - one for the
1424 # IBD and one for the INV. We'd respond to both and could get
1425 # unexpectedly disconnected if the DoS score for that error is 50.
1426 self.helper_peer.wait_for_getheaders(timeout=timeout)
1427
1428 def reconnect_p2p(self, timeout=60):
1429 """Tear down and bootstrap the P2P connection to the node.
1430
1431 The node gets disconnected several times in this test. This helper
1432 method reconnects the p2p and restarts the network thread."""
1433 self.nodes[0].disconnect_p2ps()
1434 self.bootstrap_p2p(timeout=timeout)
1435
1436 def send_blocks(self, blocks, success=True, reject_reason=None, force_send=False, reconnect=False, timeout=960):
1437 """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
1438
1439 Call with success = False if the tip shouldn't advance to the most recent block."""
1440 self.helper_peer.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason, force_send=force_send, timeout=timeout, expect_disconnect=reconnect)
1441
1442 if reconnect:
1443 self.reconnect_p2p(timeout=timeout)
1444
1445
1446 if __name__ == '__main__':
1447 FullBlockTest(__file__).main()
1448