mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 20:38:10 +00:00
ethereum/signing: all test passing, no data stream
This commit is contained in:
parent
dc02b322bf
commit
47b3baa30a
@ -3,6 +3,7 @@ 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 ButtonRequestType
|
||||||
|
from trezor.messages import FailureType
|
||||||
from apps.common.confirm import confirm
|
from apps.common.confirm import confirm
|
||||||
from trezor.ui.text import Text
|
from trezor.ui.text import Text
|
||||||
from trezor.crypto import rlp
|
from trezor.crypto import rlp
|
||||||
@ -15,16 +16,17 @@ MAX_CHAIN_ID = 2147483630
|
|||||||
|
|
||||||
@unimport
|
@unimport
|
||||||
async def ethereum_sign_tx(ctx, msg):
|
async def ethereum_sign_tx(ctx, msg):
|
||||||
from ..common import seed
|
|
||||||
from trezor.crypto.hashlib import sha3_256
|
from trezor.crypto.hashlib import sha3_256
|
||||||
from trezor.crypto.curve import secp256k1
|
|
||||||
|
|
||||||
|
print(msg)
|
||||||
msg = sanitize(msg)
|
msg = sanitize(msg)
|
||||||
check(msg)
|
check(msg)
|
||||||
|
|
||||||
|
data_total = msg.data_length
|
||||||
|
|
||||||
# detect ERC - 20 token
|
# detect ERC - 20 token
|
||||||
token = None
|
token = None
|
||||||
if len(msg.to) == 20 and len(msg.value) == 0 and msg.data_length == 68 and len(msg.data_initial_chunk) == 68 \
|
if len(msg.to) == 20 and len(msg.value) == 0 and data_total == 68 and len(msg.data_initial_chunk) == 68 \
|
||||||
and msg.data_initial_chunk[:16] == b'a9059cbb000000000000000000000000': #todo x?
|
and msg.data_initial_chunk[:16] == b'a9059cbb000000000000000000000000': #todo x?
|
||||||
token = tokens.token_by_chain_address(msg.chain_id, msg.to)
|
token = tokens.token_by_chain_address(msg.chain_id, msg.to)
|
||||||
|
|
||||||
@ -39,19 +41,44 @@ async def ethereum_sign_tx(ctx, msg):
|
|||||||
|
|
||||||
# todo layoutEthereumFee
|
# todo layoutEthereumFee
|
||||||
|
|
||||||
# todo eip 155 replay protection
|
data = bytearray()
|
||||||
# if chain_id != 0:
|
data += msg.data_initial_chunk
|
||||||
# hash v=chain_id, r=0, s=0
|
data_left = data_total - len(msg.data_initial_chunk)
|
||||||
# hash_rlp_number(chain_id)
|
|
||||||
# hash_rlp_length(0, 0)
|
|
||||||
# hash_rlp_length(0, 0)
|
|
||||||
|
|
||||||
fields = [msg.nonce, msg.gas_price, msg.gas_limit, msg.to, msg.value, msg.data_initial_chunk]
|
while data_left > 0:
|
||||||
|
resp = await send_request_chunk(ctx, data_left, data_total)
|
||||||
|
data += resp.data_chunk
|
||||||
|
data_left -= len(resp.data_chunk)
|
||||||
|
# todo stream
|
||||||
|
|
||||||
|
if msg.chain_id:
|
||||||
|
fields = [msg.nonce, msg.gas_price, msg.gas_limit, msg.to, msg.value, data, msg.chain_id, 0, 0]
|
||||||
|
else:
|
||||||
|
fields = [msg.nonce, msg.gas_price, msg.gas_limit, msg.to, msg.value, data]
|
||||||
rlp_encoded = rlp.encode(fields)
|
rlp_encoded = rlp.encode(fields)
|
||||||
sha256 = sha3_256(rlp_encoded)
|
sha256 = sha3_256()
|
||||||
|
sha256.update(rlp_encoded)
|
||||||
digest = sha256.digest(True)
|
digest = sha256.digest(True)
|
||||||
|
|
||||||
|
return await send_signature(ctx, msg, digest)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_request_chunk(ctx, data_left: int, data_total: int):
|
||||||
|
from trezor.messages.wire_types import EthereumTxAck
|
||||||
|
# todo layoutProgress ?
|
||||||
|
req = EthereumTxRequest()
|
||||||
|
if data_left <= 1024:
|
||||||
|
req.data_length = data_left
|
||||||
|
else:
|
||||||
|
req.data_length = 1024
|
||||||
|
|
||||||
|
return await ctx.call(req, EthereumTxAck)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_signature(ctx, msg: EthereumSignTx, digest):
|
||||||
|
from trezor.crypto.curve import secp256k1
|
||||||
|
from ..common import seed
|
||||||
|
|
||||||
address_n = msg.address_n or ()
|
address_n = msg.address_n or ()
|
||||||
node = await seed.get_root(ctx)
|
node = await seed.get_root(ctx)
|
||||||
node.derive_path(address_n)
|
node.derive_path(address_n)
|
||||||
@ -81,17 +108,17 @@ def check(msg: EthereumSignTx):
|
|||||||
|
|
||||||
if msg.data_length > 0:
|
if msg.data_length > 0:
|
||||||
if not msg.data_initial_chunk:
|
if not msg.data_initial_chunk:
|
||||||
raise ValueError(Failure.DataError, 'Data length provided, but no initial chunk')
|
raise ValueError(FailureType.DataError, 'Data length provided, but no initial chunk')
|
||||||
# Our encoding only supports transactions up to 2^24 bytes. To
|
# Our encoding only supports transactions up to 2^24 bytes. To
|
||||||
# prevent exceeding the limit we use a stricter limit on data length.
|
# prevent exceeding the limit we use a stricter limit on data length.
|
||||||
if msg.data_length > 16000000:
|
if msg.data_length > 16000000:
|
||||||
raise ValueError(Failure.DataError, 'Data length exceeds limit')
|
raise ValueError(FailureType.DataError, 'Data length exceeds limit')
|
||||||
if len(msg.data_initial_chunk) > msg.data_length:
|
if len(msg.data_initial_chunk) > msg.data_length:
|
||||||
raise ValueError(Failure.DataError, 'Invalid size of initial chunk')
|
raise ValueError(FailureType.DataError, 'Invalid size of initial chunk')
|
||||||
|
|
||||||
# safety checks
|
# safety checks
|
||||||
if not check_gas(msg) or not check_to(msg):
|
if not check_gas(msg) or not check_to(msg):
|
||||||
raise ValueError(Failure.DataError, 'Safety check failed')
|
raise ValueError(FailureType.DataError, 'Safety check failed')
|
||||||
|
|
||||||
|
|
||||||
def check_gas(msg: EthereumSignTx) -> bool:
|
def check_gas(msg: EthereumSignTx) -> bool:
|
||||||
@ -104,7 +131,7 @@ def check_gas(msg: EthereumSignTx) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def check_to(msg: EthereumTxRequest) -> bool:
|
def check_to(msg: EthereumTxRequest) -> bool:
|
||||||
if msg.to == 0:
|
if msg.to == b'':
|
||||||
if msg.data_length == 0:
|
if msg.data_length == 0:
|
||||||
# sending transaction to address 0 (contract creation) without a data field
|
# sending transaction to address 0 (contract creation) without a data field
|
||||||
return False
|
return False
|
||||||
|
Loading…
Reference in New Issue
Block a user