Merge #182: Fix displayaddress with descriptors and its tests

54bd668 Actually test that displayaddress is returning correct output (Andrew Chow)
0974f69 Ensure the client's fingerprint is available for descriptor displayaddress (Andrew Chow)
cea784e tests: Replace remaining process_commands with self.do_command in tests (Andrew Chow)
70e31ca tests: Properly escape arguments for cli interface (Andrew Chow)

Pull request description:

  `displayaddress` with descriptors wasn't working correctly nor was it being tested correctly. Fixed it and the tests.

ACKs for commit 54bd66:

Tree-SHA512: 84d27925a0bdb26e6ab844ded23e08d7b5f3e2aa78964d324c9223c04aaa26252a1e60e556696937b90518072fd62765fb38a15bc5f54600f837e4867cf1b148
This commit is contained in:
Andrew Chow 2019-05-28 14:28:30 -04:00
commit 64153a8a65
No known key found for this signature in database
GPG Key ID: 17565732E08E5E41
5 changed files with 59 additions and 20 deletions

View File

@ -155,6 +155,10 @@ def displayaddress(client, path=None, desc=None, sh_wpkh=False, wpkh=False):
return {'error':'Both `--wpkh` and `--sh_wpkh` can not be selected at the same time.','code':BAD_ARGUMENT}
return client.display_address(path, sh_wpkh, wpkh)
elif desc is not None:
if client.fingerprint is None:
master_xpub = client.get_pubkey_at_path('m/0h')['xpub']
client.fingerprint = get_xpub_fingerprint_hex(master_xpub)
if sh_wpkh == True or wpkh == True:
return {'error':' `--wpkh` and `--sh_wpkh` can not be combined with --desc','code':BAD_ARGUMENT}
descriptor = Descriptor.parse(desc, client.is_testnet)

View File

