Skip to content

Commit 6ad24ea

Browse files
committed
keystore/transactions: fix overflow of derivation path indices
fixes #5366
1 parent a8b9397 commit 6ad24ea

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

electrum/keystore.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,13 @@ def get_pubkey_from_xpub(self, xpub, sequence):
282282
return node.eckey.get_public_key_hex(compressed=True)
283283

284284
def get_xpubkey(self, c, i):
285-
s = ''.join(map(lambda x: bitcoin.int_to_hex(x,2), (c, i)))
285+
def encode_path_int(path_int) -> str:
286+
if path_int < 0xffff:
287+
hex = bitcoin.int_to_hex(path_int, 2)
288+
else:
289+
hex = 'ffff' + bitcoin.int_to_hex(path_int, 4)
290+
return hex
291+
s = ''.join(map(encode_path_int, (c, i)))
286292
return 'ff' + bh2u(bitcoin.DecodeBase58Check(self.xpub)) + s
287293

288294
@classmethod
@@ -296,11 +302,14 @@ def parse_xpubkey(self, pubkey):
296302
# derivation:
297303
dd = pk[78:]
298304
s = []
299-
# FIXME: due to an oversight, levels in the derivation are only
300-
# allocated 2 bytes, instead of 4 (in bip32)
301305
while dd:
302-
n = int(bitcoin.rev_hex(bh2u(dd[0:2])), 16)
306+
# 2 bytes for derivation path index
307+
n = int.from_bytes(dd[0:2], byteorder="little")
303308
dd = dd[2:]
309+
# in case of overflow, drop these 2 bytes; and use next 4 bytes instead
310+
if n == 0xffff:
311+
n = int.from_bytes(dd[0:4], byteorder="little")
312+
dd = dd[4:]
304313
s.append(n)
305314
assert len(s) == 2
306315
return xkey, s

electrum/tests/test_transaction.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,11 @@ def test_txid_partial_segwit_p2wpkh_p2sh_mixed_outputs(self):
838838
txid = 'ba5c88e07a4025a39ad3b85247cbd4f556a70d6312b18e04513c7cec9d45d6ac'
839839
self._run_naive_tests_on_tx(raw_tx, txid)
840840

841+
def test_txid_partial_issue_5366(self):
842+
raw_tx = '45505446ff000200000000010127523d70642dabd999fb43191ff6763f5b04150ba4cf38d2cfb53edf6a40ac4f0100000000fdffffff013286010000000000160014e79c7ac0b390a9caf52dc002e1095a5fbc042a18feffffffffa08601000000000000000201ff57ff045f1cf60157e9eb7a8000000038fa0b3a9c155ff3390ca0d639783d97af3b3bf66ebb69a31dfe8317fae0a7fe0324bc048fc0002253dfec9d6299711d708175f950ecee8e09db3518a5685741830000ffffcf01010043281700'
843+
txid = 'a0c159616073dc7a4a482092dab4e8516c83dddb769b65919f23f6df63d33eb8'
844+
self._run_naive_tests_on_tx(raw_tx, txid)
845+
841846
# end partial txns <---
842847

843848

0 commit comments

Comments
 (0)