Exemple #1
0
        def test_getxpub(self):
            with open(os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                   'data/bip32_vectors.json'),
                      encoding='utf-8') as f:
                vectors = json.load(f)
            for vec in vectors:
                with self.subTest(vector=vec):
                    # Setup with xprv
                    device.wipe(self.client)
                    load_device_by_xprv(client=self.client,
                                        xprv=vec['xprv'],
                                        pin='',
                                        passphrase_protection=False,
                                        label='test',
                                        language='english')

                    # Test getmasterxpub
                    gmxp_res = process_commands([
                        '-t', 'trezor', '-d', 'udp:127.0.0.1:21324',
                        'getmasterxpub'
                    ])
                    self.assertEqual(gmxp_res['xpub'], vec['master_xpub'])

                    # Test the path derivs
                    for path_vec in vec['vectors']:
                        gxp_res = process_commands([
                            '-t', 'trezor', '-d', 'udp:127.0.0.1:21324',
                            'getxpub', path_vec['path']
                        ])
                        self.assertEqual(gxp_res['xpub'], path_vec['xpub'])
Exemple #2
0
 def test_display_address_bad_args(self):
     result = process_commands(
         self.dev_args +
         ['displayaddress', '--sh_wpkh', '--wpkh', 'm/49h/1h/0h/0/0'])
     self.assertIn('error', result)
     self.assertIn('code', result)
     self.assertEqual(result['code'], -7)
Exemple #3
0
 def test_setup(self):
     result = process_commands(self.dev_args + ['setup'])
     self.assertIn('error', result)
     self.assertIn('code', result)
     self.assertEqual(result['error'],
                      'The Coldcard does not support software setup')
     self.assertEqual(result['code'], -9)
Exemple #4
0
 def test_wipe(self):
     result = process_commands(self.dev_args + ['wipe'])
     self.assertIn('error', result)
     self.assertIn('code', result)
     self.assertEqual(
         result['error'],
         'The Coldcard does not support wiping via software')
     self.assertEqual(result['code'], -9)
Exemple #5
0
 def test_no_type(self):
     gmxp_res = process_commands(['getmasterxpub'])
     self.assertIn('error', gmxp_res)
     self.assertEqual(
         gmxp_res['error'],
         'You must specify a device type or fingerprint for all commands except enumerate'
     )
     self.assertIn('code', gmxp_res)
     self.assertEqual(gmxp_res['code'], -1)
Exemple #6
0
 def test_enumerate(self):
     enum_res = process_commands(['enumerate'])
     found = False
     for device in enum_res:
         self.assertNotIn('error', device)
         if device['type'] == self.type and device[
                 'path'] == self.path and device[
                     'fingerprint'] == self.fingerprint:
             found = True
     self.assertTrue(found)
Exemple #7
0
def ledger_test_suite(rpc, userpass):
    # Look for real ledger using HWI API(self-referential, but no other way)
    enum_res = process_commands(['enumerate'])
    path = None
    master_xpub = None
    fingerprint = None
    for device in enum_res:
        if device['type'] == 'ledger':
            fingerprint = device['fingerprint']
            path = device['path']
            master_xpub = process_commands(['-f', fingerprint, 'getmasterxpub'])['xpub']
            break
    assert(path is not None and master_xpub is not None and fingerprint is not None)

    # Generic Device tests
    suite = unittest.TestSuite()
    suite.addTest(DeviceTestCase.parameterize(TestDeviceConnect, rpc, userpass, 'ledger', path, fingerprint, master_xpub))
    suite.addTest(DeviceTestCase.parameterize(TestGetKeypool, rpc, userpass, 'ledger', path, fingerprint, master_xpub))
    suite.addTest(DeviceTestCase.parameterize(TestSignTx, rpc, userpass, 'ledger', path, fingerprint, master_xpub))
    suite.addTest(DeviceTestCase.parameterize(TestDisplayAddress, rpc, userpass, 'ledger', path, fingerprint, master_xpub))
    return suite
