24
24
from test_framework .util import (
25
25
assert_equal ,
26
26
assert_raises_rpc_error ,
27
- find_vout_for_address ,
27
+ )
28
+ from test_framework .wallet import (
29
+ getnewdestination ,
30
+ MiniWallet ,
28
31
)
29
32
30
33
@@ -52,79 +55,67 @@ def items(self):
52
55
class RawTransactionsTest (BitcoinTestFramework ):
53
56
def set_test_params (self ):
54
57
self .setup_clean_chain = True
55
- self .num_nodes = 4
58
+ self .num_nodes = 3
56
59
self .extra_args = [
57
- ["-txindex" ],
58
60
["-txindex" ],
59
61
["-txindex" ],
60
62
[],
61
63
]
62
64
# whitelist all peers to speed up tx relay / mempool sync
63
65
for args in self .extra_args :
64
66
67
+ self .requires_wallet = self .is_specified_wallet_compiled ()
65
68
66
69
self .supports_cli = False
67
70
68
- def skip_test_if_missing_module (self ):
69
- self .skip_if_no_wallet ()
70
-
71
71
def setup_network (self ):
72
72
super ().setup_network ()
73
73
self .connect_nodes (0 , 2 )
74
74
75
75
def run_test (self ):
76
+ self .wallet = MiniWallet (self .nodes [0 ])
76
77
self .log .info ("Prepare some coins for multiple *rawtransaction commands" )
77
- self .generate (self .nodes [ 2 ], 1 )
78
+ self .generate (self .wallet , 10 )
78
79
self .generate (self .nodes [0 ], COINBASE_MATURITY + 1 )
79
- for amount in [1.5 , 1.0 , 5.0 ]:
80
- self .nodes [0 ].sendtoaddress (self .nodes [2 ].getnewaddress (), amount )
81
- self .sync_all ()
82
- self .generate (self .nodes [0 ], 5 )
83
80
84
81
self .getrawtransaction_tests ()
85
82
self .createrawtransaction_tests ()
86
- self .signrawtransactionwithwallet_tests ()
87
83
self .sendrawtransaction_tests ()
88
84
self .sendrawtransaction_testmempoolaccept_tests ()
89
85
self .decoderawtransaction_tests ()
90
86
self .transaction_version_number_tests ()
91
- if not self .options .descriptors :
87
+ if self . requires_wallet and not self .options .descriptors :
92
88
self .raw_multisig_transaction_legacy_tests ()
93
89
94
90
def getrawtransaction_tests (self ):
95
- addr = self .nodes [1 ].getnewaddress ()
96
- txid = self .nodes [0 ].sendtoaddress (addr , 10 )
91
+ tx = self .wallet .send_self_transfer (from_node = self .nodes [0 ])
97
92
self .generate (self .nodes [0 ], 1 )
98
- vout = find_vout_for_address (self .nodes [1 ], txid , addr )
99
- rawTx = self .nodes [1 ].createrawtransaction ([{'txid' : txid , 'vout' : vout }], {self .nodes [1 ].getnewaddress (): 9.999 })
100
- rawTxSigned = self .nodes [1 ].signrawtransactionwithwallet (rawTx )
101
- txId = self .nodes [1 ].sendrawtransaction (rawTxSigned ['hex' ])
102
- self .generateblock (self .nodes [0 ], output = self .nodes [0 ].getnewaddress (), transactions = [rawTxSigned ['hex' ]])
93
+ txId = tx ['txid' ]
103
94
err_msg = (
104
95
"No such mempool transaction. Use -txindex or provide a block hash to enable"
105
96
" blockchain transaction queries. Use gettransaction for wallet transactions."
106
97
)
107
98
108
- for n in [0 , 3 ]:
99
+ for n in [0 , 2 ]:
109
100
self .log .info (f"Test getrawtransaction { 'with' if n == 0 else 'without' } -txindex" )
110
101
111
102
if n == 0 :
112
103
# With -txindex.
113
104
# 1. valid parameters - only supply txid
114
- assert_equal (self .nodes [n ].getrawtransaction (txId ), rawTxSigned ['hex' ])
105
+ assert_equal (self .nodes [n ].getrawtransaction (txId ), tx ['hex' ])
115
106
116
107
# 2. valid parameters - supply txid and 0 for non-verbose
117
- assert_equal (self .nodes [n ].getrawtransaction (txId , 0 ), rawTxSigned ['hex' ])
108
+ assert_equal (self .nodes [n ].getrawtransaction (txId , 0 ), tx ['hex' ])
118
109
119
110
# 3. valid parameters - supply txid and False for non-verbose
120
- assert_equal (self .nodes [n ].getrawtransaction (txId , False ), rawTxSigned ['hex' ])
111
+ assert_equal (self .nodes [n ].getrawtransaction (txId , False ), tx ['hex' ])
121
112
122
113
# 4. valid parameters - supply txid and 1 for verbose.
123
114
# We only check the "hex" field of the output so we don't need to update this test every time the output format changes.
124
- assert_equal (self .nodes [n ].getrawtransaction (txId , 1 )["hex" ], rawTxSigned ['hex' ])
115
+ assert_equal (self .nodes [n ].getrawtransaction (txId , 1 )["hex" ], tx ['hex' ])
125
116
126
117
# 5. valid parameters - supply txid and True for non-verbose
127
- assert_equal (self .nodes [n ].getrawtransaction (txId , True )["hex" ], rawTxSigned ['hex' ])
118
+ assert_equal (self .nodes [n ].getrawtransaction (txId , True )["hex" ], tx ['hex' ])
128
119
else :
129
120
# Without -txindex, expect to raise.
130
121
for verbose in [None , 0 , False , 1 , True ]:
@@ -141,9 +132,9 @@ def getrawtransaction_tests(self):
141
132
assert_raises_rpc_error (- 1 , "not a boolean" , self .nodes [n ].getrawtransaction , txId , {})
142
133
143
134
# Make a tx by sending, then generate 2 blocks; block1 has the tx in it
144
- tx = self .nodes [ 2 ]. sendtoaddress ( self .nodes [1 ]. getnewaddress (), 1 )
135
+ tx = self .wallet . send_self_transfer ( from_node = self .nodes [2 ])[ 'txid' ]
145
136
block1 , block2 = self .generate (self .nodes [2 ], 2 )
146
- for n in [0 , 3 ]:
137
+ for n in [0 , 2 ]:
147
138
self .log .info (f"Test getrawtransaction { 'with' if n == 0 else 'without' } -txindex, with blockhash" )
148
139
# We should be able to get the raw transaction by providing the correct block
149
140
gottx = self .nodes [n ].getrawtransaction (txid = tx , verbose = True , blockhash = block1 )
@@ -200,20 +191,21 @@ def createrawtransaction_tests(self):
200
191
# sequence number out of range
201
192
for invalid_seq in [- 1 , 4294967296 ]:
202
193
inputs = [{'txid' : TXID , 'vout' : 1 , 'sequence' : invalid_seq }]
203
- outputs = {self .nodes [0 ].getnewaddress (): 1 }
194
+ address = getnewdestination ()[2 ]
195
+ outputs = {address : 1 }
204
196
assert_raises_rpc_error (- 8 , 'Invalid parameter, sequence number is out of range' ,
205
197
self .nodes [0 ].createrawtransaction , inputs , outputs )
206
198
# with valid sequence number
207
199
for valid_seq in [1000 , 4294967294 ]:
208
200
inputs = [{'txid' : TXID , 'vout' : 1 , 'sequence' : valid_seq }]
209
- outputs = {self .nodes [0 ].getnewaddress (): 1 }
201
+ address = getnewdestination ()[2 ]
202
+ outputs = {address : 1 }
210
203
rawtx = self .nodes [0 ].createrawtransaction (inputs , outputs )
211
204
decrawtx = self .nodes [0 ].decoderawtransaction (rawtx )
212
205
assert_equal (decrawtx ['vin' ][0 ]['sequence' ], valid_seq )
213
206
214
207
# Test `createrawtransaction` invalid `outputs`
215
- address = self .nodes [0 ].getnewaddress ()
216
- address2 = self .nodes [0 ].getnewaddress ()
208
+ address = getnewdestination ()[2 ]
217
209
assert_raises_rpc_error (- 1 , "JSON value is not an array as expected" , self .nodes [0 ].createrawtransaction , [], 'foo' )
218
210
self .nodes [0 ].createrawtransaction (inputs = [], outputs = {}) # Should not throw for backwards compatibility
219
211
self .nodes [0 ].createrawtransaction (inputs = [], outputs = [])
@@ -245,6 +237,7 @@ def createrawtransaction_tests(self):
245
237
self .nodes [2 ].createrawtransaction (inputs = [{'txid' : TXID , 'vout' : 9 }], outputs = [{address : 99 }]),
246
238
)
247
239
# Two outputs
240
+ address2 = getnewdestination ()[2 ]
248
241
tx = tx_from_hex (self .nodes [2 ].createrawtransaction (inputs = [{'txid' : TXID , 'vout' : 9 }], outputs = OrderedDict ([(address , 99 ), (address2 , 99 )])))
249
242
assert_equal (len (tx .vout ), 2 )
250
243
assert_equal (
@@ -259,122 +252,53 @@ def createrawtransaction_tests(self):
259
252
self .nodes [2 ].createrawtransaction (inputs = [{'txid' : TXID , 'vout' : 9 }], outputs = [{address : 99 }, {address2 : 99 }, {'data' : '99' }]),
260
253
)
261
254
262
- def signrawtransactionwithwallet_tests (self ):
263
- for type in ["bech32" , "p2sh-segwit" , "legacy" ]:
264
- self .log .info (f"Test signrawtransactionwithwallet with missing prevtx info ({ type } )" )
265
- addr = self .nodes [0 ].getnewaddress ("" , type )
266
- addrinfo = self .nodes [0 ].getaddressinfo (addr )
267
- pubkey = addrinfo ["scriptPubKey" ]
268
- inputs = [{'txid' : TXID , 'vout' : 3 , 'sequence' : 1000 }]
269
- outputs = {self .nodes [0 ].getnewaddress (): 1 }
270
- rawtx = self .nodes [0 ].createrawtransaction (inputs , outputs )
271
-
272
- prevtx = dict (txid = TXID , scriptPubKey = pubkey , vout = 3 , amount = 1 )
273
- succ = self .nodes [0 ].signrawtransactionwithwallet (rawtx , [prevtx ])
274
- assert succ ["complete" ]
275
-
276
- if type == "legacy" :
277
- del prevtx ["amount" ]
278
- succ = self .nodes [0 ].signrawtransactionwithwallet (rawtx , [prevtx ])
279
- assert succ ["complete" ]
280
- else :
281
- assert_raises_rpc_error (- 3 , "Missing amount" , self .nodes [0 ].signrawtransactionwithwallet , rawtx , [
282
- {
283
- "txid" : TXID ,
284
- "scriptPubKey" : pubkey ,
285
- "vout" : 3 ,
286
- }
287
- ])
288
-
289
- assert_raises_rpc_error (- 3 , "Missing vout" , self .nodes [0 ].signrawtransactionwithwallet , rawtx , [
290
- {
291
- "txid" : TXID ,
292
- "scriptPubKey" : pubkey ,
293
- "amount" : 1 ,
294
- }
295
- ])
296
- assert_raises_rpc_error (- 3 , "Missing txid" , self .nodes [0 ].signrawtransactionwithwallet , rawtx , [
297
- {
298
- "scriptPubKey" : pubkey ,
299
- "vout" : 3 ,
300
- "amount" : 1 ,
301
- }
302
- ])
303
- assert_raises_rpc_error (- 3 , "Missing scriptPubKey" , self .nodes [0 ].signrawtransactionwithwallet , rawtx , [
304
- {
305
- "txid" : TXID ,
306
- "vout" : 3 ,
307
- "amount" : 1
308
- }
309
- ])
310
-
311
255
def sendrawtransaction_tests (self ):
312
256
self .log .info ("Test sendrawtransaction with missing input" )
313
257
inputs = [{'txid' : TXID , 'vout' : 1 }] # won't exist
314
- outputs = {self .nodes [0 ].getnewaddress (): 4.998 }
258
+ address = getnewdestination ()[2 ]
259
+ outputs = {address : 4.998 }
315
260
rawtx = self .nodes [2 ].createrawtransaction (inputs , outputs )
316
- rawtx = self .nodes [2 ].signrawtransactionwithwallet (rawtx )
317
- assert_raises_rpc_error (- 25 , "bad-txns-inputs-missingorspent" , self .nodes [2 ].sendrawtransaction , rawtx ['hex' ])
261
+ assert_raises_rpc_error (- 25 , "bad-txns-inputs-missingorspent" , self .nodes [2 ].sendrawtransaction , rawtx )
318
262
319
263
def sendrawtransaction_testmempoolaccept_tests (self ):
320
264
self .log .info ("Test sendrawtransaction/testmempoolaccept with maxfeerate" )
321
265
fee_exceeds_max = "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)"
322
266
323
267
# Test a transaction with a small fee.
324
- txId = self .nodes [0 ].sendtoaddress (self .nodes [2 ].getnewaddress (), 1.0 )
325
- rawTx = self .nodes [0 ].getrawtransaction (txId , True )
326
- vout = next (o for o in rawTx ['vout' ] if o ['value' ] == Decimal ('1.00000000' ))
327
-
328
- self .sync_all ()
329
- inputs = [{"txid" : txId , "vout" : vout ['n' ]}]
330
- # Fee 10,000 satoshis, (1 - (10000 sat * 0.00000001 BTC/sat)) = 0.9999
331
- outputs = {self .nodes [0 ].getnewaddress (): Decimal ("0.99990000" )}
332
- rawTx = self .nodes [2 ].createrawtransaction (inputs , outputs )
333
- rawTxSigned = self .nodes [2 ].signrawtransactionwithwallet (rawTx )
334
- assert_equal (rawTxSigned ['complete' ], True )
335
- # Fee 10,000 satoshis, ~100 b transaction, fee rate should land around 100 sat/byte = 0.00100000 BTC/kB
268
+ # Fee rate is 0.00100000 BTC/kvB
269
+ tx = self .wallet .create_self_transfer (fee_rate = Decimal ('0.00100000' ))
336
270
# Thus, testmempoolaccept should reject
337
- testres = self .nodes [2 ].testmempoolaccept ([rawTxSigned ['hex' ]], 0.00001000 )[0 ]
271
+ testres = self .nodes [2 ].testmempoolaccept ([tx ['hex' ]], 0.00001000 )[0 ]
338
272
assert_equal (testres ['allowed' ], False )
339
273
assert_equal (testres ['reject-reason' ], 'max-fee-exceeded' )
340
274
# and sendrawtransaction should throw
341
- assert_raises_rpc_error (- 25 , fee_exceeds_max , self .nodes [2 ].sendrawtransaction , rawTxSigned ['hex' ], 0.00001000 )
275
+ assert_raises_rpc_error (- 25 , fee_exceeds_max , self .nodes [2 ].sendrawtransaction , tx ['hex' ], 0.00001000 )
342
276
# and the following calls should both succeed
343
- testres = self .nodes [2 ].testmempoolaccept (rawtxs = [rawTxSigned ['hex' ]])[0 ]
277
+ testres = self .nodes [2 ].testmempoolaccept (rawtxs = [tx ['hex' ]])[0 ]
344
278
assert_equal (testres ['allowed' ], True )
345
- self .nodes [2 ].sendrawtransaction (hexstring = rawTxSigned ['hex' ])
279
+ self .nodes [2 ].sendrawtransaction (hexstring = tx ['hex' ])
346
280
347
281
# Test a transaction with a large fee.
348
- txId = self .nodes [0 ].sendtoaddress (self .nodes [2 ].getnewaddress (), 1.0 )
349
- rawTx = self .nodes [0 ].getrawtransaction (txId , True )
350
- vout = next (o for o in rawTx ['vout' ] if o ['value' ] == Decimal ('1.00000000' ))
351
-
352
- self .sync_all ()
353
- inputs = [{"txid" : txId , "vout" : vout ['n' ]}]
354
- # Fee 2,000,000 satoshis, (1 - (2000000 sat * 0.00000001 BTC/sat)) = 0.98
355
- outputs = {self .nodes [0 ].getnewaddress () : Decimal ("0.98000000" )}
356
- rawTx = self .nodes [2 ].createrawtransaction (inputs , outputs )
357
- rawTxSigned = self .nodes [2 ].signrawtransactionwithwallet (rawTx )
358
- assert_equal (rawTxSigned ['complete' ], True )
359
- # Fee 2,000,000 satoshis, ~100 b transaction, fee rate should land around 20,000 sat/byte = 0.20000000 BTC/kB
282
+ # Fee rate is 0.20000000 BTC/kvB
283
+ tx = self .wallet .create_self_transfer (mempool_valid = False , from_node = self .nodes [0 ], fee_rate = Decimal ('0.20000000' ))
360
284
# Thus, testmempoolaccept should reject
361
- testres = self .nodes [2 ].testmempoolaccept ([rawTxSigned ['hex' ]])[0 ]
285
+ testres = self .nodes [2 ].testmempoolaccept ([tx ['hex' ]])[0 ]
362
286
assert_equal (testres ['allowed' ], False )
363
287
assert_equal (testres ['reject-reason' ], 'max-fee-exceeded' )
364
288
# and sendrawtransaction should throw
365
- assert_raises_rpc_error (- 25 , fee_exceeds_max , self .nodes [2 ].sendrawtransaction , rawTxSigned ['hex' ])
289
+ assert_raises_rpc_error (- 25 , fee_exceeds_max , self .nodes [2 ].sendrawtransaction , tx ['hex' ])
366
290
# and the following calls should both succeed
367
- testres = self .nodes [2 ].testmempoolaccept (rawtxs = [rawTxSigned ['hex' ]], maxfeerate = '0.20000000' )[0 ]
291
+ testres = self .nodes [2 ].testmempoolaccept (rawtxs = [tx ['hex' ]], maxfeerate = '0.20000000' )[0 ]
368
292
assert_equal (testres ['allowed' ], True )
369
- self .nodes [2 ].sendrawtransaction (hexstring = rawTxSigned ['hex' ], maxfeerate = '0.20000000' )
293
+ self .nodes [2 ].sendrawtransaction (hexstring = tx ['hex' ], maxfeerate = '0.20000000' )
370
294
371
295
self .log .info ("Test sendrawtransaction/testmempoolaccept with tx already in the chain" )
372
296
self .generate (self .nodes [2 ], 1 )
373
297
for node in self .nodes :
374
- testres = node .testmempoolaccept ([rawTxSigned ['hex' ]])[0 ]
298
+ testres = node .testmempoolaccept ([tx ['hex' ]])[0 ]
375
299
assert_equal (testres ['allowed' ], False )
376
300
assert_equal (testres ['reject-reason' ], 'txn-already-known' )
377
- assert_raises_rpc_error (- 27 , 'Transaction already in block chain' , node .sendrawtransaction , rawTxSigned ['hex' ])
301
+ assert_raises_rpc_error (- 27 , 'Transaction already in block chain' , node .sendrawtransaction , tx ['hex' ])
378
302
379
303
def decoderawtransaction_tests (self ):
380
304
self .log .info ("Test decoderawtransaction" )
0 commit comments