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()