/ test / functional / feature_csv_activation.py
feature_csv_activation.py
  1  #!/usr/bin/env python3
  2  # Copyright (c) 2015-2022 The Bitcoin Core 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 BitcoinTestFramework
 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(BitcoinTestFramework):
 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  
104      def create_self_transfer_from_utxo(self, input_tx):
105          utxo = self.miniwallet.get_utxo(txid=input_tx.txid_hex, mark_as_spent=False)
106          tx = self.miniwallet.create_self_transfer(utxo_to_spend=utxo)['tx']
107          return tx
108  
109      def create_bip112special(self, input, txversion):
110          tx = self.create_self_transfer_from_utxo(input)
111          tx.version = txversion
112          self.miniwallet.sign_tx(tx)
113          tx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
114          return tx
115  
116      def create_bip112emptystack(self, input, txversion):
117          tx = self.create_self_transfer_from_utxo(input)
118          tx.version = txversion
119          self.miniwallet.sign_tx(tx)
120          tx.vin[0].scriptSig = CScript([OP_CHECKSEQUENCEVERIFY] + list(CScript(tx.vin[0].scriptSig)))
121          return tx
122  
123      def send_generic_input_tx(self, coinbases):
124          input_txid = self.nodes[0].getblock(coinbases.pop(), 2)['tx'][0]['txid']
125          utxo_to_spend = self.miniwallet.get_utxo(txid=input_txid)
126          return self.miniwallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_to_spend)['tx']
127  
128      def create_bip68txs(self, bip68inputs, txversion, locktime_delta=0):
129          """Returns a list of bip68 transactions with different bits set."""
130          txs = []
131          assert len(bip68inputs) >= 16
132          for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
133              locktime = relative_locktime(sdf, srhb, stf, srlb)
134              tx = self.create_self_transfer_from_utxo(bip68inputs[i])
135              tx.version = txversion
136              tx.vin[0].nSequence = locktime + locktime_delta
137              self.miniwallet.sign_tx(tx)
138              txs.append({'tx': tx, 'sdf': sdf, 'stf': stf})
139  
140          return txs
141  
142      def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta=0):
143          """Returns a list of bip68 transactions with different bits set."""
144          txs = []
145          assert len(bip112inputs) >= 16
146          for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
147              locktime = relative_locktime(sdf, srhb, stf, srlb)
148              tx = self.create_self_transfer_from_utxo(bip112inputs[i])
149              if varyOP_CSV:  # if varying OP_CSV, nSequence is fixed
150                  tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
151              else:  # vary nSequence instead, OP_CSV is fixed
152                  tx.vin[0].nSequence = locktime + locktime_delta
153              tx.version = txversion
154              self.miniwallet.sign_tx(tx)
155              if varyOP_CSV:
156                  tx.vin[0].scriptSig = CScript([locktime, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
157              else:
158                  tx.vin[0].scriptSig = CScript([BASE_RELATIVE_LOCKTIME, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
159              txs.append({'tx': tx, 'sdf': sdf, 'stf': stf})
160          return txs
161  
162      def generate_blocks(self, number):
163          test_blocks = []
164          for _ in range(number):
165              block = self.create_test_block([])
166              test_blocks.append(block)
167              self.last_block_time += 600
168              self.tip = block.hash_int
169              self.tipheight += 1
170          return test_blocks
171  
172      def create_test_block(self, txs):
173          block = create_block(self.tip, create_coinbase(self.tipheight + 1), self.last_block_time + 600, txlist=txs)
174          block.solve()
175          return block
176  
177      def send_blocks(self, blocks, success=True, reject_reason=None):
178          """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
179  
180          Call with success = False if the tip shouldn't advance to the most recent block."""
181          self.helper_peer.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason)
182  
183      def run_test(self):
184          self.helper_peer = self.nodes[0].add_p2p_connection(P2PDataStore())
185          self.miniwallet = MiniWallet(self.nodes[0], mode=MiniWalletMode.RAW_P2PK)
186  
187          self.log.info("Generate blocks in the past for coinbase outputs.")
188          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
189          self.nodes[0].setmocktime(long_past_time - 100)  # enough so that the generated blocks will still all be before long_past_time
190          self.coinbase_blocks = self.generate(self.miniwallet, COINBASE_BLOCK_COUNT)  # blocks generated for inputs
191          self.nodes[0].setmocktime(0)  # set time back to present so yielded blocks aren't in the future as we advance last_block_time
192          self.tipheight = COINBASE_BLOCK_COUNT  # height of the next block to build
193          self.last_block_time = long_past_time
194          self.tip = int(self.nodes[0].getbestblockhash(), 16)
195  
196          # Activation height is hardcoded
197          # We advance to block height five below BIP112 activation for the following tests
198          test_blocks = self.generate_blocks(CSV_ACTIVATION_HEIGHT - 5 - COINBASE_BLOCK_COUNT)
199          self.send_blocks(test_blocks)
200          assert not softfork_active(self.nodes[0], 'csv')
201  
202          # Inputs at height = 431
203          #
204          # Put inputs for all tests in the chain at height 431 (tip now = 430) (time increases by 600s per block)
205          # Note we reuse inputs for v1 and v2 txs so must test these separately
206          # 16 normal inputs
207          bip68inputs = []
208          for _ in range(16):
209              bip68inputs.append(self.send_generic_input_tx(self.coinbase_blocks))
210  
211          # 2 sets of 16 inputs with 10 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
212          bip112basicinputs = []
213          for _ in range(2):
214              inputs = []
215              for _ in range(16):
216                  inputs.append(self.send_generic_input_tx(self.coinbase_blocks))
217              bip112basicinputs.append(inputs)
218  
219          # 2 sets of 16 varied inputs with (relative_lock_time) OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
220          bip112diverseinputs = []
221          for _ in range(2):
222              inputs = []
223              for _ in range(16):
224                  inputs.append(self.send_generic_input_tx(self.coinbase_blocks))
225              bip112diverseinputs.append(inputs)
226  
227          # 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
228          bip112specialinput = self.send_generic_input_tx(self.coinbase_blocks)
229          # 1 special input with (empty stack) OP_CSV (actually will be prepended to spending scriptSig)
230          bip112emptystackinput = self.send_generic_input_tx(self.coinbase_blocks)
231  
232          # 1 normal input
233          bip113input = self.send_generic_input_tx(self.coinbase_blocks)
234  
235          self.nodes[0].setmocktime(self.last_block_time + 600)
236          inputblockhash = self.generate(self.nodes[0], 1)[0]  # 1 block generated for inputs to be in chain at height 431
237          self.nodes[0].setmocktime(0)
238          self.tip = int(inputblockhash, 16)
239          self.tipheight += 1
240          self.last_block_time += 600
241          assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), TESTING_TX_COUNT + 1)
242  
243          # 2 more version 4 blocks
244          test_blocks = self.generate_blocks(2)
245          self.send_blocks(test_blocks)
246  
247          assert_equal(self.tipheight, CSV_ACTIVATION_HEIGHT - 2)
248          self.log.info(f"Height = {self.tipheight}, CSV not yet active (will activate for block {CSV_ACTIVATION_HEIGHT}, not {CSV_ACTIVATION_HEIGHT - 1})")
249          assert not softfork_active(self.nodes[0], 'csv')
250  
251          # Test both version 1 and version 2 transactions for all tests
252          # BIP113 test transaction will be modified before each use to put in appropriate block time
253          bip113tx_v1 = self.create_self_transfer_from_utxo(bip113input)
254          bip113tx_v1.vin[0].nSequence = 0xFFFFFFFE
255          bip113tx_v1.version = 1
256          bip113tx_v2 = self.create_self_transfer_from_utxo(bip113input)
257          bip113tx_v2.vin[0].nSequence = 0xFFFFFFFE
258          bip113tx_v2.version = 2
259  
260          # For BIP68 test all 16 relative sequence locktimes
261          bip68txs_v1 = self.create_bip68txs(bip68inputs, 1)
262          bip68txs_v2 = self.create_bip68txs(bip68inputs, 2)
263  
264          # For BIP112 test:
265          # 16 relative sequence locktimes of 10 against 10 OP_CSV OP_DROP inputs
266          bip112txs_vary_nSequence_v1 = self.create_bip112txs(bip112basicinputs[0], False, 1)
267          bip112txs_vary_nSequence_v2 = self.create_bip112txs(bip112basicinputs[0], False, 2)
268          # 16 relative sequence locktimes of 9 against 10 OP_CSV OP_DROP inputs
269          bip112txs_vary_nSequence_9_v1 = self.create_bip112txs(bip112basicinputs[1], False, 1, -1)
270          bip112txs_vary_nSequence_9_v2 = self.create_bip112txs(bip112basicinputs[1], False, 2, -1)
271          # sequence lock time of 10 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
272          bip112txs_vary_OP_CSV_v1 = self.create_bip112txs(bip112diverseinputs[0], True, 1)
273          bip112txs_vary_OP_CSV_v2 = self.create_bip112txs(bip112diverseinputs[0], True, 2)
274          # sequence lock time of 9 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
275          bip112txs_vary_OP_CSV_9_v1 = self.create_bip112txs(bip112diverseinputs[1], True, 1, -1)
276          bip112txs_vary_OP_CSV_9_v2 = self.create_bip112txs(bip112diverseinputs[1], True, 2, -1)
277          # -1 OP_CSV OP_DROP input
278          bip112tx_special_v1 = self.create_bip112special(bip112specialinput, 1)
279          bip112tx_special_v2 = self.create_bip112special(bip112specialinput, 2)
280          # (empty stack) OP_CSV input
281          bip112tx_emptystack_v1 = self.create_bip112emptystack(bip112emptystackinput, 1)
282          bip112tx_emptystack_v2 = self.create_bip112emptystack(bip112emptystackinput, 2)
283  
284          self.log.info("TESTING")
285  
286          self.log.info("Pre-Soft Fork Tests. All txs should pass.")
287          self.log.info("Test version 1 txs")
288  
289          success_txs = []
290          # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
291          bip113tx_v1.nLockTime = self.last_block_time - 600 * 5  # = MTP of prior block (not <) but < time put on current block
292          self.miniwallet.sign_tx(bip113tx_v1)
293          success_txs.append(bip113tx_v1)
294          success_txs.append(bip112tx_special_v1)
295          success_txs.append(bip112tx_emptystack_v1)
296          # add BIP 68 txs
297          success_txs.extend(all_rlt_txs(bip68txs_v1))
298          # add BIP 112 with seq=10 txs
299          success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v1))
300          success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v1))
301          # try BIP 112 with seq=9 txs
302          success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1))
303          success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v1))
304          self.send_blocks([self.create_test_block(success_txs)])
305          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
306  
307          self.log.info("Test version 2 txs")
308  
309          success_txs = []
310          # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
311          bip113tx_v2.nLockTime = self.last_block_time - 600 * 5  # = MTP of prior block (not <) but < time put on current block
312          self.miniwallet.sign_tx(bip113tx_v2)
313          success_txs.append(bip113tx_v2)
314          success_txs.append(bip112tx_special_v2)
315          success_txs.append(bip112tx_emptystack_v2)
316          # add BIP 68 txs
317          success_txs.extend(all_rlt_txs(bip68txs_v2))
318          # add BIP 112 with seq=10 txs
319          success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v2))
320          success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v2))
321          # try BIP 112 with seq=9 txs
322          success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2))
323          success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v2))
324          self.send_blocks([self.create_test_block(success_txs)])
325          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
326  
327          # 1 more version 4 block to get us to height 432 so the fork should now be active for the next block
328          assert not softfork_active(self.nodes[0], 'csv')
329          test_blocks = self.generate_blocks(1)
330          self.send_blocks(test_blocks)
331          assert softfork_active(self.nodes[0], 'csv')
332  
333          self.log.info("Post-Soft Fork Tests.")
334  
335          self.log.info("BIP 113 tests")
336          # BIP 113 tests should now fail regardless of version number if nLockTime isn't satisfied by new rules
337          bip113tx_v1.nLockTime = self.last_block_time - 600 * 5  # = MTP of prior block (not <) but < time put on current block
338          self.miniwallet.sign_tx(bip113tx_v1)
339          bip113tx_v2.nLockTime = self.last_block_time - 600 * 5  # = MTP of prior block (not <) but < time put on current block
340          self.miniwallet.sign_tx(bip113tx_v2)
341          for bip113tx in [bip113tx_v1, bip113tx_v2]:
342              self.send_blocks([self.create_test_block([bip113tx])], success=False, reject_reason='bad-txns-nonfinal')
343  
344          # BIP 113 tests should now pass if the locktime is < MTP
345          bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1  # < MTP of prior block
346          self.miniwallet.sign_tx(bip113tx_v1)
347          bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1  # < MTP of prior block
348          self.miniwallet.sign_tx(bip113tx_v2)
349          for bip113tx in [bip113tx_v1, bip113tx_v2]:
350              self.send_blocks([self.create_test_block([bip113tx])])
351              self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
352  
353          # Next block height = 437 after 4 blocks of random version
354          test_blocks = self.generate_blocks(4)
355          self.send_blocks(test_blocks)
356  
357          self.log.info("BIP 68 tests")
358          self.log.info("Test version 1 txs - all should still pass")
359  
360          success_txs = []
361          success_txs.extend(all_rlt_txs(bip68txs_v1))
362          self.send_blocks([self.create_test_block(success_txs)])
363          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
364  
365          self.log.info("Test version 2 txs")
366  
367          # All txs with SEQUENCE_LOCKTIME_DISABLE_FLAG set pass
368          bip68success_txs = [tx['tx'] for tx in bip68txs_v2 if tx['sdf']]
369          self.send_blocks([self.create_test_block(bip68success_txs)])
370          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
371  
372          # All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512
373          bip68timetxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and tx['stf']]
374          for tx in bip68timetxs:
375              self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
376  
377          bip68heighttxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and not tx['stf']]
378          for tx in bip68heighttxs:
379              self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
380  
381          # Advance one block to 438
382          test_blocks = self.generate_blocks(1)
383          self.send_blocks(test_blocks)
384  
385          # Height txs should fail and time txs should now pass 9 * 600 > 10 * 512
386          bip68success_txs.extend(bip68timetxs)
387          self.send_blocks([self.create_test_block(bip68success_txs)])
388          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
389          for tx in bip68heighttxs:
390              self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
391  
392          # Advance one block to 439
393          test_blocks = self.generate_blocks(1)
394          self.send_blocks(test_blocks)
395  
396          # All BIP 68 txs should pass
397          bip68success_txs.extend(bip68heighttxs)
398          self.send_blocks([self.create_test_block(bip68success_txs)])
399          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
400  
401          self.log.info("BIP 112 tests")
402          self.log.info("Test version 1 txs")
403  
404          # -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
405          self.send_blocks([self.create_test_block([bip112tx_special_v1])], success=False,
406                           reject_reason='block-script-verify-flag-failed (Negative locktime)')
407          self.send_blocks([self.create_test_block([bip112tx_emptystack_v1])], success=False,
408                           reject_reason='block-script-verify-flag-failed (Operation not valid with the current stack size)')
409          # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass
410  
411          success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if tx['sdf']]
412          success_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if tx['sdf']]
413          self.send_blocks([self.create_test_block(success_txs)])
414          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
415  
416          # If SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV, version 1 txs should now fail
417          fail_txs = all_rlt_txs(bip112txs_vary_nSequence_v1)
418          fail_txs += all_rlt_txs(bip112txs_vary_nSequence_9_v1)
419          fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if not tx['sdf']]
420          fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx['sdf']]
421          for tx in fail_txs:
422              self.send_blocks([self.create_test_block([tx])], success=False,
423                               reject_reason='block-script-verify-flag-failed (Locktime requirement not satisfied)')
424  
425          self.log.info("Test version 2 txs")
426  
427          # -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
428          self.send_blocks([self.create_test_block([bip112tx_special_v2])], success=False,
429                           reject_reason='block-script-verify-flag-failed (Negative locktime)')
430          self.send_blocks([self.create_test_block([bip112tx_emptystack_v2])], success=False,
431                           reject_reason='block-script-verify-flag-failed (Operation not valid with the current stack size)')
432  
433          # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met)
434          success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if tx['sdf']]
435          success_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v2 if tx['sdf']]
436  
437          self.send_blocks([self.create_test_block(success_txs)])
438          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
439  
440          # SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV for all remaining txs ##
441  
442          # All txs with nSequence 9 should fail either due to earlier mismatch or failing the CSV check
443          fail_txs = all_rlt_txs(bip112txs_vary_nSequence_9_v2)
444          fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v2 if not tx['sdf']]
445          for tx in fail_txs:
446              self.send_blocks([self.create_test_block([tx])], success=False,
447                               reject_reason='block-script-verify-flag-failed (Locktime requirement not satisfied)')
448  
449          # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail
450          fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if tx['sdf']]
451          for tx in fail_txs:
452              self.send_blocks([self.create_test_block([tx])], success=False,
453                               reject_reason='block-script-verify-flag-failed (Locktime requirement not satisfied)')
454  
455          # If sequencelock types mismatch, tx should fail
456          fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and tx['stf']]
457          fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and tx['stf']]
458          for tx in fail_txs:
459              self.send_blocks([self.create_test_block([tx])], success=False,
460                               reject_reason='block-script-verify-flag-failed (Locktime requirement not satisfied)')
461  
462          # Remaining txs should pass, just test masking works properly
463          success_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and not tx['stf']]
464          success_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and not tx['stf']]
465          self.send_blocks([self.create_test_block(success_txs)])
466          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
467  
468          # Additional test, of checking that comparison of two time types works properly
469          time_txs = []
470          for tx in [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and tx['stf']]:
471              tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME | SEQ_TYPE_FLAG
472              self.miniwallet.sign_tx(tx)
473              time_txs.append(tx)
474  
475          self.send_blocks([self.create_test_block(time_txs)])
476          self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
477  
478  
479  if __name__ == '__main__':
480      BIP68_112_113Test(__file__).main()