37
37
bip112tx_special - test negative argument to OP_CSV
38
38
bip112tx_emptystack - test empty stack (= no argument) OP_CSV
39
39
"""
40
- from decimal import Decimal
41
40
from itertools import product
42
- from io import BytesIO
43
41
import time
44
42
45
- from test_framework .blocktools import create_coinbase , create_block , create_transaction
46
- from test_framework .messages import ToHex , CTransaction
43
+ from test_framework .blocktools import (
44
+ create_block ,
45
+ create_coinbase ,
46
+ )
47
47
from test_framework .p2p import P2PDataStore
48
48
from test_framework .script import (
49
49
CScript ,
53
53
from test_framework .test_framework import BitcoinTestFramework
54
54
from test_framework .util import (
55
55
assert_equal ,
56
- hex_str_to_bytes ,
57
56
softfork_active ,
58
57
)
58
+ from test_framework .wallet import MiniWallet
59
59
60
60
TESTING_TX_COUNT = 83 # Number of testing transactions: 1 BIP113 tx, 16 BIP68 txs, 66 BIP112 txs (see comments above)
61
61
COINBASE_BLOCK_COUNT = TESTING_TX_COUNT # Number of coinbase blocks we need to generate as inputs for our txs
@@ -83,65 +83,60 @@ def relative_locktime(sdf, srhb, stf, srlb):
83
83
def all_rlt_txs (txs ):
84
84
return [tx ['tx' ] for tx in txs ]
85
85
86
- def sign_transaction (node , unsignedtx ):
87
- rawtx = ToHex (unsignedtx )
88
- signresult = node .signrawtransactionwithwallet (rawtx )
89
- tx = CTransaction ()
90
- f = BytesIO (hex_str_to_bytes (signresult ['hex' ]))
91
- tx .deserialize (f )
86
+ def create_self_transfer_from_utxo (node , input_tx ):
87
+ utxo = miniwallet .get_utxo (txid = input_tx .rehash (), mark_as_spent = False )
88
+ tx = miniwallet .create_self_transfer (from_node = node , utxo_to_spend = utxo )['tx' ]
92
89
return tx
93
90
94
- def create_bip112special (node , input , txversion , address ):
95
- tx = create_transaction (node , input , address , amount = Decimal ( "49.98" ) )
91
+ def create_bip112special (node , input , txversion ):
92
+ tx = create_self_transfer_from_utxo (node , input )
96
93
tx .nVersion = txversion
97
- signtx = sign_transaction (node , tx )
98
- signtx .vin [0 ].scriptSig = CScript ([- 1 , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (signtx .vin [0 ].scriptSig )))
99
- return signtx
94
+ tx .vin [0 ].scriptSig = CScript ([- 1 , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (tx .vin [0 ].scriptSig )))
95
+ return tx
100
96
101
- def create_bip112emptystack (node , input , txversion , address ):
102
- tx = create_transaction (node , input , address , amount = Decimal ( "49.98" ) )
97
+ def create_bip112emptystack (node , input , txversion ):
98
+ tx = create_self_transfer_from_utxo (node , input )
103
99
tx .nVersion = txversion
104
- signtx = sign_transaction (node , tx )
105
- signtx .vin [0 ].scriptSig = CScript ([OP_CHECKSEQUENCEVERIFY ] + list (CScript (signtx .vin [0 ].scriptSig )))
106
- return signtx
100
+ tx .vin [0 ].scriptSig = CScript ([OP_CHECKSEQUENCEVERIFY ] + list (CScript (tx .vin [0 ].scriptSig )))
101
+ return tx
107
102
108
- def send_generic_input_tx (node , coinbases , address ):
109
- return node .sendrawtransaction (ToHex (sign_transaction (node , create_transaction (node , node .getblock (coinbases .pop ())['tx' ][0 ], address , amount = Decimal ("49.99" )))))
103
+ def send_generic_input_tx (node , coinbases ):
104
+ input_txid = node .getblock (coinbases .pop (), 2 )['tx' ][0 ]['txid' ]
105
+ utxo_to_spend = miniwallet .get_utxo (txid = input_txid )
106
+ return miniwallet .send_self_transfer (from_node = node , utxo_to_spend = utxo_to_spend )['tx' ]
110
107
111
- def create_bip68txs (node , bip68inputs , txversion , address , locktime_delta = 0 ):
108
+ def create_bip68txs (node , bip68inputs , txversion , locktime_delta = 0 ):
112
109
"""Returns a list of bip68 transactions with different bits set."""
113
110
txs = []
114
111
assert len (bip68inputs ) >= 16
115
112
for i , (sdf , srhb , stf , srlb ) in enumerate (product (* [[True , False ]] * 4 )):
116
113
locktime = relative_locktime (sdf , srhb , stf , srlb )
117
- tx = create_transaction (node , bip68inputs [i ], address , amount = Decimal ( "49.98" ) )
114
+ tx = create_self_transfer_from_utxo (node , bip68inputs [i ])
118
115
tx .nVersion = txversion
119
116
tx .vin [0 ].nSequence = locktime + locktime_delta
120
- tx = sign_transaction (node , tx )
121
117
tx .rehash ()
122
118
txs .append ({'tx' : tx , 'sdf' : sdf , 'stf' : stf })
123
119
124
120
return txs
125
121
126
- def create_bip112txs (node , bip112inputs , varyOP_CSV , txversion , address , locktime_delta = 0 ):
122
+ def create_bip112txs (node , bip112inputs , varyOP_CSV , txversion , locktime_delta = 0 ):
127
123
"""Returns a list of bip68 transactions with different bits set."""
128
124
txs = []
129
125
assert len (bip112inputs ) >= 16
130
126
for i , (sdf , srhb , stf , srlb ) in enumerate (product (* [[True , False ]] * 4 )):
131
127
locktime = relative_locktime (sdf , srhb , stf , srlb )
132
- tx = create_transaction (node , bip112inputs [i ], address , amount = Decimal ( "49.98" ) )
128
+ tx = create_self_transfer_from_utxo (node , bip112inputs [i ])
133
129
if (varyOP_CSV ): # if varying OP_CSV, nSequence is fixed
134
130
tx .vin [0 ].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
135
131
else : # vary nSequence instead, OP_CSV is fixed
136
132
tx .vin [0 ].nSequence = locktime + locktime_delta
137
133
tx .nVersion = txversion
138
- signtx = sign_transaction (node , tx )
139
134
if (varyOP_CSV ):
140
- signtx .vin [0 ].scriptSig = CScript ([locktime , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (signtx .vin [0 ].scriptSig )))
135
+ tx .vin [0 ].scriptSig = CScript ([locktime , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (tx .vin [0 ].scriptSig )))
141
136
else :
142
- signtx .vin [0 ].scriptSig = CScript ([BASE_RELATIVE_LOCKTIME , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (signtx .vin [0 ].scriptSig )))
137
+ tx .vin [0 ].scriptSig = CScript ([BASE_RELATIVE_LOCKTIME , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (tx .vin [0 ].scriptSig )))
143
138
tx .rehash ()
144
- txs .append ({'tx' : signtx , 'sdf' : sdf , 'stf' : stf })
139
+ txs .append ({'tx' : tx , 'sdf' : sdf , 'stf' : stf })
145
140
return txs
146
141
147
142
class BIP68_112_113Test (BitcoinTestFramework ):
@@ -150,14 +145,11 @@ def set_test_params(self):
150
145
self .setup_clean_chain = True
151
146
self .extra_args = [[
152
147
153
- '-addresstype=legacy ' ,
148
+ '-acceptnonstdtxn=1 ' ,
154
149
'-par=1' , # Use only one script thread to get the exact reject reason for testing
155
150
]]
156
151
self .supports_cli = False
157
152
158
- def skip_test_if_missing_module (self ):
159
- self .skip_if_no_wallet ()
160
-
161
153
def generate_blocks (self , number ):
162
154
test_blocks = []
163
155
for _ in range (number ):
@@ -185,16 +177,18 @@ def send_blocks(self, blocks, success=True, reject_reason=None):
185
177
186
178
def run_test (self ):
187
179
self .helper_peer = self .nodes [0 ].add_p2p_connection (P2PDataStore ())
180
+ # TODO: store as class member to get rid of global variable
181
+ global miniwallet
182
+ miniwallet = MiniWallet (self .nodes [0 ], raw_script = True )
188
183
189
184
self .log .info ("Generate blocks in the past for coinbase outputs." )
190
185
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
191
186
self .nodes [0 ].setmocktime (long_past_time - 100 ) # enough so that the generated blocks will still all be before long_past_time
192
- self .coinbase_blocks = self . nodes [ 0 ] .generate (COINBASE_BLOCK_COUNT ) # blocks generated for inputs
187
+ self .coinbase_blocks = miniwallet .generate (COINBASE_BLOCK_COUNT ) # blocks generated for inputs
193
188
self .nodes [0 ].setmocktime (0 ) # set time back to present so yielded blocks aren't in the future as we advance last_block_time
194
189
self .tipheight = COINBASE_BLOCK_COUNT # height of the next block to build
195
190
self .last_block_time = long_past_time
196
191
self .tip = int (self .nodes [0 ].getbestblockhash (), 16 )
197
- self .nodeaddress = self .nodes [0 ].getnewaddress ()
198
192
199
193
# Activation height is hardcoded
200
194
# We advance to block height five below BIP112 activation for the following tests
@@ -209,31 +203,31 @@ def run_test(self):
209
203
# 16 normal inputs
210
204
bip68inputs = []
211
205
for _ in range (16 ):
212
- bip68inputs .append (send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks , self . nodeaddress ))
206
+ bip68inputs .append (send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks ))
213
207
214
208
# 2 sets of 16 inputs with 10 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
215
209
bip112basicinputs = []
216
210
for _ in range (2 ):
217
211
inputs = []
218
212
for _ in range (16 ):
219
- inputs .append (send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks , self . nodeaddress ))
213
+ inputs .append (send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks ))
220
214
bip112basicinputs .append (inputs )
221
215
222
216
# 2 sets of 16 varied inputs with (relative_lock_time) OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
223
217
bip112diverseinputs = []
224
218
for _ in range (2 ):
225
219
inputs = []
226
220
for _ in range (16 ):
227
- inputs .append (send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks , self . nodeaddress ))
221
+ inputs .append (send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks ))
228
222
bip112diverseinputs .append (inputs )
229
223
230
224
# 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
231
- bip112specialinput = send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks , self . nodeaddress )
225
+ bip112specialinput = send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks )
232
226
# 1 special input with (empty stack) OP_CSV (actually will be prepended to spending scriptSig)
233
- bip112emptystackinput = send_generic_input_tx (self .nodes [0 ],self . coinbase_blocks , self .nodeaddress )
227
+ bip112emptystackinput = send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks )
234
228
235
229
# 1 normal input
236
- bip113input = send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks , self . nodeaddress )
230
+ bip113input = send_generic_input_tx (self .nodes [0 ], self .coinbase_blocks )
237
231
238
232
self .nodes [0 ].setmocktime (self .last_block_time + 600 )
239
233
inputblockhash = self .nodes [0 ].generate (1 )[0 ] # 1 block generated for inputs to be in chain at height 431
@@ -253,36 +247,36 @@ def run_test(self):
253
247
254
248
# Test both version 1 and version 2 transactions for all tests
255
249
# BIP113 test transaction will be modified before each use to put in appropriate block time
256
- bip113tx_v1 = create_transaction (self .nodes [0 ], bip113input , self . nodeaddress , amount = Decimal ( "49.98" ) )
250
+ bip113tx_v1 = create_self_transfer_from_utxo (self .nodes [0 ], bip113input )
257
251
bip113tx_v1 .vin [0 ].nSequence = 0xFFFFFFFE
258
252
bip113tx_v1 .nVersion = 1
259
- bip113tx_v2 = create_transaction (self .nodes [0 ], bip113input , self . nodeaddress , amount = Decimal ( "49.98" ) )
253
+ bip113tx_v2 = create_self_transfer_from_utxo (self .nodes [0 ], bip113input )
260
254
bip113tx_v2 .vin [0 ].nSequence = 0xFFFFFFFE
261
255
bip113tx_v2 .nVersion = 2
262
256
263
257
# For BIP68 test all 16 relative sequence locktimes
264
- bip68txs_v1 = create_bip68txs (self .nodes [0 ], bip68inputs , 1 , self . nodeaddress )
265
- bip68txs_v2 = create_bip68txs (self .nodes [0 ], bip68inputs , 2 , self . nodeaddress )
258
+ bip68txs_v1 = create_bip68txs (self .nodes [0 ], bip68inputs , 1 )
259
+ bip68txs_v2 = create_bip68txs (self .nodes [0 ], bip68inputs , 2 )
266
260
267
261
# For BIP112 test:
268
262
# 16 relative sequence locktimes of 10 against 10 OP_CSV OP_DROP inputs
269
- bip112txs_vary_nSequence_v1 = create_bip112txs (self .nodes [0 ], bip112basicinputs [0 ], False , 1 , self . nodeaddress )
270
- bip112txs_vary_nSequence_v2 = create_bip112txs (self .nodes [0 ], bip112basicinputs [0 ], False , 2 , self . nodeaddress )
263
+ bip112txs_vary_nSequence_v1 = create_bip112txs (self .nodes [0 ], bip112basicinputs [0 ], False , 1 )
264
+ bip112txs_vary_nSequence_v2 = create_bip112txs (self .nodes [0 ], bip112basicinputs [0 ], False , 2 )
271
265
# 16 relative sequence locktimes of 9 against 10 OP_CSV OP_DROP inputs
272
- bip112txs_vary_nSequence_9_v1 = create_bip112txs (self .nodes [0 ], bip112basicinputs [1 ], False , 1 , self . nodeaddress , - 1 )
273
- bip112txs_vary_nSequence_9_v2 = create_bip112txs (self .nodes [0 ], bip112basicinputs [1 ], False , 2 , self . nodeaddress , - 1 )
266
+ bip112txs_vary_nSequence_9_v1 = create_bip112txs (self .nodes [0 ], bip112basicinputs [1 ], False , 1 , - 1 )
267
+ bip112txs_vary_nSequence_9_v2 = create_bip112txs (self .nodes [0 ], bip112basicinputs [1 ], False , 2 , - 1 )
274
268
# sequence lock time of 10 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
275
- bip112txs_vary_OP_CSV_v1 = create_bip112txs (self .nodes [0 ], bip112diverseinputs [0 ], True , 1 , self . nodeaddress )
276
- bip112txs_vary_OP_CSV_v2 = create_bip112txs (self .nodes [0 ], bip112diverseinputs [0 ], True , 2 , self . nodeaddress )
269
+ bip112txs_vary_OP_CSV_v1 = create_bip112txs (self .nodes [0 ], bip112diverseinputs [0 ], True , 1 )
270
+ bip112txs_vary_OP_CSV_v2 = create_bip112txs (self .nodes [0 ], bip112diverseinputs [0 ], True , 2 )
277
271
# sequence lock time of 9 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
278
- bip112txs_vary_OP_CSV_9_v1 = create_bip112txs (self .nodes [0 ], bip112diverseinputs [1 ], True , 1 , self . nodeaddress , - 1 )
279
- bip112txs_vary_OP_CSV_9_v2 = create_bip112txs (self .nodes [0 ], bip112diverseinputs [1 ], True , 2 , self . nodeaddress , - 1 )
272
+ bip112txs_vary_OP_CSV_9_v1 = create_bip112txs (self .nodes [0 ], bip112diverseinputs [1 ], True , 1 , - 1 )
273
+ bip112txs_vary_OP_CSV_9_v2 = create_bip112txs (self .nodes [0 ], bip112diverseinputs [1 ], True , 2 , - 1 )
280
274
# -1 OP_CSV OP_DROP input
281
- bip112tx_special_v1 = create_bip112special (self .nodes [0 ], bip112specialinput , 1 , self . nodeaddress )
282
- bip112tx_special_v2 = create_bip112special (self .nodes [0 ], bip112specialinput , 2 , self . nodeaddress )
275
+ bip112tx_special_v1 = create_bip112special (self .nodes [0 ], bip112specialinput , 1 )
276
+ bip112tx_special_v2 = create_bip112special (self .nodes [0 ], bip112specialinput , 2 )
283
277
# (empty stack) OP_CSV input
284
- bip112tx_emptystack_v1 = create_bip112emptystack (self .nodes [0 ], bip112emptystackinput , 1 , self . nodeaddress )
285
- bip112tx_emptystack_v2 = create_bip112emptystack (self .nodes [0 ], bip112emptystackinput , 2 , self . nodeaddress )
278
+ bip112tx_emptystack_v1 = create_bip112emptystack (self .nodes [0 ], bip112emptystackinput , 1 )
279
+ bip112tx_emptystack_v2 = create_bip112emptystack (self .nodes [0 ], bip112emptystackinput , 2 )
286
280
287
281
self .log .info ("TESTING" )
288
282
@@ -292,8 +286,8 @@ def run_test(self):
292
286
success_txs = []
293
287
# BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
294
288
bip113tx_v1 .nLockTime = self .last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
295
- bip113signed1 = sign_transaction ( self . nodes [ 0 ], bip113tx_v1 )
296
- success_txs .append (bip113signed1 )
289
+ bip113tx_v1 . rehash ( )
290
+ success_txs .append (bip113tx_v1 )
297
291
success_txs .append (bip112tx_special_v1 )
298
292
success_txs .append (bip112tx_emptystack_v1 )
299
293
# add BIP 68 txs
@@ -312,8 +306,8 @@ def run_test(self):
312
306
success_txs = []
313
307
# BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
314
308
bip113tx_v2 .nLockTime = self .last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
315
- bip113signed2 = sign_transaction ( self . nodes [ 0 ], bip113tx_v2 )
316
- success_txs .append (bip113signed2 )
309
+ bip113tx_v2 . rehash ( )
310
+ success_txs .append (bip113tx_v2 )
317
311
success_txs .append (bip112tx_special_v2 )
318
312
success_txs .append (bip112tx_emptystack_v2 )
319
313
# add BIP 68 txs
@@ -338,17 +332,18 @@ def run_test(self):
338
332
self .log .info ("BIP 113 tests" )
339
333
# BIP 113 tests should now fail regardless of version number if nLockTime isn't satisfied by new rules
340
334
bip113tx_v1 .nLockTime = self .last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
341
- bip113signed1 = sign_transaction ( self . nodes [ 0 ], bip113tx_v1 )
335
+ bip113tx_v1 . rehash ( )
342
336
bip113tx_v2 .nLockTime = self .last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
343
- bip113signed2 = sign_transaction ( self . nodes [ 0 ], bip113tx_v2 )
344
- for bip113tx in [bip113signed1 , bip113signed2 ]:
337
+ bip113tx_v2 . rehash ( )
338
+ for bip113tx in [bip113tx_v1 , bip113tx_v2 ]:
345
339
self .send_blocks ([self .create_test_block ([bip113tx ])], success = False , reject_reason = 'bad-txns-nonfinal' )
340
+
346
341
# BIP 113 tests should now pass if the locktime is < MTP
347
342
bip113tx_v1 .nLockTime = self .last_block_time - 600 * 5 - 1 # < MTP of prior block
348
- bip113signed1 = sign_transaction ( self . nodes [ 0 ], bip113tx_v1 )
343
+ bip113tx_v1 . rehash ( )
349
344
bip113tx_v2 .nLockTime = self .last_block_time - 600 * 5 - 1 # < MTP of prior block
350
- bip113signed2 = sign_transaction ( self . nodes [ 0 ], bip113tx_v2 )
351
- for bip113tx in [bip113signed1 , bip113signed2 ]:
345
+ bip113tx_v2 . rehash ( )
346
+ for bip113tx in [bip113tx_v1 , bip113tx_v2 ]:
352
347
self .send_blocks ([self .create_test_block ([bip113tx ])])
353
348
self .nodes [0 ].invalidateblock (self .nodes [0 ].getbestblockhash ())
354
349
@@ -471,8 +466,8 @@ def run_test(self):
471
466
time_txs = []
472
467
for tx in [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_v2 if not tx ['sdf' ] and tx ['stf' ]]:
473
468
tx .vin [0 ].nSequence = BASE_RELATIVE_LOCKTIME | SEQ_TYPE_FLAG
474
- signtx = sign_transaction ( self . nodes [ 0 ], tx )
475
- time_txs .append (signtx )
469
+ tx . rehash ( )
470
+ time_txs .append (tx )
476
471
477
472
self .send_blocks ([self .create_test_block (time_txs )])
478
473
self .nodes [0 ].invalidateblock (self .nodes [0 ].getbestblockhash ())
0 commit comments