URI: 
       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():