|
|
@ -13,7 +13,7 @@ from electrum.bip32 import BIP32Node, convert_bip32_intpath_to_strpath |
|
|
|
from electrum.bitcoin import EncodeBase58Check, int_to_hex, is_b58_address, is_segwit_script_type, var_int |
|
|
|
from electrum.crypto import hash_160 |
|
|
|
from electrum.i18n import _ |
|
|
|
from electrum.keystore import AddressIndexGeneric, Hardware_KeyStore |
|
|
|
from electrum.keystore import Hardware_KeyStore |
|
|
|
from electrum.logging import get_logger |
|
|
|
from electrum.plugin import Device, runs_in_hwd_thread |
|
|
|
from electrum.transaction import PartialTransaction, Transaction |
|
|
@ -357,7 +357,6 @@ class Ledger_Client_Legacy(Ledger_Client): |
|
|
|
|
|
|
|
self.signing = False |
|
|
|
|
|
|
|
self.preflightDone = False |
|
|
|
self._product_key = product_key |
|
|
|
self._soft_device_id = None |
|
|
|
|
|
|
@ -480,58 +479,14 @@ class Ledger_Client_Legacy(Ledger_Client): |
|
|
|
def supports_segwit_trustedInputs(self): |
|
|
|
return self.segwitTrustedInputs |
|
|
|
|
|
|
|
@runs_in_hwd_thread |
|
|
|
def perform_hw1_preflight(self): |
|
|
|
try: |
|
|
|
firmwareInfo = self.dongleObject.getFirmwareVersion() |
|
|
|
firmware = firmwareInfo['version'] |
|
|
|
self.multiOutputSupported = versiontuple(firmware) >= versiontuple(MULTI_OUTPUT_SUPPORT) |
|
|
|
self.nativeSegwitSupported = versiontuple(firmware) >= versiontuple(SEGWIT_SUPPORT) |
|
|
|
self.segwitSupported = self.nativeSegwitSupported or (firmwareInfo['specialVersion'] == 0x20 and versiontuple(firmware) >= versiontuple(SEGWIT_SUPPORT_SPECIAL)) |
|
|
|
self.segwitTrustedInputs = versiontuple(firmware) >= versiontuple(SEGWIT_TRUSTEDINPUTS) |
|
|
|
|
|
|
|
try: |
|
|
|
self.dongleObject.getOperationMode() |
|
|
|
except BTChipException as e: |
|
|
|
if (e.sw == 0x6985): |
|
|
|
self.close() |
|
|
|
self.handler.get_setup() |
|
|
|
# Acquire the new client on the next run |
|
|
|
else: |
|
|
|
raise e |
|
|
|
if self.has_detached_pin_support(self.dongleObject) and not self.is_pin_validated(self.dongleObject): |
|
|
|
assert self.handler, "no handler for client" |
|
|
|
remaining_attempts = self.dongleObject.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: |
|
|
|
raise UserFacingException('Aborted by user - please unplug the dongle and plug it again before retrying') |
|
|
|
pin = pin.encode() |
|
|
|
self.dongleObject.verifyPin(pin) |
|
|
|
except BTChipException as e: |
|
|
|
if (e.sw == 0x6faa): |
|
|
|
raise UserFacingException("Dongle is temporarily locked - please unplug it and replug it again") |
|
|
|
if ((e.sw & 0xFFF0) == 0x63c0): |
|
|
|
raise UserFacingException("Invalid PIN - please unplug the dongle and plug it again before retrying") |
|
|
|
if e.sw == 0x6f00 and e.message == 'Invalid channel': |
|
|
|
# based on docs 0x6f00 might be a more general error, hence we also compare message to be sure |
|
|
|
raise UserFacingException("Invalid channel.\n" |
|
|
|
"Please make sure that 'Browser support' is disabled on your device.") |
|
|
|
raise e |
|
|
|
|
|
|
|
@runs_in_hwd_thread |
|
|
|
def checkDevice(self): |
|
|
|
if not self.preflightDone: |
|
|
|
try: |
|
|
|
self.perform_hw1_preflight() |
|
|
|
except BTChipException as e: |
|
|
|
if (e.sw == 0x6d00 or e.sw == 0x6700): |
|
|
|
raise UserFacingException(_("Device not in Bitcoin mode")) from e |
|
|
|
raise e |
|
|
|
self.preflightDone = True |
|
|
|
firmwareInfo = self.dongleObject.getFirmwareVersion() |
|
|
|
firmware = firmwareInfo['version'] |
|
|
|
self.multiOutputSupported = versiontuple(firmware) >= versiontuple(MULTI_OUTPUT_SUPPORT) |
|
|
|
self.nativeSegwitSupported = versiontuple(firmware) >= versiontuple(SEGWIT_SUPPORT) |
|
|
|
self.segwitSupported = self.nativeSegwitSupported or (firmwareInfo['specialVersion'] == 0x20 and versiontuple(firmware) >= versiontuple(SEGWIT_SUPPORT_SPECIAL)) |
|
|
|
self.segwitTrustedInputs = versiontuple(firmware) >= versiontuple(SEGWIT_TRUSTEDINPUTS) |
|
|
|
|
|
|
|
def password_dialog(self, msg=None): |
|
|
|
response = self.handler.get_word(msg) |
|
|
@ -702,7 +657,6 @@ class Ledger_Client_Legacy(Ledger_Client): |
|
|
|
firstTransaction = True |
|
|
|
inputIndex = 0 |
|
|
|
rawTx = tx.serialize_to_network() |
|
|
|
self.dongleObject.enableAlternate2fa(False) |
|
|
|
if segwitTransaction: |
|
|
|
self.dongleObject.startUntrustedTransaction(True, inputIndex, chipInputs, redeemScripts[inputIndex], version=tx.version) |
|
|
|
# we don't set meaningful outputAddress, amount and fees |
|
|
@ -778,7 +732,6 @@ class Ledger_Client_Legacy(Ledger_Client): |
|
|
|
def sign_message( |
|
|
|
self, |
|
|
|
address_path: str, |
|
|
|
sequence: 'AddressIndexGeneric', |
|
|
|
message: str, |
|
|
|
password, |
|
|
|
*, |
|
|
|