@ -3,6 +3,7 @@
import atexit
import json
import os
import shlex
import shutil
import subprocess
import tempfile
@ -79,12 +80,15 @@ class DeviceTestCase(unittest.TestCase):
return suite
def do_command(self, args):
cli_args = []
for arg in args:
cli_args.append(shlex.quote(arg))
if self.interface == 'cli':
proc = subprocess.Popen(['hwi ' + ' '.join(args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
proc = subprocess.Popen(['hwi ' + ' '.join(cli_args)], stdout=subprocess.PIPE, shell=True)
result = proc.communicate()
return json.loads(result[0].decode())
elif self.interface == 'bindist':
proc = subprocess.Popen(['../dist/hwi ' + ' '.join(args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
proc = subprocess.Popen(['../dist/hwi ' + ' '.join(cli_args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
result = proc.communicate()
return json.loads(result[0].decode())
elif self.interface == 'stdin':
@ -456,45 +460,68 @@ class TestDisplayAddress(DeviceTestCase):
self.assertEqual(result['code'], -7)
def test_display_address_path(self):
self.do_command(self.dev_args + ['displayaddress', '--path', 'm/44h/1h/0h/0/0'])
self.do_command(self.dev_args + ['displayaddress', '--sh_wpkh', '--path', 'm/49h/1h/0h/0/0'])
self.do_command(self.dev_args + ['displayaddress', '--wpkh', '--path', 'm/84h/1h/0h/0/0'])
result = self.do_command(self.dev_args + ['displayaddress', '--path', 'm/44h/1h/0h/0/0'])
self.assertNotIn('error', result)
self.assertNotIn('code', result)
self.assertIn('address', result)
result = self.do_command(self.dev_args + ['displayaddress', '--sh_wpkh', '--path', 'm/49h/1h/0h/0/0'])
self.assertNotIn('error', result)
self.assertNotIn('code', result)
self.assertIn('address', result)
result = self.do_command(self.dev_args + ['displayaddress', '--wpkh', '--path', 'm/84h/1h/0h/0/0'])
self.assertNotIn('error', result)
self.assertNotIn('code', result)
self.assertIn('address', result)
def test_display_address_bad_path(self):
result = self.do_command(self.dev_args + ['displayaddress', '--path', 'f'])
self.assertEquals(result['code'], -7)
def test_display_address_descriptor(self):
account_xpub = process_commands(self.dev_args + ['getxpub', 'm/84h/1h/0h'])['xpub']
p2sh_segwit_account_xpub = process_commands(self.dev_args + ['getxpub', 'm/49h/1h/0h'])['xpub']
legacy_account_xpub = process_commands(self.dev_args + ['getxpub', 'm/44h/1h/0h'])['xpub']
account_xpub = self.do_command(self.dev_args + ['getxpub', 'm/84h/1h/0h'])['xpub']
p2sh_segwit_account_xpub = self.do_command(self.dev_args + ['getxpub', 'm/49h/1h/0h'])['xpub']
legacy_account_xpub = self.do_command(self.dev_args + ['getxpub', 'm/44h/1h/0h'])['xpub']
# Native SegWit address using xpub:
process_commands(self.dev_args + ['displayaddress', '--desc', 'wpkh([' + self.fingerprint + '/84h/1h/0h)]' + account_xpub + '/0/0)'])
result = self.do_command(self.dev_args + ['displayaddress', '--desc', 'wpkh([' + self.fingerprint + '/84h/1h/0h]' + account_xpub + '/0/0)'])
self.assertNotIn('error', result)
self.assertNotIn('code', result)
self.assertIn('address', result)
# Native SegWit address using hex encoded pubkey:
process_commands(self.dev_args + ['displayaddress', '--desc', 'wpkh([' + self.fingerprint + '/84h/1h/0h)]' + xpub_to_pub_hex(account_xpub) + '/0/0)'])
result = self.do_command(self.dev_args + ['displayaddress', '--desc', 'wpkh([' + self.fingerprint + '/84h/1h/0h]' + xpub_to_pub_hex(account_xpub) + '/0/0)'])
self.assertNotIn('error', result)
self.assertNotIn('code', result)
self.assertIn('address', result)
# P2SH wrapped SegWit address using xpub:
process_commands(self.dev_args + ['displayaddress', '--desc', 'sh(wpkh([' + self.fingerprint + '/49h/1h/0h)]' + p2sh_segwit_account_xpub + '/0/0))'])
result = self.do_command(self.dev_args + ['displayaddress', '--desc', 'sh(wpkh([' + self.fingerprint + '/49h/1h/0h]' + p2sh_segwit_account_xpub + '/0/0))'])
self.assertNotIn('error', result)
self.assertNotIn('code', result)
self.assertIn('address', result)
# Legacy address
process_commands(self.dev_args + ['displayaddress', '--desc', 'pkh([' + self.fingerprint + '/44h/1h/0h)]' + legacy_account_xpub + '/0/0)'])
result = self.do_command(self.dev_args + ['displayaddress', '--desc', 'pkh([' + self.fingerprint + '/44h/1h/0h]' + legacy_account_xpub + '/0/0)'])
self.assertNotIn('error', result)
self.assertNotIn('code', result)
self.assertIn('address', result)
# Should check xpub
result = process_commands(self.dev_args + ['displayaddress', '--desc', 'wpkh([' + self.fingerprint + '/84h/1h/0h)]' + "not_and_xpub" + '/0/0)'])
result = self.do_command(self.dev_args + ['displayaddress', '--desc', 'wpkh([' + self.fingerprint + '/84h/1h/0h]' + "not_and_xpub" + '/0/0)'])
self.assertIn('error', result)
self.assertIn('code', result)
self.assertEqual(result['code'], -7)
# Should check hex pub
result = process_commands(self.dev_args + ['displayaddress', '--desc', 'wpkh([' + self.fingerprint + '/84h/1h/0h)]' + "not_and_xpub" + '/0/0)'])
result = self.do_command(self.dev_args + ['displayaddress', '--desc', 'wpkh([' + self.fingerprint + '/84h/1h/0h]' + "not_and_xpub" + '/0/0)'])
self.assertIn('error', result)
self.assertIn('code', result)
self.assertEqual(result['code'], -7)
# Should check fingerprint
process_commands(self.dev_args + ['displayaddress', '--desc', 'wpkh([00000000/84h/1h/0h)]' + account_xpub + '/0/0)'])
self.do_command(self.dev_args + ['displayaddress', '--desc', 'wpkh([00000000/84h/1h/0h]' + account_xpub + '/0/0)'])
self.assertIn('error', result)
self.assertIn('code', result)
self.assertEqual(result['code'], -7)

View File

@ -93,7 +93,7 @@ def digitalbitbox_test_suite(rpc, userpass, simulator, interface):
self.assertTrue(result['success'])
# Reset back to original
result = process_commands(self.dev_args + ['wipe'])
result = self.do_command(self.dev_args + ['wipe'])
self.assertTrue(result['success'])
send_plain(b'{"password":"0000"}', dev)
send_encrypt(json.dumps({"seed":{"source":"backup","filename":"test_backup.pdf","key":"key"}}), '0000', dev)

View File

@ -4,6 +4,7 @@ import argparse
import atexit
import json
import os
import shlex
import socket
import subprocess
import sys
@ -82,12 +83,15 @@ class KeepkeyTestCase(unittest.TestCase):
return suite
def do_command(self, args):
cli_args = []
for arg in args:
cli_args.append(shlex.quote(arg))
if self.interface == 'cli':
proc = subprocess.Popen(['hwi ' + ' '.join(args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
proc = subprocess.Popen(['hwi ' + ' '.join(cli_args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
result = proc.communicate()
return json.loads(result[0].decode())
elif self.interface == 'bindist':
proc = subprocess.Popen(['../dist/hwi ' + ' '.join(args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
proc = subprocess.Popen(['../dist/hwi ' + ' '.join(cli_args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
result = proc.communicate()
return json.loads(result[0].decode())
elif self.interface == 'stdin':

View File

@ -4,6 +4,7 @@ import argparse
import atexit
import json
import os
import shlex
import socket
import subprocess
import sys
@ -82,12 +83,15 @@ class TrezorTestCase(unittest.TestCase):
return suite
def do_command(self, args):
cli_args = []
for arg in args:
cli_args.append(shlex.quote(arg))
if self.interface == 'cli':
proc = subprocess.Popen(['hwi ' + ' '.join(args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
proc = subprocess.Popen(['hwi ' + ' '.join(cli_args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
result = proc.communicate()
return json.loads(result[0].decode())
elif self.interface == 'bindist':
proc = subprocess.Popen(['../dist/hwi ' + ' '.join(args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
proc = subprocess.Popen(['../dist/hwi ' + ' '.join(cli_args)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True)
result = proc.communicate()
return json.loads(result[0].decode())
elif self.interface == 'stdin':