# This file is part of the Trezor project. # # Copyright (C) 2012-2019 SatoshiLabs and contributors # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the License along with this library. # If not, see . from . import exceptions, messages from .tools import expect, normalize_nfc, session def int_to_big_endian(value): return value.to_bytes((value.bit_length() + 7) // 8, "big") # ====== Client functions ====== # @expect(messages.EthereumAddress, field="address") def get_address(client, n, show_display=False, multisig=None): return client.call( messages.EthereumGetAddress(address_n=n, show_display=show_display) ) @expect(messages.EthereumPublicKey) def get_public_node(client, n, show_display=False): return client.call( messages.EthereumGetPublicKey(address_n=n, show_display=show_display) ) @session def sign_tx( client, n, nonce, gas_price, gas_limit, to, value, data=None, chain_id=None, tx_type=None, ): msg = messages.EthereumSignTx( address_n=n, nonce=int_to_big_endian(nonce), gas_price=int_to_big_endian(gas_price), gas_limit=int_to_big_endian(gas_limit), value=int_to_big_endian(value), to=to, chain_id=chain_id, tx_type=tx_type, ) if data: msg.data_length = len(data) data, chunk = data[1024:], data[:1024] msg.data_initial_chunk = chunk response = client.call(msg) while response.data_length is not None: data_length = response.data_length data, chunk = data[data_length:], data[:data_length] response = client.call(messages.EthereumTxAck(data_chunk=chunk)) # https://github.com/trezor/trezor-core/pull/311 # only signature bit returned. recalculate signature_v if response.signature_v <= 1: response.signature_v += 2 * chain_id + 35 return response.signature_v, response.signature_r, response.signature_s @session def sign_tx_eip1559( client, n, *, nonce, gas_limit, to, value, data=b"", chain_id, max_gas_fee, max_priority_fee, access_list=() ): length = len(data) data, chunk = data[1024:], data[:1024] msg = messages.EthereumSignTxEIP1559( address_n=n, nonce=int_to_big_endian(nonce), gas_limit=int_to_big_endian(gas_limit), value=int_to_big_endian(value), to=to, chain_id=chain_id, max_gas_fee=int_to_big_endian(max_gas_fee), max_priority_fee=int_to_big_endian(max_priority_fee), access_list=access_list, data_length=length, data_initial_chunk=chunk, ) response = client.call(msg) while response.data_length is not None: data_length = response.data_length data, chunk = data[data_length:], data[:data_length] response = client.call(messages.EthereumTxAck(data_chunk=chunk)) return response.signature_v, response.signature_r, response.signature_s @expect(messages.EthereumMessageSignature) def sign_message(client, n, message): message = normalize_nfc(message) return client.call(messages.EthereumSignMessage(address_n=n, message=message)) def verify_message(client, address, signature, message): message = normalize_nfc(message) try: resp = client.call( messages.EthereumVerifyMessage( address=address, signature=signature, message=message ) ) except exceptions.TrezorFailure: return False return isinstance(resp, messages.Success)