3737bip112tx_special - test negative argument to OP_CSV
3838bip112tx_emptystack - test empty stack (= no argument) OP_CSV
3939"""
40- from decimal import Decimal
4140from itertools import product
42- from io import BytesIO
4341import time
4442
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+ )
4747from test_framework .p2p import P2PDataStore
4848from test_framework .script import (
4949 CScript ,
5353from test_framework .test_framework import BitcoinTestFramework
5454from test_framework .util import (
5555 assert_equal ,
56- hex_str_to_bytes ,
5756 softfork_active ,
5857)
58+ from test_framework .wallet import MiniWallet
5959
6060TESTING_TX_COUNT = 83 # Number of testing transactions: 1 BIP113 tx, 16 BIP68 txs, 66 BIP112 txs (see comments above)
6161COINBASE_BLOCK_COUNT = TESTING_TX_COUNT # Number of coinbase blocks we need to generate as inputs for our txs
@@ -83,80 +83,73 @@ def relative_locktime(sdf, srhb, stf, srlb):
8383def all_rlt_txs (txs ):
8484 return [tx ['tx' ] for tx in txs ]
8585
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 )
92- return tx
93-
94- def create_bip112special (node , input , txversion , address ):
95- tx = create_transaction (node , input , address , amount = Decimal ("49.98" ))
96- 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
100-
101- def create_bip112emptystack (node , input , txversion , address ):
102- tx = create_transaction (node , input , address , amount = Decimal ("49.98" ))
103- 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
107-
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" )))))
110-
111- def create_bip68txs (node , bip68inputs , txversion , address , locktime_delta = 0 ):
112- """Returns a list of bip68 transactions with different bits set."""
113- txs = []
114- assert len (bip68inputs ) >= 16
115- for i , (sdf , srhb , stf , srlb ) in enumerate (product (* [[True , False ]] * 4 )):
116- locktime = relative_locktime (sdf , srhb , stf , srlb )
117- tx = create_transaction (node , bip68inputs [i ], address , amount = Decimal ("49.98" ))
118- tx .nVersion = txversion
119- tx .vin [0 ].nSequence = locktime + locktime_delta
120- tx = sign_transaction (node , tx )
121- tx .rehash ()
122- txs .append ({'tx' : tx , 'sdf' : sdf , 'stf' : stf })
123-
124- return txs
125-
126- def create_bip112txs (node , bip112inputs , varyOP_CSV , txversion , address , locktime_delta = 0 ):
127- """Returns a list of bip68 transactions with different bits set."""
128- txs = []
129- assert len (bip112inputs ) >= 16
130- for i , (sdf , srhb , stf , srlb ) in enumerate (product (* [[True , False ]] * 4 )):
131- locktime = relative_locktime (sdf , srhb , stf , srlb )
132- tx = create_transaction (node , bip112inputs [i ], address , amount = Decimal ("49.98" ))
133- if (varyOP_CSV ): # if varying OP_CSV, nSequence is fixed
134- tx .vin [0 ].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
135- else : # vary nSequence instead, OP_CSV is fixed
136- tx .vin [0 ].nSequence = locktime + locktime_delta
137- tx .nVersion = txversion
138- signtx = sign_transaction (node , tx )
139- if (varyOP_CSV ):
140- signtx .vin [0 ].scriptSig = CScript ([locktime , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (signtx .vin [0 ].scriptSig )))
141- else :
142- signtx .vin [0 ].scriptSig = CScript ([BASE_RELATIVE_LOCKTIME , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (signtx .vin [0 ].scriptSig )))
143- tx .rehash ()
144- txs .append ({'tx' : signtx , 'sdf' : sdf , 'stf' : stf })
145- return txs
14686
14787class BIP68_112_113Test (BitcoinTestFramework ):
14888 def set_test_params (self ):
14989 self .num_nodes = 1
15090 self .setup_clean_chain = True
15191 self .extra_args = [[
15292153- '-addresstype=legacy ' ,
93+ '-acceptnonstdtxn=1 ' ,
15494 '-par=1' , # Use only one script thread to get the exact reject reason for testing
15595 ]]
15696 self .supports_cli = False
15797
158- def skip_test_if_missing_module (self ):
159- self .skip_if_no_wallet ()
98+ def create_self_transfer_from_utxo (self , input_tx ):
99+ utxo = self .miniwallet .get_utxo (txid = input_tx .rehash (), mark_as_spent = False )
100+ tx = self .miniwallet .create_self_transfer (from_node = self .nodes [0 ], utxo_to_spend = utxo )['tx' ]
101+ return tx
102+
103+ def create_bip112special (self , input , txversion ):
104+ tx = self .create_self_transfer_from_utxo (input )
105+ tx .nVersion = txversion
106+ tx .vin [0 ].scriptSig = CScript ([- 1 , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (tx .vin [0 ].scriptSig )))
107+ return tx
108+
109+ def create_bip112emptystack (self , input , txversion ):
110+ tx = self .create_self_transfer_from_utxo (input )
111+ tx .nVersion = txversion
112+ tx .vin [0 ].scriptSig = CScript ([OP_CHECKSEQUENCEVERIFY ] + list (CScript (tx .vin [0 ].scriptSig )))
113+ return tx
114+
115+ def send_generic_input_tx (self , coinbases ):
116+ input_txid = self .nodes [0 ].getblock (coinbases .pop (), 2 )['tx' ][0 ]['txid' ]
117+ utxo_to_spend = self .miniwallet .get_utxo (txid = input_txid )
118+ return self .miniwallet .send_self_transfer (from_node = self .nodes [0 ], utxo_to_spend = utxo_to_spend )['tx' ]
119+
120+ def create_bip68txs (self , bip68inputs , txversion , locktime_delta = 0 ):
121+ """Returns a list of bip68 transactions with different bits set."""
122+ txs = []
123+ assert len (bip68inputs ) >= 16
124+ for i , (sdf , srhb , stf , srlb ) in enumerate (product (* [[True , False ]] * 4 )):
125+ locktime = relative_locktime (sdf , srhb , stf , srlb )
126+ tx = self .create_self_transfer_from_utxo (bip68inputs [i ])
127+ tx .nVersion = txversion
128+ tx .vin [0 ].nSequence = locktime + locktime_delta
129+ tx .rehash ()
130+ txs .append ({'tx' : tx , 'sdf' : sdf , 'stf' : stf })
131+
132+ return txs
133+
134+ def create_bip112txs (self , bip112inputs , varyOP_CSV , txversion , locktime_delta = 0 ):
135+ """Returns a list of bip68 transactions with different bits set."""
136+ txs = []
137+ assert len (bip112inputs ) >= 16
138+ for i , (sdf , srhb , stf , srlb ) in enumerate (product (* [[True , False ]] * 4 )):
139+ locktime = relative_locktime (sdf , srhb , stf , srlb )
140+ tx = self .create_self_transfer_from_utxo (bip112inputs [i ])
141+ if (varyOP_CSV ): # if varying OP_CSV, nSequence is fixed
142+ tx .vin [0 ].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
143+ else : # vary nSequence instead, OP_CSV is fixed
144+ tx .vin [0 ].nSequence = locktime + locktime_delta
145+ tx .nVersion = txversion
146+ if (varyOP_CSV ):
147+ tx .vin [0 ].scriptSig = CScript ([locktime , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (tx .vin [0 ].scriptSig )))
148+ else :
149+ tx .vin [0 ].scriptSig = CScript ([BASE_RELATIVE_LOCKTIME , OP_CHECKSEQUENCEVERIFY , OP_DROP ] + list (CScript (tx .vin [0 ].scriptSig )))
150+ tx .rehash ()
151+ txs .append ({'tx' : tx , 'sdf' : sdf , 'stf' : stf })
152+ return txs
160153
161154 def generate_blocks (self , number ):
162155 test_blocks = []
@@ -185,16 +178,16 @@ def send_blocks(self, blocks, success=True, reject_reason=None):
185178
186179 def run_test (self ):
187180 self .helper_peer = self .nodes [0 ].add_p2p_connection (P2PDataStore ())
181+ self .miniwallet = MiniWallet (self .nodes [0 ], raw_script = True )
188182
189183 self .log .info ("Generate blocks in the past for coinbase outputs." )
190184 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
191185 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
186+ self .coinbase_blocks = self .miniwallet .generate (COINBASE_BLOCK_COUNT ) # blocks generated for inputs
193187 self .nodes [0 ].setmocktime (0 ) # set time back to present so yielded blocks aren't in the future as we advance last_block_time
194188 self .tipheight = COINBASE_BLOCK_COUNT # height of the next block to build
195189 self .last_block_time = long_past_time
196190 self .tip = int (self .nodes [0 ].getbestblockhash (), 16 )
197- self .nodeaddress = self .nodes [0 ].getnewaddress ()
198191
199192 # Activation height is hardcoded
200193 # We advance to block height five below BIP112 activation for the following tests
@@ -209,31 +202,31 @@ def run_test(self):
209202 # 16 normal inputs
210203 bip68inputs = []
211204 for _ in range (16 ):
212- bip68inputs .append (send_generic_input_tx (self .nodes [ 0 ], self . coinbase_blocks , self . nodeaddress ))
205+ bip68inputs .append (self . send_generic_input_tx (self .coinbase_blocks ))
213206
214207 # 2 sets of 16 inputs with 10 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
215208 bip112basicinputs = []
216209 for _ in range (2 ):
217210 inputs = []
218211 for _ in range (16 ):
219- inputs .append (send_generic_input_tx (self .nodes [ 0 ], self . coinbase_blocks , self . nodeaddress ))
212+ inputs .append (self . send_generic_input_tx (self .coinbase_blocks ))
220213 bip112basicinputs .append (inputs )
221214
222215 # 2 sets of 16 varied inputs with (relative_lock_time) OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
223216 bip112diverseinputs = []
224217 for _ in range (2 ):
225218 inputs = []
226219 for _ in range (16 ):
227- inputs .append (send_generic_input_tx (self .nodes [ 0 ], self . coinbase_blocks , self . nodeaddress ))
220+ inputs .append (self . send_generic_input_tx (self .coinbase_blocks ))
228221 bip112diverseinputs .append (inputs )
229222
230223 # 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 )
224+ bip112specialinput = self . send_generic_input_tx (self .coinbase_blocks )
232225 # 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 )
226+ bip112emptystackinput = self . send_generic_input_tx (self .coinbase_blocks )
234227
235228 # 1 normal input
236- bip113input = send_generic_input_tx (self .nodes [ 0 ], self . coinbase_blocks , self . nodeaddress )
229+ bip113input = self . send_generic_input_tx (self .coinbase_blocks )
237230
238231 self .nodes [0 ].setmocktime (self .last_block_time + 600 )
239232 inputblockhash = self .nodes [0 ].generate (1 )[0 ] # 1 block generated for inputs to be in chain at height 431
@@ -253,36 +246,36 @@ def run_test(self):
253246
254247 # Test both version 1 and version 2 transactions for all tests
255248 # 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" ) )
249+ bip113tx_v1 = self .create_self_transfer_from_utxo ( bip113input )
257250 bip113tx_v1 .vin [0 ].nSequence = 0xFFFFFFFE
258251 bip113tx_v1 .nVersion = 1
259- bip113tx_v2 = create_transaction ( self .nodes [ 0 ], bip113input , self . nodeaddress , amount = Decimal ( "49.98" ) )
252+ bip113tx_v2 = self .create_self_transfer_from_utxo ( bip113input )
260253 bip113tx_v2 .vin [0 ].nSequence = 0xFFFFFFFE
261254 bip113tx_v2 .nVersion = 2
262255
263256 # 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 )
257+ bip68txs_v1 = self .create_bip68txs ( bip68inputs , 1 )
258+ bip68txs_v2 = self .create_bip68txs ( bip68inputs , 2 )
266259
267260 # For BIP112 test:
268261 # 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 )
262+ bip112txs_vary_nSequence_v1 = self .create_bip112txs ( bip112basicinputs [0 ], False , 1 )
263+ bip112txs_vary_nSequence_v2 = self .create_bip112txs ( bip112basicinputs [0 ], False , 2 )
271264 # 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 )
265+ bip112txs_vary_nSequence_9_v1 = self .create_bip112txs ( bip112basicinputs [1 ], False , 1 , - 1 )
266+ bip112txs_vary_nSequence_9_v2 = self .create_bip112txs ( bip112basicinputs [1 ], False , 2 , - 1 )
274267 # 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 )
268+ bip112txs_vary_OP_CSV_v1 = self .create_bip112txs ( bip112diverseinputs [0 ], True , 1 )
269+ bip112txs_vary_OP_CSV_v2 = self .create_bip112txs ( bip112diverseinputs [0 ], True , 2 )
277270 # 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 )
271+ bip112txs_vary_OP_CSV_9_v1 = self .create_bip112txs ( bip112diverseinputs [1 ], True , 1 , - 1 )
272+ bip112txs_vary_OP_CSV_9_v2 = self .create_bip112txs ( bip112diverseinputs [1 ], True , 2 , - 1 )
280273 # -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 )
274+ bip112tx_special_v1 = self .create_bip112special ( bip112specialinput , 1 )
275+ bip112tx_special_v2 = self .create_bip112special ( bip112specialinput , 2 )
283276 # (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 )
277+ bip112tx_emptystack_v1 = self .create_bip112emptystack ( bip112emptystackinput , 1 )
278+ bip112tx_emptystack_v2 = self .create_bip112emptystack ( bip112emptystackinput , 2 )
286279
287280 self .log .info ("TESTING" )
288281
@@ -292,8 +285,8 @@ def run_test(self):
292285 success_txs = []
293286 # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
294287 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 )
288+ bip113tx_v1 . rehash ( )
289+ success_txs .append (bip113tx_v1 )
297290 success_txs .append (bip112tx_special_v1 )
298291 success_txs .append (bip112tx_emptystack_v1 )
299292 # add BIP 68 txs
@@ -312,8 +305,8 @@ def run_test(self):
312305 success_txs = []
313306 # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
314307 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 )
308+ bip113tx_v2 . rehash ( )
309+ success_txs .append (bip113tx_v2 )
317310 success_txs .append (bip112tx_special_v2 )
318311 success_txs .append (bip112tx_emptystack_v2 )
319312 # add BIP 68 txs
@@ -338,17 +331,18 @@ def run_test(self):
338331 self .log .info ("BIP 113 tests" )
339332 # BIP 113 tests should now fail regardless of version number if nLockTime isn't satisfied by new rules
340333 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 )
334+ bip113tx_v1 . rehash ( )
342335 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 ]:
336+ bip113tx_v2 . rehash ( )
337+ for bip113tx in [bip113tx_v1 , bip113tx_v2 ]:
345338 self .send_blocks ([self .create_test_block ([bip113tx ])], success = False , reject_reason = 'bad-txns-nonfinal' )
339+
346340 # BIP 113 tests should now pass if the locktime is < MTP
347341 bip113tx_v1 .nLockTime = self .last_block_time - 600 * 5 - 1 # < MTP of prior block
348- bip113signed1 = sign_transaction ( self . nodes [ 0 ], bip113tx_v1 )
342+ bip113tx_v1 . rehash ( )
349343 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 ]:
344+ bip113tx_v2 . rehash ( )
345+ for bip113tx in [bip113tx_v1 , bip113tx_v2 ]:
352346 self .send_blocks ([self .create_test_block ([bip113tx ])])
353347 self .nodes [0 ].invalidateblock (self .nodes [0 ].getbestblockhash ())
354348
@@ -471,8 +465,8 @@ def run_test(self):
471465 time_txs = []
472466 for tx in [tx ['tx' ] for tx in bip112txs_vary_OP_CSV_v2 if not tx ['sdf' ] and tx ['stf' ]]:
473467 tx .vin [0 ].nSequence = BASE_RELATIVE_LOCKTIME | SEQ_TYPE_FLAG
474- signtx = sign_transaction ( self . nodes [ 0 ], tx )
475- time_txs .append (signtx )
468+ tx . rehash ( )
469+ time_txs .append (tx )
476470
477471 self .send_blocks ([self .create_test_block (time_txs )])
478472 self .nodes [0 ].invalidateblock (self .nodes [0 ].getbestblockhash ())
0 commit comments