def hsm_status_report(): # Return a JSON-able object. Documented and external programs # rely on this output... and yet, don't overshare either. from auth import UserAuthorizedAction from main import hsm_active, settings from hsm_ux import ApproveHSMPolicy rv = dict() rv['active'] = bool(hsm_active) if not hsm_active: rv['policy_available'] = hsm_policy_available() ar = UserAuthorizedAction.active_request if ar and isinstance(ar, ApproveHSMPolicy): # we are waiting for local user to approve entry into HSM mode rv['approval_wait'] = True rv['users'] = Users.list() rv['wallets'] = [ms.name for ms in MultisigWallet.get_all()] rv['chain'] = settings.get('chain', 'BTC') if hsm_active: hsm_active.status_report(rv) return rv
def __init__(self, j, idx): # read json dict provided self.spent_so_far = 0 # for velocity def check_user(u): if not Users.valid_username(u): raise ValueError("Unknown user: %s" % u) return u self.index = idx + 1 self.per_period = pop_int(j, 'per_period', 0, MAX_SATS) self.max_amount = pop_int(j, 'max_amount', 0, MAX_SATS) self.users = pop_list(j, 'users', check_user) self.whitelist = pop_list(j, 'whitelist', cleanup_whitelist_value) self.min_users = pop_int(j, 'min_users', 1, len(self.users)) self.local_conf = pop_bool(j, 'local_conf') self.wallet = pop_string(j, 'wallet', 1, 20) assert sorted(set(self.users)) == sorted(self.users), 'dup users' # usernames need to be correct and already known if self.min_users is None: self.min_users = len(self.users) if self.users else None else: # redundant w/ code in pop_int() above assert 1 <= self.min_users <= len(self.users), "range" # if specified, 'wallet' must be an existing multisig wallet's name if self.wallet and self.wallet != '1': names = [ms.name for ms in MultisigWallet.get_all()] assert self.wallet in names, "unknown MS wallet: " + self.wallet assert_empty_dict(j)
def generate_public_contents(): # Generate public details about wallet. # # simple text format: # key = value # or #comments # but value is JSON from main import settings from public_constants import AF_CLASSIC num_rx = 5 chain = chains.current_chain() with stash.SensitiveValues() as sv: yield ('''\ # Coldcard Wallet Summary File ## For wallet with master key fingerprint: {xfp} Wallet operates on blockchain: {nb} For BIP44, this is coin_type '{ct}', and internally we use symbol {sym} for this blockchain. ## IMPORTANT WARNING Do **not** deposit to any address in this file unless you have a working wallet system that is ready to handle the funds at that address! ## Top-level, 'master' extended public key ('m/'): {xpub} What follows are derived public keys and payment addresses, as may be needed for different systems. '''.format(nb=chain.name, xpub=chain.serialize_public(sv.node), sym=chain.ctype, ct=chain.b44_cointype, xfp=xfp2str(sv.node.my_fingerprint()))) for name, path, addr_fmt in chains.CommonDerivations: if '{coin_type}' in path: path = path.replace('{coin_type}', str(chain.b44_cointype)) if '{' in name: name = name.format(core_name=chain.core_name) show_slip132 = ('Core' not in name) yield ('''## For {name}: {path}\n\n'''.format(name=name, path=path)) yield ( '''First %d receive addresses (account=0, change=0):\n\n''' % num_rx) submaster = None for i in range(num_rx): subpath = path.format(account=0, change=0, idx=i) # find the prefix of the path that is hardneded if "'" in subpath: hard_sub = subpath.rsplit("'", 1)[0] + "'" else: hard_sub = 'm' if hard_sub != submaster: # dump the xpub needed if submaster: yield "\n" node = sv.derive_path(hard_sub, register=False) yield ("%s => %s\n" % (hard_sub, chain.serialize_public(node))) if show_slip132 and addr_fmt != AF_CLASSIC and ( addr_fmt in chain.slip132): yield ( "%s => %s ##SLIP-132##\n" % (hard_sub, chain.serialize_public(node, addr_fmt))) submaster = hard_sub node.blank() del node # show the payment address node = sv.derive_path(subpath, register=False) yield ('%s => %s\n' % (subpath, chain.address(node, addr_fmt))) node.blank() del node yield ('\n\n') from multisig import MultisigWallet if MultisigWallet.exists(): yield '\n# Your Multisig Wallets\n\n' from uio import StringIO for ms in MultisigWallet.get_all(): fp = StringIO() ms.render_export(fp) print("\n---\n", file=fp) yield fp.getvalue() del fp