6
6
7
7
import random
8
8
9
+ from decimal import Decimal
9
10
from test_framework .test_framework import BitcoinTestFramework
10
11
from test_framework .util import assert_equal
11
12
from test_framework .descriptors import descsum_create
@@ -233,20 +234,85 @@ def do_test_addr(self, comment, pattern, privmap, treefn, keys):
233
234
# tr descriptors cannot be imported when Taproot is not active
234
235
result = self .privs_tr_enabled .importdescriptors ([{"desc" : desc , "timestamp" : "now" }])
235
236
assert (result [0 ]["success" ])
236
- result = self .privs_tr_disabled .importdescriptors ([{"desc" : desc , "timestamp" : "now" }])
237
- assert (not result [0 ]["success" ])
238
- assert_equal (result [0 ]["error" ]["code" ], - 4 )
239
- assert_equal (result [0 ]["error" ]["message" ], "Cannot import tr() descriptor when Taproot is not active" )
240
237
result = self .pubs_tr_enabled .importdescriptors ([{"desc" : desc_pub , "timestamp" : "now" }])
241
238
assert (result [0 ]["success" ])
242
- result = self .pubs_tr_disabled .importdescriptors ([{"desc" : desc_pub , "timestamp" : "now" }])
243
- assert (not result [0 ]["success" ])
244
- assert_equal (result [0 ]["error" ]["code" ], - 4 )
245
- assert_equal (result [0 ]["error" ]["message" ], "Cannot import tr() descriptor when Taproot is not active" )
239
+ if desc .startswith ("tr" ):
240
+ result = self .privs_tr_disabled .importdescriptors ([{"desc" : desc , "timestamp" : "now" }])
241
+ assert (not result [0 ]["success" ])
242
+ assert_equal (result [0 ]["error" ]["code" ], - 4 )
243
+ assert_equal (result [0 ]["error" ]["message" ], "Cannot import tr() descriptor when Taproot is not active" )
244
+ result = self .pubs_tr_disabled .importdescriptors ([{"desc" : desc_pub , "timestamp" : "now" }])
245
+ assert (not result [0 ]["success" ])
246
+ assert_equal (result [0 ]["error" ]["code" ], - 4 )
247
+ assert_equal (result [0 ]["error" ]["message" ], "Cannot import tr() descriptor when Taproot is not active" )
248
+
249
+ def do_test_sendtoaddress (self , comment , pattern , privmap , treefn , keys_pay , keys_change ):
250
+ self .log .info ("Testing %s through sendtoaddress" % comment )
251
+ desc_pay = self .make_desc (pattern , privmap , keys_pay )
252
+ desc_change = self .make_desc (pattern , privmap , keys_change )
253
+ desc_pay_pub = self .make_desc (pattern , privmap , keys_pay , True )
254
+ desc_change_pub = self .make_desc (pattern , privmap , keys_change , True )
255
+ assert_equal (self .nodes [0 ].getdescriptorinfo (desc_pay )['descriptor' ], desc_pay_pub )
256
+ assert_equal (self .nodes [0 ].getdescriptorinfo (desc_change )['descriptor' ], desc_change_pub )
257
+ result = self .rpc_online .importdescriptors ([{"desc" : desc_pay , "active" : True , "timestamp" : "now" }])
258
+ assert (result [0 ]['success' ])
259
+ result = self .rpc_online .importdescriptors ([{"desc" : desc_change , "active" : True , "timestamp" : "now" , "internal" : True }])
260
+ assert (result [0 ]['success' ])
261
+ for i in range (4 ):
262
+ addr_g = self .rpc_online .getnewaddress (address_type = 'bech32' )
263
+ if treefn is not None :
264
+ addr_r = self .make_addr (treefn , keys_pay , i )
265
+ assert_equal (addr_g , addr_r )
266
+ boring_balance = int (self .boring .getbalance () * 100000000 )
267
+ to_amnt = random .randrange (1000000 , boring_balance )
268
+ self .boring .sendtoaddress (address = addr_g , amount = Decimal (to_amnt ) / 100000000 , subtractfeefromamount = True )
269
+ self .nodes [0 ].generatetoaddress (1 , self .boring .getnewaddress ())
270
+ test_balance = int (self .rpc_online .getbalance () * 100000000 )
271
+ ret_amnt = random .randrange (100000 , test_balance )
272
+ res = self .rpc_online .sendtoaddress (address = self .boring .getnewaddress (), amount = Decimal (ret_amnt ) / 100000000 , subtractfeefromamount = True )
273
+ self .nodes [0 ].generatetoaddress (1 , self .boring .getnewaddress ())
274
+ assert (self .rpc_online .gettransaction (res )["confirmations" ] > 0 )
275
+
276
+ def do_test_psbt (self , comment , pattern , privmap , treefn , keys_pay , keys_change ):
277
+ self .log .info ("Testing %s through PSBT" % comment )
278
+ desc_pay = self .make_desc (pattern , privmap , keys_pay , False )
279
+ desc_change = self .make_desc (pattern , privmap , keys_change , False )
280
+ desc_pay_pub = self .make_desc (pattern , privmap , keys_pay , True )
281
+ desc_change_pub = self .make_desc (pattern , privmap , keys_change , True )
282
+ assert_equal (self .nodes [0 ].getdescriptorinfo (desc_pay )['descriptor' ], desc_pay_pub )
283
+ assert_equal (self .nodes [0 ].getdescriptorinfo (desc_change )['descriptor' ], desc_change_pub )
284
+ result = self .psbt_online .importdescriptors ([{"desc" : desc_pay_pub , "active" : True , "timestamp" : "now" }])
285
+ assert (result [0 ]['success' ])
286
+ result = self .psbt_online .importdescriptors ([{"desc" : desc_change_pub , "active" : True , "timestamp" : "now" , "internal" : True }])
287
+ assert (result [0 ]['success' ])
288
+ result = self .psbt_offline .importdescriptors ([{"desc" : desc_pay , "active" : True , "timestamp" : "now" }])
289
+ assert (result [0 ]['success' ])
290
+ result = self .psbt_offline .importdescriptors ([{"desc" : desc_change , "active" : True , "timestamp" : "now" , "internal" : True }])
291
+ assert (result [0 ]['success' ])
292
+ for i in range (4 ):
293
+ addr_g = self .psbt_online .getnewaddress (address_type = 'bech32' )
294
+ if treefn is not None :
295
+ addr_r = self .make_addr (treefn , keys_pay , i )
296
+ assert_equal (addr_g , addr_r )
297
+ boring_balance = int (self .boring .getbalance () * 100000000 )
298
+ to_amnt = random .randrange (1000000 , boring_balance )
299
+ self .boring .sendtoaddress (address = addr_g , amount = Decimal (to_amnt ) / 100000000 , subtractfeefromamount = True )
300
+ self .nodes [0 ].generatetoaddress (1 , self .boring .getnewaddress ())
301
+ test_balance = int (self .psbt_online .getbalance () * 100000000 )
302
+ ret_amnt = random .randrange (100000 , test_balance )
303
+ psbt = self .psbt_online .walletcreatefundedpsbt ([], [{self .boring .getnewaddress (): Decimal (ret_amnt ) / 100000000 }], None , {"subtractFeeFromOutputs" :[0 ]})['psbt' ]
304
+ res = self .psbt_offline .walletprocesspsbt (psbt )
305
+ assert (res ['complete' ])
306
+ rawtx = self .nodes [0 ].finalizepsbt (res ['psbt' ])['hex' ]
307
+ txid = self .nodes [0 ].sendrawtransaction (rawtx )
308
+ self .nodes [0 ].generatetoaddress (1 , self .boring .getnewaddress ())
309
+ assert (self .psbt_online .gettransaction (txid )['confirmations' ] > 0 )
246
310
247
311
def do_test (self , comment , pattern , privmap , treefn , nkeys ):
248
- keys = self .rand_keys (nkeys )
249
- self .do_test_addr (comment , pattern , privmap , treefn , keys )
312
+ keys = self .rand_keys (nkeys * 4 )
313
+ self .do_test_addr (comment , pattern , privmap , treefn , keys [0 :nkeys ])
314
+ self .do_test_sendtoaddress (comment , pattern , privmap , treefn , keys [0 :nkeys ], keys [nkeys :2 * nkeys ])
315
+ self .do_test_psbt (comment , pattern , privmap , treefn , keys [2 * nkeys :3 * nkeys ], keys [3 * nkeys :4 * nkeys ])
250
316
251
317
def run_test (self ):
252
318
self .log .info ("Creating wallets..." )
@@ -258,8 +324,20 @@ def run_test(self):
258
324
self .pubs_tr_enabled = self .nodes [0 ].get_wallet_rpc ("pubs_tr_enabled" )
259
325
self .nodes [2 ].createwallet (wallet_name = "pubs_tr_disabled" , descriptors = True , blank = True , disable_private_keys = True )
260
326
self .pubs_tr_disabled = self .nodes [2 ].get_wallet_rpc ("pubs_tr_disabled" )
327
+ self .nodes [0 ].createwallet (wallet_name = "boring" )
261
328
self .nodes [0 ].createwallet (wallet_name = "addr_gen" , descriptors = True , disable_private_keys = True , blank = True )
329
+ self .nodes [0 ].createwallet (wallet_name = "rpc_online" , descriptors = True , blank = True )
330
+ self .nodes [0 ].createwallet (wallet_name = "psbt_online" , descriptors = True , disable_private_keys = True , blank = True )
331
+ self .nodes [1 ].createwallet (wallet_name = "psbt_offline" , descriptors = True , blank = True )
332
+ self .boring = self .nodes [0 ].get_wallet_rpc ("boring" )
262
333
self .addr_gen = self .nodes [0 ].get_wallet_rpc ("addr_gen" )
334
+ self .rpc_online = self .nodes [0 ].get_wallet_rpc ("rpc_online" )
335
+ self .psbt_online = self .nodes [0 ].get_wallet_rpc ("psbt_online" )
336
+ self .psbt_offline = self .nodes [1 ].get_wallet_rpc ("psbt_offline" )
337
+
338
+ self .log .info ("Mining blocks..." )
339
+ gen_addr = self .boring .getnewaddress ()
340
+ self .nodes [0 ].generatetoaddress (101 , gen_addr )
263
341
264
342
self .do_test (
265
343
"tr(XPRV)" ,
@@ -275,13 +353,27 @@ def run_test(self):
275
353
lambda k1 : (key (H_POINT ), [pk (k1 )]),
276
354
1
277
355
)
356
+ self .do_test (
357
+ "wpkh(XPRV)" ,
358
+ "wpkh($1/*)" ,
359
+ [True ],
360
+ None ,
361
+ 1
362
+ )
278
363
self .do_test (
279
364
"tr(XPRV,{H,{H,XPUB}})" ,
280
365
"tr($1/*,{pk($H),{pk($H),pk($2/*)}})" ,
281
366
[True , False ],
282
367
lambda k1 , k2 : (key (k1 ), [pk (H_POINT ), [pk (H_POINT ), pk (k2 )]]),
283
368
2
284
369
)
370
+ self .do_test (
371
+ "wsh(multi(1,XPRV,XPUB))" ,
372
+ "wsh(multi(1,$1/*,$2/*))" ,
373
+ [True , False ],
374
+ None ,
375
+ 2
376
+ )
285
377
self .do_test (
286
378
"tr(XPUB,{{H,{H,XPUB}},{H,{H,{H,XPRV}}}})" ,
287
379
"tr($1/*,{{pk($H),{pk($H),pk($2/*)}},{pk($H),{pk($H),{pk($H),pk($3/*)}}}})" ,
@@ -290,5 +382,19 @@ def run_test(self):
290
382
3
291
383
)
292
384
385
+ self .log .info ("Sending everything back..." )
386
+
387
+ txid = self .rpc_online .sendtoaddress (address = self .boring .getnewaddress (), amount = self .rpc_online .getbalance (), subtractfeefromamount = True )
388
+ self .nodes [0 ].generatetoaddress (1 , self .boring .getnewaddress ())
389
+ assert (self .rpc_online .gettransaction (txid )["confirmations" ] > 0 )
390
+
391
+ psbt = self .psbt_online .walletcreatefundedpsbt ([], [{self .boring .getnewaddress (): self .psbt_online .getbalance ()}], None , {"subtractFeeFromOutputs" : [0 ]})['psbt' ]
392
+ res = self .psbt_offline .walletprocesspsbt (psbt )
393
+ assert (res ['complete' ])
394
+ rawtx = self .nodes [0 ].finalizepsbt (res ['psbt' ])['hex' ]
395
+ txid = self .nodes [0 ].sendrawtransaction (rawtx )
396
+ self .nodes [0 ].generatetoaddress (1 , self .boring .getnewaddress ())
397
+ assert (self .psbt_online .gettransaction (txid )['confirmations' ] > 0 )
398
+
293
399
if __name__ == '__main__' :
294
400
WalletTaprootTest ().main ()
0 commit comments