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)
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)
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
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