Exemple #8
0
 def test_sign_msg(self):
     process_commands(
         self.dev_args +
         ['signmessage', 'Message signing test', 'm/44h/1h/0h/0/0'])
Exemple #9
0
 def test_display_address(self):
     process_commands(self.dev_args + ['displayaddress', 'm/44h/1h/0h/0/0'])
     process_commands(self.dev_args +
                      ['displayaddress', '--sh_wpkh', 'm/49h/1h/0h/0/0'])
     process_commands(self.dev_args +
                      ['displayaddress', '--wpkh', 'm/84h/1h/0h/0/0'])
Exemple #10
0
    def _test_signtx(self, input_type, multisig):
        # Import some keys to the watch only wallet and send coins to them
        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--sh_wpkh', '30', '40'])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--sh_wpkh', '--internal', '30', '40'])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        sh_wpkh_addr = self.wrpc.getnewaddress('', 'p2sh-segwit')
        wpkh_addr = self.wrpc.getnewaddress('', 'bech32')
        pkh_addr = self.wrpc.getnewaddress('', 'legacy')
        self.wrpc.importaddress(wpkh_addr)
        self.wrpc.importaddress(pkh_addr)

        # pubkeys to construct 2-of-3 multisig descriptors for import
        sh_wpkh_info = self.wrpc.getaddressinfo(sh_wpkh_addr)
        wpkh_info = self.wrpc.getaddressinfo(wpkh_addr)
        pkh_info = self.wrpc.getaddressinfo(pkh_addr)

        # Get origin info/key pair so wallet doesn't forget how to
        # sign with keys post-import
        pubkeys = [sh_wpkh_info['desc'][8:-2],\
                wpkh_info['desc'][5:-1],\
                pkh_info['desc'][4:-1]]

        sh_multi_desc = {
            'desc':
            'sh(multi(2,' + pubkeys[0] + ',' + pubkeys[1] + ',' + pubkeys[2] +
            '))',
            "timestamp":
            "now",
            "label":
            "shmulti"
        }
        sh_wsh_multi_desc = {
            'desc':
            'sh(wsh(multi(2,' + pubkeys[0] + ',' + pubkeys[1] + ',' +
            pubkeys[2] + ')))',
            "timestamp":
            "now",
            "label":
            "shwshmulti"
        }
        # re-order pubkeys to allow import without "already have private keys" error
        wsh_multi_desc = {
            'desc':
            'wsh(multi(2,' + pubkeys[2] + ',' + pubkeys[1] + ',' + pubkeys[0] +
            '))',
            "timestamp":
            "now",
            "label":
            "wshmulti"
        }
        multi_result = self.wrpc.importmulti(
            [sh_multi_desc, sh_wsh_multi_desc, wsh_multi_desc])
        self.assertTrue(multi_result[0]['success'])
        self.assertTrue(multi_result[1]['success'])
        self.assertTrue(multi_result[2]['success'])

        sh_multi_addr = self.wrpc.getaddressesbylabel("shmulti").popitem()[0]
        sh_wsh_multi_addr = self.wrpc.getaddressesbylabel(
            "shwshmulti").popitem()[0]
        wsh_multi_addr = self.wrpc.getaddressesbylabel("wshmulti").popitem()[0]

        send_amount = 2
        number_inputs = 0
        # Single-sig
        if input_type == 'segwit' or input_type == 'all':
            self.wpk_rpc.sendtoaddress(sh_wpkh_addr, send_amount)
            self.wpk_rpc.sendtoaddress(wpkh_addr, send_amount)
            number_inputs += 2
        if input_type == 'legacy' or input_type == 'all':
            self.wpk_rpc.sendtoaddress(pkh_addr, send_amount)
            number_inputs += 1
        # Now do segwit/legacy multisig
        if multisig:
            if input_type == 'legacy' or input_type == 'all':
                self.wpk_rpc.sendtoaddress(sh_multi_addr, send_amount)
                number_inputs += 1
            if input_type == 'segwit' or input_type == 'all':
                self.wpk_rpc.sendtoaddress(wsh_multi_addr, send_amount)
                self.wpk_rpc.sendtoaddress(sh_wsh_multi_addr, send_amount)
                number_inputs += 2

        self.wpk_rpc.generatetoaddress(6, self.wpk_rpc.getnewaddress())

        # Spend different amounts, requiring 1 to 3 inputs
        for i in range(number_inputs):
            # Create a psbt spending the above
            psbt = self.wrpc.walletcreatefundedpsbt(
                [], [{
                    self.wpk_rpc.getnewaddress(): (i + 1) * send_amount
                }], 0, {
                    'includeWatching': True,
                    'subtractFeeFromOutputs': [0]
                }, True)
            sign_res = process_commands(self.dev_args +
                                        ['signtx', psbt['psbt']])
            finalize_res = self.wrpc.finalizepsbt(sign_res['psbt'])
            self.assertTrue(finalize_res['complete'])
        self.wrpc.sendrawtransaction(finalize_res['hex'])
