Ledger: move get_client() to the plugin
Mirrors the trezor code
This commit is contained in:
parent
deccca1827
commit
986e198e87
|
@ -42,8 +42,6 @@ class BTChipWallet(BIP44_Wallet):
|
||||||
self.handler = None
|
self.handler = None
|
||||||
self.force_watching_only = False
|
self.force_watching_only = False
|
||||||
|
|
||||||
self.transport = None
|
|
||||||
self.client = None
|
|
||||||
self.device_checked = False
|
self.device_checked = False
|
||||||
self.signing = False
|
self.signing = False
|
||||||
|
|
||||||
|
@ -53,8 +51,8 @@ class BTChipWallet(BIP44_Wallet):
|
||||||
QMessageBox.warning(QDialog(), _('Warning'), _(message), _('OK'))
|
QMessageBox.warning(QDialog(), _('Warning'), _(message), _('OK'))
|
||||||
else:
|
else:
|
||||||
self.signing = False
|
self.signing = False
|
||||||
if clear_client and self.client is not None:
|
if clear_client:
|
||||||
self.client.bad = True
|
self.plugin.client = None
|
||||||
self.device_checked = False
|
self.device_checked = False
|
||||||
raise Exception(message)
|
raise Exception(message)
|
||||||
|
|
||||||
|
@ -76,75 +74,7 @@ class BTChipWallet(BIP44_Wallet):
|
||||||
return BIP44_Wallet.address_id(self, address)[2:]
|
return BIP44_Wallet.address_id(self, address)[2:]
|
||||||
|
|
||||||
def get_client(self, noPin=False):
|
def get_client(self, noPin=False):
|
||||||
if not BTCHIP:
|
return self.plugin.get_client(self, noPin=noPin)
|
||||||
self.give_error('please install github.com/btchip/btchip-python')
|
|
||||||
|
|
||||||
aborted = False
|
|
||||||
if not self.client or self.client.bad:
|
|
||||||
try:
|
|
||||||
d = getDongle(BTCHIP_DEBUG)
|
|
||||||
self.client = btchip(d)
|
|
||||||
firmware = self.client.getFirmwareVersion()['version'].split(".")
|
|
||||||
if not checkFirmware(firmware):
|
|
||||||
d.close()
|
|
||||||
try:
|
|
||||||
updateFirmware()
|
|
||||||
except Exception, e:
|
|
||||||
aborted = True
|
|
||||||
raise e
|
|
||||||
d = getDongle(BTCHIP_DEBUG)
|
|
||||||
self.client = btchip(d)
|
|
||||||
try:
|
|
||||||
self.client.getOperationMode()
|
|
||||||
except BTChipException, e:
|
|
||||||
if (e.sw == 0x6985):
|
|
||||||
d.close()
|
|
||||||
dialog = StartBTChipPersoDialog()
|
|
||||||
dialog.exec_()
|
|
||||||
# Then fetch the reference again as it was invalidated
|
|
||||||
d = getDongle(BTCHIP_DEBUG)
|
|
||||||
self.client = btchip(d)
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
if not noPin:
|
|
||||||
# Immediately prompts for the PIN
|
|
||||||
remaining_attempts = self.client.getVerifyPinRemainingAttempts()
|
|
||||||
if remaining_attempts <> 1:
|
|
||||||
msg = "Enter your Ledger PIN - remaining attempts : " + str(remaining_attempts)
|
|
||||||
else:
|
|
||||||
msg = "Enter your Ledger PIN - WARNING : LAST ATTEMPT. If the PIN is not correct, the dongle will be wiped."
|
|
||||||
confirmed, p, pin = self.password_dialog(msg)
|
|
||||||
if not confirmed:
|
|
||||||
aborted = True
|
|
||||||
raise Exception('Aborted by user - please unplug the dongle and plug it again before retrying')
|
|
||||||
pin = pin.encode()
|
|
||||||
self.client.verifyPin(pin)
|
|
||||||
|
|
||||||
except BTChipException, e:
|
|
||||||
try:
|
|
||||||
self.client.dongle.close()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
self.client = None
|
|
||||||
if (e.sw == 0x6faa):
|
|
||||||
raise Exception("Dongle is temporarily locked - please unplug it and replug it again")
|
|
||||||
if ((e.sw & 0xFFF0) == 0x63c0):
|
|
||||||
raise Exception("Invalid PIN - please unplug the dongle and plug it again before retrying")
|
|
||||||
raise e
|
|
||||||
except Exception, e:
|
|
||||||
try:
|
|
||||||
self.client.dongle.close()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
self.client = None
|
|
||||||
if not aborted:
|
|
||||||
raise Exception("Could not connect to your Ledger wallet. Please verify access permissions, PIN, or unplug the dongle and plug it again")
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
self.client.bad = False
|
|
||||||
self.device_checked = False
|
|
||||||
self.proper_device = False
|
|
||||||
return self.client
|
|
||||||
|
|
||||||
def derive_xkeys(self, root, derivation, password):
|
def derive_xkeys(self, root, derivation, password):
|
||||||
derivation = '/'.join(derivation.split('/')[1:])
|
derivation = '/'.join(derivation.split('/')[1:])
|
||||||
|
@ -193,7 +123,8 @@ class BTChipWallet(BIP44_Wallet):
|
||||||
def sign_message(self, address, message, password):
|
def sign_message(self, address, message, password):
|
||||||
use2FA = False
|
use2FA = False
|
||||||
self.signing = True
|
self.signing = True
|
||||||
self.get_client() # prompt for the PIN before displaying the dialog if necessary
|
# prompt for the PIN before displaying the dialog if necessary
|
||||||
|
client = self.get_client()
|
||||||
if not self.check_proper_device():
|
if not self.check_proper_device():
|
||||||
self.give_error('Wrong device or password')
|
self.give_error('Wrong device or password')
|
||||||
address_path = self.address_id(address)
|
address_path = self.address_id(address)
|
||||||
|
@ -208,7 +139,7 @@ class BTChipWallet(BIP44_Wallet):
|
||||||
if not confirmed:
|
if not confirmed:
|
||||||
raise Exception('Aborted by user')
|
raise Exception('Aborted by user')
|
||||||
pin = pin.encode()
|
pin = pin.encode()
|
||||||
self.client.bad = True
|
client.bad = True
|
||||||
self.device_checked = False
|
self.device_checked = False
|
||||||
self.get_client(True)
|
self.get_client(True)
|
||||||
signature = self.get_client().signMessageSign(pin)
|
signature = self.get_client().signMessageSign(pin)
|
||||||
|
@ -221,7 +152,7 @@ class BTChipWallet(BIP44_Wallet):
|
||||||
self.give_error(e, True)
|
self.give_error(e, True)
|
||||||
finally:
|
finally:
|
||||||
self.handler.stop()
|
self.handler.stop()
|
||||||
self.client.bad = use2FA
|
client.bad = use2FA
|
||||||
self.signing = False
|
self.signing = False
|
||||||
|
|
||||||
# Parse the ASN.1 signature
|
# Parse the ASN.1 signature
|
||||||
|
@ -334,7 +265,7 @@ class BTChipWallet(BIP44_Wallet):
|
||||||
if not confirmed:
|
if not confirmed:
|
||||||
raise Exception('Aborted by user')
|
raise Exception('Aborted by user')
|
||||||
pin = pin.encode()
|
pin = pin.encode()
|
||||||
self.client.bad = True
|
client.bad = True
|
||||||
self.device_checked = False
|
self.device_checked = False
|
||||||
self.get_client(True)
|
self.get_client(True)
|
||||||
self.handler.show_message("Signing ...")
|
self.handler.show_message("Signing ...")
|
||||||
|
@ -361,7 +292,7 @@ class BTChipWallet(BIP44_Wallet):
|
||||||
updatedTransaction = format_transaction(transactionOutput, preparedTrustedInputs)
|
updatedTransaction = format_transaction(transactionOutput, preparedTrustedInputs)
|
||||||
updatedTransaction = hexlify(updatedTransaction)
|
updatedTransaction = hexlify(updatedTransaction)
|
||||||
tx.update(updatedTransaction)
|
tx.update(updatedTransaction)
|
||||||
self.client.bad = use2FA
|
client.bad = use2FA
|
||||||
self.signing = False
|
self.signing = False
|
||||||
|
|
||||||
def check_proper_device(self):
|
def check_proper_device(self):
|
||||||
|
@ -404,6 +335,7 @@ class LedgerPlugin(BasePlugin):
|
||||||
BasePlugin.__init__(self, parent, config, name)
|
BasePlugin.__init__(self, parent, config, name)
|
||||||
self.wallet_class.plugin = self
|
self.wallet_class.plugin = self
|
||||||
self.device = self.wallet_class.device
|
self.device = self.wallet_class.device
|
||||||
|
self.client = None
|
||||||
|
|
||||||
def is_enabled(self):
|
def is_enabled(self):
|
||||||
return BTCHIP
|
return BTCHIP
|
||||||
|
@ -441,3 +373,74 @@ class LedgerPlugin(BasePlugin):
|
||||||
@hook
|
@hook
|
||||||
def close_wallet(self, wallet):
|
def close_wallet(self, wallet):
|
||||||
self.client = None
|
self.client = None
|
||||||
|
|
||||||
|
def get_client(self, wallet, noPin=False):
|
||||||
|
aborted = False
|
||||||
|
client = self.client
|
||||||
|
if not client or client.bad:
|
||||||
|
try:
|
||||||
|
d = getDongle(BTCHIP_DEBUG)
|
||||||
|
client = btchip(d)
|
||||||
|
firmware = client.getFirmwareVersion()['version'].split(".")
|
||||||
|
if not checkFirmware(firmware):
|
||||||
|
d.close()
|
||||||
|
try:
|
||||||
|
updateFirmware()
|
||||||
|
except Exception, e:
|
||||||
|
aborted = True
|
||||||
|
raise e
|
||||||
|
d = getDongle(BTCHIP_DEBUG)
|
||||||
|
client = btchip(d)
|
||||||
|
try:
|
||||||
|
client.getOperationMode()
|
||||||
|
except BTChipException, e:
|
||||||
|
if (e.sw == 0x6985):
|
||||||
|
d.close()
|
||||||
|
dialog = StartBTChipPersoDialog()
|
||||||
|
dialog.exec_()
|
||||||
|
# Then fetch the reference again as it was invalidated
|
||||||
|
d = getDongle(BTCHIP_DEBUG)
|
||||||
|
client = btchip(d)
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
if not noPin:
|
||||||
|
# Immediately prompts for the PIN
|
||||||
|
remaining_attempts = client.getVerifyPinRemainingAttempts()
|
||||||
|
if remaining_attempts <> 1:
|
||||||
|
msg = "Enter your Ledger PIN - remaining attempts : " + str(remaining_attempts)
|
||||||
|
else:
|
||||||
|
msg = "Enter your Ledger PIN - WARNING : LAST ATTEMPT. If the PIN is not correct, the dongle will be wiped."
|
||||||
|
confirmed, p, pin = wallet.password_dialog(msg)
|
||||||
|
if not confirmed:
|
||||||
|
aborted = True
|
||||||
|
raise Exception('Aborted by user - please unplug the dongle and plug it again before retrying')
|
||||||
|
pin = pin.encode()
|
||||||
|
client.verifyPin(pin)
|
||||||
|
|
||||||
|
except BTChipException, e:
|
||||||
|
try:
|
||||||
|
client.dongle.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
client = None
|
||||||
|
if (e.sw == 0x6faa):
|
||||||
|
raise Exception("Dongle is temporarily locked - please unplug it and replug it again")
|
||||||
|
if ((e.sw & 0xFFF0) == 0x63c0):
|
||||||
|
raise Exception("Invalid PIN - please unplug the dongle and plug it again before retrying")
|
||||||
|
raise e
|
||||||
|
except Exception, e:
|
||||||
|
try:
|
||||||
|
client.dongle.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
client = None
|
||||||
|
if not aborted:
|
||||||
|
raise Exception("Could not connect to your Ledger wallet. Please verify access permissions, PIN, or unplug the dongle and plug it again")
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
client.bad = False
|
||||||
|
wallet.device_checked = False
|
||||||
|
wallet.proper_device = False
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
return self.client
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
import threading
|
||||||
|
|
||||||
from PyQt4.Qt import (QDialog, QInputDialog, QLineEdit,
|
from PyQt4.Qt import (QDialog, QInputDialog, QLineEdit,
|
||||||
QVBoxLayout, QLabel, SIGNAL)
|
QVBoxLayout, QLabel, SIGNAL)
|
||||||
import PyQt4.QtCore as QtCore
|
import PyQt4.QtCore as QtCore
|
||||||
import threading
|
|
||||||
|
|
||||||
from electrum.plugins import BasePlugin, hook
|
from electrum.i18n import _
|
||||||
|
from electrum.plugins import hook
|
||||||
from ledger import LedgerPlugin, BTChipWallet
|
from .ledger import LedgerPlugin, BTChipWallet
|
||||||
|
|
||||||
class Plugin(LedgerPlugin):
|
class Plugin(LedgerPlugin):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue