1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-02 04:18:20 +00:00
trezor-firmware/core/src/apps/ethereum/address.py

55 lines
1.6 KiB
Python

from ubinascii import hexlify, unhexlify
from trezor import wire
if False:
from .networks import NetworkInfo
def address_from_bytes(address_bytes: bytes, network: NetworkInfo | None = None) -> str:
"""
Converts address in bytes to a checksummed string as defined
in https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md
"""
from trezor.crypto.hashlib import sha3_256
if network is not None and network.rskip60:
prefix = str(network.chain_id) + "0x"
else:
prefix = ""
address_hex = hexlify(address_bytes).decode()
digest = sha3_256((prefix + address_hex).encode(), keccak=True).digest()
def maybe_upper(i: int) -> str:
"""Uppercase i-th letter only if the corresponding nibble has high bit set."""
digest_byte = digest[i // 2]
hex_letter = address_hex[i]
if i % 2 == 0:
# even letter -> high nibble
bit = 0x80
else:
# odd letter -> low nibble
bit = 0x08
if digest_byte & bit:
return hex_letter.upper()
else:
return hex_letter
return "0x" + "".join(maybe_upper(i) for i in range(len(address_hex)))
def bytes_from_address(address: str) -> bytes:
if len(address) == 40:
return unhexlify(address)
elif len(address) == 42:
if address[0:2] not in ("0x", "0X"):
raise wire.ProcessError("Ethereum: invalid beginning of an address")
return unhexlify(address[2:])
elif len(address) == 0:
return bytes()
raise wire.ProcessError("Ethereum: Invalid address length")