trezor / python-trezor

:snake: Don't use this repo, use the new monorepo instead:
https://github.com/trezor/trezor-firmware
GNU Lesser General Public License v3.0
201 stars 194 forks source link

Ethereum transaction fails to generate raw transaction #334

Closed Vighanesh closed 5 years ago

Vighanesh commented 5 years ago

Hello team, I am generating raw transactions of ethereum using python-trezor in debug mode. As soon as second confirmation is executed I get following error

b'{"to_address":"0xde13445c7037479bad48fa251f3d165ea78b370a","amount":2926500000000000,"chain_id":"3","bip_path":"m/44\'/60\'/10\'/0/0"}'
Traceback (most recent call last):
  File "/home/vighanesh/PycharmProjects/rest_wallet/crypto/WalletClient.py", line 130, in sign_eth_tx
    chain_id=chain_id)
  File "/home/vighanesh/PycharmProjects/rest_wallet/crypto/trezorlib/client.py", line 71, in _deprecated_redirect
    return self.where(client, *args, **kwargs)
  File "/home/vighanesh/PycharmProjects/rest_wallet/crypto/trezorlib/tools.py", line 214, in wrapped_f
    return f(*args, **kwargs)
  File "/home/vighanesh/PycharmProjects/rest_wallet/crypto/trezorlib/ethereum.py", line 52, in sign_tx
    response = client.call(msg)
  File "/home/vighanesh/PycharmProjects/rest_wallet/crypto/trezorlib/tools.py", line 214, in wrapped_f
    return f(*args, **kwargs)
  File "/home/vighanesh/PycharmProjects/rest_wallet/crypto/trezorlib/client.py", line 155, in call
    raise exceptions.TrezorFailure(resp)
crypto.trezorlib.exceptions.TrezorFailure: DataError: messages.c:229:array overflow
prusnak commented 5 years ago

Show us your code, you are doing some weird stuff for sure, but without seeing your code we cannot help

Vighanesh commented 5 years ago

Hello prunsak, I solved the problem, I was having old commit due to which it was using self.get_eth_address(bip_path) and this method result in bytes as address and current commit follows list i.e. parse_path(bip_path) This is the I have taken from old commit and added my own logics in it.

    def sign_eth_tx(self, chain_id, bip_path, amount, to_address):
        try:
            from ethjsonrpc import EthJsonRpc
            import rlp
            amount = str(amount)
            chain_id = int(chain_id)

            ether_units = {
                'wei': 1,
                'kwei': 1000,
                'babbage': 1000,
                'femtoether': 1000,
                'mwei': 1000000,
                'lovelace': 1000000,
                'picoether': 1000000,
                'gwei': 1000000000,
                'shannon': 1000000000,
                'nanoether': 1000000000,
                'nano': 1000000000,
                'szabo': 1000000000000,
                'microether': 1000000000000,
                'micro': 1000000000000,
                'finney': 1000000000000000,
                'milliether': 1000000000000000,
                'milli': 1000000000000000,
                'ether': 1000000000000000000,
                'eth': 1000000000000000000,
            }

            if ' ' in amount:
                value, unit = amount.split(' ', 1)
                if unit.lower() not in ether_units:
                    response_dict = {'success': False, 'message': 'Invalid unit passed'}
                    return response_dict
                value = int(value) * ether_units[unit.lower()]
            else:
                value = int(amount)

            to_address = self.ethereum_decode_hex(to_address)
            address_n = parse_path(bip_path)
            print(type(address_n))
            # changed this line line to parse path and the problem resolved.
            # address = self.get_eth_address(bip_path)
            address = address_n

            host, port = "localhost:8545".split(":")
            eth = EthJsonRpc(host, int(port))
            data = ''
            # eth.eth_gasPrice()
            gas_price = 21000
            # eth.eth_estimateGas(to_address=to_address, from_address=address, value=('0x%x' % value),
            #                     data='0x%s' % (binascii.hexlify(data).decode()))
            gas_limit = 21000
            # eth.eth_getTransactionCount(address)
            nonce = 0
            signature = self.client.ethereum_sign_tx(n=address, tx_type=None, nonce=nonce, gas_price=gas_price,
                                                     gas_limit=gas_limit, to=to_address, value=value, data=data,
                                                     chain_id=chain_id)
            transaction = rlp.encode((nonce, gas_price, to_address, value, data) + signature)
            tx_hash = '0x%s' % binascii.hexlify(transaction).decode()
            print(tx_hash)
            return tx_hash
        except Exception as e:
            print(traceback.format_exc())

Sorry for your inconvenience