URI: 
       ttrezor: single passphrase entry - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 535956149a8a6b2801b434d2d00ecb3ba2e9bde1
   DIR parent 2bbe829f32daeef0993cedb88ef7618992d6a98b
  HTML Author: Neil Booth <kyuupichan@gmail.com>
       Date:   Thu, 11 Feb 2016 19:51:56 +0900
       
       ttrezor: single passphrase entry
       
       Only require the user to input the passphrase once, unless creating
       a wallet.
       Should they mis-enter the passphrase, they will be warned Electrum
       couldn't pair the device, and when they actually need to use it
       tthey will be prompted again.
       Fixes #1672
       
       Diffstat:
         M lib/plugins.py                      |       9 +++++----
         M plugins/hw_wallet/qt.py             |      27 +++++++++++++++++++--------
         M plugins/keepkey/cmdline.py          |       2 +-
         M plugins/trezor/clientbase.py        |      19 +++++++++++++++++--
         M plugins/trezor/cmdline.py           |       2 +-
         M plugins/trezor/plugin.py            |       3 ++-
       
       6 files changed, 45 insertions(+), 17 deletions(-)
       ---
   DIR diff --git a/lib/plugins.py b/lib/plugins.py
       t@@ -418,10 +418,11 @@ class DeviceMgr(ThreadJob, PrintError):
                # The user input has wrong PIN or passphrase, or cancelled input,
                # or it is not pairable
                raise DeviceUnpairableError(
       -            _('Unable to pair with your %s.\n\n'
       -              'Ensure you are able to pair it, or you have the seed phrase, '
       -              'before you request bitcoins to be sent to this wallet.'
       -            ) % plugin.device)
       +            _('Electrum cannot pair with your %s.\n\n'
       +              'Before you request bitcoins to be sent to addresses in this '
       +              'wallet, ensure you can pair with your device, or that you have '
       +              'its seed (and passphrase, if any).  Otherwise all bitcoins you '
       +              'receive will be unspendable.') % plugin.device)
        
            def unpaired_device_infos(self, handler, plugin, devices=None):
                '''Returns a list of DeviceInfo objects: one for each connected,
   DIR diff --git a/plugins/hw_wallet/qt.py b/plugins/hw_wallet/qt.py
       t@@ -25,7 +25,6 @@ from electrum_gui.qt.util import *
        
        from electrum.i18n import _
        from electrum.util import PrintError
       -from electrum.wallet import BIP44_Wallet
        
        # The trickiest thing about this handler was getting windows properly
        # parented on MacOSX.
       t@@ -80,17 +79,29 @@ class QtHandlerBase(QObject, PrintError):
                self.done.wait()
                return self.word
        
       -    def get_passphrase(self, msg):
       +    def get_passphrase(self, msg, confirm):
                self.done.clear()
       -        self.win.emit(SIGNAL('passphrase_dialog'), msg)
       +        self.win.emit(SIGNAL('passphrase_dialog'), msg, confirm)
                self.done.wait()
                return self.passphrase
        
       -    def passphrase_dialog(self, msg):
       -        d = PasswordDialog(self.top_level_window(), None, msg, PW_PASSPHRASE)
       -        confirmed, p, passphrase = d.run()
       -        if confirmed:
       -            passphrase = BIP44_Wallet.normalize_passphrase(passphrase)
       +    def passphrase_dialog(self, msg, confirm):
       +        # If confirm is true, require the user to enter the passphrase twice
       +        parent = self.top_level_window()
       +        if confirm:
       +            d = PasswordDialog(parent, None, msg, PW_PASSPHRASE)
       +            confirmed, p, passphrase = d.run()
       +        else:
       +            d = WindowModalDialog(parent, _("Enter Passphrase"))
       +            pw = QLineEdit()
       +            pw.setEchoMode(2)
       +            pw.setMinimumWidth(200)
       +            vbox = QVBoxLayout()
       +            vbox.addWidget(WWLabel(msg))
       +            vbox.addWidget(pw)
       +            vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))
       +            d.setLayout(vbox)
       +            passphrase = unicode(pw.text()) if d.exec_() else None
                self.passphrase = passphrase
                self.done.set()
        
   DIR diff --git a/plugins/keepkey/cmdline.py b/plugins/keepkey/cmdline.py
       t@@ -3,7 +3,7 @@ from electrum.util import print_msg
        
        class KeepKeyCmdLineHandler:
        
       -    def get_passphrase(self, msg):
       +    def get_passphrase(self, msg, confirm):
                import getpass
                print_msg(msg)
                return getpass.getpass('')
   DIR diff --git a/plugins/trezor/clientbase.py b/plugins/trezor/clientbase.py
       t@@ -2,6 +2,7 @@ import time
        
        from electrum.i18n import _
        from electrum.util import PrintError, UserCancelled
       +from electrum.wallet import BIP44_Wallet
        
        
        class GuiMixin(object):
       t@@ -52,10 +53,17 @@ class GuiMixin(object):
                return self.proto.PinMatrixAck(pin=pin)
        
            def callback_PassphraseRequest(self, req):
       -        msg = _("Please enter your %s passphrase")
       -        passphrase = self.handler.get_passphrase(msg % self.device)
       +        if self.creating_wallet:
       +            msg = _("Enter a passphrase to generate this wallet.  Each time "
       +                    "you use this wallet your %s will prompt you for the "
       +                    "passphrase.  If you forget the passphrase you cannot "
       +                    "access the bitcoins in the wallet.") % self.device
       +        else:
       +            msg = _("Enter the passphrase to unlock this wallet:")
       +        passphrase = self.handler.get_passphrase(msg, self.creating_wallet)
                if passphrase is None:
                    return self.proto.Cancel()
       +        passphrase = BIP44_Wallet.normalize_passphrase(passphrase)
                return self.proto.PassphraseAck(passphrase=passphrase)
        
            def callback_WordRequest(self, msg):
       t@@ -72,6 +80,7 @@ class GuiMixin(object):
                    return self.proto.Cancel()
                return self.proto.CharacterAck(**char_info)
        
       +
        class TrezorClientBase(GuiMixin, PrintError):
        
            def __init__(self, handler, plugin, proto):
       t@@ -82,6 +91,7 @@ class TrezorClientBase(GuiMixin, PrintError):
                self.tx_api = plugin
                self.types = plugin.types
                self.msg = None
       +        self.creating_wallet = False
                self.used()
        
            def __str__(self):
       t@@ -175,6 +185,10 @@ class TrezorClientBase(GuiMixin, PrintError):
                    self.print_error("clear_session: ignoring error", str(e))
                    pass
        
       +    def get_public_node(self, address_n, creating):
       +        self.creating_wallet = creating
       +        return super(TrezorClientBase, self).get_public_node(address_n)
       +
            def close(self):
                '''Called when Our wallet was closed or the device removed.'''
                self.print_error("closing client")
       t@@ -200,6 +214,7 @@ class TrezorClientBase(GuiMixin, PrintError):
                    finally:
                        self.used()
                        self.handler.finished()
       +                self.creating_wallet = False
                        self.msg = None
        
                return wrapped
   DIR diff --git a/plugins/trezor/cmdline.py b/plugins/trezor/cmdline.py
       t@@ -3,7 +3,7 @@ from electrum.util import print_msg
        
        class TrezorCmdLineHandler:
        
       -    def get_passphrase(self, msg):
       +    def get_passphrase(self, msg, confirm):
                import getpass
                print_msg(msg)
                return getpass.getpass('')
   DIR diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py
       t@@ -24,7 +24,8 @@ class TrezorCompatibleWallet(BIP44_HW_Wallet):
            def get_public_key(self, bip32_path):
                client = self.get_client()
                address_n = client.expand_path(bip32_path)
       -        node = client.get_public_node(address_n).node
       +        creating = self.next_account_number() == 0
       +        node = client.get_public_node(address_n, creating).node
                xpub = ("0488B21E".decode('hex') + chr(node.depth)
                        + self.i4b(node.fingerprint) + self.i4b(node.child_num)
                        + node.chain_code + node.public_key)