5
5
"""Test generation and spending of P2TR addresses."""
6
6
7
7
import random
8
+ import uuid
8
9
9
10
from decimal import Decimal
10
11
from test_framework .address import output_key_to_p2tr
@@ -229,89 +230,127 @@ def make_addr(treefn, keys, i):
229
230
230
231
def do_test_addr (self , comment , pattern , privmap , treefn , keys ):
231
232
self .log .info ("Testing %s address derivation" % comment )
233
+
234
+ # Create wallets
235
+ wallet_uuid = uuid .uuid4 ().hex
236
+ self .nodes [0 ].createwallet (wallet_name = f"privs_tr_enabled_{ wallet_uuid } " , descriptors = True , blank = True )
237
+ self .nodes [0 ].createwallet (wallet_name = f"pubs_tr_enabled_{ wallet_uuid } " , descriptors = True , blank = True , disable_private_keys = True )
238
+ self .nodes [0 ].createwallet (wallet_name = f"addr_gen_{ wallet_uuid } " , descriptors = True , disable_private_keys = True , blank = True )
239
+ privs_tr_enabled = self .nodes [0 ].get_wallet_rpc (f"privs_tr_enabled_{ wallet_uuid } " )
240
+ pubs_tr_enabled = self .nodes [0 ].get_wallet_rpc (f"pubs_tr_enabled_{ wallet_uuid } " )
241
+ addr_gen = self .nodes [0 ].get_wallet_rpc (f"addr_gen_{ wallet_uuid } " )
242
+
232
243
desc = self .make_desc (pattern , privmap , keys , False )
233
244
desc_pub = self .make_desc (pattern , privmap , keys , True )
234
245
assert_equal (self .nodes [0 ].getdescriptorinfo (desc )['descriptor' ], desc_pub )
235
- result = self . addr_gen .importdescriptors ([{"desc" : desc_pub , "active" : True , "timestamp" : "now" }])
246
+ result = addr_gen .importdescriptors ([{"desc" : desc_pub , "active" : True , "timestamp" : "now" }])
236
247
assert (result [0 ]['success' ])
248
+ address_type = "bech32m" if "tr" in pattern else "bech32"
237
249
for i in range (4 ):
238
- addr_g = self . addr_gen .getnewaddress (address_type = 'bech32m' )
250
+ addr_g = addr_gen .getnewaddress (address_type = address_type )
239
251
if treefn is not None :
240
252
addr_r = self .make_addr (treefn , keys , i )
241
253
assert_equal (addr_g , addr_r )
242
- desc_a = self . addr_gen .getaddressinfo (addr_g )['desc' ]
254
+ desc_a = addr_gen .getaddressinfo (addr_g )['desc' ]
243
255
if desc .startswith ("tr(" ):
244
256
assert desc_a .startswith ("tr(" )
245
257
rederive = self .nodes [1 ].deriveaddresses (desc_a )
246
258
assert_equal (len (rederive ), 1 )
247
259
assert_equal (rederive [0 ], addr_g )
248
260
249
261
# tr descriptors can be imported
250
- result = self . privs_tr_enabled .importdescriptors ([{"desc" : desc , "timestamp" : "now" }])
262
+ result = privs_tr_enabled .importdescriptors ([{"desc" : desc , "timestamp" : "now" }])
251
263
assert (result [0 ]["success" ])
252
- result = self . pubs_tr_enabled .importdescriptors ([{"desc" : desc_pub , "timestamp" : "now" }])
264
+ result = pubs_tr_enabled .importdescriptors ([{"desc" : desc_pub , "timestamp" : "now" }])
253
265
assert (result [0 ]["success" ])
254
266
267
+ # Cleanup
268
+ privs_tr_enabled .unloadwallet ()
269
+ pubs_tr_enabled .unloadwallet ()
270
+ addr_gen .unloadwallet ()
271
+
255
272
def do_test_sendtoaddress (self , comment , pattern , privmap , treefn , keys_pay , keys_change ):
256
273
self .log .info ("Testing %s through sendtoaddress" % comment )
274
+
275
+ # Create wallets
276
+ wallet_uuid = uuid .uuid4 ().hex
277
+ self .nodes [0 ].createwallet (wallet_name = f"rpc_online_{ wallet_uuid } " , descriptors = True , blank = True )
278
+ rpc_online = self .nodes [0 ].get_wallet_rpc (f"rpc_online_{ wallet_uuid } " )
279
+
257
280
desc_pay = self .make_desc (pattern , privmap , keys_pay )
258
281
desc_change = self .make_desc (pattern , privmap , keys_change )
259
282
desc_pay_pub = self .make_desc (pattern , privmap , keys_pay , True )
260
283
desc_change_pub = self .make_desc (pattern , privmap , keys_change , True )
261
284
assert_equal (self .nodes [0 ].getdescriptorinfo (desc_pay )['descriptor' ], desc_pay_pub )
262
285
assert_equal (self .nodes [0 ].getdescriptorinfo (desc_change )['descriptor' ], desc_change_pub )
263
- result = self . rpc_online .importdescriptors ([{"desc" : desc_pay , "active" : True , "timestamp" : "now" }])
286
+ result = rpc_online .importdescriptors ([{"desc" : desc_pay , "active" : True , "timestamp" : "now" }])
264
287
assert (result [0 ]['success' ])
265
- result = self . rpc_online .importdescriptors ([{"desc" : desc_change , "active" : True , "timestamp" : "now" , "internal" : True }])
288
+ result = rpc_online .importdescriptors ([{"desc" : desc_change , "active" : True , "timestamp" : "now" , "internal" : True }])
266
289
assert (result [0 ]['success' ])
290
+ address_type = "bech32m" if "tr" in pattern else "bech32"
267
291
for i in range (4 ):
268
- addr_g = self . rpc_online .getnewaddress (address_type = 'bech32m' )
292
+ addr_g = rpc_online .getnewaddress (address_type = address_type )
269
293
if treefn is not None :
270
294
addr_r = self .make_addr (treefn , keys_pay , i )
271
295
assert_equal (addr_g , addr_r )
272
296
boring_balance = int (self .boring .getbalance () * 100000000 )
273
297
to_amnt = random .randrange (1000000 , boring_balance )
274
298
self .boring .sendtoaddress (address = addr_g , amount = Decimal (to_amnt ) / 100000000 , subtractfeefromamount = True )
275
299
self .generatetoaddress (self .nodes [0 ], 1 , self .boring .getnewaddress (), sync_fun = self .no_op )
276
- test_balance = int (self . rpc_online .getbalance () * 100000000 )
300
+ test_balance = int (rpc_online .getbalance () * 100000000 )
277
301
ret_amnt = random .randrange (100000 , test_balance )
278
302
# Increase fee_rate to compensate for the wallet's inability to estimate fees for script path spends.
279
- res = self . rpc_online .sendtoaddress (address = self .boring .getnewaddress (), amount = Decimal (ret_amnt ) / 100000000 , subtractfeefromamount = True , fee_rate = 200 )
303
+ res = rpc_online .sendtoaddress (address = self .boring .getnewaddress (), amount = Decimal (ret_amnt ) / 100000000 , subtractfeefromamount = True , fee_rate = 200 )
280
304
self .generatetoaddress (self .nodes [0 ], 1 , self .boring .getnewaddress (), sync_fun = self .no_op )
281
- assert (self .rpc_online .gettransaction (res )["confirmations" ] > 0 )
305
+ assert (rpc_online .gettransaction (res )["confirmations" ] > 0 )
306
+
307
+ # Cleanup
308
+ txid = rpc_online .sendall (recipients = [self .boring .getnewaddress ()])["txid" ]
309
+ self .generatetoaddress (self .nodes [0 ], 1 , self .boring .getnewaddress (), sync_fun = self .no_op )
310
+ assert (rpc_online .gettransaction (txid )["confirmations" ] > 0 )
311
+ rpc_online .unloadwallet ()
282
312
283
313
def do_test_psbt (self , comment , pattern , privmap , treefn , keys_pay , keys_change ):
284
314
self .log .info ("Testing %s through PSBT" % comment )
315
+
316
+ # Create wallets
317
+ wallet_uuid = uuid .uuid4 ().hex
318
+ self .nodes [0 ].createwallet (wallet_name = f"psbt_online_{ wallet_uuid } " , descriptors = True , disable_private_keys = True , blank = True )
319
+ self .nodes [1 ].createwallet (wallet_name = f"psbt_offline_{ wallet_uuid } " , descriptors = True , blank = True )
320
+ psbt_online = self .nodes [0 ].get_wallet_rpc (f"psbt_online_{ wallet_uuid } " )
321
+ psbt_offline = self .nodes [1 ].get_wallet_rpc (f"psbt_offline_{ wallet_uuid } " )
322
+
285
323
desc_pay = self .make_desc (pattern , privmap , keys_pay , False )
286
324
desc_change = self .make_desc (pattern , privmap , keys_change , False )
287
325
desc_pay_pub = self .make_desc (pattern , privmap , keys_pay , True )
288
326
desc_change_pub = self .make_desc (pattern , privmap , keys_change , True )
289
327
assert_equal (self .nodes [0 ].getdescriptorinfo (desc_pay )['descriptor' ], desc_pay_pub )
290
328
assert_equal (self .nodes [0 ].getdescriptorinfo (desc_change )['descriptor' ], desc_change_pub )
291
- result = self . psbt_online .importdescriptors ([{"desc" : desc_pay_pub , "active" : True , "timestamp" : "now" }])
329
+ result = psbt_online .importdescriptors ([{"desc" : desc_pay_pub , "active" : True , "timestamp" : "now" }])
292
330
assert (result [0 ]['success' ])
293
- result = self . psbt_online .importdescriptors ([{"desc" : desc_change_pub , "active" : True , "timestamp" : "now" , "internal" : True }])
331
+ result = psbt_online .importdescriptors ([{"desc" : desc_change_pub , "active" : True , "timestamp" : "now" , "internal" : True }])
294
332
assert (result [0 ]['success' ])
295
- result = self . psbt_offline .importdescriptors ([{"desc" : desc_pay , "active" : True , "timestamp" : "now" }])
333
+ result = psbt_offline .importdescriptors ([{"desc" : desc_pay , "active" : True , "timestamp" : "now" }])
296
334
assert (result [0 ]['success' ])
297
- result = self . psbt_offline .importdescriptors ([{"desc" : desc_change , "active" : True , "timestamp" : "now" , "internal" : True }])
335
+ result = psbt_offline .importdescriptors ([{"desc" : desc_change , "active" : True , "timestamp" : "now" , "internal" : True }])
298
336
assert (result [0 ]['success' ])
337
+ address_type = "bech32m" if "tr" in pattern else "bech32"
299
338
for i in range (4 ):
300
- addr_g = self . psbt_online .getnewaddress (address_type = 'bech32m' )
339
+ addr_g = psbt_online .getnewaddress (address_type = address_type )
301
340
if treefn is not None :
302
341
addr_r = self .make_addr (treefn , keys_pay , i )
303
342
assert_equal (addr_g , addr_r )
304
343
boring_balance = int (self .boring .getbalance () * 100000000 )
305
344
to_amnt = random .randrange (1000000 , boring_balance )
306
345
self .boring .sendtoaddress (address = addr_g , amount = Decimal (to_amnt ) / 100000000 , subtractfeefromamount = True )
307
346
self .generatetoaddress (self .nodes [0 ], 1 , self .boring .getnewaddress (), sync_fun = self .no_op )
308
- test_balance = int (self . psbt_online .getbalance () * 100000000 )
347
+ test_balance = int (psbt_online .getbalance () * 100000000 )
309
348
ret_amnt = random .randrange (100000 , test_balance )
310
349
# Increase fee_rate to compensate for the wallet's inability to estimate fees for script path spends.
311
- psbt = self . psbt_online .walletcreatefundedpsbt ([], [{self .boring .getnewaddress (): Decimal (ret_amnt ) / 100000000 }], None , {"subtractFeeFromOutputs" :[0 ], "fee_rate" : 200 , "change_type" : "bech32m" })['psbt' ]
312
- res = self . psbt_offline .walletprocesspsbt (psbt = psbt , finalize = False )
350
+ psbt = psbt_online .walletcreatefundedpsbt ([], [{self .boring .getnewaddress (): Decimal (ret_amnt ) / 100000000 }], None , {"subtractFeeFromOutputs" :[0 ], "fee_rate" : 200 , "change_type" : address_type })['psbt' ]
351
+ res = psbt_offline .walletprocesspsbt (psbt = psbt , finalize = False )
313
352
314
- decoded = self . psbt_offline .decodepsbt (res ["psbt" ])
353
+ decoded = psbt_offline .decodepsbt (res ["psbt" ])
315
354
if pattern .startswith ("tr(" ):
316
355
for psbtin in decoded ["inputs" ]:
317
356
assert "non_witness_utxo" not in psbtin
@@ -326,7 +365,17 @@ def do_test_psbt(self, comment, pattern, privmap, treefn, keys_pay, keys_change)
326
365
rawtx = self .nodes [0 ].finalizepsbt (res ['psbt' ])['hex' ]
327
366
txid = self .nodes [0 ].sendrawtransaction (rawtx )
328
367
self .generatetoaddress (self .nodes [0 ], 1 , self .boring .getnewaddress (), sync_fun = self .no_op )
329
- assert (self .psbt_online .gettransaction (txid )['confirmations' ] > 0 )
368
+ assert (psbt_online .gettransaction (txid )['confirmations' ] > 0 )
369
+
370
+ # Cleanup
371
+ psbt = psbt_online .sendall (recipients = [self .boring .getnewaddress ()], options = {"psbt" : True })["psbt" ]
372
+ res = psbt_offline .walletprocesspsbt (psbt = psbt , finalize = False )
373
+ rawtx = self .nodes [0 ].finalizepsbt (res ['psbt' ])['hex' ]
374
+ txid = self .nodes [0 ].sendrawtransaction (rawtx )
375
+ self .generatetoaddress (self .nodes [0 ], 1 , self .boring .getnewaddress (), sync_fun = self .no_op )
376
+ assert (psbt_online .gettransaction (txid )['confirmations' ] > 0 )
377
+ psbt_online .unloadwallet ()
378
+ psbt_offline .unloadwallet ()
330
379
331
380
def do_test (self , comment , pattern , privmap , treefn ):
332
381
nkeys = len (privmap )
@@ -336,21 +385,8 @@ def do_test(self, comment, pattern, privmap, treefn):
336
385
self .do_test_psbt (comment , pattern , privmap , treefn , keys [2 * nkeys :3 * nkeys ], keys [3 * nkeys :4 * nkeys ])
337
386
338
387
def run_test (self ):
339
- self .log .info ("Creating wallets..." )
340
- self .nodes [0 ].createwallet (wallet_name = "privs_tr_enabled" , descriptors = True , blank = True )
341
- self .privs_tr_enabled = self .nodes [0 ].get_wallet_rpc ("privs_tr_enabled" )
342
- self .nodes [0 ].createwallet (wallet_name = "pubs_tr_enabled" , descriptors = True , blank = True , disable_private_keys = True )
343
- self .pubs_tr_enabled = self .nodes [0 ].get_wallet_rpc ("pubs_tr_enabled" )
344
388
self .nodes [0 ].createwallet (wallet_name = "boring" )
345
- self .nodes [0 ].createwallet (wallet_name = "addr_gen" , descriptors = True , disable_private_keys = True , blank = True )
346
- self .nodes [0 ].createwallet (wallet_name = "rpc_online" , descriptors = True , blank = True )
347
- self .nodes [0 ].createwallet (wallet_name = "psbt_online" , descriptors = True , disable_private_keys = True , blank = True )
348
- self .nodes [1 ].createwallet (wallet_name = "psbt_offline" , descriptors = True , blank = True )
349
389
self .boring = self .nodes [0 ].get_wallet_rpc ("boring" )
350
- self .addr_gen = self .nodes [0 ].get_wallet_rpc ("addr_gen" )
351
- self .rpc_online = self .nodes [0 ].get_wallet_rpc ("rpc_online" )
352
- self .psbt_online = self .nodes [0 ].get_wallet_rpc ("psbt_online" )
353
- self .psbt_offline = self .nodes [1 ].get_wallet_rpc ("psbt_offline" )
354
390
355
391
self .log .info ("Mining blocks..." )
356
392
gen_addr = self .boring .getnewaddress ()
@@ -460,18 +496,5 @@ def run_test(self):
460
496
lambda k1 : key (k1 )
461
497
)
462
498
463
- self .log .info ("Sending everything back..." )
464
-
465
- txid = self .rpc_online .sendall (recipients = [self .boring .getnewaddress ()])["txid" ]
466
- self .generatetoaddress (self .nodes [0 ], 1 , self .boring .getnewaddress (), sync_fun = self .no_op )
467
- assert (self .rpc_online .gettransaction (txid )["confirmations" ] > 0 )
468
-
469
- psbt = self .psbt_online .sendall (recipients = [self .boring .getnewaddress ()], options = {"psbt" : True })["psbt" ]
470
- res = self .psbt_offline .walletprocesspsbt (psbt = psbt , finalize = False )
471
- rawtx = self .nodes [0 ].finalizepsbt (res ['psbt' ])['hex' ]
472
- txid = self .nodes [0 ].sendrawtransaction (rawtx )
473
- self .generatetoaddress (self .nodes [0 ], 1 , self .boring .getnewaddress (), sync_fun = self .no_op )
474
- assert (self .psbt_online .gettransaction (txid )['confirmations' ] > 0 )
475
-
476
499
if __name__ == '__main__' :
477
500
WalletTaprootTest ().main ()
0 commit comments