1
0

bip32: fix hardened char "h" vs "'" compatibility for some hw wallets

in particular, ledger: fix sign_message for some wallets

```
156.02 | E | plugins.ledger.ledger |
Traceback (most recent call last):
  File "...\electrum\electrum\plugins\ledger\ledger.py", line 1265, in sign_message
    result = base64.b64decode(self.client.sign_message(message, address_path))
  File "...\Python310\site-packages\ledger_bitcoin\client.py", line 230, in sign_message
    sw, response = self._make_request(self.builder.sign_message(message_bytes, bip32_path), client_intepreter)
  File "...\Python310\site-packages\ledger_bitcoin\command_builder.py", line 176, in sign_message
    bip32_path: List[bytes] = bip32_path_from_string(bip32_path)
  File "...\Python310\site-packages\ledger_bitcoin\common.py", line 68, in bip32_path_from_string
    return [int(p).to_bytes(4, byteorder="big") if "'" not in p
  File "...\Python310\site-packages\ledger_bitcoin\common.py", line 68, in <listcomp>
    return [int(p).to_bytes(4, byteorder="big") if "'" not in p
ValueError: invalid literal for int() with base 10: '84h'
```

Regression from df2bd61de6, where the
default hardened char was changed from "'" to "h". Note that there was
no corresponding wallet db upgrade, so some files use one char and
others use the other.
This commit is contained in:
SomberNight
2023-04-27 17:03:16 +00:00
parent 9e1bb940ac
commit 499f51535f
5 changed files with 27 additions and 12 deletions

View File

@@ -352,7 +352,9 @@ def convert_bip32_strpath_to_intpath(n: str) -> List[int]:
return path
def convert_bip32_intpath_to_strpath(path: Sequence[int]) -> str:
def convert_bip32_intpath_to_strpath(path: Sequence[int], *, hardened_char=BIP32_HARDENED_CHAR) -> str:
assert isinstance(hardened_char, str), hardened_char
assert len(hardened_char) == 1, hardened_char
s = "m/"
for child_index in path:
if not isinstance(child_index, int):
@@ -361,7 +363,7 @@ def convert_bip32_intpath_to_strpath(path: Sequence[int]) -> str:
raise ValueError(f"bip32 path child index out of range: {child_index}")
prime = ""
if child_index & BIP32_PRIME:
prime = BIP32_HARDENED_CHAR
prime = hardened_char
child_index = child_index ^ BIP32_PRIME
s += str(child_index) + prime + '/'
# cut trailing "/"
@@ -380,13 +382,13 @@ def is_bip32_derivation(s: str) -> bool:
return True
def normalize_bip32_derivation(s: Optional[str]) -> Optional[str]:
def normalize_bip32_derivation(s: Optional[str], *, hardened_char=BIP32_HARDENED_CHAR) -> Optional[str]:
if s is None:
return None
if not is_bip32_derivation(s):
raise ValueError(f"invalid bip32 derivation: {s}")
ints = convert_bip32_strpath_to_intpath(s)
return convert_bip32_intpath_to_strpath(ints)
return convert_bip32_intpath_to_strpath(ints, hardened_char=hardened_char)
def is_all_public_derivation(path: Union[str, Iterable[int]]) -> bool: