Browse Source

wizard: fix trezor device initialization

master
ThomasV 9 years ago
parent
commit
3b830cbcfa
  1. 12
      lib/base_wizard.py
  2. 83
      plugins/trezor/plugin.py
  3. 24
      plugins/trezor/qt_generic.py

12
lib/base_wizard.py

@ -193,10 +193,18 @@ class BaseWizard(object):
self.account_id_dialog(run_next=f) self.account_id_dialog(run_next=f)
def on_hardware_account_id(self, account_id): 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)) derivation = bip44_derivation(int(account_id))
plugin = self.plugins.get_plugin(self.hw_type) 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) self.on_keystore(k, None)
def on_hardware_seed(self): def on_hardware_seed(self):

83
plugins/trezor/plugin.py

@ -143,7 +143,7 @@ class TrezorCompatiblePlugin(HW_PluginBase):
client.used() client.used()
return client return client
def initialize_device(self, keystore): def initialize_device(self, device_id, wizard, handler):
# Initialization method # Initialization method
msg = _("Choose how you want to initialize your %s.\n\n" msg = _("Choose how you want to initialize your %s.\n\n"
"The first two methods are secure as no secret information " "The first two methods are secure as no secret information "
@ -153,22 +153,23 @@ class TrezorCompatiblePlugin(HW_PluginBase):
"only do those on a computer you know to be trustworthy " "only do those on a computer you know to be trustworthy "
"and free of malware." "and free of malware."
) % (self.device, self.device) ) % (self.device, self.device)
choices = [
methods = [
# Must be short as QT doesn't word-wrap radio button text # Must be short as QT doesn't word-wrap radio button text
_("Let the device generate a completely new seed randomly"), (TIM_NEW, _("Let the device generate a completely new seed randomly")),
_("Recover from a seed you have previously written down"), (TIM_RECOVER, _("Recover from a seed you have previously written down")),
_("Upload a BIP39 mnemonic to generate the seed"), (TIM_MNEMONIC, _("Upload a BIP39 mnemonic to generate the seed")),
_("Upload a master private key") (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) \ (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': if method == TIM_RECOVER and self.device == 'TREZOR':
# Warn user about firmware lameness # Warn user about firmware lameness
keystore.handler.show_error(_( handler.show_error(_(
"You will be asked to enter 24 words regardless of your " "You will be asked to enter 24 words regardless of your "
"seed's actual length. If you enter a word incorrectly or " "seed's actual length. If you enter a word incorrectly or "
"misspell it, you cannot change it or go back - you will need " "misspell it, you cannot change it or go back - you will need "
@ -176,52 +177,42 @@ class TrezorCompatiblePlugin(HW_PluginBase):
"the words carefully!")) "the words carefully!"))
language = 'english' language = 'english'
devmgr = self.device_manager()
client = devmgr.client_by_id(device_id, handler)
def initialize_method(): if method == TIM_NEW:
client = self.get_client(keystore) 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) pin_protection, label, language)
elif method == TIM_RECOVER: elif method == TIM_RECOVER:
word_count = 6 * (item + 2) # 12, 18 or 24 word_count = 6 * (item + 2) # 12, 18 or 24
client.step = 0 client.step = 0
client.recovery_device(word_count, passphrase_protection, client.recovery_device(word_count, passphrase_protection,
pin_protection, label, language) pin_protection, label, language)
elif method == TIM_MNEMONIC: elif method == TIM_MNEMONIC:
pin = pin_protection # It's the pin, not a boolean pin = pin_protection # It's the pin, not a boolean
client.load_device_by_mnemonic(str(item), pin, client.load_device_by_mnemonic(str(item), pin,
passphrase_protection, passphrase_protection,
label, language)
else:
pin = pin_protection # It's the pin, not a boolean
client.load_device_by_xprv(item, pin, passphrase_protection,
label, language) label, language)
# After successful initialization get xpub else:
self.xpub = client.get_xpub(derivation) pin = pin_protection # It's the pin, not a boolean
client.load_device_by_xprv(item, pin, passphrase_protection,
return initialize_method label, language)
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)
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 '''Called when creating a new wallet. Select the device to use. If
the device is uninitialized, go through the intialization the device is uninitialized, go through the intialization
process. Then create the wallet accounts.''' process.'''
handler = self.create_handler(wizard)
devmgr = self.device_manager() devmgr = self.device_manager()
device_info = devmgr.select_device(handler, self) device_info = devmgr.select_device(handler, self)
device_id = device_info.device.id_ device_id = device_info.device.id_
if device_info.initialized: if not device_info.initialized:
task = lambda: self.init_xpub(derivation, device_id, handler) self.initialize_device(device_id, wizard, handler)
else:
task = self.initialize_device(keystore) client = devmgr.client_by_id(device_id, handler)
thread.add(task, on_done=on_done, on_error=on_error) client.used()
return client.get_xpub(derivation)
def sign_transaction(self, keystore, tx, prev_tx, xpub_path): def sign_transaction(self, keystore, tx, prev_tx, xpub_path):
self.prev_tx = prev_tx self.prev_tx = prev_tx

24
plugins/trezor/qt_generic.py

@ -284,30 +284,6 @@ def qt_plugin_class(base_plugin_class):
# Trigger a pairing # Trigger a pairing
keystore.thread.add(partial(self.get_client, keystore)) 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 @hook
def receive_menu(self, menu, addrs, wallet): def receive_menu(self, menu, addrs, wallet):
for keystore in wallet.get_keystores(): for keystore in wallet.get_keystores():

Loading…
Cancel
Save