diff --git a/core/src/apps/ethereum/onekey/sign_tx.py b/core/src/apps/ethereum/onekey/sign_tx.py index 787ba5f49..49d8afee9 100644 --- a/core/src/apps/ethereum/onekey/sign_tx.py +++ b/core/src/apps/ethereum/onekey/sign_tx.py @@ -41,6 +41,8 @@ # the full value: v = 2 * chain_id + 35 + v_bit MAX_CHAIN_ID = (0xFFFF_FFFF - 36) // 2 +DATA_LEFT: bytearray | None = None + @with_keychain_from_chain_id async def sign_tx( @@ -217,10 +219,15 @@ async def sign_tx( rlp.write_header(sha, data_total, rlp.STRING_HEADER_BYTE, data) sha.extend(data) - while data_left > 0: - resp = await send_request_chunk(ctx, data_left) - data_left -= len(resp.data_chunk) - sha.extend(resp.data_chunk) + global DATA_LEFT + if DATA_LEFT is not None: + sha.extend(DATA_LEFT) + DATA_LEFT = None + else: + while data_left > 0: + resp = await send_request_chunk(ctx, data_left) + data_left -= len(resp.data_chunk) + sha.extend(resp.data_chunk) # eip 155 replay protection rlp.write(sha, msg.chain_id) @@ -360,7 +367,7 @@ def is_safe_exec_transaction(msg: EthereumSignTxAny) -> bool: if ( len(msg.to) in (40, 42) and len(msg.value) == 0 - and 437 <= msg.data_length <= 1024 + and 437 <= msg.data_length and msg.data_initial_chunk[:16] == b"\x6a\x76\x12\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x6a761202 == keccak("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)")[:4].hex() @@ -369,6 +376,15 @@ def is_safe_exec_transaction(msg: EthereumSignTxAny) -> bool: return False +def get_remaining_data() -> bytearray | None: + return DATA_LEFT + + +def reset_data_left() -> None: + global DATA_LEFT + DATA_LEFT = None + + async def handle_safe_tx( ctx: wire.Context, msg: EthereumSignTxAny, from_addr: str, is_eip1559: bool = True ) -> None: @@ -391,7 +407,17 @@ async def handle_safe_tx( data_len = int.from_bytes(data[308:340], "big") call_data = None call_method = None - if data_len > 0: + data_left = msg.data_length - len(msg.data_initial_chunk) + global DATA_LEFT + if data_left > 0: + DATA_LEFT = bytearray(data_left) + DATA_LEFT[:] = bytes() + while data_left > 0: + resp = await send_request_chunk(ctx, data_left) + data_left -= len(resp.data_chunk) + DATA_LEFT.extend(resp.data_chunk) + + if data_len > 0 and DATA_LEFT is None: nest_data = data[340 : 340 + data_len] if ( len(nest_data) == 68 @@ -455,9 +481,18 @@ async def handle_safe_tx( else: call_data = hexlify(nest_data).decode() call_method = None - assert signature_pos >= 340 + data_len - signatures_len = int.from_bytes(data[signature_pos : signature_pos + 20], "big") - signatures = data[signature_pos + 20 : signature_pos + 20 + signatures_len] + assert signature_pos >= 340 + data_len, "invalid call data" + if DATA_LEFT is not None: + remaining_data = data[340:] + DATA_LEFT + nest_data = remaining_data[:data_len] + call_data = hexlify(nest_data).decode() + call_method = None + signature_data = remaining_data[signature_pos - 340 :] + else: + signature_data = data[signature_pos:] + signatures_len = int.from_bytes(signature_data[:20], "big") + assert len(signature_data) >= 20 + signatures_len, "invalid call data length" + signatures = signature_data[20 : 20 + signatures_len] if not is_eip1559: from ..layout import require_confirm_safe_exec_transaction @@ -617,7 +652,7 @@ def check(msg: EthereumSignTx) -> None: if len(msg.gas_price) + len(msg.gas_limit) > 30: raise wire.DataError("Fee overflow") - + reset_data_left() check_common_fields(msg) diff --git a/core/src/apps/ethereum/onekey/sign_tx_eip1559.py b/core/src/apps/ethereum/onekey/sign_tx_eip1559.py index 399513389..460d73a1f 100644 --- a/core/src/apps/ethereum/onekey/sign_tx_eip1559.py +++ b/core/src/apps/ethereum/onekey/sign_tx_eip1559.py @@ -30,11 +30,13 @@ from .keychain import with_keychain_from_chain_id from .sign_tx import ( check_common_fields, + get_remaining_data, handle_approve, handle_erc20, handle_erc_721_or_1155, handle_safe_tx, is_safe_tx, + reset_data_left, send_request_chunk, ) @@ -263,10 +265,15 @@ async def sign_tx_eip1559( rlp.write_header(sha, data_total, rlp.STRING_HEADER_BYTE, data) sha.extend(data) - while data_left > 0: - resp = await send_request_chunk(ctx, data_left) - data_left -= len(resp.data_chunk) - sha.extend(resp.data_chunk) + remaining_data = get_remaining_data() + if remaining_data is not None: + sha.extend(remaining_data) + reset_data_left() + else: + while data_left > 0: + resp = await send_request_chunk(ctx, data_left) + data_left -= len(resp.data_chunk) + sha.extend(resp.data_chunk) write_access_list(sha, msg.access_list) @@ -323,5 +330,6 @@ def check(msg: EthereumSignTxEIP1559) -> None: raise wire.DataError("Fee overflow") if len(msg.max_priority_fee) + len(msg.gas_limit) > 30: raise wire.DataError("Fee overflow") + reset_data_left() check_common_fields(msg) diff --git a/core/src/trezor/lvglui/scrs/reset_device.py b/core/src/trezor/lvglui/scrs/reset_device.py index 79459caa5..11980c29d 100644 --- a/core/src/trezor/lvglui/scrs/reset_device.py +++ b/core/src/trezor/lvglui/scrs/reset_device.py @@ -1,5 +1,6 @@ from typing import TYPE_CHECKING +from trezor import utils from trezor.enums import BackupType from trezor.lvglui.i18n import gettext as _, keys as i18n_keys from trezor.lvglui.scrs.components.container import ( @@ -83,6 +84,7 @@ def __init__( .pad_bottom(48), 0, ) + self.container.add_flag(lv.obj.FLAG.EVENT_BUBBLE) self.clear_flag(lv.obj.FLAG.SCROLLABLE) self.content_area.set_scroll_dir(lv.DIR.VER) self.content_area.clear_flag(lv.obj.FLAG.SCROLL_ELASTIC) @@ -98,9 +100,11 @@ def __init__( word_label = lv.label(word) word_label.set_align(lv.ALIGN.LEFT_MID) word_label.set_text(f"{i+1:>2}. {mnemonics[i]}") + word.add_flag(lv.obj.FLAG.EVENT_BUBBLE) word.set_grid_cell( lv.GRID_ALIGN.STRETCH, col, 1, lv.GRID_ALIGN.STRETCH, row, 1 ) + self.content_area.add_event_cb(self.on_event, lv.EVENT.SCROLL_BEGIN, None) def add_indicator(self, indicator_text: str): self.word_count_indicator = lv.btn(self) @@ -138,6 +142,8 @@ def on_event(self, event_obj: lv.event_t): if code == lv.EVENT.CLICKED: if target == self.word_count_indicator: BackupTypeSelector(self) + elif code == lv.EVENT.SCROLL_BEGIN: + utils.lcd_resume() # region # self.panel = lv.obj(self.content_area) # self.panel.set_size(464, lv.SIZE.CONTENT) @@ -479,8 +485,6 @@ def eventhandler(self, event_obj): code = event_obj.code target = event_obj.get_target() if code == lv.EVENT.CLICKED: - from trezor import utils - if utils.lcd_resume(): return if target == self.member_count_groups.selected_btn: