Beispiel #1
0
def test_public(sim_execfile):
    "verify contents of public 'dump' file"
    from pycoin.key.BIP32Node import BIP32Node
    from pycoin.contrib.segwit_addr import encode as sw_encode
    from pycoin.contrib.segwit_addr import decode as sw_decode
    from pycoin.encoding import a2b_hashed_base58, hash160

    pub = sim_execfile('devtest/dump_public.py')
    assert 'Error' not in pub

    #print(pub)

    pub, dev = pub.split('#DEBUG#', 1)
    assert 'pub' in pub
    assert 'prv' not in pub
    assert 'prv' in dev

    lines = [i.strip() for i in pub.split('\n')]

    for ln in lines:
        if ln[1:4] == 'pub':
            node_pub = BIP32Node.from_wallet_key(ln)
            break

    node_prv = BIP32Node.from_wallet_key(dev.strip())

    # pub and private are linked
    assert node_prv.hwif(as_private=False) == node_pub.hwif()

    # check every path we derived
    count = 0
    for ln in lines:
        if ln[0:1] == 'm' and '=>' in ln:
            subpath, result = ln.split(' => ', 1)

            sk = node_prv.subkey_for_path(subpath[2:])

            if result[0:2] in {'tp', 'xp'}:
                expect = BIP32Node.from_wallet_key(result)
                assert sk.hwif(as_private=False) == result
            elif result[0] in '1mn':
                assert result == sk.address(False)
            elif result[0:3] in {'bc1', 'tb1'}:
                h20 = sk.hash160()
                assert result == sw_encode(result[0:2], 0, h20)
            elif result[0] in '23':
                h20 = hash160(b'\x00\x14' + sk.hash160())
                assert h20 == a2b_hashed_base58(result)[1:]
            else:
                raise ValueError(result)

            count += 1
            print("OK: %s" % ln)

    assert count > 12
 def doit(addr, sk):
     if addr[0] in '1mn':
         assert addr == sk.address(False)
     elif addr[0:3] in {'bc1', 'tb1'}:
         h20 = sk.hash160()
         assert addr == sw_encode(addr[0:2], 0, h20)
     elif addr[0] in '23':
         h20 = hash160(b'\x00\x14' + sk.hash160())
         assert h20 == a2b_hashed_base58(addr)[1:]
     else:
         raise ValueError(addr)
Beispiel #3
0
def test_export_core(dev, acct_num, cap_menu, pick_menu_item, goto_home,
                     cap_story, need_keypress, microsd_path, bitcoind_wallet):
    # test UX and operation of the 'bitcoin core' wallet export
    from pycoin.contrib.segwit_addr import encode as sw_encode

    goto_home()
    pick_menu_item('Advanced')
    pick_menu_item('MicroSD Card')
    pick_menu_item('Export Wallet')
    pick_menu_item('Bitcoin Core')

    time.sleep(0.1)
    title, story = cap_story()

    assert 'This saves' in story
    assert 'run that command' in story

    assert 'Press 1 to' in story
    if acct_num is not None:
        need_keypress('1')
        time.sleep(0.1)
        for n in acct_num:
            need_keypress(n)
    else:
        acct_num = '0'

    need_keypress('y')

    time.sleep(0.1)
    title, story = cap_story()

    assert 'Bitcoin Core file written' in story
    fname = story.split('\n')[-1]

    need_keypress('y')

    path = microsd_path(fname)
    addrs = []
    js = None
    with open(path, 'rt') as fp:
        for ln in fp:
            if 'importmulti' in ln:
                assert ln.startswith("importmulti '")
                assert ln.endswith("'\n")
                assert not js, "dup importmulti lines"
                js = ln[13:-2]
            elif '=>' in ln:
                path, addr = ln.strip().split(' => ', 1)
                assert path.startswith(f"m/84'/1'/{acct_num}'/0")
                assert addr.startswith('tb1q')
                sk = BIP32Node.from_wallet_key(
                    simulator_fixed_xprv).subkey_for_path(path[2:])
                h20 = sk.hash160()
                assert addr == sw_encode(addr[0:2], 0, h20)
                addrs.append(addr)

    assert len(addrs) == 3

    obj = json.loads(js)
    xfp = xfp2str(simulator_fixed_xfp).lower()

    for n, here in enumerate(obj):
        assert here['range'] == [0, 1000]
        assert here['timestamp'] == 'now'
        assert here['internal'] == bool(n)
        assert here['keypool'] == True
        assert here['watchonly'] == True

        d = here['desc']
        desc, chk = d.split('#', 1)
        assert len(chk) == 8
        assert desc.startswith(f'wpkh([{xfp}/84h/1h/{acct_num}h]')

        expect = BIP32Node.from_wallet_key(simulator_fixed_xprv)\
                    .subkey_for_path(f"84'/1'/{acct_num}'.pub").hwif()

        assert expect in desc
        assert expect + f'/{n}/*' in desc

    # test against bitcoind
    for x in obj:
        x['label'] = 'testcase'
    bitcoind_wallet.importmulti(obj)
    x = bitcoind_wallet.getaddressinfo(addrs[-1])
    from pprint import pprint
    pprint(x)
    assert x['address'] == addrs[-1]
    assert x['label'] == 'testcase'
    assert x['iswatchonly'] == True
    assert x['iswitness'] == True
    assert x['hdkeypath'] == f"m/84'/1'/{acct_num}'/0/%d" % (len(addrs) - 1)
