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