Exemple #11
0
    def test_getkeypool(self):
        non_keypool_desc = process_commands(self.dev_args +
                                            ['getkeypool', '0', '20'])
        import_result = self.wpk_rpc.importmulti(non_keypool_desc)
        self.assertTrue(import_result[0]['success'])

        keypool_desc = process_commands(self.dev_args +
                                        ['getkeypool', '--keypool', '0', '20'])
        import_result = self.wpk_rpc.importmulti(keypool_desc)
        self.assertFalse(import_result[0]['success'])

        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(self.wrpc.getnewaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/44'/1'/0'/0/{}".format(i))

        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--internal', '0', '20'])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(
                self.wrpc.getrawchangeaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/44'/1'/0'/1/{}".format(i))

        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--sh_wpkh', '0', '20'])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(self.wrpc.getnewaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/49'/1'/0'/0/{}".format(i))
        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--sh_wpkh', '--internal', '0', '20'])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(
                self.wrpc.getrawchangeaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/49'/1'/0'/1/{}".format(i))

        keypool_desc = process_commands(
            self.dev_args + ['getkeypool', '--keypool', '--wpkh', '0', '20'])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(self.wrpc.getnewaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/84'/1'/0'/0/{}".format(i))
        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--wpkh', '--internal', '0', '20'])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(
                self.wrpc.getrawchangeaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/84'/1'/0'/1/{}".format(i))

        keypool_desc = process_commands(self.dev_args + [
            'getkeypool', '--keypool', '--sh_wpkh', '--account', '3', '0', '20'
        ])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(self.wrpc.getnewaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/49'/1'/3'/0/{}".format(i))
        keypool_desc = process_commands(self.dev_args + [
            'getkeypool', '--keypool', '--sh_wpkh', '--internal', '--account',
            '3', '0', '20'
        ])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(
                self.wrpc.getrawchangeaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/49'/1'/3'/1/{}".format(i))
        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--wpkh', '--account', '3', '0', '20'])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(self.wrpc.getnewaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/84'/1'/3'/0/{}".format(i))
        keypool_desc = process_commands(self.dev_args + [
            'getkeypool', '--keypool', '--wpkh', '--internal', '--account',
            '3', '0', '20'
        ])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(
                self.wrpc.getrawchangeaddress())
            self.assertEqual(addr_info['hdkeypath'],
                             "m/84'/1'/3'/1/{}".format(i))

        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--path', 'm/0h/0h/4h/*', '0', '20'])
        import_result = self.wrpc.importmulti(keypool_desc)
        self.assertTrue(import_result[0]['success'])
        for i in range(0, 21):
            addr_info = self.wrpc.getaddressinfo(self.wrpc.getnewaddress())
            self.assertEqual(addr_info['hdkeypath'], "m/0'/0'/4'/{}".format(i))

        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--path', '/0h/0h/4h/*', '0', '20'])
        self.assertEqual(keypool_desc['error'], 'Path must start with m/')
        self.assertEqual(keypool_desc['code'], -7)
        keypool_desc = process_commands(
            self.dev_args +
            ['getkeypool', '--keypool', '--path', 'm/0h/0h/4h/', '0', '20'])
        self.assertEqual(keypool_desc['error'], 'Path must end with /*')
        self.assertEqual(keypool_desc['code'], -7)
Exemple #12
0
 def test_type_only_autodetech(self):
     gmxp_res = process_commands(['-t', self.type, 'getmasterxpub'])
     self.assertEqual(gmxp_res['xpub'], self.master_xpub)
Exemple #13
0
 def test_fingerprint_autodetect(self):
     gmxp_res = process_commands(['-f', self.fingerprint, 'getmasterxpub'])
     self.assertEqual(gmxp_res['xpub'], self.master_xpub)
Exemple #14
0
 def test_path_type(self):
     gmxp_res = process_commands(
         ['-t', self.type, '-d', self.path, 'getmasterxpub'])
     self.assertEqual(gmxp_res['xpub'], self.master_xpub)
Exemple #15
0
 def test_getkeypool_bad_args(self):
     result = process_commands(
         self.dev_args + ['getkeypool', '--sh_wpkh', '--wpkh', '0', '20'])
     self.assertIn('error', result)
     self.assertIn('code', result)
     self.assertEqual(result['code'], -7)
Exemple #16
0
def hwi_command(args):
    result = process_commands(args)
    if 'error' in result:
        raise ValueError(result['error'])
    return result
Exemple #17
0
def coldcard_test_suite(simulator, rpc, userpass):
    # Start the Coldcard simulator
    simulator_proc = subprocess.Popen(
        ['python3', os.path.basename(simulator)],
        cwd=os.path.dirname(simulator),
        stdout=subprocess.DEVNULL)
    # Wait for simulator to be up
    while True:
        enum_res = process_commands(['enumerate'])
        if len(enum_res) > 0 and 'error' not in enum_res[0]:
            break
        time.sleep(0.5)
    # Cleanup
    def cleanup_simulator():
        dev = ColdcardDevice(sn='/tmp/ckcc-simulator.sock')
        resp = dev.send_recv(CCProtocolPacker.logout())

    atexit.register(cleanup_simulator)

    # Coldcard specific setup and wipe tests
    class TestColdcardSetupWipe(DeviceTestCase):
        def test_setup(self):
            result = process_commands(self.dev_args + ['setup'])
            self.assertIn('error', result)
            self.assertIn('code', result)
            self.assertEqual(result['error'],
                             'The Coldcard does not support software setup')
            self.assertEqual(result['code'], -9)

        def test_wipe(self):
            result = process_commands(self.dev_args + ['wipe'])
            self.assertIn('error', result)
            self.assertIn('code', result)
            self.assertEqual(
                result['error'],
                'The Coldcard does not support wiping via software')
            self.assertEqual(result['code'], -9)

    # Generic device tests
    suite = unittest.TestSuite()
    suite.addTest(
        DeviceTestCase.parameterize(TestColdcardSetupWipe, rpc, userpass,
                                    'coldcard', '/tmp/ckcc-simulator.sock',
                                    '0f056943', ''))
    suite.addTest(
        DeviceTestCase.parameterize(
            TestDeviceConnect, rpc, userpass, 'coldcard',
            '/tmp/ckcc-simulator.sock', '0f056943',
            'tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd'
        ))
    suite.addTest(
        DeviceTestCase.parameterize(
            TestGetKeypool, rpc, userpass, 'coldcard',
            '/tmp/ckcc-simulator.sock', '0f056943',
            'tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd'
        ))
    suite.addTest(
        DeviceTestCase.parameterize(
            TestDisplayAddress, rpc, userpass, 'coldcard',
            '/tmp/ckcc-simulator.sock', '0f056943',
            'tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd'
        ))
    suite.addTest(
        DeviceTestCase.parameterize(
            TestSignMessage, rpc, userpass, 'coldcard',
            '/tmp/ckcc-simulator.sock', '0f056943',
            'tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd'
        ))
    suite.addTest(
        DeviceTestCase.parameterize(
            TestSignTx, rpc, userpass, 'coldcard', '/tmp/ckcc-simulator.sock',
            '0f056943',
            'tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd'
        ))
    return suite