43
43
bip112tx_special - test negative argument to OP_CSV
44
44
"""
45
45
from decimal import Decimal
46
+ from itertools import product
46
47
from io import BytesIO
47
48
import time
48
49
61
62
hex_str_to_bytes ,
62
63
)
63
64
64
- base_relative_locktime = 10
65
- seq_disable_flag = 1 << 31
66
- seq_random_high_bit = 1 << 25
67
- seq_type_flag = 1 << 22
68
- seq_random_low_bit = 1 << 18
69
-
70
- # b31,b25,b22,b18 represent the 31st, 25th, 22nd and 18th bits respectively in the nSequence field
71
- # relative_locktimes[b31][b25][b22][b18] is a base_relative_locktime with the indicated bits set if their indices are 1
72
- relative_locktimes = []
73
- for b31 in range (2 ):
74
- b25times = []
75
- for b25 in range (2 ):
76
- b22times = []
77
- for b22 in range (2 ):
78
- b18times = []
79
- for b18 in range (2 ):
80
- rlt = base_relative_locktime
81
- if (b31 ):
82
- rlt = rlt | seq_disable_flag
83
- if (b25 ):
84
- rlt = rlt | seq_random_high_bit
85
- if (b22 ):
86
- rlt = rlt | seq_type_flag
87
- if (b18 ):
88
- rlt = rlt | seq_random_low_bit
89
- b18times .append (rlt )
90
- b22times .append (b18times )
91
- b25times .append (b22times )
92
- relative_locktimes .append (b25times )
93
-
94
- def all_rlt_txs (txarray ):
95
- txs = []
96
- for b31 in range (2 ):
97
- for b25 in range (2 ):
98
- for b22 in range (2 ):
99
- for b18 in range (2 ):
100
- txs .append (txarray [b31 ][b25 ][b22 ][b18 ])
101
- return 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
+ def relative_locktime (sdf , srhb , stf , srlb ):
72
+ """Returns a locktime with certain bits set."""
73
+
74
+ locktime = BASE_RELATIVE_LOCKTIME
75
+ if sdf :
76
+ locktime |= SEQ_DISABLE_FLAG
77
+ if srhb :
78
+ locktime |= SEQ_RANDOM_HIGH_BIT
79
+ if stf :
80
+ locktime |= SEQ_TYPE_FLAG
81
+ if srlb :
82
+ locktime |= SEQ_RANDOM_LOW_BIT
83
+ return locktime
84
+
85
+ def all_rlt_txs (txs ):
86
+ return [tx ['tx' ] for tx in txs ]
102
87
103
88
class BIP68_112_113Test (ComparisonTestFramework ):
104
89
def set_test_params (self ):
@@ -152,24 +137,18 @@ def create_test_block(self, txs, version=536870912):
152
137
return block
153
138
154
139
def create_bip68txs (self , bip68inputs , txversion , locktime_delta = 0 ):
140
+ """Returns a list of bip68 transactions with different bits set."""
155
141
txs = []
156
142
assert (len (bip68inputs ) >= 16 )
157
- i = 0
158
- for b31 in range (2 ):
159
- b25txs = []
160
- for b25 in range (2 ):
161
- b22txs = []
162
- for b22 in range (2 ):
163
- b18txs = []
164
- for b18 in range (2 ):
165
- tx = self .create_transaction (self .nodes [0 ], bip68inputs [i ], self .nodeaddress , Decimal ("49.98" ))
166
- i += 1
167
- tx .nVersion = txversion
168
- tx .vin [0 ].nSequence = relative_locktimes [b31 ][b25 ][b22 ][b18 ] + locktime_delta
169
- b18txs .append (self .sign_transaction (self .nodes [0 ], tx ))
170
- b22txs .append (b18txs )
171
- b25txs .append (b22txs )
172
- txs .append (b25txs )
143
+ for i , (sdf , srhb , stf , srlb ) in enumerate (product (* [[True , False ]] * 4 )):
144
+ locktime = relative_locktime (sdf , srhb , stf , srlb )
145
+ tx = self .create_transaction (self .nodes [0 ], bip68inputs [i ], self .nodeaddress , Decimal ("49.98" ))
146
+ tx .nVersion = txversion
147
+ tx .vin [0 ].nSequence = locktime + locktime_delta
148
+ tx = self .sign_transaction (self .nodes [0 ], tx )
149
+ tx .rehash ()
150
+ txs .append ({'tx' : tx , 'sdf' : sdf , 'stf' : stf })
151
+
173
152
return txs
174
153
175
154
def create_bip112special (self , input , txversion ):
@@ -180,32 +159,24 @@ def create_bip112special(self, input, txversion):
180
159
return signtx
181
160
182
161
def create_bip112txs (self , bip112inputs , varyOP_CSV , txversion , locktime_delta = 0 ):
162
+ """Returns a list of bip68 transactions with different bits set."""
183
163
txs = []
184
164
assert (len (bip112inputs ) >= 16 )
185
- i = 0
186
- for b31 in range (2 ):
187
- b25txs = []
188
- for b25 in range (2 ):
189
- b22txs = []
190
- for b22 in range (2 ):
191
- b18txs = []
192
- for b18 in range (2 ):
193
- tx = self .create_transaction (self .nodes [0 ], bip112inputs [i ], self .nodeaddress , Decimal ("49.98" ))
194
- i += 1
195
- if (varyOP_CSV ): # if varying OP_CSV, nSequence is fixed
196
- tx .vin [0 ].nSequence = base_relative_locktime + locktime_delta
197
- else : # vary nSequence instead, OP_CSV is fixed
198
- tx .vin [0 ].nSequence = relative_locktimes [b31 ][b25 ][b22 ][b18 ] + locktime_delta
199
- tx .nVersion = txversion
200
- signtx = self .sign_transaction (self .nodes [0 ], tx )
201
- if (varyOP_CSV ):
202
- signtx .vin [0 ].scriptSig = CScript ([relative_locktimes [b31 ][b25 ][b22 ][b18 ], OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (signtx .vin [0 ].scriptSig )))
203
- else :
204
- signtx .vin [0 ].scriptSig = CScript ([base_relative_locktime , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (signtx .vin [0 ].scriptSig )))
205
- b18txs .append (signtx )
206
- b22txs .append (b18txs )
207
- b25txs .append (b22txs )
208
- txs .append (b25txs )
165
+ for i , (sdf , srhb , stf , srlb ) in enumerate (product (* [[True , False ]] * 4 )):
166
+ locktime = relative_locktime (sdf , srhb , stf , srlb )
167
+ tx = self .create_transaction (self .nodes [0 ], bip112inputs [i ], self .nodeaddress , Decimal ("49.98" ))
168
+ if (varyOP_CSV ): # if varying OP_CSV, nSequence is fixed
169
+ tx .vin [0 ].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
170
+ else : # vary nSequence instead, OP_CSV is fixed
171
+ tx .vin [0 ].nSequence = locktime + locktime_delta
172
+ tx .nVersion = txversion
173
+ signtx = self .sign_transaction (self .nodes [0 ], tx )
174
+ if (varyOP_CSV ):
175
+ signtx .vin [0 ].scriptSig = CScript ([locktime , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (signtx .vin [0 ].scriptSig )))
176
+ else :
177
+ signtx .vin [0 ].scriptSig = CScript ([BASE_RELATIVE_LOCKTIME , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (signtx .vin [0 ].scriptSig )))
178
+ tx .rehash ()
179
+ txs .append ({'tx' : signtx , 'sdf' : sdf , 'stf' : stf })
209
180
return txs
210
181
211
182
def get_tests (self ):
@@ -410,25 +381,17 @@ def get_tests(self):
410
381
411
382
self .log .info ("Test version 2 txs" )
412
383
413
- bip68success_txs = []
414
384
# All txs with SEQUENCE_LOCKTIME_DISABLE_FLAG set pass
415
- for b25 in range (2 ):
416
- for b22 in range (2 ):
417
- for b18 in range (2 ):
418
- bip68success_txs .append (bip68txs_v2 [1 ][b25 ][b22 ][b18 ])
385
+ bip68success_txs = [tx ['tx' ] for tx in bip68txs_v2 if tx ['sdf' ]]
419
386
yield TestInstance ([[self .create_test_block (bip68success_txs ), True ]])
420
387
self .nodes [0 ].invalidateblock (self .nodes [0 ].getbestblockhash ())
388
+
421
389
# All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512
422
- bip68timetxs = []
423
- for b25 in range (2 ):
424
- for b18 in range (2 ):
425
- bip68timetxs .append (bip68txs_v2 [0 ][b25 ][1 ][b18 ])
390
+ bip68timetxs = [tx ['tx' ] for tx in bip68txs_v2 if not tx ['sdf' ] and tx ['stf' ]]
426
391
for tx in bip68timetxs :
427
392
yield TestInstance ([[self .create_test_block ([tx ]), False ]])
428
- bip68heighttxs = []
429
- for b25 in range (2 ):
430
- for b18 in range (2 ):
431
- bip68heighttxs .append (bip68txs_v2 [0 ][b25 ][0 ][b18 ])
393
+
394
+ bip68heighttxs = [tx ['tx' ] for tx in bip68txs_v2 if not tx ['sdf' ] and not tx ['stf' ]]
432
395
for tx in bip68heighttxs :
433
396
yield TestInstance ([[self .create_test_block ([tx ]), False ]])
434
397
@@ -458,25 +421,17 @@ def get_tests(self):
458
421
# -1 OP_CSV tx should fail
459
422
yield TestInstance ([[self .create_test_block ([bip112tx_special_v1 ]), False ]])
460
423
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass
461
- success_txs = []
462
- for b25 in range (2 ):
463
- for b22 in range (2 ):
464
- for b18 in range (2 ):
465
- success_txs .append (bip112txs_vary_OP_CSV_v1 [1 ][b25 ][b22 ][b18 ])
466
- success_txs .append (bip112txs_vary_OP_CSV_9_v1 [1 ][b25 ][b22 ][b18 ])
424
+
425
+ success_txs = [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_v1 if tx ['sdf' ]]
426
+ success_txs += [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_9_v1 if tx ['sdf' ]]
467
427
yield TestInstance ([[self .create_test_block (success_txs ), True ]])
468
428
self .nodes [0 ].invalidateblock (self .nodes [0 ].getbestblockhash ())
469
429
470
430
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV, version 1 txs should now fail
471
- fail_txs = []
472
- fail_txs .extend (all_rlt_txs (bip112txs_vary_nSequence_v1 ))
473
- fail_txs .extend (all_rlt_txs (bip112txs_vary_nSequence_9_v1 ))
474
- for b25 in range (2 ):
475
- for b22 in range (2 ):
476
- for b18 in range (2 ):
477
- fail_txs .append (bip112txs_vary_OP_CSV_v1 [0 ][b25 ][b22 ][b18 ])
478
- fail_txs .append (bip112txs_vary_OP_CSV_9_v1 [0 ][b25 ][b22 ][b18 ])
479
-
431
+ fail_txs = all_rlt_txs (bip112txs_vary_nSequence_v1 )
432
+ fail_txs += all_rlt_txs (bip112txs_vary_nSequence_9_v1 )
433
+ fail_txs += [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx ['sdf' ]]
434
+ fail_txs += [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx ['sdf' ]]
480
435
for tx in fail_txs :
481
436
yield TestInstance ([[self .create_test_block ([tx ]), False ]])
482
437
@@ -486,64 +441,44 @@ def get_tests(self):
486
441
yield TestInstance ([[self .create_test_block ([bip112tx_special_v2 ]), False ]])
487
442
488
443
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met)
489
- success_txs = []
490
- for b25 in range (2 ):
491
- for b22 in range (2 ):
492
- for b18 in range (2 ):
493
- success_txs .append (bip112txs_vary_OP_CSV_v2 [1 ][b25 ][b22 ][b18 ]) # 8/16 of vary_OP_CSV
494
- success_txs .append (bip112txs_vary_OP_CSV_9_v2 [1 ][b25 ][b22 ][b18 ]) # 8/16 of vary_OP_CSV_9
444
+ success_txs = [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_v2 if tx ['sdf' ]]
445
+ success_txs += [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_9_v2 if tx ['sdf' ]]
495
446
496
447
yield TestInstance ([[self .create_test_block (success_txs ), True ]])
497
448
self .nodes [0 ].invalidateblock (self .nodes [0 ].getbestblockhash ())
498
449
499
450
# SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV for all remaining txs ##
500
451
501
452
# All txs with nSequence 9 should fail either due to earlier mismatch or failing the CSV check
502
- fail_txs = []
503
- fail_txs .extend (all_rlt_txs (bip112txs_vary_nSequence_9_v2 )) # 16/16 of vary_nSequence_9
504
- for b25 in range (2 ):
505
- for b22 in range (2 ):
506
- for b18 in range (2 ):
507
- fail_txs .append (bip112txs_vary_OP_CSV_9_v2 [0 ][b25 ][b22 ][b18 ]) # 16/16 of vary_OP_CSV_9
508
-
453
+ fail_txs = all_rlt_txs (bip112txs_vary_nSequence_9_v2 )
454
+ fail_txs += [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_9_v2 if not tx ['sdf' ]]
509
455
for tx in fail_txs :
510
456
yield TestInstance ([[self .create_test_block ([tx ]), False ]])
511
457
512
458
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail
513
- fail_txs = []
514
- for b25 in range (2 ):
515
- for b22 in range (2 ):
516
- for b18 in range (2 ):
517
- fail_txs .append (bip112txs_vary_nSequence_v2 [1 ][b25 ][b22 ][b18 ]) # 8/16 of vary_nSequence
459
+ fail_txs = [tx ['tx' ] for tx in bip112txs_vary_nSequence_v2 if tx ['sdf' ]]
518
460
for tx in fail_txs :
519
461
yield TestInstance ([[self .create_test_block ([tx ]), False ]])
520
462
521
463
# If sequencelock types mismatch, tx should fail
522
- fail_txs = []
523
- for b25 in range (2 ):
524
- for b18 in range (2 ):
525
- fail_txs .append (bip112txs_vary_nSequence_v2 [0 ][b25 ][1 ][b18 ]) # 12/16 of vary_nSequence
526
- fail_txs .append (bip112txs_vary_OP_CSV_v2 [0 ][b25 ][1 ][b18 ]) # 12/16 of vary_OP_CSV
464
+ fail_txs = [tx ['tx' ] for tx in bip112txs_vary_nSequence_v2 if not tx ['sdf' ] and tx ['stf' ]]
465
+ fail_txs += [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_v2 if not tx ['sdf' ] and tx ['stf' ]]
527
466
for tx in fail_txs :
528
467
yield TestInstance ([[self .create_test_block ([tx ]), False ]])
529
468
530
469
# Remaining txs should pass, just test masking works properly
531
- success_txs = []
532
- for b25 in range (2 ):
533
- for b18 in range (2 ):
534
- success_txs .append (bip112txs_vary_nSequence_v2 [0 ][b25 ][0 ][b18 ]) # 16/16 of vary_nSequence
535
- success_txs .append (bip112txs_vary_OP_CSV_v2 [0 ][b25 ][0 ][b18 ]) # 16/16 of vary_OP_CSV
470
+ success_txs = [tx ['tx' ] for tx in bip112txs_vary_nSequence_v2 if not tx ['sdf' ] and not tx ['stf' ]]
471
+ success_txs += [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_v2 if not tx ['sdf' ] and not tx ['stf' ]]
536
472
yield TestInstance ([[self .create_test_block (success_txs ), True ]]) # 124
537
473
self .nodes [0 ].invalidateblock (self .nodes [0 ].getbestblockhash ())
538
474
539
475
# Additional test, of checking that comparison of two time types works properly
540
476
time_txs = []
541
- for b25 in range (2 ):
542
- for b18 in range (2 ):
543
- tx = bip112txs_vary_OP_CSV_v2 [0 ][b25 ][1 ][b18 ]
544
- tx .vin [0 ].nSequence = base_relative_locktime | seq_type_flag
545
- signtx = self .sign_transaction (self .nodes [0 ], tx )
546
- time_txs .append (signtx )
477
+ for tx in [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_v2 if not tx ['sdf' ] and tx ['stf' ]]:
478
+ tx .vin [0 ].nSequence = BASE_RELATIVE_LOCKTIME | SEQ_TYPE_FLAG
479
+ signtx = self .sign_transaction (self .nodes [0 ], tx )
480
+ time_txs .append (signtx )
481
+
547
482
yield TestInstance ([[self .create_test_block (time_txs ), True ]])
548
483
self .nodes [0 ].invalidateblock (self .nodes [0 ].getbestblockhash ())
549
484
0 commit comments