ethereum/singing: layout seperated
This commit is contained in:
parent
2317aaedb9
commit
7d0cafecc3
|
@ -0,0 +1,59 @@
|
||||||
|
from trezor import wire, ui
|
||||||
|
from trezor.utils import unimport, chunks
|
||||||
|
from trezor.messages import ButtonRequestType
|
||||||
|
from trezor.ui.text import Text
|
||||||
|
from apps.common.confirm import *
|
||||||
|
from . import networks
|
||||||
|
|
||||||
|
|
||||||
|
@unimport
|
||||||
|
async def confirm_tx(ctx, to, value, chain_id, token=None):
|
||||||
|
content = Text('Confirm transaction', ui.ICON_RESET,
|
||||||
|
ui.BOLD, format_amount(value, token, chain_id),
|
||||||
|
ui.NORMAL, 'to',
|
||||||
|
ui.MONO, *split_address(to)) # todo no addres shown, why?
|
||||||
|
return await confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||||
|
|
||||||
|
|
||||||
|
@unimport
|
||||||
|
async def confirm_fee(ctx, spending, fee, chain_id, token=None):
|
||||||
|
content = Text('Confirm transaction', ui.ICON_RESET,
|
||||||
|
'Sending: %s' % format_amount(spending, token, chain_id),
|
||||||
|
'Fee: %s' % format_amount(fee, token, chain_id))
|
||||||
|
return await hold_to_confirm(ctx, content, ButtonRequestType.SignTx)
|
||||||
|
|
||||||
|
|
||||||
|
@unimport
|
||||||
|
async def confirm_data(ctx, data, data_total):
|
||||||
|
content = Text('Confirm data', ui.ICON_RESET,
|
||||||
|
ui.MONO, data[:16], # todo nothing displayed?
|
||||||
|
'of total: ', data_total)
|
||||||
|
return await confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||||
|
|
||||||
|
|
||||||
|
@unimport
|
||||||
|
async def confirm_fee(ctx, value, gas_price, gas_limit, token):
|
||||||
|
content = Text('Confirm fee', ui.ICON_RESET,
|
||||||
|
'price:', ui.MONO, gas_price, # todo wording
|
||||||
|
'limit:', ui.MONO, gas_limit,
|
||||||
|
'value: ', value)
|
||||||
|
return await confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||||
|
|
||||||
|
|
||||||
|
def split_address(address):
|
||||||
|
return chunks(address, 17)
|
||||||
|
|
||||||
|
|
||||||
|
def format_amount(value, token, chain_id):
|
||||||
|
value = int.from_bytes(value, 'little')
|
||||||
|
if token:
|
||||||
|
suffix = token.ticker
|
||||||
|
decimals = token.decimals
|
||||||
|
elif value < 1e18:
|
||||||
|
suffix = 'Wei'
|
||||||
|
decimals = 0
|
||||||
|
else:
|
||||||
|
decimals = 18
|
||||||
|
suffix = networks.suffix_by_chain_id(chain_id)
|
||||||
|
|
||||||
|
return '%s %s' % (value // 10 ** decimals, suffix)
|
|
@ -1,15 +1,10 @@
|
||||||
from trezor import wire, ui
|
|
||||||
from trezor.utils import unimport
|
from trezor.utils import unimport
|
||||||
from trezor.messages.EthereumSignTx import EthereumSignTx
|
from trezor.messages.EthereumSignTx import EthereumSignTx
|
||||||
from trezor.messages.EthereumTxRequest import EthereumTxRequest
|
from trezor.messages.EthereumTxRequest import EthereumTxRequest
|
||||||
from trezor.messages import ButtonRequestType
|
|
||||||
from trezor.messages import FailureType
|
from trezor.messages import FailureType
|
||||||
from apps.common.confirm import confirm
|
|
||||||
from apps.common.hash_writer import HashWriter
|
from apps.common.hash_writer import HashWriter
|
||||||
from trezor.ui.text import Text
|
|
||||||
from trezor.crypto import rlp
|
from trezor.crypto import rlp
|
||||||
from apps.ethereum import networks, tokens
|
from apps.ethereum import tokens, layout
|
||||||
|
|
||||||
|
|
||||||
# maximum supported chain id
|
# maximum supported chain id
|
||||||
MAX_CHAIN_ID = 2147483630
|
MAX_CHAIN_ID = 2147483630
|
||||||
|
@ -33,16 +28,16 @@ async def ethereum_sign_tx(ctx, msg):
|
||||||
msg.data_initial_chunk[:16] == b'\xa9\x05\x9c\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00':
|
msg.data_initial_chunk[:16] == b'\xa9\x05\x9c\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00':
|
||||||
token = tokens.token_by_chain_address(msg.chain_id, msg.to)
|
token = tokens.token_by_chain_address(msg.chain_id, msg.to)
|
||||||
|
|
||||||
if token is not None:
|
if token is None:
|
||||||
# todo: await layout_ethereum_confirm_tx(msg->data_initial_chunk.bytes + 16, 20, msg->data_initial_chunk.bytes + 36, 32, token);
|
await layout.confirm_tx(ctx, msg.to, msg.value, msg.chain_id, token)
|
||||||
await layout_ethereum_confirm_tx(ctx, msg.to, msg.value, msg.chain_id, token)
|
|
||||||
else:
|
else:
|
||||||
await layout_ethereum_confirm_tx(ctx, msg.to, msg.value, msg.chain_id, token)
|
# todo is this tested?
|
||||||
|
await layout.confirm_tx(ctx, msg.data_initial_chunk[16:36], msg.data_initial_chunk.bytes[36:68], msg.chain_id, token)
|
||||||
|
|
||||||
# if token == None and msg.data_length > 0:
|
if token is None and msg.data_length > 0:
|
||||||
# layoutEthereumData(msg->data_initial_chunk.bytes, msg->data_initial_chunk.size, data_total);
|
await layout.confirm_data(ctx, msg.data_initial_chunk, data_total)
|
||||||
|
|
||||||
# todo layoutEthereumFee
|
await layout.confirm_fee(ctx, msg.value, msg.gas_price, msg.gas_limit, token)
|
||||||
|
|
||||||
data = bytearray()
|
data = bytearray()
|
||||||
data += msg.data_initial_chunk
|
data += msg.data_initial_chunk
|
||||||
|
@ -63,7 +58,7 @@ async def ethereum_sign_tx(ctx, msg):
|
||||||
sha.extend(rlp.encode(data, False))
|
sha.extend(rlp.encode(data, False))
|
||||||
|
|
||||||
while data_left > 0:
|
while data_left > 0:
|
||||||
resp = await send_request_chunk(ctx, data_left, data_total)
|
resp = await send_request_chunk(ctx, data_left)
|
||||||
data_left -= len(resp.data_chunk)
|
data_left -= len(resp.data_chunk)
|
||||||
sha.extend(resp.data_chunk)
|
sha.extend(resp.data_chunk)
|
||||||
|
|
||||||
|
@ -73,7 +68,7 @@ async def ethereum_sign_tx(ctx, msg):
|
||||||
sha.extend(rlp.encode(0))
|
sha.extend(rlp.encode(0))
|
||||||
sha.extend(rlp.encode(0))
|
sha.extend(rlp.encode(0))
|
||||||
|
|
||||||
digest = sha.get_digest(True)
|
digest = sha.get_digest(True) # True -> use keccak mode
|
||||||
return await send_signature(ctx, msg, digest)
|
return await send_signature(ctx, msg, digest)
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,7 +86,7 @@ def get_total_length(msg: EthereumSignTx, data_total: int) -> int:
|
||||||
return length
|
return length
|
||||||
|
|
||||||
|
|
||||||
async def send_request_chunk(ctx, data_left: int, data_total: int):
|
async def send_request_chunk(ctx, data_left: int):
|
||||||
from trezor.messages.wire_types import EthereumTxAck
|
from trezor.messages.wire_types import EthereumTxAck
|
||||||
# todo layoutProgress ?
|
# todo layoutProgress ?
|
||||||
req = EthereumTxRequest()
|
req = EthereumTxRequest()
|
||||||
|
@ -183,28 +178,3 @@ def sanitize(msg):
|
||||||
if msg.chain_id is None:
|
if msg.chain_id is None:
|
||||||
msg.chain_id = 0
|
msg.chain_id = 0
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
@unimport
|
|
||||||
async def layout_ethereum_confirm_tx(ctx, to, value, chain_id, token=None):
|
|
||||||
content = Text('Confirm transaction', ui.ICON_RESET,
|
|
||||||
ui.BOLD, format_amount(value, token, chain_id),
|
|
||||||
ui.NORMAL, 'to',
|
|
||||||
ui.MONO, to)
|
|
||||||
|
|
||||||
return await confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
|
||||||
|
|
||||||
|
|
||||||
def format_amount(value, token, chain_id):
|
|
||||||
value = int.from_bytes(value, 'little')
|
|
||||||
if token:
|
|
||||||
suffix = token.ticker
|
|
||||||
decimals = token.decimals
|
|
||||||
elif value < 1e18:
|
|
||||||
suffix = 'Wei'
|
|
||||||
decimals = 0
|
|
||||||
else:
|
|
||||||
decimals = 18
|
|
||||||
suffix = networks.suffix_by_chain_id(chain_id)
|
|
||||||
|
|
||||||
return '%s %s' % (value // 10 ** decimals, suffix)
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
from common import *
|
||||||
|
from apps.ethereum.layout import format_amount
|
||||||
|
|
||||||
|
|
||||||
|
class TestEthereumLayout(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_format(self):
|
||||||
|
text = format_amount((1).to_bytes(5, 'little'), None, 1)
|
||||||
|
self.assertEqual(text, '1 Wei')
|
||||||
|
text = format_amount((1000).to_bytes(5, 'little'), None, 1)
|
||||||
|
self.assertEqual(text, '1000 Wei')
|
||||||
|
|
||||||
|
text = format_amount((1000000000000000001).to_bytes(20, 'little'), None, 1)
|
||||||
|
self.assertEqual(text, '1 ETH')
|
||||||
|
text = format_amount((10000000000000000001).to_bytes(20, 'little'), None, 1)
|
||||||
|
self.assertEqual(text, '10 ETH')
|
||||||
|
text = format_amount((10000000000000000001).to_bytes(20, 'little'), None, 61)
|
||||||
|
self.assertEqual(text, '10 ETC')
|
||||||
|
text = format_amount((1000000000000000001).to_bytes(20, 'little'), None, 31)
|
||||||
|
self.assertEqual(text, '1 tRSK')
|
||||||
|
|
||||||
|
# unknown chain
|
||||||
|
text = format_amount((1).to_bytes(20, 'little'), None, 9999)
|
||||||
|
self.assertEqual(text, '1 Wei')
|
||||||
|
text = format_amount((10000000000000000001).to_bytes(20, 'little'), None, 9999)
|
||||||
|
self.assertEqual(text, '10 UNKN')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -1,30 +0,0 @@
|
||||||
from common import *
|
|
||||||
from apps.ethereum import sign_tx
|
|
||||||
|
|
||||||
|
|
||||||
class TestEthereumSignTx(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_format(self):
|
|
||||||
text = sign_tx.format_amount((1).to_bytes(5, 'little'), None, 1)
|
|
||||||
self.assertEqual(text, '1 Wei')
|
|
||||||
text = sign_tx.format_amount((1000).to_bytes(5, 'little'), None, 1)
|
|
||||||
self.assertEqual(text, '1000 Wei')
|
|
||||||
|
|
||||||
text = sign_tx.format_amount((1000000000000000001).to_bytes(20, 'little'), None, 1)
|
|
||||||
self.assertEqual(text, '1 ETH')
|
|
||||||
text = sign_tx.format_amount((10000000000000000001).to_bytes(20, 'little'), None, 1)
|
|
||||||
self.assertEqual(text, '10 ETH')
|
|
||||||
text = sign_tx.format_amount((10000000000000000001).to_bytes(20, 'little'), None, 61)
|
|
||||||
self.assertEqual(text, '10 ETC')
|
|
||||||
text = sign_tx.format_amount((1000000000000000001).to_bytes(20, 'little'), None, 31)
|
|
||||||
self.assertEqual(text, '1 tRSK')
|
|
||||||
|
|
||||||
# unknown chain
|
|
||||||
text = sign_tx.format_amount((1).to_bytes(20, 'little'), None, 9999)
|
|
||||||
self.assertEqual(text, '1 Wei')
|
|
||||||
text = sign_tx.format_amount((10000000000000000001).to_bytes(20, 'little'), None, 9999)
|
|
||||||
self.assertEqual(text, '10 UNKN')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
Loading…
Reference in New Issue