Merge branch '202604_pr10603_ledger'
adapt Ledger_Client_Legacy to work with newer ledger bitcoin app manual merge of https://github.com/spesmilo/electrum/pull/10603
This commit is contained in:
@@ -349,9 +349,9 @@ hidapi==0.14.0.post4 \
|
||||
idna==3.10 \
|
||||
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
|
||||
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
|
||||
ledger-bitcoin==0.4.0 \
|
||||
--hash=sha256:2242452e78cf4b57c8b8d3509e831860fd4851b0a1bfab95f2f5e3f47d4d1500 \
|
||||
--hash=sha256:a33e78710671ec21e1003d0483406e955b48866ccf515fd8e7d8d81f4e1c1cf9
|
||||
ledger-bitcoin==0.4.1 \
|
||||
--hash=sha256:3cb4297ed7e557ef98349cdcbd667ef7368c047d6818c7cdcbca7af98b8006b6 \
|
||||
--hash=sha256:b1fe1cdfd0f869f1e27968118832b11708904f71840b0a97219a0492ce1a7002
|
||||
ledgercomm==1.2.1 \
|
||||
--hash=sha256:015cfc05f16b8c59f8cc1d9fc0b8935923f1fcc3806d33eeb6b0e055b44f5a91 \
|
||||
--hash=sha256:8ffef5703355b8ec7b73bca325f70288f4d0dafcb299c09833de9c197fb6dd34
|
||||
|
||||
@@ -14,7 +14,7 @@ hidapi>=0.7.99.post15
|
||||
libusb1>=1.6
|
||||
|
||||
# device plugin: ledger
|
||||
ledger-bitcoin>=0.2.0,<1.0
|
||||
ledger-bitcoin>=0.4.1,<1.0
|
||||
hidapi
|
||||
|
||||
# device plugin: coldcard
|
||||
|
||||
@@ -347,8 +347,9 @@ class Ledger_Client(HardwareClientBase, ABC):
|
||||
def __init__(self, *, plugin: HW_PluginBase):
|
||||
HardwareClientBase.__init__(self, plugin=plugin)
|
||||
|
||||
@abstractmethod
|
||||
def get_master_fingerprint(self) -> bytes:
|
||||
return self.request_root_fingerprint_from_device()
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def show_address(self, address_path: str, txin_type: str):
|
||||
@@ -390,6 +391,31 @@ class Ledger_Client_Legacy(Ledger_Client):
|
||||
self._product_key = product_key
|
||||
self._soft_device_id = None
|
||||
|
||||
def _get_master_fingerprint(self) -> bytes:
|
||||
"""Return the 4-byte master (root) key fingerprint.
|
||||
|
||||
Tries the dedicated GET_MASTER_FINGERPRINT APDU first (INS 0xD0),
|
||||
which does NOT require DERIVE_MASTER permission. If the device
|
||||
does not support it (old firmware), falls back to
|
||||
getWalletPublicKey("") + HASH160.
|
||||
"""
|
||||
try:
|
||||
return self.dongleObject.getMasterFingerprint()
|
||||
except BTChipException as e:
|
||||
if e.sw in (0x6d00, 0x6a80): # INS not supported / bad data
|
||||
_logger.info("getMasterFingerprint APDU not supported (sw=0x%04x), "
|
||||
"falling back to getWalletPublicKey", e.sw)
|
||||
else:
|
||||
raise
|
||||
return self._get_node_fingerprint("")
|
||||
|
||||
def _get_node_fingerprint(self, bip32_path: str) -> bytes:
|
||||
"""Return the 4-byte fingerprint for an arbitrary BIP32 node
|
||||
by calling getWalletPublicKey + HASH160.
|
||||
"""
|
||||
nodeData = self.dongleObject.getWalletPublicKey(bip32_path)
|
||||
return hash_160(compress_public_key(nodeData['publicKey']))[0:4]
|
||||
|
||||
def is_pairable(self):
|
||||
return True
|
||||
|
||||
@@ -424,7 +450,7 @@ class Ledger_Client_Legacy(Ledger_Client):
|
||||
# modern ledger can provide xpub without user interaction
|
||||
# (hw1 would prompt for PIN)
|
||||
if not self.is_hw1():
|
||||
self._soft_device_id = self.request_root_fingerprint_from_device()
|
||||
self._soft_device_id = self._get_master_fingerprint().hex()
|
||||
return self._soft_device_id
|
||||
|
||||
def is_hw1(self) -> bool:
|
||||
@@ -433,6 +459,14 @@ class Ledger_Client_Legacy(Ledger_Client):
|
||||
def device_model_name(self):
|
||||
return LedgerPlugin.device_name_from_product_key(self._product_key)
|
||||
|
||||
@runs_in_hwd_thread
|
||||
def request_root_fingerprint_from_device(self) -> str:
|
||||
return self._get_master_fingerprint().hex()
|
||||
|
||||
@runs_in_hwd_thread
|
||||
def get_master_fingerprint(self) -> bytes:
|
||||
return self._get_master_fingerprint()
|
||||
|
||||
@runs_in_hwd_thread
|
||||
def has_usable_connection_with_device(self):
|
||||
try:
|
||||
@@ -460,9 +494,10 @@ class Ledger_Client_Legacy(Ledger_Client):
|
||||
bip32_path = bip32_path[2:] # cut off "m/"
|
||||
if len(bip32_intpath) >= 1:
|
||||
prevPath = bip32.convert_bip32_intpath_to_strpath(bip32_intpath[:-1])[2:]
|
||||
nodeData = self.dongleObject.getWalletPublicKey(prevPath)
|
||||
publicKey = compress_public_key(nodeData['publicKey'])
|
||||
fingerprint_bytes = hash_160(publicKey)[0:4]
|
||||
if len(prevPath) == 0:
|
||||
fingerprint_bytes = self._get_master_fingerprint()
|
||||
else:
|
||||
fingerprint_bytes = self._get_node_fingerprint(prevPath)
|
||||
childnum_bytes = bip32_intpath[-1].to_bytes(length=4, byteorder="big")
|
||||
else:
|
||||
fingerprint_bytes = bytes(4)
|
||||
@@ -1216,7 +1251,7 @@ class Ledger_KeyStore(Hardware_KeyStore):
|
||||
|
||||
class LedgerPlugin(HW_PluginBase):
|
||||
keystore_class = Ledger_KeyStore
|
||||
minimum_library = (0, 2, 0)
|
||||
minimum_library = (0, 4, 1)
|
||||
maximum_library = (1, 0)
|
||||
DEVICE_IDS = [(0x2581, 0x1807), # HW.1 legacy btchip # not supported anymore (but we log an exception)
|
||||
(0x2581, 0x2b7c), # HW.1 transitional production # not supported anymore
|
||||
|
||||
Reference in New Issue
Block a user