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 CSV soft fork activation.
6 7 This soft fork will activate the following BIPS:
8 BIP 68 - nSequence relative lock times
9 BIP 112 - CHECKSEQUENCEVERIFY
10 BIP 113 - MedianTimePast semantics for nLockTime
11 12 mine 83 blocks whose coinbases will be used to generate inputs for our tests
13 mine 344 blocks and seed block chain with the 83 inputs used for our tests at height 427
14 mine 2 blocks and verify soft fork not yet activated
15 mine 1 block and test that soft fork is activated (rules enforced for next block)
16 Test BIP 113 is enforced
17 Mine 4 blocks so next height is 580 and test BIP 68 is enforced for time and height
18 Mine 1 block so next height is 581 and test BIP 68 now passes time but not height
19 Mine 1 block so next height is 582 and test BIP 68 now passes time and height
20 Test that BIP 112 is enforced
21 22 Various transactions will be used to test that the BIPs rules are not enforced before the soft fork activates
23 And that after the soft fork activates transactions pass and fail as they should according to the rules.
24 For each BIP, transactions of versions 1 and 2 will be tested.
25 ----------------
26 BIP 113:
27 bip113tx - modify the nLocktime variable
28 29 BIP 68:
30 bip68txs - 16 txs with nSequence relative locktime of 10 with various bits set as per the relative_locktimes below
31 32 BIP 112:
33 bip112txs_vary_nSequence - 16 txs with nSequence relative_locktimes of 10 evaluated against 10 OP_CSV OP_DROP
34 bip112txs_vary_nSequence_9 - 16 txs with nSequence relative_locktimes of 9 evaluated against 10 OP_CSV OP_DROP
35 bip112txs_vary_OP_CSV - 16 txs with nSequence = 10 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
36 bip112txs_vary_OP_CSV_9 - 16 txs with nSequence = 9 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
37 bip112tx_special - test negative argument to OP_CSV
38 bip112tx_emptystack - test empty stack (= no argument) OP_CSV
39 """
40 from itertools import product
41 import time
42 43 from test_framework.blocktools import (
44 create_block,
45 create_coinbase,
46 )
47 from test_framework.p2p import P2PDataStore
48 from test_framework.script import (
49 CScript,
50 OP_CHECKSEQUENCEVERIFY,
51 OP_DROP,
52 )
53 from test_framework.test_framework import LimenkaTestFramework
54 from test_framework.util import (
55 assert_equal,
56 softfork_active,
57 )
58 from test_framework.wallet import (
59 MiniWallet,
60 MiniWalletMode,
61 )
62 63 TESTING_TX_COUNT = 83 # Number of testing transactions: 1 BIP113 tx, 16 BIP68 txs, 66 BIP112 txs (see comments above)
64 COINBASE_BLOCK_COUNT = TESTING_TX_COUNT # Number of coinbase blocks we need to generate as inputs for our txs
65 BASE_RELATIVE_LOCKTIME = 10
66 SEQ_DISABLE_FLAG = 1 << 31
67 SEQ_RANDOM_HIGH_BIT = 1 << 25
68 SEQ_TYPE_FLAG = 1 << 22
69 SEQ_RANDOM_LOW_BIT = 1 << 18
70 71 72 def relative_locktime(sdf, srhb, stf, srlb):
73 """Returns a locktime with certain bits set."""
74 75 locktime = BASE_RELATIVE_LOCKTIME
76 if sdf:
77 locktime |= SEQ_DISABLE_FLAG
78 if srhb:
79 locktime |= SEQ_RANDOM_HIGH_BIT
80 if stf:
81 locktime |= SEQ_TYPE_FLAG
82 if srlb:
83 locktime |= SEQ_RANDOM_LOW_BIT
84 return locktime
85 86 87 def all_rlt_txs(txs):
88 return [tx['tx'] for tx in txs]
89 90 91 CSV_ACTIVATION_HEIGHT = 432
92 93 94 class BIP68_112_113Test(LimenkaTestFramework):
95 def set_test_params(self):
96 self.num_nodes = 1
97 self.setup_clean_chain = True
98 # whitelist peers to speed up tx relay / mempool sync
99 self.noban_tx_relay = True
100 self.extra_args = [[
101 f'-testactivationheight=csv@{CSV_ACTIVATION_HEIGHT}',
102 ]]
103 self.supports_cli = False
104 105 def create_self_transfer_from_utxo(self, input_tx):
106 utxo = self.miniwallet.get_utxo(txid=input_tx.rehash(), mark_as_spent=False)
107 tx = self.miniwallet.create_self_transfer(utxo_to_spend=utxo)['tx']
108 return tx
109 110 def create_bip112special(self, input, txversion):
111 tx = self.create_self_transfer_from_utxo(input)
112 tx.version = txversion
113 self.miniwallet.sign_tx(tx)
114 tx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
115 tx.rehash()
116 return tx
117 118 def create_bip112emptystack(self, input, txversion):
119 tx = self.create_self_transfer_from_utxo(input)
120 tx.version = txversion
121 self.miniwallet.sign_tx(tx)
122 tx.vin[0].scriptSig = CScript([OP_CHECKSEQUENCEVERIFY] + list(CScript(tx.vin[0].scriptSig)))
123 tx.rehash()
124 return tx
125 126 def send_generic_input_tx(self, coinbases):
127 input_txid = self.nodes[0].getblock(coinbases.pop(), 2)['tx'][0]['txid']
128 utxo_to_spend = self.miniwallet.get_utxo(txid=input_txid)
129 return self.miniwallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_to_spend)['tx']
130 131 def create_bip68txs(self, bip68inputs, txversion, locktime_delta=0):
132 """Returns a list of bip68 transactions with different bits set."""
133 txs = []
134 assert len(bip68inputs) >= 16
135 for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
136 locktime = relative_locktime(sdf, srhb, stf, srlb)
137 tx = self.create_self_transfer_from_utxo(bip68inputs[i])
138 tx.version = txversion
139 tx.vin[0].nSequence = locktime + locktime_delta
140 self.miniwallet.sign_tx(tx)
141 txs.append({'tx': tx, 'sdf': sdf, 'stf': stf})
142 143 return txs
144 145 def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta=0):
146 """Returns a list of bip68 transactions with different bits set."""
147 txs = []
148 assert len(bip112inputs) >= 16
149 for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
150 locktime = relative_locktime(sdf, srhb, stf, srlb)
151 tx = self.create_self_transfer_from_utxo(bip112inputs[i])
152 if varyOP_CSV: # if varying OP_CSV, nSequence is fixed
153 tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
154 else: # vary nSequence instead, OP_CSV is fixed
155 tx.vin[0].nSequence = locktime + locktime_delta
156 tx.version = txversion
157 self.miniwallet.sign_tx(tx)
158 if varyOP_CSV:
159 tx.vin[0].scriptSig = CScript([locktime, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
160 else:
161 tx.vin[0].scriptSig = CScript([BASE_RELATIVE_LOCKTIME, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
162 tx.rehash()
163 txs.append({'tx': tx, 'sdf': sdf, 'stf': stf})
164 return txs
165 166 def generate_blocks(self, number):
167 test_blocks = []
168 for _ in range(number):
169 block = self.create_test_block([])
170 test_blocks.append(block)
171 self.last_block_time += 600
172 self.tip = block.sha256
173 self.tipheight += 1
174 return test_blocks
175 176 def create_test_block(self, txs):
177 block = create_block(self.tip, create_coinbase(self.tipheight + 1), self.last_block_time + 600, txlist=txs)
178 block.solve()
179 return block
180 181 def send_blocks(self, blocks, success=True, reject_reason=None):
182 """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
183 184 Call with success = False if the tip shouldn't advance to the most recent block."""
185 self.helper_peer.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason)
186 187 def run_test(self):
188 self.helper_peer = self.nodes[0].add_p2p_connection(P2PDataStore())
189 self.miniwallet = MiniWallet(self.nodes[0], mode=MiniWalletMode.RAW_P2PK)
190 191 self.log.info("Generate blocks in the past for coinbase outputs.")
192 long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future
193 self.nodes[0].setmocktime(long_past_time - 100) # enough so that the generated blocks will still all be before long_past_time
194 self.coinbase_blocks = self.generate(self.miniwallet, COINBASE_BLOCK_COUNT) # blocks generated for inputs
195 self.nodes[0].setmocktime(0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time
196 self.tipheight = COINBASE_BLOCK_COUNT # height of the next block to build
197 self.last_block_time = long_past_time
198 self.tip = int(self.nodes[0].getbestblockhash(), 16)
199 200 # Activation height is hardcoded
201 # We advance to block height five below BIP112 activation for the following tests
202 test_blocks = self.generate_blocks(CSV_ACTIVATION_HEIGHT - 5 - COINBASE_BLOCK_COUNT)
203 self.send_blocks(test_blocks)
204 assert not softfork_active(self.nodes[0], 'csv')
205 206 # Inputs at height = 431
207 #
208 # Put inputs for all tests in the chain at height 431 (tip now = 430) (time increases by 600s per block)
209 # Note we reuse inputs for v1 and v2 txs so must test these separately
210 # 16 normal inputs
211 bip68inputs = []
212 for _ in range(16):
213 bip68inputs.append(self.send_generic_input_tx(self.coinbase_blocks))
214 215 # 2 sets of 16 inputs with 10 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
216 bip112basicinputs = []
217 for _ in range(2):
218 inputs = []
219 for _ in range(16):
220 inputs.append(self.send_generic_input_tx(self.coinbase_blocks))
221 bip112basicinputs.append(inputs)
222 223 # 2 sets of 16 varied inputs with (relative_lock_time) OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
224 bip112diverseinputs = []
225 for _ in range(2):
226 inputs = []
227 for _ in range(16):
228 inputs.append(self.send_generic_input_tx(self.coinbase_blocks))
229 bip112diverseinputs.append(inputs)
230 231 # 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
232 bip112specialinput = self.send_generic_input_tx(self.coinbase_blocks)
233 # 1 special input with (empty stack) OP_CSV (actually will be prepended to spending scriptSig)
234 bip112emptystackinput = self.send_generic_input_tx(self.coinbase_blocks)
235 236 # 1 normal input
237 bip113input = self.send_generic_input_tx(self.coinbase_blocks)
238 239 self.nodes[0].setmocktime(self.last_block_time + 600)
240 inputblockhash = self.generate(self.nodes[0], 1)[0] # 1 block generated for inputs to be in chain at height 431
241 self.nodes[0].setmocktime(0)
242 self.tip = int(inputblockhash, 16)
243 self.tipheight += 1
244 self.last_block_time += 600
245 assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), TESTING_TX_COUNT + 1)
246 247 # 2 more version 4 blocks
248 test_blocks = self.generate_blocks(2)
249 self.send_blocks(test_blocks)
250 251 assert_equal(self.tipheight, CSV_ACTIVATION_HEIGHT - 2)
252 self.log.info(f"Height = {self.tipheight}, CSV not yet active (will activate for block {CSV_ACTIVATION_HEIGHT}, not {CSV_ACTIVATION_HEIGHT - 1})")
253 assert not softfork_active(self.nodes[0], 'csv')
254 255 # Test both version 1 and version 2 transactions for all tests
256 # BIP113 test transaction will be modified before each use to put in appropriate block time
257 bip113tx_v1 = self.create_self_transfer_from_utxo(bip113input)
258 bip113tx_v1.vin[0].nSequence = 0xFFFFFFFE
259 bip113tx_v1.version = 1
260 bip113tx_v2 = self.create_self_transfer_from_utxo(bip113input)
261 bip113tx_v2.vin[0].nSequence = 0xFFFFFFFE
262 bip113tx_v2.version = 2
263 264 # For BIP68 test all 16 relative sequence locktimes
265 bip68txs_v1 = self.create_bip68txs(bip68inputs, 1)
266 bip68txs_v2 = self.create_bip68txs(bip68inputs, 2)
267 268 # For BIP112 test:
269 # 16 relative sequence locktimes of 10 against 10 OP_CSV OP_DROP inputs
270 bip112txs_vary_nSequence_v1 = self.create_bip112txs(bip112basicinputs[0], False, 1)
271 bip112txs_vary_nSequence_v2 = self.create_bip112txs(bip112basicinputs[0], False, 2)
272 # 16 relative sequence locktimes of 9 against 10 OP_CSV OP_DROP inputs
273 bip112txs_vary_nSequence_9_v1 = self.create_bip112txs(bip112basicinputs[1], False, 1, -1)
274 bip112txs_vary_nSequence_9_v2 = self.create_bip112txs(bip112basicinputs[1], False, 2, -1)
275 # sequence lock time of 10 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
276 bip112txs_vary_OP_CSV_v1 = self.create_bip112txs(bip112diverseinputs[0], True, 1)
277 bip112txs_vary_OP_CSV_v2 = self.create_bip112txs(bip112diverseinputs[0], True, 2)
278 # sequence lock time of 9 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
279 bip112txs_vary_OP_CSV_9_v1 = self.create_bip112txs(bip112diverseinputs[1], True, 1, -1)
280 bip112txs_vary_OP_CSV_9_v2 = self.create_bip112txs(bip112diverseinputs[1], True, 2, -1)
281 # -1 OP_CSV OP_DROP input
282 bip112tx_special_v1 = self.create_bip112special(bip112specialinput, 1)
283 bip112tx_special_v2 = self.create_bip112special(bip112specialinput, 2)
284 # (empty stack) OP_CSV input
285 bip112tx_emptystack_v1 = self.create_bip112emptystack(bip112emptystackinput, 1)
286 bip112tx_emptystack_v2 = self.create_bip112emptystack(bip112emptystackinput, 2)
287 288 self.log.info("TESTING")
289 290 self.log.info("Pre-Soft Fork Tests. All txs should pass.")
291 self.log.info("Test version 1 txs")
292 293 success_txs = []
294 # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
295 bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
296 self.miniwallet.sign_tx(bip113tx_v1)
297 success_txs.append(bip113tx_v1)
298 success_txs.append(bip112tx_special_v1)
299 success_txs.append(bip112tx_emptystack_v1)
300 # add BIP 68 txs
301 success_txs.extend(all_rlt_txs(bip68txs_v1))
302 # add BIP 112 with seq=10 txs
303 success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v1))
304 success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v1))
305 # try BIP 112 with seq=9 txs
306 success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1))
307 success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v1))
308 self.send_blocks([self.create_test_block(success_txs)])
309 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
310 311 self.log.info("Test version 2 txs")
312 313 success_txs = []
314 # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
315 bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
316 self.miniwallet.sign_tx(bip113tx_v2)
317 success_txs.append(bip113tx_v2)
318 success_txs.append(bip112tx_special_v2)
319 success_txs.append(bip112tx_emptystack_v2)
320 # add BIP 68 txs
321 success_txs.extend(all_rlt_txs(bip68txs_v2))
322 # add BIP 112 with seq=10 txs
323 success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v2))
324 success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v2))
325 # try BIP 112 with seq=9 txs
326 success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2))
327 success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v2))
328 self.send_blocks([self.create_test_block(success_txs)])
329 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
330 331 # 1 more version 4 block to get us to height 432 so the fork should now be active for the next block
332 assert not softfork_active(self.nodes[0], 'csv')
333 test_blocks = self.generate_blocks(1)
334 self.send_blocks(test_blocks)
335 assert softfork_active(self.nodes[0], 'csv')
336 337 self.log.info("Post-Soft Fork Tests.")
338 339 self.log.info("BIP 113 tests")
340 # BIP 113 tests should now fail regardless of version number if nLockTime isn't satisfied by new rules
341 bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
342 self.miniwallet.sign_tx(bip113tx_v1)
343 bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
344 self.miniwallet.sign_tx(bip113tx_v2)
345 for bip113tx in [bip113tx_v1, bip113tx_v2]:
346 self.send_blocks([self.create_test_block([bip113tx])], success=False, reject_reason='bad-txns-nonfinal')
347 348 # BIP 113 tests should now pass if the locktime is < MTP
349 bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
350 self.miniwallet.sign_tx(bip113tx_v1)
351 bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
352 self.miniwallet.sign_tx(bip113tx_v2)
353 for bip113tx in [bip113tx_v1, bip113tx_v2]:
354 self.send_blocks([self.create_test_block([bip113tx])])
355 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
356 357 # Next block height = 437 after 4 blocks of random version
358 test_blocks = self.generate_blocks(4)
359 self.send_blocks(test_blocks)
360 361 self.log.info("BIP 68 tests")
362 self.log.info("Test version 1 txs - all should still pass")
363 364 success_txs = []
365 success_txs.extend(all_rlt_txs(bip68txs_v1))
366 self.send_blocks([self.create_test_block(success_txs)])
367 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
368 369 self.log.info("Test version 2 txs")
370 371 # All txs with SEQUENCE_LOCKTIME_DISABLE_FLAG set pass
372 bip68success_txs = [tx['tx'] for tx in bip68txs_v2 if tx['sdf']]
373 self.send_blocks([self.create_test_block(bip68success_txs)])
374 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
375 376 # All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512
377 bip68timetxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and tx['stf']]
378 for tx in bip68timetxs:
379 self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
380 381 bip68heighttxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and not tx['stf']]
382 for tx in bip68heighttxs:
383 self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
384 385 # Advance one block to 438
386 test_blocks = self.generate_blocks(1)
387 self.send_blocks(test_blocks)
388 389 # Height txs should fail and time txs should now pass 9 * 600 > 10 * 512
390 bip68success_txs.extend(bip68timetxs)
391 self.send_blocks([self.create_test_block(bip68success_txs)])
392 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
393 for tx in bip68heighttxs:
394 self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
395 396 # Advance one block to 439
397 test_blocks = self.generate_blocks(1)
398 self.send_blocks(test_blocks)
399 400 # All BIP 68 txs should pass
401 bip68success_txs.extend(bip68heighttxs)
402 self.send_blocks([self.create_test_block(bip68success_txs)])
403 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
404 405 self.log.info("BIP 112 tests")
406 self.log.info("Test version 1 txs")
407 408 # -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
409 self.send_blocks([self.create_test_block([bip112tx_special_v1])], success=False,
410 reject_reason='mandatory-script-verify-flag-failed (Negative locktime)')
411 self.send_blocks([self.create_test_block([bip112tx_emptystack_v1])], success=False,
412 reject_reason='mandatory-script-verify-flag-failed (Operation not valid with the current stack size)')
413 # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass
414 415 success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if tx['sdf']]
416 success_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if tx['sdf']]
417 self.send_blocks([self.create_test_block(success_txs)])
418 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
419 420 # If SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV, version 1 txs should now fail
421 fail_txs = all_rlt_txs(bip112txs_vary_nSequence_v1)
422 fail_txs += all_rlt_txs(bip112txs_vary_nSequence_9_v1)
423 fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if not tx['sdf']]
424 fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx['sdf']]
425 for tx in fail_txs:
426 self.send_blocks([self.create_test_block([tx])], success=False,
427 reject_reason='mandatory-script-verify-flag-failed (Locktime requirement not satisfied)')
428 429 self.log.info("Test version 2 txs")
430 431 # -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
432 self.send_blocks([self.create_test_block([bip112tx_special_v2])], success=False,
433 reject_reason='mandatory-script-verify-flag-failed (Negative locktime)')
434 self.send_blocks([self.create_test_block([bip112tx_emptystack_v2])], success=False,
435 reject_reason='mandatory-script-verify-flag-failed (Operation not valid with the current stack size)')
436 437 # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met)
438 success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if tx['sdf']]
439 success_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v2 if tx['sdf']]
440 441 self.send_blocks([self.create_test_block(success_txs)])
442 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
443 444 # SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV for all remaining txs ##
445 446 # All txs with nSequence 9 should fail either due to earlier mismatch or failing the CSV check
447 fail_txs = all_rlt_txs(bip112txs_vary_nSequence_9_v2)
448 fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v2 if not tx['sdf']]
449 for tx in fail_txs:
450 self.send_blocks([self.create_test_block([tx])], success=False,
451 reject_reason='mandatory-script-verify-flag-failed (Locktime requirement not satisfied)')
452 453 # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail
454 fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if tx['sdf']]
455 for tx in fail_txs:
456 self.send_blocks([self.create_test_block([tx])], success=False,
457 reject_reason='mandatory-script-verify-flag-failed (Locktime requirement not satisfied)')
458 459 # If sequencelock types mismatch, tx should fail
460 fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and tx['stf']]
461 fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and tx['stf']]
462 for tx in fail_txs:
463 self.send_blocks([self.create_test_block([tx])], success=False,
464 reject_reason='mandatory-script-verify-flag-failed (Locktime requirement not satisfied)')
465 466 # Remaining txs should pass, just test masking works properly
467 success_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and not tx['stf']]
468 success_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and not tx['stf']]
469 self.send_blocks([self.create_test_block(success_txs)])
470 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
471 472 # Additional test, of checking that comparison of two time types works properly
473 time_txs = []
474 for tx in [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and tx['stf']]:
475 tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME | SEQ_TYPE_FLAG
476 self.miniwallet.sign_tx(tx)
477 time_txs.append(tx)
478 479 self.send_blocks([self.create_test_block(time_txs)])
480 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
481 482 483 if __name__ == '__main__':
484 BIP68_112_113Test(__file__).main()
485