Ejemplo n.º 1
0
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 = dash_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 = dash_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.')
Ejemplo n.º 2
0
 def on_lbl_hw_account_base_path_linkActivated(self, text):
     path, ok = QInputDialog.getText(self, 'Account base path query', 'Enter a new BIP32 base path:',
                                            text=self.hw_account_base_bip32_path)
     if ok:
         try:
             dash_utils.bip32_path_string_to_n(path)
             if self.hw_account_base_bip32_path != path:
                 self.hw_account_base_bip32_path = path
                 self.display_bip32_base_path()
                 self.load_utxos()
         except Exception:
             self.errorMsg('Invalid BIP32 path')
Ejemplo n.º 3
0
 def on_btn_src_bip32_path_clicked(self, checked):
     path, ok = QInputDialog.getText(self, 'BIP32 path query', 'Enter a new BIP32 path:',
                                            text=self.hw_src_bip32_path)
     if ok:
         try:
             dash_utils.bip32_path_string_to_n(path)
             if self.hw_src_bip32_path != path:
                 self.hw_src_bip32_path = path
                 self.hw_src_address = ''  # will be retrieved in self.load_utxos
                 self.edt_src_bip32_path.setText(self.hw_src_bip32_path)
                 self.load_utxos()
         except Exception as e:
             self.errorMsg('Invalid BIP32 path')
def sign_message(hw_session: HwSessionInfo, bip32path, message):
    client = hw_session.hw_client
    address_n = dash_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')
Ejemplo n.º 5
0
    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 = dash_utils.get_default_bip32_base_path(
            hw_session.app_config.dash_network)
        path_n = dash_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.')
Ejemplo n.º 6
0
 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
Ejemplo n.º 7
0
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 = dash_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 = dash_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)
Ejemplo n.º 8
0
    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="Please confirm", 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
                if isinstance(bip32_path, str):
                    bip32_path = dash_utils.bip32_path_string_to_n(bip32_path)
                return btc.get_address(client, hw_session.app_config.hw_coin_name, bip32_path, show_display)

            elif hw_session.app_config.hw_type == HWType.keepkey:

                if isinstance(bip32_path, str):
                    bip32_path = dash_utils.bip32_path_string_to_n(bip32_path)
                return client.get_address(hw_session.app_config.hw_coin_name, bip32_path, show_display)

            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)
                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.')
Ejemplo n.º 9
0
def sign_message(hw_client, hw_coin_name: str, bip32path: str, message: str):
    address_n = dash_utils.bip32_path_string_to_n(bip32path)
    try:
        return btc.sign_message(hw_client, hw_coin_name, address_n, message)
    except exceptions.Cancelled:
        raise CancelException('Cancelled')
    except exceptions.TrezorFailure as e:
        if e.failure.message == 'Device not initialized':
            raise HwNotInitialized(e.failure.message)
        else:
            raise
Ejemplo n.º 10
0
    def get_session_info_trezor(get_public_node_fun, hw_session: HwSessionInfo):
        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 = dash_utils.get_default_bip32_base_path(hw_session.app_config.dash_network)
        path_n = dash_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='Confirm',
                                         text='<b>Complete the action on your hardware wallet device</b>',
                                         show_window_delay_ms=1000)

        hw_session.set_base_info(path, pub)
    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
Ejemplo n.º 12
0
 def refresh_adresses_preview(self):
     if self.mnemonic:
         bip32_path = self.edtHwOptionsBip32Path.text()
         passphrase = self.edtHwOptionsPassphrase.text()
         passphrase = self.mnemonic.normalize_string(passphrase)
         mnem_str = ' '.join(self.get_cur_mnemonic_words())
         bip32_seed = self.mnemonic.to_seed(mnem_str, passphrase)
         bip32_master_key = bitcoin.bip32_master_key(bip32_seed)
         bip32_path_n = bip32_path_string_to_n(bip32_path)
         if len(bip32_path_n) > 0:
             last_idx = bip32_path_n[-1]
             addresses = []
             for idx in range(10):
                 bip32_path_n[-1] = last_idx + idx
                 pk = self.get_bip32_private_key(bip32_path_n,
                                                 bip32_master_key)
                 pubkey = bitcoin.privkey_to_pubkey(pk)
                 addr = pubkey_to_address(pubkey)
                 path_str = bip32_path_n_to_string(bip32_path_n)
                 addresses.append((path_str, addr))
             self.address_preview_model.apply_addresses(addresses)
             self.address_preview_model.refresh_view()
             self.viewAddresses.resizeColumnsToContents()
