electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 4b1d8353040513f6a3e371b7385711eb9f146a70
parent 01dac92e19481690e31b06632c1b1833468cee0b
Author: SomberNight <somber.night@protonmail.com>
Date:   Thu,  9 Apr 2020 18:00:35 +0200

wizard hww: scan devices fewer times and move away from GUI thread

Diffstat:
Melectrum/base_wizard.py | 7+++----
Melectrum/plugin.py | 17+++++++++--------
Melectrum/plugins/coldcard/coldcard.py | 1+
Melectrum/plugins/digitalbitbox/digitalbitbox.py | 1+
Melectrum/plugins/hw_wallet/plugin.py | 6++++--
Melectrum/plugins/keepkey/keepkey.py | 1+
Melectrum/plugins/ledger/ledger.py | 1+
Melectrum/plugins/safe_t/safe_t.py | 1+
Melectrum/plugins/trezor/trezor.py | 1+
9 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/electrum/base_wizard.py b/electrum/base_wizard.py @@ -348,7 +348,7 @@ class BaseWizard(Logger): assert isinstance(self.plugin, HW_PluginBase) devmgr = self.plugins.device_manager try: - self.plugin.setup_device(device_info, self, purpose) + client = self.plugin.setup_device(device_info, self, purpose) except OSError as e: self.show_error(_('We encountered an error while connecting to your device:') + '\n' + str(e) + '\n' @@ -376,19 +376,18 @@ class BaseWizard(Logger): self.show_error(str(e)) self.choose_hw_device(purpose, storage=storage) return + if purpose == HWD_SETUP_NEW_WALLET: def f(derivation, script_type): derivation = normalize_bip32_derivation(derivation) self.run('on_hw_derivation', name, device_info, derivation, script_type) self.derivation_and_script_type_dialog(f) elif purpose == HWD_SETUP_DECRYPT_WALLET: - client = devmgr.client_by_id(device_info.device.id_) password = client.get_password_for_storage_encryption() try: storage.decrypt(password) except InvalidPassword: # try to clear session so that user can type another passphrase - client = devmgr.client_by_id(device_info.device.id_) if hasattr(client, 'clear_session'): # FIXME not all hw wallet plugins have this client.clear_session() raise @@ -435,7 +434,7 @@ class BaseWizard(Logger): assert isinstance(self.plugin, HW_PluginBase) try: xpub = self.plugin.get_xpub(device_info.device.id_, derivation, xtype, self) - client = devmgr.client_by_id(device_info.device.id_) + client = devmgr.client_by_id(device_info.device.id_, scan_now=False) if not client: raise Exception("failed to find client for device id") root_fingerprint = client.request_root_fingerprint_from_device() label = client.label() # use this as device_info.label might be outdated! diff --git a/electrum/plugin.py b/electrum/plugin.py @@ -401,7 +401,7 @@ class DeviceMgr(ThreadJob): def create_client(self, device: 'Device', handler: Optional['HardwareHandlerBase'], plugin: 'HW_PluginBase') -> Optional['HardwareClientBase']: # Get from cache first - client = self.client_lookup(device.id_) + client = self._client_by_id(device.id_) if client: return client client = plugin.create_client(device, handler) @@ -437,7 +437,7 @@ class DeviceMgr(ThreadJob): self._close_client(id_) def _close_client(self, id_): - client = self.client_lookup(id_) + client = self._client_by_id(id_) self.clients.pop(client, None) if client: client.close() @@ -446,19 +446,20 @@ class DeviceMgr(ThreadJob): with self.lock: self.xpub_ids[xpub] = id_ - def client_lookup(self, id_) -> Optional['HardwareClientBase']: + def _client_by_id(self, id_) -> Optional['HardwareClientBase']: with self.lock: for client, (path, client_id) in self.clients.items(): if client_id == id_: return client return None - def client_by_id(self, id_) -> Optional['HardwareClientBase']: + def client_by_id(self, id_, *, scan_now: bool = True) -> Optional['HardwareClientBase']: '''Returns a client for the device ID if one is registered. If a device is wiped or in bootloader mode pairing is impossible; in such cases we communicate by device ID and not wallet.''' - self.scan_devices() - return self.client_lookup(id_) + if scan_now: + self.scan_devices() + return self._client_by_id(id_) @with_scan_lock def client_for_keystore(self, plugin: 'HW_PluginBase', handler: Optional['HardwareHandlerBase'], @@ -495,7 +496,7 @@ class DeviceMgr(ThreadJob): def client_by_xpub(self, plugin: 'HW_PluginBase', xpub, handler: 'HardwareHandlerBase', devices: Sequence['Device']) -> Optional['HardwareClientBase']: _id = self.xpub_id(xpub) - client = self.client_lookup(_id) + client = self._client_by_id(_id) if client: # An unpaired client might have another wallet's handler # from a prior scan. Replace to fix dialog parenting. @@ -511,7 +512,7 @@ class DeviceMgr(ThreadJob): # The wallet has not been previously paired, so let the user # choose an unpaired device and compare its first address. xtype = bip32.xpub_type(xpub) - client = self.client_lookup(info.device.id_) + client = self._client_by_id(info.device.id_) if client and client.is_pairable(): # See comment above for same code client.handler = handler diff --git a/electrum/plugins/coldcard/coldcard.py b/electrum/plugins/coldcard/coldcard.py @@ -524,6 +524,7 @@ class ColdcardPlugin(HW_PluginBase): def setup_device(self, device_info, wizard, purpose): device_id = device_info.device.id_ client = self.scan_and_create_client_for_device(device_id=device_id, wizard=wizard) + return client def get_xpub(self, device_id, derivation, xtype, wizard): # this seems to be part of the pairing process only, not during normal ops? diff --git a/electrum/plugins/digitalbitbox/digitalbitbox.py b/electrum/plugins/digitalbitbox/digitalbitbox.py @@ -705,6 +705,7 @@ class DigitalBitboxPlugin(HW_PluginBase): client.setupRunning = True wizard.run_task_without_blocking_gui( task=lambda: client.get_xpub("m/44'/0'", 'standard')) + return client def is_mobile_paired(self): diff --git a/electrum/plugins/hw_wallet/plugin.py b/electrum/plugins/hw_wallet/plugin.py @@ -25,6 +25,7 @@ # SOFTWARE. from typing import TYPE_CHECKING, Dict, List, Union, Tuple, Sequence, Optional, Type +from functools import partial from electrum.plugin import BasePlugin, hook, Device, DeviceMgr, DeviceInfo from electrum.i18n import _ @@ -67,14 +68,15 @@ class HW_PluginBase(BasePlugin): def scan_and_create_client_for_device(self, *, device_id: str, wizard: 'BaseWizard') -> 'HardwareClientBase': devmgr = self.device_manager() - client = devmgr.client_by_id(device_id) + client = wizard.run_task_without_blocking_gui( + task=partial(devmgr.client_by_id, device_id)) if client is None: raise UserFacingException(_('Failed to create a client for this device.') + '\n' + _('Make sure it is in the correct state.')) client.handler = self.create_handler(wizard) return client - def setup_device(self, device_info: DeviceInfo, wizard: 'BaseWizard', purpose): + def setup_device(self, device_info: DeviceInfo, wizard: 'BaseWizard', purpose) -> 'HardwareClientBase': """Called when creating a new wallet or when using the device to decrypt an existing wallet. Select the device to use. If the device is uninitialized, go through the initialization process. diff --git a/electrum/plugins/keepkey/keepkey.py b/electrum/plugins/keepkey/keepkey.py @@ -283,6 +283,7 @@ class KeepKeyPlugin(HW_PluginBase): wizard.run_task_without_blocking_gui( task=lambda: client.get_xpub("m", 'standard')) client.used() + return client def get_xpub(self, device_id, derivation, xtype, wizard): if xtype not in self.SUPPORTED_XTYPES: diff --git a/electrum/plugins/ledger/ledger.py b/electrum/plugins/ledger/ledger.py @@ -610,6 +610,7 @@ class LedgerPlugin(HW_PluginBase): client = self.scan_and_create_client_for_device(device_id=device_id, wizard=wizard) wizard.run_task_without_blocking_gui( task=lambda: client.get_xpub("m/44'/0'", 'standard')) # TODO replace by direct derivation once Nano S > 1.1 + return client def get_xpub(self, device_id, derivation, xtype, wizard): if xtype not in self.SUPPORTED_XTYPES: diff --git a/electrum/plugins/safe_t/safe_t.py b/electrum/plugins/safe_t/safe_t.py @@ -257,6 +257,7 @@ class SafeTPlugin(HW_PluginBase): wizard.run_task_without_blocking_gui( task=lambda: client.get_xpub("m", 'standard')) client.used() + return client def get_xpub(self, device_id, derivation, xtype, wizard): if xtype not in self.SUPPORTED_XTYPES: diff --git a/electrum/plugins/trezor/trezor.py b/electrum/plugins/trezor/trezor.py @@ -288,6 +288,7 @@ class TrezorPlugin(HW_PluginBase): wizard.run_task_without_blocking_gui( task=lambda: client.get_xpub('m', 'standard', creating=is_creating_wallet)) client.used() + return client def get_xpub(self, device_id, derivation, xtype, wizard): if xtype not in self.SUPPORTED_XTYPES: