diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index 6eb0c50..2061ef5 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -106,8 +106,17 @@ class EthAppClient: filters_count, sig)) - def eip712_filtering_show_field(self, name: str, sig: bytes): - return self._exchange_async(self._cmd_builder.eip712_filtering_show_field(name, sig)) + def eip712_filtering_amount_join_token(self, token_idx: int, sig: bytes): + return self._exchange_async(self._cmd_builder.eip712_filtering_amount_join_token(token_idx, + sig)) + + def eip712_filtering_amount_join_value(self, token_idx: int, name: str, sig: bytes): + return self._exchange_async(self._cmd_builder.eip712_filtering_amount_join_value(token_idx, + name, + sig)) + + def eip712_filtering_raw(self, name: str, sig: bytes): + return self._exchange_async(self._cmd_builder.eip712_filtering_raw(name, sig)) def sign(self, bip32_path: str, diff --git a/client/src/ledger_app_clients/ethereum/command_builder.py b/client/src/ledger_app_clients/ethereum/command_builder.py index 6ceb730..1e9466b 100644 --- a/client/src/ledger_app_clients/ethereum/command_builder.py +++ b/client/src/ledger_app_clients/ethereum/command_builder.py @@ -41,8 +41,10 @@ class P2Type(IntEnum): LEGACY_IMPLEM = 0x00 NEW_IMPLEM = 0x01 FILTERING_ACTIVATE = 0x00 - FILTERING_CONTRACT_NAME = 0x0f - FILTERING_FIELD_NAME = 0xff + FILTERING_MESSAGE_INFO = 0x0f + FILTERING_TOKEN_ADDR_CHECK = 0xfd + FILTERING_AMOUNT_FIELD = 0xfe + FILTERING_RAW = 0xff class CommandBuilder: @@ -170,13 +172,35 @@ class CommandBuilder: data += sig return self._serialize(InsType.EIP712_SEND_FILTERING, P1Type.COMPLETE_SEND, - P2Type.FILTERING_CONTRACT_NAME, + P2Type.FILTERING_MESSAGE_INFO, data) - def eip712_filtering_show_field(self, name: str, sig: bytes) -> bytes: + def eip712_filtering_amount_join_token(self, token_idx: int, sig: bytes) -> bytes: + data = bytearray() + data.append(token_idx) + data.append(len(sig)) + data += sig return self._serialize(InsType.EIP712_SEND_FILTERING, P1Type.COMPLETE_SEND, - P2Type.FILTERING_FIELD_NAME, + P2Type.FILTERING_TOKEN_ADDR_CHECK, + data) + + def eip712_filtering_amount_join_value(self, token_idx: int, name: str, sig: bytes) -> bytes: + data = bytearray() + data.append(len(name)) + data += name.encode() + data.append(token_idx) + data.append(len(sig)) + data += sig + return self._serialize(InsType.EIP712_SEND_FILTERING, + P1Type.COMPLETE_SEND, + P2Type.FILTERING_AMOUNT_FIELD, + data) + + def eip712_filtering_raw(self, name: str, sig: bytes) -> bytes: + return self._serialize(InsType.EIP712_SEND_FILTERING, + P1Type.COMPLETE_SEND, + P2Type.FILTERING_RAW, self._eip712_filtering_send_name(name, sig)) def set_external_plugin(self, plugin_name: str, contract_address: bytes, selector: bytes, sig: bytes) -> bytes: diff --git a/client/src/ledger_app_clients/ethereum/eip712/InputData.py b/client/src/ledger_app_clients/ethereum/eip712/InputData.py index ad4beff..f507748 100644 --- a/client/src/ledger_app_clients/ethereum/eip712/InputData.py +++ b/client/src/ledger_app_clients/ethereum/eip712/InputData.py @@ -200,7 +200,15 @@ def send_struct_impl_field(value, field): if filtering_paths: path = ".".join(current_path) if path in filtering_paths.keys(): - send_filtering_show_field(filtering_paths[path]) + if filtering_paths[path]["type"] == "amount_join_token": + send_filtering_amount_join_token(filtering_paths[path]["token"]) + elif filtering_paths[path]["type"] == "amount_join_value": + send_filtering_amount_join_value(filtering_paths[path]["token"], + filtering_paths[path]["name"]) + elif filtering_paths[path]["type"] == "raw": + send_filtering_raw(filtering_paths[path]["name"]) + else: + assert False with app_client.eip712_send_struct_impl_struct_field(data): enable_autonext() @@ -251,15 +259,22 @@ def send_struct_impl(structs, data, structname): return True +def start_signature_payload(ctx: dict, magic: int) -> bytearray: + to_sign = bytearray() + # magic number so that signature for one type of filter can't possibly be + # valid for another, defined in APDU specs + to_sign.append(magic) + to_sign += ctx["chainid"] + to_sign += ctx["caddr"] + to_sign += ctx["schema_hash"] + return to_sign + + # ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures def send_filtering_message_info(display_name: str, filters_count: int): global sig_ctx - to_sign = bytearray() - to_sign.append(183) - to_sign += sig_ctx["chainid"] - to_sign += sig_ctx["caddr"] - to_sign += sig_ctx["schema_hash"] + to_sign = start_signature_payload(sig_ctx, 183) to_sign.append(filters_count) to_sign += display_name.encode() @@ -269,21 +284,44 @@ def send_filtering_message_info(display_name: str, filters_count: int): disable_autonext() -# ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures -def send_filtering_show_field(display_name): +def send_filtering_amount_join_token(token_idx: int): global sig_ctx path_str = ".".join(current_path) - to_sign = bytearray() - to_sign.append(72) - to_sign += sig_ctx["chainid"] - to_sign += sig_ctx["caddr"] - to_sign += sig_ctx["schema_hash"] + to_sign = start_signature_payload(sig_ctx, 11) + to_sign += path_str.encode() + to_sign.append(token_idx) + sig = keychain.sign_data(keychain.Key.CAL, to_sign) + with app_client.eip712_filtering_amount_join_token(token_idx, sig): + pass + + +def send_filtering_amount_join_value(token_idx: int, display_name: str): + global sig_ctx + + path_str = ".".join(current_path) + + to_sign = start_signature_payload(sig_ctx, 22) + to_sign += path_str.encode() + to_sign += display_name.encode() + to_sign.append(token_idx) + sig = keychain.sign_data(keychain.Key.CAL, to_sign) + with app_client.eip712_filtering_amount_join_value(token_idx, display_name, sig): + pass + + +# ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures +def send_filtering_raw(display_name): + global sig_ctx + + path_str = ".".join(current_path) + + to_sign = start_signature_payload(sig_ctx, 72) to_sign += path_str.encode() to_sign += display_name.encode() sig = keychain.sign_data(keychain.Key.CAL, to_sign) - with app_client.eip712_filtering_show_field(display_name, sig): + with app_client.eip712_filtering_raw(display_name, sig): pass @@ -294,6 +332,12 @@ def prepare_filtering(filtr_data, message): filtering_paths = filtr_data["fields"] else: filtering_paths = {} + if "tokens" in filtr_data: + for token in filtr_data["tokens"]: + app_client.provide_token_metadata(token["ticker"], + bytes.fromhex(token["addr"][2:]), + token["decimals"], + token["chain_id"]) def handle_optional_domain_values(domain): diff --git a/tests/ragger/eip712_input_files/00-simple_mail-filter.json b/tests/ragger/eip712_input_files/00-simple_mail-filter.json index 33399d1..bb49570 100644 --- a/tests/ragger/eip712_input_files/00-simple_mail-filter.json +++ b/tests/ragger/eip712_input_files/00-simple_mail-filter.json @@ -1,7 +1,13 @@ { "name": "Test JSON", "fields": { - "from.name": "From", - "to.name" : "To" + "from.name": { + "type": "raw", + "name": "From" + }, + "to.name": { + "type": "raw", + "name": "To" + } } -} +} \ No newline at end of file diff --git a/tests/ragger/eip712_input_files/08-opensea-filter.json b/tests/ragger/eip712_input_files/08-opensea-filter.json index 6f1d9f5..e70eb80 100644 --- a/tests/ragger/eip712_input_files/08-opensea-filter.json +++ b/tests/ragger/eip712_input_files/08-opensea-filter.json @@ -1,9 +1,21 @@ { "name": "OpenSea", "fields": { - "maker": "Maker", - "taker": "Taker", - "basePrice": "Base Price", - "expirationTime": "Expiration Time" + "maker": { + "type": "raw", + "name": "Maker" + }, + "taker": { + "type": "raw", + "name": "Taker" + }, + "basePrice": { + "type": "raw", + "name": "Base Price" + }, + "expirationTime": { + "type": "raw", + "name": "Expiration Time" + } } -} +} \ No newline at end of file diff --git a/tests/ragger/eip712_input_files/11-complex_structs-filter.json b/tests/ragger/eip712_input_files/11-complex_structs-filter.json index a38240d..7623043 100644 --- a/tests/ragger/eip712_input_files/11-complex_structs-filter.json +++ b/tests/ragger/eip712_input_files/11-complex_structs-filter.json @@ -1,9 +1,21 @@ { "name": "Depthy Test", "fields": { - "contents": "Message", - "from.name": "Sender", - "to.members.[].name": "Recipient", - "attach.list.[].name": "Attachment" + "contents": { + "type": "raw", + "name": "Message" + }, + "from.name": { + "type": "raw", + "name": "Sender" + }, + "to.members.[].name": { + "type": "raw", + "name": "Recipient" + }, + "attach.list.[].name": { + "type": "raw", + "name": "Attachment" + } } -} +} \ No newline at end of file diff --git a/tests/ragger/eip712_input_files/12-sign_in-filter.json b/tests/ragger/eip712_input_files/12-sign_in-filter.json index 69da4f1..46aa82a 100644 --- a/tests/ragger/eip712_input_files/12-sign_in-filter.json +++ b/tests/ragger/eip712_input_files/12-sign_in-filter.json @@ -1,7 +1,13 @@ { "name": "Ethereum sign-in", "fields": { - "curDate": "Timestamp", - "id": "Identifier" + "curDate": { + "type": "raw", + "name": "Timestamp" + }, + "id": { + "type": "raw", + "name": "Identifier" + } } -} +} \ No newline at end of file