Ejemplo n.º 13
0
        def get_addresses_to_scan(self, thread_ctrl: CtrlObject, addr_scan_ctrl: dict):
            """
            :param self:
            :param addr_scan_ctrl: (only for self.utxo_src_mode == 2) penultimate element of bip32 path to scan, used
                to switch sanning between normal and change addresses
            :return: yield List[Tuple[str (address), str (bip32 path)]]
            """
            try:
                if self.utxo_src_mode == 1:

                    if self.mn_src_index is not None:
                        if self.mn_src_index == len(self.masternode_addresses):
                            # show addresses of all masternodes
                            for chunk_nr in range(int(math.ceil(len(self.masternode_addresses) / ADDRESS_CHUNK))):
                                if self.finishing or thread_ctrl.finish:
                                    return
                                yield [x for x in self.masternode_addresses[
                                                  chunk_nr * ADDRESS_CHUNK : (chunk_nr + 1) * ADDRESS_CHUNK] if x[0] and x[1]]
                        elif self.mn_src_index < len(self.masternode_addresses) and self.mn_src_index >= 0:
                            if self.finishing or thread_ctrl.finish:
                                return
                            if self.masternode_addresses[self.mn_src_index][0] and \
                                self.masternode_addresses[self.mn_src_index][1]:
                                yield [self.masternode_addresses[self.mn_src_index]]

                elif self.utxo_src_mode == 2:
                    # hw wallet account: scan all addresses and change addresses for a specific account
                    # stop when a defined number of subsequent address has balance 0

                    addr_count = 0
                    addr_n = dash_utils.bip32_path_string_to_n(self.hw_account_base_bip32_path)
                    db_cur = self.db_intf.get_cursor()

                    try:
                        bip32_path_n = addr_n[:] + [self.hw_account_number + 0x80000000, 0, 0]
                        cur_addr_buf = []
                        last_level2_nr = addr_scan_ctrl.get('level2')
                        while True:
                            restart_iteration = False
                            for nr in range(1000):
                                if self.finishing or thread_ctrl.finish:
                                    return
                                if last_level2_nr != addr_scan_ctrl.get('level2'):
                                    last_level2_nr = addr_scan_ctrl.get('level2')
                                    restart_iteration = True
                                    break
                                bip32_path_n[-2] = addr_scan_ctrl.get('level2')
                                bip32_path_n[-1] = nr

                                cur_addr = hw_intf.get_address_ext(self.main_ui.hw_session, bip32_path_n, db_cur,
                                                                   self.app_config.hw_encrypt_string,
                                                                   self.app_config.hw_decrypt_string)

                                bip32_path = dash_utils.bip32_path_n_to_string(bip32_path_n)
                                cur_addr_buf.append((cur_addr, bip32_path))
                                addr_count += 1
                                if len(cur_addr_buf) >= ADDRESS_CHUNK:
                                    yield cur_addr_buf
                                    cur_addr_buf.clear()
                            if restart_iteration:
                                continue
                            if cur_addr_buf:
                                yield cur_addr_buf
                            break
                    finally:
                        if db_cur.connection.total_changes > 0:
                            self.db_intf.commit()
                        self.db_intf.release_cursor()

                elif self.utxo_src_mode == 3:

                    db_cur = self.db_intf.get_cursor()
                    try:
                        # address from a specific bip32 path
                        bip32_path_n = dash_utils.bip32_path_string_to_n(self.hw_src_bip32_path)
                        cur_addr = hw_intf.get_address_ext(self.main_ui.hw_session, bip32_path_n, db_cur,
                                                           self.app_config.hw_encrypt_string,
                                                           self.app_config.hw_decrypt_string)
                        self.hw_src_address = cur_addr
                        yield [(cur_addr, self.hw_src_bip32_path)]

                    finally:
                        if db_cur.connection.total_changes > 0:
                            self.db_intf.commit()
                        self.db_intf.release_cursor()

            except Exception as e:
                logging.exception('Exception occurred')
                raise
Ejemplo n.º 14
0
 def get_session_info_trezor(cli, hw_session: HwSessionInfo):
     path = dash_utils.get_default_bip32_base_path(
         hw_session.app_config.dash_network)
     path_n = dash_utils.bip32_path_string_to_n(path)
     pub = cli.get_public_node(path_n).node.public_key
     hw_session.set_base_info(path, pub)
Ejemplo n.º 15
0
def sign_tx(hw_session: HWSessionBase, rt_data: AppRuntimeData,
            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_bin = bytes.fromhex(utxo_.txid)
            if prev_hash_bin not in txes_:
                tx = tx_api_.get_tx(utxo_.txid)
                txes_[prev_hash_bin] = tx
        return txes_

    insight_network = 'insight_dash'
    if rt_data.is_testnet:
        insight_network += '_testnet'
    dash_network = rt_data.dash_network

    tx_api = MyTxApiInsight(rt_data.dashd_intf, rt_data.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 = dash_utils.bip32_path_string_to_n(utxo.bip32_path)
        it = trezor_proto.TxInputType(address_n=address_n,
                                      amount=utxo.satoshis,
                                      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 dash_utils.get_chain_params(
                dash_network).B58_PREFIXES_SCRIPT_ADDRESS:
            stype = trezor_proto.OutputScriptType.PAYTOSCRIPTHASH
            logging.debug('Transaction type: PAYTOSCRIPTHASH' + str(stype))
        elif out.address[0] in dash_utils.get_chain_params(
                dash_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 = dash_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,
                                     rt_data.hw_coin_name,
                                     inputs,
                                     outputs,
                                     prev_txes=txes)
                return signed[1], inputs_amount
            except exceptions.Cancelled:
                raise
            except Exception:
                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')
    except exceptions.TrezorFailure as e:
        if e.failure.message == 'Device not initialized':
            raise HwNotInitialized(e.failure.message)
        else:
            raise