commit 535956149a8a6b2801b434d2d00ecb3ba2e9bde1
parent 2bbe829f32daeef0993cedb88ef7618992d6a98b
Author: Neil Booth <kyuupichan@gmail.com>
Date: Thu, 11 Feb 2016 19:51:56 +0900
trezor: 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
they will be prompted again.
Fixes #1672
Diffstat:
6 files changed, 45 insertions(+), 17 deletions(-)
diff --git a/lib/plugins.py b/lib/plugins.py
@@ -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,
diff --git a/plugins/hw_wallet/qt.py b/plugins/hw_wallet/qt.py
@@ -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.
@@ -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()
diff --git a/plugins/keepkey/cmdline.py b/plugins/keepkey/cmdline.py
@@ -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('')
diff --git a/plugins/trezor/clientbase.py b/plugins/trezor/clientbase.py
@@ -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):
@@ -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):
@@ -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):
@@ -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):
@@ -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")
@@ -200,6 +214,7 @@ class TrezorClientBase(GuiMixin, PrintError):
finally:
self.used()
self.handler.finished()
+ self.creating_wallet = False
self.msg = None
return wrapped
diff --git a/plugins/trezor/cmdline.py b/plugins/trezor/cmdline.py
@@ -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('')
diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py
@@ -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)