twizard: fix trezor device initialization - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 3b830cbcfa2363febcc81d1eb7a1c392fb665277 DIR parent 80675121ce4882aa59ab98e662a2c3e8239602c6 HTML Author: ThomasV <thomasv@electrum.org> Date: Tue, 23 Aug 2016 09:21:24 +0200 wizard: fix trezor device initialization Diffstat: M lib/base_wizard.py | 12 ++++++++++-- M plugins/trezor/plugin.py | 83 ++++++++++++++----------------- M plugins/trezor/qt_generic.py | 24 ------------------------ 3 files changed, 47 insertions(+), 72 deletions(-) --- DIR diff --git a/lib/base_wizard.py b/lib/base_wizard.py t@@ -193,10 +193,18 @@ class BaseWizard(object): self.account_id_dialog(run_next=f) def on_hardware_account_id(self, account_id): - from keystore import load_keystore, bip44_derivation + from keystore import hardware_keystore, bip44_derivation derivation = bip44_derivation(int(account_id)) plugin = self.plugins.get_plugin(self.hw_type) - k = plugin.create_keystore(self.hw_type, derivation, self) + xpub = plugin.setup_device(derivation, self) + # create keystore + d = { + 'type': 'hardware', + 'hw_type': self.hw_type, + 'derivation': derivation, + 'xpub': xpub, + } + k = hardware_keystore(self.hw_type, d) self.on_keystore(k, None) def on_hardware_seed(self): DIR diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py t@@ -143,7 +143,7 @@ class TrezorCompatiblePlugin(HW_PluginBase): client.used() return client - def initialize_device(self, keystore): + def initialize_device(self, device_id, wizard, handler): # Initialization method msg = _("Choose how you want to initialize your %s.\n\n" "The first two methods are secure as no secret information " t@@ -153,22 +153,23 @@ class TrezorCompatiblePlugin(HW_PluginBase): "only do those on a computer you know to be trustworthy " "and free of malware." ) % (self.device, self.device) - - methods = [ + choices = [ # Must be short as QT doesn't word-wrap radio button text - _("Let the device generate a completely new seed randomly"), - _("Recover from a seed you have previously written down"), - _("Upload a BIP39 mnemonic to generate the seed"), - _("Upload a master private key") + (TIM_NEW, _("Let the device generate a completely new seed randomly")), + (TIM_RECOVER, _("Recover from a seed you have previously written down")), + (TIM_MNEMONIC, _("Upload a BIP39 mnemonic to generate the seed")), + (TIM_PRIVKEY, _("Upload a master private key")) ] + f = lambda x: self._initialize_device(x, device_id, handler) + wizard.choice_dialog(title=_('Initialize Device'), message=msg, choices=choices, run_next=f) - method = keystore.handler.query_choice(msg, methods) + def _initialize_device(self, method, device_id, handler): (item, label, pin_protection, passphrase_protection) \ - = wallet.handler.request_trezor_init_settings(method, self.device) + = handler.request_trezor_init_settings(method, self.device) if method == TIM_RECOVER and self.device == 'TREZOR': # Warn user about firmware lameness - keystore.handler.show_error(_( + handler.show_error(_( "You will be asked to enter 24 words regardless of your " "seed's actual length. If you enter a word incorrectly or " "misspell it, you cannot change it or go back - you will need " t@@ -176,52 +177,42 @@ class TrezorCompatiblePlugin(HW_PluginBase): "the words carefully!")) language = 'english' + devmgr = self.device_manager() + client = devmgr.client_by_id(device_id, handler) - def initialize_method(): - client = self.get_client(keystore) - - if method == TIM_NEW: - strength = 64 * (item + 2) # 128, 192 or 256 - client.reset_device(True, strength, passphrase_protection, + if method == TIM_NEW: + strength = 64 * (item + 2) # 128, 192 or 256 + client.reset_device(True, strength, passphrase_protection, pin_protection, label, language) - elif method == TIM_RECOVER: - word_count = 6 * (item + 2) # 12, 18 or 24 - client.step = 0 - client.recovery_device(word_count, passphrase_protection, + elif method == TIM_RECOVER: + word_count = 6 * (item + 2) # 12, 18 or 24 + client.step = 0 + client.recovery_device(word_count, passphrase_protection, pin_protection, label, language) - elif method == TIM_MNEMONIC: - pin = pin_protection # It's the pin, not a boolean - client.load_device_by_mnemonic(str(item), pin, - passphrase_protection, - label, language) - else: - pin = pin_protection # It's the pin, not a boolean - client.load_device_by_xprv(item, pin, passphrase_protection, + elif method == TIM_MNEMONIC: + pin = pin_protection # It's the pin, not a boolean + client.load_device_by_mnemonic(str(item), pin, + passphrase_protection, label, language) - # After successful initialization get xpub - self.xpub = client.get_xpub(derivation) - - return initialize_method - - def init_xpub(self, derivation, device_id, handler): - devmgr = self.device_manager() - client = devmgr.client_by_id(device_id, handler) - if client: - client.used() - self.xpub = client.get_xpub(derivation) + else: + pin = pin_protection # It's the pin, not a boolean + client.load_device_by_xprv(item, pin, passphrase_protection, + label, language) - def setup_device(self, derivation, thread, handler, on_done, on_error): + def setup_device(self, derivation, wizard): '''Called when creating a new wallet. Select the device to use. If the device is uninitialized, go through the intialization - process. Then create the wallet accounts.''' + process.''' + handler = self.create_handler(wizard) devmgr = self.device_manager() device_info = devmgr.select_device(handler, self) device_id = device_info.device.id_ - if device_info.initialized: - task = lambda: self.init_xpub(derivation, device_id, handler) - else: - task = self.initialize_device(keystore) - thread.add(task, on_done=on_done, on_error=on_error) + if not device_info.initialized: + self.initialize_device(device_id, wizard, handler) + + client = devmgr.client_by_id(device_id, handler) + client.used() + return client.get_xpub(derivation) def sign_transaction(self, keystore, tx, prev_tx, xpub_path): self.prev_tx = prev_tx DIR diff --git a/plugins/trezor/qt_generic.py b/plugins/trezor/qt_generic.py t@@ -284,30 +284,6 @@ def qt_plugin_class(base_plugin_class): # Trigger a pairing keystore.thread.add(partial(self.get_client, keystore)) - def create_keystore(self, hw_type, derivation, wizard): - from electrum.keystore import hardware_keystore - handler = self.create_handler(wizard) - thread = TaskThread(wizard, wizard.on_error) - # Setup device and create accounts in separate thread; wait until done - loop = QEventLoop() - exc_info = [] - self.setup_device(derivation, thread, handler, on_done=loop.quit, - on_error=lambda info: exc_info.extend(info)) - loop.exec_() - # If an exception was thrown, show to user and exit install wizard - if exc_info: - wizard.on_error(exc_info) - raise UserCancelled - # create keystore - d = { - 'xpub': self.xpub, - 'type': 'hardware', - 'hw_type': hw_type, - 'derivation': derivation - } - k = hardware_keystore(hw_type, d) - return k - @hook def receive_menu(self, menu, addrs, wallet): for keystore in wallet.get_keystores():