def enroll_xpub(name, min_signers, path, num_signers, output_file=None, verbose=False, just_add=False): ''' Create a skeleton file which defines a multisig wallet. When completed, use with: "ckcc upload -m wallet.txt" or put on SD card. ''' dev = ColdcardDevice(sn=force_serial) dev.check_mitm() xfp = dev.master_fingerprint my_xpub = dev.send_recv(CCProtocolPacker.get_xpub(path), timeout=None) new_line = "%s: %s" % (xfp2str(xfp), my_xpub) if just_add: click.echo(new_line) sys.exit(0) N = num_signers if N < min_signers: N = min_signers if not (1 <= N < 15): click.echo("N must be 1..15") sys.exit(1) if min_signers == 0: min_signers = N if not (1 <= min_signers <= N): click.echo( f"Minimum number of signers (M) must be between 1 and N={N}") sys.exit(1) if not (1 <= len(name) <= 20) or name != str(name.encode('utf8'), 'ascii', 'ignore'): click.echo("Name must be between 1 and 20 characters of ASCII.") sys.exit(1) # render into a template config = f'name: {name}\npolicy: {min_signers} of {N}\n\n#path: {path}\n{new_line}\n' if num_signers != 1: config += '\n'.join(f'#{i+2}# FINGERPRINT: xpub123123123123123' for i in range(num_signers - 1)) config += '\n' if verbose or not output_file: click.echo(config[:-1]) if output_file: output_file.write(config) output_file.close() click.echo(f"Wrote to: {output_file.name}")
def get_pubkey_at_path(self, path): path = path.replace('h', '\'') path = path.replace('H', '\'') xpub = self.device.send_recv(CCProtocolPacker.get_xpub(path), timeout=None) if self.is_testnet: return {'xpub': xpub_main_2_test(xpub)} else: return {'xpub': xpub}
def get_xpub(subpath): """Get the XPUB for this wallet (master level, or any derivation)""" with get_device() as dev: if len(subpath) == 1: if subpath[0] == 'bip44': subpath = BIP44_FIRST xpub = dev.send_recv(CCProtocolPacker.get_xpub(subpath), timeout=None) click.echo(xpub)
def get_pubkey(subpath): """ Get the public key for a derivation path Dump 33-byte (compressed, SEC encoded) public key value. """ with get_device() as dev: xpub = dev.send_recv(CCProtocolPacker.get_xpub(subpath), timeout=None) pubkey, _ = decode_xpub(xpub) vk = VerifyingKey.from_string(get_pubkey_string(pubkey), curve=SECP256k1) click.echo(b2a_hex(vk.to_string("compressed")))
def get_xpub(subpath): "Get the XPUB for this wallet (master level, or any derivation)" dev = ColdcardDevice(sn=force_serial) if len(subpath) == 1: if subpath[0] == 'bip44': subpath = BIP44_FIRST xpub = dev.send_recv(CCProtocolPacker.get_xpub(subpath), timeout=None) click.echo(xpub)
def doit(M, addr_fmt=None, do_import=True): passwords = ['Me', 'Myself', 'And I', ''] if 0: # WORKING, but slow .. and it's constant data keys = [] for pw in passwords: xfp = set_bip39_pw(pw) sk = dev.send_recv(CCProtocolPacker.get_xpub("m/45'")) node = BIP32Node.from_wallet_key(sk) keys.append((xfp, None, node)) assert len(set(x for x,_,_ in keys)) == 4, keys pprint(keys) else: # Much, FASTER! assert dev.is_simulator keys = [(3503269483, None, BIP32Node.from_hwif('tpubD9429UXFGCTKJ9NdiNK4rC5ygqSUkginycYHccqSg5gkmyQ7PZRHNjk99M6a6Y3NY8ctEUUJvCu6iCCui8Ju3xrHRu3Ez1CKB4ZFoRZDdP9')), (2389277556, None, BIP32Node.from_hwif('tpubD97nVL37v5tWyMf9ofh5rznwhh1593WMRg6FT4o6MRJkKWANtwAMHYLrcJFsFmPfYbY1TE1LLQ4KBb84LBPt1ubvFwoosvMkcWJtMwvXgSc')), (3190206587, None, BIP32Node.from_hwif('tpubD9ArfXowvGHnuECKdGXVKDMfZVGdephVWg8fWGWStH3VKHzT4ph3A4ZcgXWqFu1F5xGTfxncmrnf3sLC86dup2a8Kx7z3xQ3AgeNTQeFxPa')), (1130956047, None, BIP32Node.from_hwif('tpubD8NXmKsmWp3a3DXhbihAYbYLGaRNVdTnr6JoSxxfXYQcmwVtW2hv8QoDwng6JtEonmJoL3cNEwfd2cLXMpGezwZ2vL2dQ7259bueNKj9C8n')), ] if do_import: # render as a file for import config = f"name: Myself-{M}\npolicy: {M} / 4\n\n" if addr_fmt: config += f'format: {addr_fmt.upper()}\n' config += '\n'.join('%s: %s' % (xfp2str(xfp), sk.hwif()) for xfp, _, sk in keys) #print(config) title, story = offer_ms_import(config) #print(story) # dont care if update or create; accept it. time.sleep(.1) need_keypress('y') def select_wallet(idx): # select to specific pw xfp = set_bip39_pw(passwords[idx]) assert xfp == keys[idx][0] return (keys, select_wallet)
def get_xpub(self, bip32_path, xtype): assert xtype in ColdcardPlugin.SUPPORTED_XTYPES print_error('[coldcard]', 'Derive xtype = %r' % xtype) xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000) # TODO handle timeout? # change type of xpub to the requested type try: __, depth, fingerprint, child_number, c, cK = deserialize_xpub(xpub) except InvalidMasterKeyVersionBytes: raise UserFacingException(_('Invalid xpub magic. Make sure your {} device is set to the correct chain.') .format(self.device)) from None if xtype != 'standard': xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number) return xpub
def get_xpub(self, bip32_path, xtype): assert xtype in ColdcardPlugin.SUPPORTED_XTYPES _logger.info('Derive xtype = %r' % xtype) xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000) # TODO handle timeout? # change type of xpub to the requested type try: node = BIP32Node.from_xkey(xpub) except InvalidMasterKeyVersionBytes: raise UserFacingException(_('Invalid xpub magic. Make sure your {} device is set to the correct chain.') .format(self.device)) from None if xtype != 'standard': xpub = node._replace(xtype=xtype).to_xpub() return xpub
def get_xpub(self, bip32_path, xtype): assert xtype in ColdcardPlugin.SUPPORTED_XTYPES print_error('[coldcard]', 'Derive xtype = %r' % xtype) xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000) # TODO handle timeout? # change type of xpub to the requested type try: node = BIP32Node.from_xkey(xpub) except InvalidMasterKeyVersionBytes: raise UserFacingException(_('Invalid xpub magic. Make sure your {} device is set to the correct chain.') .format(self.device)) from None if xtype != 'standard': xpub = node._replace(xtype=xtype).to_xpub() return xpub
def get_xpub(self, bip32_path, xtype): assert xtype in ColdcardPlugin.SUPPORTED_XTYPES print_error('[coldcard]', 'Derive xtype = %r' % xtype) xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000) # TODO handle timeout? # change type of xpub to the requested type try: __, depth, fingerprint, child_number, c, cK = deserialize_xpub(xpub) except InvalidMasterKeyVersionBytes: raise Exception(_('Invalid xpub magic. Make sure your {} device is set to the correct chain.') .format(self.device)) from None if xtype != 'standard': xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number) return xpub
def master_xpub(dev): r = dev.send_recv(CCProtocolPacker.get_xpub('m'), timeout=None, encrypt=1) assert r[1:4] == 'pub', r if r[0:4] == dev.master_xpub[0:4]: assert r == dev.master_xpub elif dev.master_xpub: # testnet vs. mainnet difference from pycoin.key.BIP32Node import BIP32Node a = BIP32Node.from_wallet_key(r) b = BIP32Node.from_wallet_key(dev.master_xpub) assert a.secret_exponent() == b.secret_exponent() return r
def get_pubkey(subpath): '''Get the public key for a derivation path Dump 33-byte (compressed, SEC encoded) public key value. ''' try: from pycoin.key.BIP32Node import BIP32Node except: raise click.Abort("pycoin must be installed, not found.") dev = ColdcardDevice(sn=force_serial) xpub = dev.send_recv(CCProtocolPacker.get_xpub(subpath), timeout=None) node = BIP32Node.from_hwif(xpub) click.echo(b2a_hex(node.sec()))
def master_xpub(dev): if hasattr(dev.dev, 'pipe'): # this works better against simulator in HSM mode, where the xpub cmd may be disabled return simulator_fixed_xpub r = dev.send_recv(CCProtocolPacker.get_xpub('m'), timeout=None, encrypt=1) assert r[1:4] == 'pub', r if r[0:4] == dev.master_xpub[0:4]: assert r == dev.master_xpub elif dev.master_xpub: # testnet vs. mainnet difference from pycoin.key.BIP32Node import BIP32Node a = BIP32Node.from_wallet_key(r) b = BIP32Node.from_wallet_key(dev.master_xpub) assert a.secret_exponent() == b.secret_exponent() return r