commit 4d980cd4bdf3db7bbe0711b92f820d2525917322
parent d2a58a2ec3682daea6a1f248eb7a543e2bad47fa
Author: ghost43 <somber.night@protonmail.com>
Date: Mon, 6 Apr 2020 17:53:59 +0000
Merge pull request #6064 from matejcik/trezor-0.12-passphrase
trezor: bump lib version, implement new passphrase-on-device UI
Diffstat:
6 files changed, 102 insertions(+), 10 deletions(-)
diff --git a/contrib/requirements/requirements-hw.txt b/contrib/requirements/requirements-hw.txt
@@ -8,7 +8,7 @@
# see https://github.com/spesmilo/electrum/issues/5859
Cython>=0.27
-trezor[hidapi]>=0.11.5
+trezor[hidapi]>=0.12.0
safet>=0.1.5
keepkey>=6.3.1
btchip-python>=0.1.26
diff --git a/electrum/plugins/trezor/__init__.py b/electrum/plugins/trezor/__init__.py
@@ -2,7 +2,7 @@ from electrum.i18n import _
fullname = 'Trezor Wallet'
description = _('Provides support for Trezor hardware wallet')
-requires = [('trezorlib','github.com/trezor/python-trezor')]
+requires = [('trezorlib','pypi.org/project/trezor/')]
registers_keystore = ('hardware', 'trezor', _("Trezor wallet"))
available_for = ['qt', 'cmdline']
diff --git a/electrum/plugins/trezor/clientbase.py b/electrum/plugins/trezor/clientbase.py
@@ -9,7 +9,7 @@ from electrum.bip32 import BIP32Node, convert_bip32_path_to_list_of_uint32 as pa
from electrum.logging import Logger
from electrum.plugins.hw_wallet.plugin import OutdatedHwFirmwareException, HardwareClientBase
-from trezorlib.client import TrezorClient
+from trezorlib.client import TrezorClient, PASSPHRASE_ON_DEVICE
from trezorlib.exceptions import TrezorFailure, Cancelled, OutdatedFirmwareError
from trezorlib.messages import WordRequestType, FailureType, RecoveryDeviceType, ButtonRequestType
import trezorlib.btc
@@ -30,8 +30,10 @@ MESSAGES = {
_("Confirm the total amount spent and the transaction fee on your {} device"),
ButtonRequestType.Address:
_("Confirm wallet address on your {} device"),
- ButtonRequestType.PassphraseType:
+ ButtonRequestType._Deprecated_ButtonRequest_PassphraseType:
_("Choose on your {} device where to enter your passphrase"),
+ ButtonRequestType.PassphraseEntry:
+ _("Please enter your passphrase on the {} device"),
'default': _("Check your {} device to continue"),
}
@@ -259,7 +261,7 @@ class TrezorClientBase(HardwareClientBase, Logger):
raise Cancelled
return pin
- def get_passphrase(self):
+ def get_passphrase(self, available_on_device):
if self.creating_wallet:
msg = _("Enter a passphrase to generate this wallet. Each time "
"you use this wallet your {} will prompt you for the "
@@ -267,7 +269,11 @@ class TrezorClientBase(HardwareClientBase, Logger):
"access the bitcoins in the wallet.").format(self.device)
else:
msg = _("Enter the passphrase to unlock this wallet:")
+
+ self.handler.passphrase_on_device = available_on_device
passphrase = self.handler.get_passphrase(msg, self.creating_wallet)
+ if passphrase is PASSPHRASE_ON_DEVICE:
+ return passphrase
if passphrase is None:
raise Cancelled
passphrase = bip39_normalize_passphrase(passphrase)
diff --git a/electrum/plugins/trezor/cmdline.py b/electrum/plugins/trezor/cmdline.py
@@ -1,7 +1,22 @@
from electrum.plugin import hook
-from .trezor import TrezorPlugin
+from electrum.i18n import _
+from electrum.util import print_stderr
+from .trezor import TrezorPlugin, PASSPHRASE_ON_DEVICE
from ..hw_wallet import CmdLineHandler
+class TrezorCmdLineHandler(CmdLineHandler):
+ def __init__(self):
+ self.passphrase_on_device = False
+ super().__init__()
+
+ def get_passphrase(self, msg, confirm):
+ import getpass
+ print_stderr(msg)
+ if self.passphrase_on_device and self.yes_no_question(_('Enter passphrase on device?')):
+ return PASSPHRASE_ON_DEVICE
+ else:
+ return getpass.getpass('')
+
class Plugin(TrezorPlugin):
handler = CmdLineHandler()
@hook
diff --git a/electrum/plugins/trezor/qt.py b/electrum/plugins/trezor/qt.py
@@ -16,7 +16,7 @@ from electrum.util import bh2u
from ..hw_wallet.qt import QtHandlerBase, QtPluginBase
from ..hw_wallet.plugin import only_hook_if_libraries_available
from .trezor import (TrezorPlugin, TIM_NEW, TIM_RECOVER, TrezorInitSettings,
- Capability, BackupType, RecoveryDeviceType)
+ PASSPHRASE_ON_DEVICE, Capability, BackupType, RecoveryDeviceType)
PASSPHRASE_HELP_SHORT =_(
@@ -119,6 +119,7 @@ class QtHandler(QtHandlerBase):
self.close_matrix_dialog_signal.connect(self._close_matrix_dialog)
self.pin_matrix_widget_class = pin_matrix_widget_class
self.matrix_dialog = None
+ self.passphrase_on_device = False
def get_pin(self, msg):
self.done.clear()
@@ -163,6 +164,72 @@ class QtHandler(QtHandlerBase):
self.matrix_dialog.get_matrix(msg)
self.done.set()
+ def passphrase_dialog(self, msg, confirm):
+ # If confirm is true, require the user to enter the passphrase twice
+ parent = self.top_level_window()
+ d = WindowModalDialog(parent, _('Enter Passphrase'))
+
+ OK_button = OkButton(d, _('Enter Passphrase'))
+ OnDevice_button = QPushButton(_('Enter Passphrase on Device'))
+
+ new_pw = QLineEdit()
+ new_pw.setEchoMode(2)
+ conf_pw = QLineEdit()
+ conf_pw.setEchoMode(2)
+
+ vbox = QVBoxLayout()
+ label = QLabel(msg + "\n")
+ label.setWordWrap(True)
+
+ grid = QGridLayout()
+ grid.setSpacing(8)
+ grid.setColumnMinimumWidth(0, 150)
+ grid.setColumnMinimumWidth(1, 100)
+ grid.setColumnStretch(1,1)
+
+ vbox.addWidget(label)
+
+ grid.addWidget(QLabel(_('Passphrase:')), 0, 0)
+ grid.addWidget(new_pw, 0, 1)
+
+ if confirm:
+ grid.addWidget(QLabel(_('Confirm Passphrase:')), 1, 0)
+ grid.addWidget(conf_pw, 1, 1)
+
+ vbox.addLayout(grid)
+
+ def enable_OK():
+ if not confirm:
+ ok = True
+ else:
+ ok = new_pw.text() == conf_pw.text()
+ OK_button.setEnabled(ok)
+
+ new_pw.textChanged.connect(enable_OK)
+ conf_pw.textChanged.connect(enable_OK)
+
+ vbox.addWidget(OK_button)
+
+ if self.passphrase_on_device:
+ vbox.addWidget(OnDevice_button)
+
+ d.setLayout(vbox)
+
+ self.passphrase = None
+
+ def ok_clicked():
+ self.passphrase = new_pw.text()
+
+ def on_device_clicked():
+ self.passphrase = PASSPHRASE_ON_DEVICE
+
+ OK_button.clicked.connect(ok_clicked)
+ OnDevice_button.clicked.connect(on_device_clicked)
+ OnDevice_button.clicked.connect(d.accept)
+
+ d.exec_()
+ self.done.set()
+
class QtPlugin(QtPluginBase):
# Derived classes must provide the following class-static variables:
diff --git a/electrum/plugins/trezor/trezor.py b/electrum/plugins/trezor/trezor.py
@@ -32,6 +32,8 @@ try:
InputScriptType, OutputScriptType, MultisigRedeemScriptType,
TxInputType, TxOutputType, TxOutputBinType, TransactionType, SignTx)
+ from trezorlib.client import PASSPHRASE_ON_DEVICE
+
TREZORLIB = True
except Exception as e:
_logger.exception('error importing trezorlib')
@@ -52,6 +54,8 @@ except Exception as e:
BackupType = _EnumMissing()
RecoveryDeviceType = _EnumMissing()
+ PASSPHRASE_ON_DEVICE = object()
+
# Trezor initialization methods
TIM_NEW, TIM_RECOVER = range(2)
@@ -109,11 +113,11 @@ class TrezorPlugin(HW_PluginBase):
# wallet_class, types
firmware_URL = 'https://wallet.trezor.io'
- libraries_URL = 'https://github.com/trezor/python-trezor'
+ libraries_URL = 'https://pypi.org/project/trezor/'
minimum_firmware = (1, 5, 2)
keystore_class = TrezorKeyStore
- minimum_library = (0, 11, 5)
- maximum_library = (0, 12)
+ minimum_library = (0, 12, 0)
+ maximum_library = (0, 13)
SUPPORTED_XTYPES = ('standard', 'p2wpkh-p2sh', 'p2wpkh', 'p2wsh-p2sh', 'p2wsh')
DEVICE_IDS = (TREZOR_PRODUCT_KEY,)