URI: 
       tMerge pull request #6064 from matejcik/trezor-0.12-passphrase - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 4d980cd4bdf3db7bbe0711b92f820d2525917322
   DIR parent d2a58a2ec3682daea6a1f248eb7a543e2bad47fa
  HTML 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
       
       ttrezor: bump lib version, implement new passphrase-on-device UI
       Diffstat:
         M contrib/requirements/requirements-… |       2 +-
         M electrum/plugins/trezor/__init__.py |       2 +-
         M electrum/plugins/trezor/clientbase… |      12 +++++++++---
         M electrum/plugins/trezor/cmdline.py  |      17 ++++++++++++++++-
         M electrum/plugins/trezor/qt.py       |      69 ++++++++++++++++++++++++++++++-
         M electrum/plugins/trezor/trezor.py   |      10 +++++++---
       
       6 files changed, 102 insertions(+), 10 deletions(-)
       ---
   DIR diff --git a/contrib/requirements/requirements-hw.txt b/contrib/requirements/requirements-hw.txt
       t@@ -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
   DIR diff --git a/electrum/plugins/trezor/__init__.py b/electrum/plugins/trezor/__init__.py
       t@@ -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']
        
   DIR diff --git a/electrum/plugins/trezor/clientbase.py b/electrum/plugins/trezor/clientbase.py
       t@@ -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
       t@@ -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"),
        }
        
       t@@ -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 "
       t@@ -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)
   DIR diff --git a/electrum/plugins/trezor/cmdline.py b/electrum/plugins/trezor/cmdline.py
       t@@ -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
   DIR diff --git a/electrum/plugins/trezor/qt.py b/electrum/plugins/trezor/qt.py
       t@@ -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 =_(
       t@@ -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()
       t@@ -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:
   DIR diff --git a/electrum/plugins/trezor/trezor.py b/electrum/plugins/trezor/trezor.py
       t@@ -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')
       t@@ -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)
       t@@ -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,)