Beispiel #4
0
def test_export_coldcard(acct_num, dev, cap_menu, pick_menu_item, goto_home,
                         cap_story, need_keypress, microsd_path, addr_vs_path):
    from pycoin.contrib.segwit_addr import encode as sw_encode

    # test UX and values produced.
    goto_home()
    pick_menu_item('Advanced')
    pick_menu_item('MicroSD Card')
    pick_menu_item('Export Wallet')
    pick_menu_item('Generic JSON')

    time.sleep(0.1)
    title, story = cap_story()
    assert 'Saves JSON file' in story

    need_keypress('y')
    if acct_num:
        for n in acct_num:
            need_keypress(n)
    else:
        acct_num = '0'
    need_keypress('y')

    time.sleep(0.1)
    title, story = cap_story()

    assert 'Generic Export file written' in story
    fname = story.split('\n')[-1]

    need_keypress('y')

    path = microsd_path(fname)
    with open(path, 'rt') as fp:
        obj = json.load(fp)

        for fn in ['xfp', 'xpub', 'chain']:
            assert fn in obj
            assert obj[fn]
        assert obj['account'] == int(acct_num or 0)

        for fn in ['bip44', 'bip49', 'bip84', 'bip48_1', 'bip48_2']:
            assert fn in obj
            v = obj[fn]
            assert all(
                [i in v for i in ['deriv', 'name', 'first', 'xpub', 'xfp']])

            if 'bip48' not in fn:
                assert v['deriv'].endswith(f"'/{acct_num}'")
            else:
                b48n = fn[-1]
                assert v['deriv'].endswith(f"'/{acct_num}'/{b48n}'")

            node = BIP32Node.from_wallet_key(v['xpub'])
            first = node.subkey_for_path('0/0')
            addr = v['first']

            if fn == 'bip44':
                assert first.address() == v['first']
                addr_vs_path(addr, v['deriv'] + '/0/0', AF_CLASSIC)
            elif 'bip48' in fn:
                assert addr == None
            else:
                assert v['_pub'][1:4] == 'pub'

                if fn == 'bip84':
                    h20 = first.hash160()
                    assert addr == sw_encode(addr[0:2], 0, h20)
                    addr_vs_path(addr, v['deriv'] + '/0/0', AF_P2WPKH)
                else:
                    addr_fmt = AF_P2WSH_P2SH
Beispiel #5
0
def test_export_coldcard(acct_num, dev, cap_menu, pick_menu_item, goto_home,
                         cap_story, need_keypress, microsd_path, addr_vs_path):
    from pycoin.contrib.segwit_addr import encode as sw_encode

    # test UX and values produced.
    goto_home()
    pick_menu_item('Advanced')
    pick_menu_item('MicroSD Card')
    pick_menu_item('Export Wallet')
    pick_menu_item('Generic JSON')

    time.sleep(0.1)
    title, story = cap_story()
    assert 'Saves JSON file' in story

    need_keypress('y')
    if acct_num:
        for n in acct_num:
            need_keypress(n)
    else:
        acct_num = '0'
    need_keypress('y')

    time.sleep(0.1)
    title, story = cap_story()

    assert 'Generic Export file written' in story
    fname = story.split('\n')[-1]

    need_keypress('y')

    path = microsd_path(fname)
    with open(path, 'rt') as fp:
        obj = json.load(fp)

        for fn in ['xfp', 'xpub', 'chain']:
            assert fn in obj
            assert obj[fn]
        assert obj['account'] == int(acct_num or 0)

        for fn in ['bip44', 'bip49', 'bip84', 'bip48_1', 'bip48_2', 'bip45']:
            if obj['account'] and fn == 'bip45':
                assert fn not in obj
                continue

            assert fn in obj
            v = obj[fn]
            assert all([i in v for i in ['deriv', 'name', 'xpub', 'xfp']])

            if fn == 'bip45':
                assert v['deriv'] == "m/45'"
            elif 'bip48' not in fn:
                assert v['deriv'].endswith(f"'/{acct_num}'")
            else:
                b48n = fn[-1]
                assert v['deriv'].endswith(f"'/{acct_num}'/{b48n}'")

            node = BIP32Node.from_wallet_key(v['xpub'])
            assert v['xpub'] == node.hwif(as_private=False)
            first = node.subkey_for_path('0/0')
            addr = v.get('first', None)

            if fn == 'bip44':
                assert first.address() == v['first']
                addr_vs_path(addr, v['deriv'] + '/0/0', AF_CLASSIC)
            elif ('bip48_' in fn) or (fn == 'bip45'):
                # multisig: cant do addrs
                assert addr == None
            else:
                assert v['_pub'][1:4] == 'pub'
                assert slip132undo(v['_pub'])[0] == v['xpub']

                h20 = first.hash160()
                if fn == 'bip84':
                    assert addr == sw_encode(addr[0:2], 0, h20)
                    addr_vs_path(addr, v['deriv'] + '/0/0', AF_P2WPKH)
                elif fn == 'bip49':
                    # don't have test logic for verifying these addrs
                    # - need to make script, and bleh
                    assert addr[0] in '23'
                    #addr_vs_path(addr, v['deriv'] + '/0/0', AF_P2WSH_P2SH, script=)
                else:
                    assert False