diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index 18d774f..6f6cdbc 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -124,6 +124,16 @@ class EthAppClient: def get_challenge(self): return self._send(self._cmd_builder.get_challenge()) + def get_public_addr(self, + display: bool = True, + chaincode: bool = False, + bip32_path: str = "m/44'/60'/0'/0/0", + chain_id: Optional[int] = None): + return self._send(self._cmd_builder.get_public_addr(display, + chaincode, + bip32_path, + chain_id)) + def provide_domain_name(self, challenge: int, name: str, addr: bytes): payload = format_tlv(DOMAIN_NAME_TAG.STRUCTURE_TYPE, 3) # TrustedDomainName payload += format_tlv(DOMAIN_NAME_TAG.STRUCTURE_VERSION, 1) diff --git a/client/src/ledger_app_clients/ethereum/command_builder.py b/client/src/ledger_app_clients/ethereum/command_builder.py index 8f2dbfd..a677671 100644 --- a/client/src/ledger_app_clients/ethereum/command_builder.py +++ b/client/src/ledger_app_clients/ethereum/command_builder.py @@ -1,5 +1,6 @@ import struct from enum import IntEnum +from typing import Optional from ragger.bip import pack_derivation_path from typing import List @@ -7,6 +8,7 @@ from .eip712 import EIP712FieldType class InsType(IntEnum): + GET_PUBLIC_ADDR = 0x02 SIGN = 0x04 EIP712_SEND_STRUCT_DEF = 0x1a EIP712_SEND_STRUCT_IMPL = 0x1c @@ -204,3 +206,16 @@ class CommandBuilder: payload = payload[0xff:] p1 = 0 return chunks + + def get_public_addr(self, + display: bool, + chaincode: bool, + bip32_path: str, + chain_id: Optional[int]) -> bytes: + payload = pack_derivation_path(bip32_path) + if chain_id is not None: + payload += struct.pack(">Q", chain_id) + return self._serialize(InsType.GET_PUBLIC_ADDR, + int(display), + int(chaincode), + payload) diff --git a/client/src/ledger_app_clients/ethereum/response_parser.py b/client/src/ledger_app_clients/ethereum/response_parser.py index 26a2638..a00205c 100644 --- a/client/src/ledger_app_clients/ethereum/response_parser.py +++ b/client/src/ledger_app_clients/ethereum/response_parser.py @@ -13,3 +13,39 @@ def signature(data: bytes) -> tuple[bytes, bytes, bytes]: def challenge(data: bytes) -> int: assert len(data) == 4 return int.from_bytes(data, "big") + +def pk_addr(data: bytes, has_chaincode: bool = False): + idx = 0 + + if len(data) < (idx + 1): + return None + pk_len = data[idx] + idx += 1 + + if len(data) < (idx + pk_len): + return None + pk = data[idx:idx + pk_len] + idx += pk_len + + if len(data) < (idx + 1): + return None + addr_len = data[idx] + idx += 1 + + if len(data) < (idx + addr_len): + return None + addr = data[idx:idx + addr_len] + idx += addr_len + + if has_chaincode: + if len(data) < (idx + 32): + return None + chaincode = data[idx:idx + 32] + idx += 32 + else: + chaincode = None + + if idx != len(data): + return None + + return pk, addr.decode(), chaincode