66
77import random
88
9+ from decimal import Decimal
910from test_framework .test_framework import BitcoinTestFramework
1011from test_framework .util import assert_equal
1112from test_framework .descriptors import descsum_create
@@ -233,20 +234,85 @@ def do_test_addr(self, comment, pattern, privmap, treefn, keys):
233234 # tr descriptors cannot be imported when Taproot is not active
234235 result = self .privs_tr_enabled .importdescriptors ([{"desc" : desc , "timestamp" : "now" }])
235236 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" )
240237 result = self .pubs_tr_enabled .importdescriptors ([{"desc" : desc_pub , "timestamp" : "now" }])
241238 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 )
246310
247311 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 ])
250316
251317 def run_test (self ):
252318 self .log .info ("Creating wallets..." )
@@ -258,8 +324,20 @@ def run_test(self):
258324 self .pubs_tr_enabled = self .nodes [0 ].get_wallet_rpc ("pubs_tr_enabled" )
259325 self .nodes [2 ].createwallet (wallet_name = "pubs_tr_disabled" , descriptors = True , blank = True , disable_private_keys = True )
260326 self .pubs_tr_disabled = self .nodes [2 ].get_wallet_rpc ("pubs_tr_disabled" )
327+ self .nodes [0 ].createwallet (wallet_name = "boring" )
261328 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" )
262333 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 )
263341
264342 self .do_test (
265343 "tr(XPRV)" ,
@@ -275,13 +353,27 @@ def run_test(self):
275353 lambda k1 : (key (H_POINT ), [pk (k1 )]),
276354 1
277355 )
356+ self .do_test (
357+ "wpkh(XPRV)" ,
358+ "wpkh($1/*)" ,
359+ [True ],
360+ None ,
361+ 1
362+ )
278363 self .do_test (
279364 "tr(XPRV,{H,{H,XPUB}})" ,
280365 "tr($1/*,{pk($H),{pk($H),pk($2/*)}})" ,
281366 [True , False ],
282367 lambda k1 , k2 : (key (k1 ), [pk (H_POINT ), [pk (H_POINT ), pk (k2 )]]),
283368 2
284369 )
370+ self .do_test (
371+ "wsh(multi(1,XPRV,XPUB))" ,
372+ "wsh(multi(1,$1/*,$2/*))" ,
373+ [True , False ],
374+ None ,
375+ 2
376+ )
285377 self .do_test (
286378 "tr(XPUB,{{H,{H,XPUB}},{H,{H,{H,XPRV}}}})" ,
287379 "tr($1/*,{{pk($H),{pk($H),pk($2/*)}},{pk($H),{pk($H),{pk($H),pk($3/*)}}}})" ,
@@ -290,5 +382,19 @@ def run_test(self):
290382 3
291383 )
292384
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+
293399if __name__ == '__main__' :
294400 WalletTaprootTest ().main ()
0 commit comments