def get_xpub(hw_session: HwSessionInfo, bip32_path): client = hw_session.hw_client if client: if isinstance(bip32_path, str): bip32_path.strip() if bip32_path.lower().find('m/') >= 0: bip32_path = bip32_path[2:] if hw_session.app_config.hw_type == HWType.trezor: from trezorlib import btc if isinstance(bip32_path, str): bip32_path = stash_utils.bip32_path_string_to_n(bip32_path) return btc.get_public_node(client, bip32_path).xpub elif hw_session.app_config.hw_type == HWType.keepkey: if isinstance(bip32_path, str): bip32_path = stash_utils.bip32_path_string_to_n(bip32_path) return client.get_public_node(bip32_path).xpub elif hw_session.app_config.hw_type == HWType.ledger_nano_s: import hw_intf_ledgernano as ledger if isinstance(bip32_path, list): # ledger requires bip32 path argument as a string bip32_path = bip32_path_n_to_string(bip32_path) return ledger.get_xpub(client, bip32_path) else: raise Exception('Unknown hardware wallet type: ' + hw_session.app_config.hw_type) else: raise Exception('HW client not open.')
def sign_message(hw_session: HwSessionInfo, bip32path, message): client = hw_session.hw_client address_n = stash_utils.bip32_path_string_to_n(bip32path) try: return btc.sign_message(client, hw_session.app_config.hw_coin_name, address_n, message) except exceptions.Cancelled: raise CancelException('Cancelled')
def get_session_info_trezor(get_public_node_fun, hw_session: HwSessionInfo, hw_client): nonlocal hw_type def call_get_public_node(ctrl, get_public_node_fun, path_n): pk = get_public_node_fun(path_n).node.public_key return pk path = stash_utils.get_default_bip32_base_path( hw_session.app_config.stash_network) path_n = stash_utils.bip32_path_string_to_n(path) # show message for Trezor T device while waiting for the user to choose the passphrase input method pub = WndUtils.run_thread_dialog(call_get_public_node, (get_public_node_fun, path_n), title=DEFAULT_HW_BUSY_TITLE, text=DEFAULT_HW_BUSY_MESSAGE, force_close_dlg_callback=partial( cancel_hw_thread_dialog, hw_client), show_window_delay_ms=1000) if pub: hw_session.set_base_info(path, pub) else: raise Exception('Couldn\'t read data from the hardware wallet.')
def set_bip32_path(self, path): Bip44Entry.set_bip32_path(self, path) if path: path_n = bip32_path_string_to_n(path) if path_n[-2] == 1: self.__is_change = True else: self.__is_change = False
def get_address_and_pubkey(hw_session: HwSessionInfo, bip32_path): client = hw_session.hw_client if client: if isinstance(bip32_path, str): bip32_path.strip() if bip32_path.lower().find('m/') >= 0: # removing m/ prefix because of keepkey library bip32_path = bip32_path[2:] if hw_session.app_config.hw_type == HWType.trezor: from trezorlib import btc if isinstance(bip32_path, str): bip32_path = stash_utils.bip32_path_string_to_n(bip32_path) return { 'address': btc.get_address(client, hw_session.app_config.hw_coin_name, bip32_path, False), 'publicKey': btc.get_public_node(client, bip32_path).node.public_key } elif hw_session.app_config.hw_type == HWType.keepkey: if isinstance(bip32_path, str): bip32_path = stash_utils.bip32_path_string_to_n(bip32_path) return { 'address': client.get_address(hw_session.app_config.hw_coin_name, bip32_path, False), 'publicKey': client.get_public_node(bip32_path).node.public_key } elif hw_session.app_config.hw_type == HWType.ledger_nano_s: import hw_intf_ledgernano as ledger if isinstance(bip32_path, list): # ledger requires bip32 path argument as a string bip32_path = bip32_path_n_to_string(bip32_path) return ledger.get_address_and_pubkey(client, bip32_path) else: raise Exception('Unknown hardware wallet type: ' + hw_session.app_config.hw_type)
def get_child_entry(self, index) -> 'Bip44Entry': child = self.child_entries.get(index) if not child: key = self.get_bip32key() child_key = key.ChildKey(index) child_xpub = child_key.ExtendedKey(False, True) if self.bip32_path: bip32_path_n = bip32_path_string_to_n(self.bip32_path) bip32_path_n.append(index) bip32_path = bip32_path_n_to_string(bip32_path_n) else: raise Exception('Unknown BIP32 path of the parrent') child = Bip44Entry(tree_id=self.tree_id, id=None, parent=self, xpub=child_xpub, address_index=index, bip32_path=bip32_path, bip32_key=child_key) self.child_entries[index] = child return child
def sign_tx(hw_session: HwSessionInfo, utxos_to_spend: List[wallet_common.UtxoType], tx_outputs: List[wallet_common.TxOutputType], tx_fee): """ Creates a signed transaction. :param hw_session: :param utxos_to_spend: list of utxos to send :param tx_outputs: list of transaction outputs :param tx_fee: transaction fee :return: tuple (serialized tx, total transaction amount in satoshis) """ def load_prev_txes(tx_api, skip_cache: bool = False): txes = {} tx_api.skip_cache = skip_cache for utxo in utxos_to_spend: prev_hash = bytes.fromhex(utxo.txid) if prev_hash not in txes: tx = tx_api[prev_hash] txes[prev_hash] = tx return txes insight_network = 'insight_stash' if hw_session.app_config.is_testnet(): insight_network += '_testnet' stash_network = hw_session.app_config.stash_network c_name = hw_session.app_config.hw_coin_name coin = coins.by_name[c_name] url = hw_session.app_config.get_tx_api_url() coin['bitcore'].clear() coin['bitcore'].append(url) tx_api = MyTxApiInsight(coin, '', hw_session.stashd_intf, hw_session.app_config.tx_cache_dir) client = hw_session.hw_client inputs = [] outputs = [] inputs_amount = 0 for utxo_index, utxo in enumerate(utxos_to_spend): if not utxo.bip32_path: raise Exception('No BIP32 path for UTXO ' + utxo.txid) address_n = stash_utils.bip32_path_string_to_n(utxo.bip32_path) it = trezor_proto.TxInputType( address_n=address_n, prev_hash=binascii.unhexlify(utxo.txid), prev_index=int(utxo.output_index)) inputs.append(it) inputs_amount += utxo.satoshis outputs_amount = 0 for out in tx_outputs: outputs_amount += out.satoshis if out.address[0] in stash_utils.get_chain_params(stash_network).B58_PREFIXES_SCRIPT_ADDRESS: stype = trezor_proto.OutputScriptType.PAYTOSCRIPTHASH logging.debug('Transaction type: PAYTOSCRIPTHASH' + str(stype)) elif out.address[0] in stash_utils.get_chain_params(stash_network).B58_PREFIXES_PUBKEY_ADDRESS: stype = trezor_proto.OutputScriptType.PAYTOADDRESS logging.debug('Transaction type: PAYTOADDRESS ' + str(stype)) else: raise Exception('Invalid prefix of the destination address.') if out.bip32_path: address_n = stash_utils.bip32_path_string_to_n(out.bip32_path) else: address_n = None ot = trezor_proto.TxOutputType( address=out.address if address_n is None else None, address_n=address_n, amount=out.satoshis, script_type=stype ) outputs.append(ot) if outputs_amount + tx_fee != inputs_amount: raise Exception('Transaction validation failure: inputs + fee != outputs') try: for skip_cache in (False, True): txes = load_prev_txes(tx_api, skip_cache) try: signed = btc.sign_tx(client, hw_session.app_config.hw_coin_name, inputs, outputs, prev_txes=txes) return signed[1], inputs_amount except exceptions.Cancelled: raise except Exception as e: if skip_cache: raise log.exception('Exception occurred while signing transaction. Turning off the transaction cache ' 'and retrying...') raise Exception('Internal error: transaction not signed') except exceptions.Cancelled: raise CancelException('Cancelled')
def _get_address(ctrl, hw_session: HwSessionInfo, bip32_path: str, show_display: bool = False, message_to_display: str = None): if ctrl: ctrl.dlg_config_fun(dlg_title=DEFAULT_HW_BUSY_TITLE, show_progress_bar=False) if message_to_display: ctrl.display_msg_fun(message_to_display) else: ctrl.display_msg_fun( '<b>Click the confirmation button on your hardware wallet to exit...</b>' ) client = hw_session.hw_client if client: if isinstance(bip32_path, str): bip32_path.strip() if bip32_path.lower().find('m/') >= 0: # removing m/ prefix because of keepkey library bip32_path = bip32_path[2:] if hw_session.app_config.hw_type == HWType.trezor: from trezorlib import btc from trezorlib import exceptions try: if isinstance(bip32_path, str): bip32_path = stash_utils.bip32_path_string_to_n( bip32_path) ret = btc.get_address(client, hw_session.app_config.hw_coin_name, bip32_path, show_display) return ret except (CancelException, exceptions.Cancelled): raise CancelException() elif hw_session.app_config.hw_type == HWType.keepkey: from keepkeylib.client import CallException try: if isinstance(bip32_path, str): bip32_path = stash_utils.bip32_path_string_to_n( bip32_path) return client.get_address( hw_session.app_config.hw_coin_name, bip32_path, show_display) except CallException as e: if isinstance(e.args, tuple) and len(e.args) >= 2 and isinstance(e.args[1], str) and \ e.args[1].find('cancel') >= 0: raise CancelException('Cancelled') elif hw_session.app_config.hw_type == HWType.ledger_nano_s: import hw_intf_ledgernano as ledger if isinstance(bip32_path, list): # ledger requires bip32 path argument as a string bip32_path = bip32_path_n_to_string(bip32_path) adr_pubkey = ledger.get_address_and_pubkey( client, bip32_path, show_display) return adr_pubkey.get('address') else: raise Exception('Unknown hardware wallet type: ' + hw_session.app_config.hw_type) else: raise Exception('HW client not open.')