@@ -33,8 +33,9 @@ def pak_to_option(pak):
3333 ("02f4a7445f9c48ee8590a930d3fc4f0f5763e3d1d003fdf5fc822e7ba18f380632" , "036b3786f029751ada9f02f519a86c7e02fb2963a7013e7e668eb5f7ec069b9e7e" )]
3434
3535# Args that will be re-used in slightly different ways across runs
36- args = [["-acceptnonstdtxn=0" , "-initialfreecoins=100000000" ]] \
37- + [["-acceptnonstdtxn=0" , "-enforce_pak=1" , "-initialfreecoins=100000000" ]]* 4
36+ # TODO remove lol once parent chain hrp default is changed
37+ args = [["-acceptnonstdtxn=0" , "-initialfreecoins=100000000" , "-parent_bech32_hrp=lol" ]] \
38+ + [["-acceptnonstdtxn=0" , "-enforce_pak=1" , "-initialfreecoins=100000000" , "-parent_bech32_hrp=lol" ]]* 4
3839args [i_reject ] = args [i_reject ] + ['-pak=reject' ]
3940# Novalidate has pak entry, should not act on it ever
4041args [i_novalidate ] = args [i_novalidate ] + pak_to_option (pak1 )
@@ -199,6 +200,7 @@ def compare(actual, expected):
199200 # We will re-use the same xpub, but each wallet will create its own online pak
200201 # so the lists will be incompatible, even if all else was synced
201202 xpub = "tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B"
203+ xpub_desc = "pkh(" + xpub + "/0/*)" # Transform this into a descriptor
202204 init_results = []
203205 info_results = []
204206 for i in range (5 ):
@@ -213,8 +215,8 @@ def compare(actual, expected):
213215 assert_equal (init_results [i ]["address_lookahead" ], info_results [i ]["address_lookahead" ])
214216 assert_equal (init_results [i ]["liquid_pak" ], info_results [i ]["liquid_pak" ])
215217 assert_equal (init_results [i ]["liquid_pak_address" ], info_results [i ]["liquid_pak_address" ])
216- assert_equal (info_results [i ]["bitcoin_xpub " ], xpub )
217- assert_equal (info_results [i ]["derivation_path " ], "/0/ 0" )
218+ assert_equal (info_results [i ]["bitcoin_descriptor " ], xpub_desc )
219+ assert_equal (info_results [i ]["bip32_counter " ], "0" )
218220
219221 # Use custom derivation counter values, check if stored correctly,
220222 # address lookahead looks correct and that new liquid_pak was chosen
@@ -224,7 +226,7 @@ def compare(actual, expected):
224226 assert_raises_rpc_error (- 8 , "bip32_counter must be between 0 and 1,000,000,000, inclusive." , self .nodes [i_undefined ].initpegoutwallet , xpub , 1000000001 )
225227
226228 new_init = self .nodes [i_undefined ].initpegoutwallet (xpub , 2 )
227- assert_equal (self .nodes [i_undefined ].getwalletpakinfo ()["derivation_path " ], "/0/ 2" )
229+ assert_equal (self .nodes [i_undefined ].getwalletpakinfo ()["bip32_counter " ], "2" )
228230 assert_equal (new_init ["address_lookahead" ][0 ], init_results [i_undefined ]["address_lookahead" ][2 ])
229231 assert (new_init ["liquid_pak" ] != init_results [i_undefined ]["liquid_pak" ])
230232
@@ -244,9 +246,9 @@ def compare(actual, expected):
244246
245247 # Check PAK settings persistance in wallet across restart
246248 restarted_info = self .nodes [i_undefined ].getwalletpakinfo ()
247- assert_equal (restarted_info ["bitcoin_xpub " ], xpub )
249+ assert_equal (restarted_info ["bitcoin_descriptor " ], xpub_desc )
248250 assert_equal (restarted_info ["liquid_pak" ], new_init ["liquid_pak" ])
249- assert_equal (restarted_info ["derivation_path " ], "/0/ 2" )
251+ assert_equal (restarted_info ["bip32_counter " ], "2" )
250252
251253 # Have nodes send pegouts, check it fails to enter mempool of other nodes with incompatible
252254 # PAK settings
@@ -260,10 +262,12 @@ def compare(actual, expected):
260262
261263 # pak1 will now create a pegout.
262264 pak1_pegout_txid = self .nodes [i_pak1 ].sendtomainchain ("" , 1 )["txid" ]
263- assert_equal (self .nodes [i_pak1 ].getwalletpakinfo ()["derivation_path" ], "/0/1" )
265+ assert_equal (self .nodes [i_pak1 ].getwalletpakinfo ()["bip32_counter" ], "1" )
266+ # Also spend the change to make chained payment that will be rejected as well
267+ pak1_child_txid = self .nodes [i_pak1 ].sendtoaddress (self .nodes [i_pak1 ].getnewaddress (), self .nodes [i_pak1 ].getbalance (), "" , "" , True )
264268
265269
266- # Wait for two nodes to get transaction in mempool only
270+ # Wait for node("follow the leader" conf-undefined) to get transaction in
267271 time_to_wait = 15
268272 while time_to_wait > 0 :
269273 # novalidate doesn't allow >80 byte op_return outputs due to no enforce_pak
@@ -283,15 +287,111 @@ def compare(actual, expected):
283287
284288 assert_equal (pak1_pegout_txid in self .nodes [i_novalidate ].getrawmempool (), False )
285289 assert_equal (pak1_pegout_txid in self .nodes [i_undefined ].getrawmempool (), False )
290+ assert_equal (pak1_pegout_txid in self .nodes [i_pak1 ].getrawmempool (), True )
286291 assert_equal (pak1_pegout_txid in self .nodes [i_pak2 ].getrawmempool (), False )
287292 assert_equal (pak1_pegout_txid in self .nodes [i_reject ].getrawmempool (), False )
288293
294+ assert_equal (self .nodes [i_pak1 ].gettransaction (pak1_pegout_txid )["confirmations" ], 0 )
295+
296+ # Make sure child payment also bumped from mempool
297+ assert_equal (pak1_child_txid in self .nodes [i_novalidate ].getrawmempool (), False )
298+ assert_equal (pak1_child_txid in self .nodes [i_undefined ].getrawmempool (), False )
299+ assert_equal (pak1_child_txid in self .nodes [i_pak1 ].getrawmempool (), True )
300+ assert_equal (pak1_child_txid in self .nodes [i_pak2 ].getrawmempool (), False )
301+ assert_equal (pak1_child_txid in self .nodes [i_reject ].getrawmempool (), False )
302+
303+ assert_equal (self .nodes [i_pak1 ].gettransaction (pak1_child_txid )["confirmations" ], 0 )
289304 # Fail to peg-out too-small value
290305 assert_raises_rpc_error (- 8 , "Invalid amount for send, must send more than 0.0001 BTC" , self .nodes [i_undefined ].sendtomainchain , "" , Decimal ('0.0009' ))
291306
292307 # Use wrong network's extended pubkey
293308 mainnetxpub = "xpub6AATBi58516uxLogbuaG3jkom7x1qyDoZzMN2AePBuQnMFKUV9xC2BW9vXsFJ9rELsvbeGQcFWhtbyM4qDeijM22u3AaSiSYEvuMZkJqtLn"
294- assert_raises_rpc_error (- 8 , "bitcoin_xpub is invalid for this network" , self .nodes [i_undefined ].initpegoutwallet , mainnetxpub )
309+ assert_raises_rpc_error (- 8 , "bitcoin_descriptor is not a valid descriptor string." , self .nodes [i_undefined ].initpegoutwallet , mainnetxpub )
310+
311+ # Test fixed online pubkey
312+ init_info = self .nodes [i_pak1 ].initpegoutwallet (xpub )
313+ init_info2 = self .nodes [i_pak1 ].initpegoutwallet (xpub , 0 , init_info ['liquid_pak' ])
314+ assert_equal (init_info , init_info2 )
315+ init_info3 = self .nodes [i_pak1 ].initpegoutwallet (xpub )
316+ assert (init_info != init_info3 )
317+
318+ # Test Descriptor PAK Support
319+
320+ # Non-supported descriptors
321+ assert_raises_rpc_error (- 8 , "bitcoin_descriptor is not of any type supported: pkh(<xpub>), sh(wpkh(<xpub>)), wpkh(<xpub>), or <xpub>." , self .nodes [i_pak1 ].initpegoutwallet , "pk(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/0/*)" )
322+
323+ assert_raises_rpc_error (- 8 , "bitcoin_descriptor must be a ranged descriptor." , self .nodes [i_pak1 ].initpegoutwallet , "pkh(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B)" )
324+
325+ # key origins aren't supported in 0.17
326+ assert_raises_rpc_error (- 8 , "bitcoin_descriptor is not a valid descriptor string." , self .nodes [i_pak1 ].initpegoutwallet , "pkh([d34db33f/44'/0'/0']tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/*)" )
327+
328+ # Peg out with each new type, check that destination script matches
329+ wpkh_desc = "wpkh(" + xpub + "/0/*)"
330+ wpkh_info = self .nodes [i_pak1 ].initpegoutwallet (wpkh_desc )
331+ wpkh_pak_info = self .nodes [i_pak1 ].getwalletpakinfo ()
332+
333+ # Add to pak list for pak1, restart
334+ self .stop_nodes ()
335+ extra_args = copy .deepcopy (args )
336+ extra_args [i_pak1 ] = extra_args [i_pak1 ]+ ["-" + wpkh_info ["pakentry" ]]
337+ self .start_nodes (extra_args )
338+
339+ # Make block commitment and get some block subsidy
340+ self .nodes [i_pak1 ].generate (101 )
341+ wpkh_stmc = self .nodes [i_pak1 ].sendtomainchain ("" , 1 )
342+ wpkh_txid = wpkh_stmc ['txid' ]
343+
344+ # Also check some basic return fields of sendtomainchain with pak
345+ assert_equal (wpkh_stmc ["bitcoin_address" ], wpkh_info ["address_lookahead" ][0 ])
346+ validata = self .nodes [i_pak1 ].validateaddress (wpkh_stmc ["bitcoin_address" ])
347+ assert (not validata ["isvalid" ])
348+ assert (validata ["isvalid_parent" ])
349+ assert_equal (wpkh_pak_info ["bip32_counter" ], wpkh_stmc ["bip32_counter" ])
350+ assert_equal (wpkh_pak_info ["bitcoin_descriptor" ], wpkh_stmc ["bitcoin_descriptor" ])
351+
352+ sh_wpkh_desc = "sh(wpkh(" + xpub + "/0/1/*))"
353+ sh_wpkh_info = self .nodes [i_pak1 ].initpegoutwallet (sh_wpkh_desc )
354+
355+ # Add to pak list for pak1, restart
356+ self .stop_nodes ()
357+ extra_args = copy .deepcopy (args )
358+ extra_args [i_pak1 ] = extra_args [i_pak1 ]+ ["-" + sh_wpkh_info ["pakentry" ]]
359+
360+ # Restart and connect peers
361+ self .start_nodes (extra_args )
362+ connect_nodes_bi (self .nodes ,0 ,1 )
363+ connect_nodes_bi (self .nodes ,1 ,2 )
364+ connect_nodes_bi (self .nodes ,2 ,3 )
365+ connect_nodes_bi (self .nodes ,3 ,4 )
366+
367+ self .nodes [i_pak1 ].generate (1 )
368+ sh_wpkh_txid = self .nodes [i_pak1 ].sendtomainchain ("" , 1 )['txid' ]
369+
370+ # Make sure peg-outs look correct
371+ wpkh_raw = self .nodes [i_pak1 ].decoderawtransaction (self .nodes [i_pak1 ].gettransaction (wpkh_txid )['hex' ])
372+ sh_wpkh_raw = self .nodes [i_pak1 ].decoderawtransaction (self .nodes [i_pak1 ].gettransaction (sh_wpkh_txid )['hex' ])
373+
374+ peg_out_found = False
375+ for output in wpkh_raw ["vout" ]:
376+ if "pegout_addresses" in output ["scriptPubKey" ]:
377+ if output ["scriptPubKey" ]["pegout_addresses" ][0 ] \
378+ == wpkh_info ["address_lookahead" ][0 ]:
379+ peg_out_found = True
380+ break
381+ else :
382+ raise Exception ("Found unexpected peg-out output" )
383+ assert (peg_out_found )
384+
385+ peg_out_found = False
386+ for output in sh_wpkh_raw ["vout" ]:
387+ if "pegout_addresses" in output ["scriptPubKey" ]:
388+ if output ["scriptPubKey" ]["pegout_addresses" ][0 ] \
389+ == sh_wpkh_info ["address_lookahead" ][0 ]:
390+ peg_out_found = True
391+ break
392+ else :
393+ raise Exception ("Found unexpected peg-out output" )
394+ assert (peg_out_found )
295395
296396if __name__ == '__main__' :
297397 PAKTest ().main ()
0 commit comments