From 809d6aefcacf5b7b8244bee3e62763715c0a7ac2 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Tue, 1 May 2018 22:44:57 +0200 Subject: [PATCH] finish prev --- plugins/trezor/clientbase.py | 8 +++--- plugins/trezor/qt.py | 56 +++++++++++++++++++++++++++--------- plugins/trezor/trezor.py | 14 +++++++-- 3 files changed, 58 insertions(+), 20 deletions(-) diff --git a/plugins/trezor/clientbase.py b/plugins/trezor/clientbase.py index 721544988..a8a423228 100644 --- a/plugins/trezor/clientbase.py +++ b/plugins/trezor/clientbase.py @@ -85,11 +85,11 @@ class GuiMixin(object): def callback_WordRequest(self, msg): if (msg.type is not None - and msg.type in (self.types.WordRequestType_Matrix9, - self.types.WordRequestType_Matrix6)): - num = 9 if msg.type == self.types.WordRequestType_Matrix9 else 6 + and msg.type in (self.types.WordRequestType.Matrix9, + self.types.WordRequestType.Matrix6)): + num = 9 if msg.type == self.types.WordRequestType.Matrix9 else 6 char = self.handler.get_matrix(num) - if (char == 'x'): + if char == 'x': return self.proto.Cancel() return self.proto.WordAck(word=char) diff --git a/plugins/trezor/qt.py b/plugins/trezor/qt.py index 9185f1b2c..006f87a00 100644 --- a/plugins/trezor/qt.py +++ b/plugins/trezor/qt.py @@ -12,7 +12,8 @@ from electrum.util import PrintError, UserCancelled, bh2u from electrum.wallet import Wallet, Standard_Wallet from ..hw_wallet.qt import QtHandlerBase, QtPluginBase -from .trezor import TrezorPlugin, TIM_NEW, TIM_RECOVER, TIM_MNEMONIC +from .trezor import (TrezorPlugin, TIM_NEW, TIM_RECOVER, TIM_MNEMONIC, + RECOVERY_TYPE_SCRAMBLED_WORDS, RECOVERY_TYPE_MATRIX) PASSPHRASE_HELP_SHORT =_( @@ -30,7 +31,7 @@ PASSPHRASE_NOT_PIN = _( "If you forget a passphrase you will be unable to access any " "bitcoins in the wallet behind it. A passphrase is not a PIN. " "Only change this if you are sure you understand it.") -MATRIX_RECOVERY = ( +MATRIX_RECOVERY = _( "Enter the recovery words by pressing the buttons according to what " "the device shows on its display. You can also use your NUMPAD.\n" "Press BACKSPACE to go back a choice or word.\n") @@ -49,7 +50,7 @@ class MatrixDialog(WindowModalDialog): grid = QGridLayout() grid.setSpacing(0) - self.char_buttons = []; + self.char_buttons = [] for y in range(3): for x in range(3): button = QPushButton('?') @@ -58,8 +59,7 @@ class MatrixDialog(WindowModalDialog): self.char_buttons.append(button) vbox.addLayout(grid) - hbox = QHBoxLayout() - self.backspace_button = QPushButton(_("<=")) + self.backspace_button = QPushButton("<=") self.backspace_button.clicked.connect(partial(self.process_key, Qt.Key_Backspace)) self.cancel_button = QPushButton(_("Cancel")) self.cancel_button.clicked.connect(partial(self.process_key, Qt.Key_Escape)) @@ -84,7 +84,7 @@ class MatrixDialog(WindowModalDialog): self.data = 'x' elif self.is_valid(key): self.char_buttons[key - ord('1')].setFocus() - self.data = '%c' % key; + self.data = '%c' % key if self.data: self.loop.exit(0) @@ -103,12 +103,14 @@ class QtHandler(QtHandlerBase): pin_signal = pyqtSignal(object) matrix_signal = pyqtSignal(object) + close_matrix_dialog_signal = pyqtSignal() def __init__(self, win, pin_matrix_widget_class, device): super(QtHandler, self).__init__(win, device) self.pin_signal.connect(self.pin_dialog) - self.pin_matrix_widget_class = pin_matrix_widget_class self.matrix_signal.connect(self.matrix_recovery_dialog) + self.close_matrix_dialog_signal.connect(self._close_matrix_dialog) + self.pin_matrix_widget_class = pin_matrix_widget_class self.matrix_dialog = None def get_pin(self, msg): @@ -123,9 +125,13 @@ class QtHandler(QtHandlerBase): self.done.wait() data = self.matrix_dialog.data if data == 'x': + self.close_matrix_dialog_signal.emit() + return data + + def _close_matrix_dialog(self): + if self.matrix_dialog: self.matrix_dialog.accept() self.matrix_dialog = None - return data def pin_dialog(self, msg): # Needed e.g. when resetting a device @@ -193,12 +199,12 @@ class QtPlugin(QtPluginBase): gb.setLayout(hbox1) vbox.addWidget(gb) gb.setTitle(_("Select your seed length:")) - bg = QButtonGroup() + bg_numwords = QButtonGroup() for i, count in enumerate([12, 18, 24]): rb = QRadioButton(gb) rb.setText(_("%d words") % count) - bg.addButton(rb) - bg.setId(rb, i) + bg_numwords.addButton(rb) + bg_numwords.setId(rb, i) hbox1.addWidget(rb) rb.setChecked(True) cb_pin = QCheckBox(_('Enable PIN protection')) @@ -241,16 +247,40 @@ class QtPlugin(QtPluginBase): vbox.addWidget(passphrase_warning) vbox.addWidget(cb_phrase) + # ask for recovery type (random word order OR matrix) + if method == TIM_RECOVER: + gb_rectype = QGroupBox() + hbox_rectype = QHBoxLayout() + gb_rectype.setLayout(hbox_rectype) + vbox.addWidget(gb_rectype) + gb_rectype.setTitle(_("Select recovery type:")) + bg_rectype = QButtonGroup() + + rb1 = QRadioButton(gb_rectype) + rb1.setText(_('Scrambled words')) + bg_rectype.addButton(rb1) + bg_rectype.setId(rb1, RECOVERY_TYPE_SCRAMBLED_WORDS) + hbox_rectype.addWidget(rb1) + rb1.setChecked(True) + + rb2 = QRadioButton(gb_rectype) + rb2.setText(_('Matrix')) + bg_rectype.addButton(rb2) + bg_rectype.setId(rb2, RECOVERY_TYPE_MATRIX) + hbox_rectype.addWidget(rb2) + wizard.exec_layout(vbox, next_enabled=next_enabled) if method in [TIM_NEW, TIM_RECOVER]: - item = bg.checkedId() + item = bg_numwords.checkedId() pin = cb_pin.isChecked() + recovery_type = bg_rectype.checkedId() else: item = ' '.join(str(clean_text(text)).split()) pin = str(pin.text()) + recovery_type = None - return (item, name.text(), pin, cb_phrase.isChecked()) + return (item, name.text(), pin, cb_phrase.isChecked(), recovery_type) class Plugin(TrezorPlugin, QtPlugin): diff --git a/plugins/trezor/trezor.py b/plugins/trezor/trezor.py index 3539b9de4..c589a1a97 100644 --- a/plugins/trezor/trezor.py +++ b/plugins/trezor/trezor.py @@ -16,6 +16,7 @@ from ..hw_wallet import HW_PluginBase # TREZOR initialization methods TIM_NEW, TIM_RECOVER, TIM_MNEMONIC, TIM_PRIVKEY = range(0, 4) +RECOVERY_TYPE_SCRAMBLED_WORDS, RECOVERY_TYPE_MATRIX = range(0, 2) # script "generation" SCRIPT_GEN_LEGACY, SCRIPT_GEN_P2SH_SEGWIT, SCRIPT_GEN_NATIVE_SEGWIT = range(0, 3) @@ -216,9 +217,9 @@ class TrezorPlugin(HW_PluginBase): wizard.loop.exit(0) def _initialize_device(self, settings, method, device_id, wizard, handler): - item, label, pin_protection, passphrase_protection = settings + item, label, pin_protection, passphrase_protection, recovery_type = settings - if method == TIM_RECOVER: + if method == TIM_RECOVER and recovery_type == RECOVERY_TYPE_SCRAMBLED_WORDS: 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 " @@ -241,8 +242,15 @@ class TrezorPlugin(HW_PluginBase): elif method == TIM_RECOVER: word_count = 6 * (item + 2) # 12, 18 or 24 client.step = 0 + if recovery_type == RECOVERY_TYPE_SCRAMBLED_WORDS: + recovery_type_trezor = self.types.RecoveryDeviceType.ScrambledWords + else: + recovery_type_trezor = self.types.RecoveryDeviceType.Matrix client.recovery_device(word_count, passphrase_protection, - pin_protection, label, language) + pin_protection, label, language, + type=recovery_type_trezor) + if recovery_type == RECOVERY_TYPE_MATRIX: + handler.close_matrix_dialog_signal.emit() elif method == TIM_MNEMONIC: pin = pin_protection # It's the pin, not a boolean client.load_device_by_mnemonic(str(item), pin,