From 1df042da68bad988d7e374c2385b701d94005375 Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Fri, 19 Apr 2024 19:04:01 +0530 Subject: [PATCH 01/22] feat (app): Added tron app directory --- apps/tron_app/tron_api.c | 197 ++++++++++++++++++ apps/tron_app/tron_api.h | 114 ++++++++++ apps/tron_app/tron_context.h | 38 ++++ apps/tron_app/tron_main.c | 0 apps/tron_app/tron_priv.h | 59 ++++++ apps/tron_app/tron_pub_key.c | 0 apps/tron_app/tron_sign_txn.c | 0 .../proto-options/google/protobuf/any.options | 2 + common/proto-options/tron/contract.options | 63 ++++++ common/proto-options/tron/tron.options | 13 ++ 10 files changed, 486 insertions(+) create mode 100644 apps/tron_app/tron_api.c create mode 100644 apps/tron_app/tron_api.h create mode 100644 apps/tron_app/tron_context.h create mode 100644 apps/tron_app/tron_main.c create mode 100644 apps/tron_app/tron_priv.h create mode 100644 apps/tron_app/tron_pub_key.c create mode 100644 apps/tron_app/tron_sign_txn.c create mode 100644 common/proto-options/google/protobuf/any.options create mode 100644 common/proto-options/tron/contract.options create mode 100644 common/proto-options/tron/tron.options diff --git a/apps/tron_app/tron_api.c b/apps/tron_app/tron_api.c new file mode 100644 index 00000000..ff084747 --- /dev/null +++ b/apps/tron_app/tron_api.c @@ -0,0 +1,197 @@ + +/** + * @file tron_api.c + * @author Cypherock X1 Team + * @brief Defines helpers apis for tron app. + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "tron_api.h" + +#include +#include + +#include "common_error.h" +#include "core_api.h" +#include "events.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ +bool decode_tron_query(const uint8_t *data, + uint16_t data_size, + tron_query_t *query_out) { + if (NULL == data || NULL == query_out || 0 == data_size) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + + // zeroise for safety from garbage in the query reference + memzero(query_out, sizeof(tron_query_t)); + + /* Create a stream that reads from the buffer. */ + pb_istream_t stream = pb_istream_from_buffer(data, data_size); + + /* Now we are ready to decode the message. */ + bool status = pb_decode(&stream, TRON_QUERY_FIELDS, query_out); + + /* Send error to host if status is false*/ + if (false == status) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + } + + return status; +} + +bool encode_tron_result(const tron_result_t *result, + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out) { + if (NULL == result || NULL == buffer || NULL == bytes_written_out) + return false; + + /* Create a stream that will write to our buffer. */ + pb_ostream_t stream = pb_ostream_from_buffer(buffer, max_buffer_len); + + /* Now we are ready to encode the message! */ + bool status = pb_encode(&stream, TRON_RESULT_FIELDS, result); + + if (true == status) { + *bytes_written_out = stream.bytes_written; + } + + return status; +} + +bool check_tron_query(const tron_query_t *query, pb_size_t exp_query_tag) { + if ((NULL == query) || (exp_query_tag != query->which_request)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_QUERY); + return false; + } + return true; +} + +tron_result_t init_tron_result(pb_size_t result_tag) { + tron_result_t result = TRON_RESULT_INIT_ZERO; + result.which_response = result_tag; + return result; +} + +void tron_send_error(pb_size_t which_error, uint32_t error_code) { + tron_result_t result = init_tron_result(TRON_RESULT_COMMON_ERROR_TAG); + result.common_error = init_common_error(which_error, error_code); + tron_send_result(&result); +} + +void tron_send_result(const tron_result_t *result) { + // TODO: Set the options file for all + uint8_t buffer[1700] = {0}; + size_t bytes_encoded = 0; + ASSERT(encode_tron_result(result, buffer, sizeof(buffer), &bytes_encoded)); + send_response_to_host(&buffer[0], bytes_encoded); +} + +bool tron_get_query(tron_query_t *query, pb_size_t exp_query_tag) { + evt_status_t event = get_events(EVENT_CONFIG_USB, MAX_INACTIVITY_TIMEOUT); + + if (true == event.p0_event.flag) { + return false; + } + + if (!decode_tron_query( + event.usb_event.p_msg, event.usb_event.msg_size, query)) { + return false; + } + + if (!check_tron_query(query, exp_query_tag)) { + return false; + } + + return true; +} diff --git a/apps/tron_app/tron_api.h b/apps/tron_app/tron_api.h new file mode 100644 index 00000000..16c88e27 --- /dev/null +++ b/apps/tron_app/tron_api.h @@ -0,0 +1,114 @@ + +/** + * @file tron_api.h + * @author Cypherock X1 Team + * @brief Header file to export some helper functions for the TRON app + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef TRON_API_H +#define TRON_API_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief API to decode query from host with `TRON_QUERY_FIELDS` + * + * @param[in] data: PB encoded bytestream received from host + * @param[in] data_size: size of pb encoded bytestream + * @param[out] query_out: @ref tron_query_t obj to copy the decoded result to + * @return bool True if decoding was successful, else false + */ +bool decode_tron_query(const uint8_t *data, + uint16_t data_size, + tron_query_t *query_out); + +/** + * @brief Encodes the TRON result with `TRON_RESULT_FIELDS` to byte-stream + * + * @param[in] result: object of populated @ref tron_result_t to be encoded + * @param[out] buffer: buffer to fill byte-stream into + * @param[in] max_buffer_len: Max length allowed for writing bytestream to + * buffer + * @param[out] bytes_written_out: bytes written to bytestream + * @return bool True if decoding was successful, else false + */ +bool encode_tron_result(const tron_result_t *result, + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out); + +/** + * @brief This API checks if the `which_request` field of the query of type + * `tron_query_t` matches against the expected tag. + * + * @param query The query of type `tron_query_t` to be checked + * @param exp_query_tag The expected tag of the query + * @return true If the query tag matches the expected tag + * @return false If the query tag does not match the expected tag + */ +bool check_tron_query(const tron_query_t *query, pb_size_t exp_query_tag); + +/** + * @brief Returns zero initialized object of type + * tron_result_t result_tag set in result.which_response field + * + * @param result_tag Result tag to be set in the tron_result_t result + * @return tron_result_t Result object of type tron_result_t + */ +tron_result_t init_tron_result(pb_size_t result_tag); + +/** + * @brief Send the error to the host. + * + * @param which_error The error type to be sent + * @param error_code The error code to sent to the host + */ +void tron_send_error(pb_size_t which_error, uint32_t error_code); + +/** + * @brief This API encodes tron_result_t in protobuf structure. + * @details If the encoding is successful, then it sends the corresponding + * result to the host. + * + * The function ASSERTs the result of encode_tron_result internally. + * + * @param result The result which needs to be sent to the host. + */ +void tron_send_result(const tron_result_t *result); + +/** + * @brief This API receives request of type tron_query_t of type + * exp_query_tag from the host. + * + * @param query The reference to which the query needs to be populated + * @param exp_query_tag The expected tag of the query + * @return true If the query was recieved from the host matching the tag + * @return false If the request timed out or the recieved request did not match + * the tag + */ +bool tron_get_query(tron_query_t *query, pb_size_t exp_query_tag); + +#endif diff --git a/apps/tron_app/tron_context.h b/apps/tron_app/tron_context.h new file mode 100644 index 00000000..03814b3d --- /dev/null +++ b/apps/tron_app/tron_context.h @@ -0,0 +1,38 @@ +/** + * @file tron_context.h + * @author Cypherock X1 Team + * @brief Header file defining typedefs and MACROS for the TRON app + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef TRON_CONTEXT_H +#define TRON_CONTEXT_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ +#include +#include + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +// TODO: Populate structure for TRON +typedef struct { +} tron_config_t; + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +#endif /* TRON_CONTEXT_H */ diff --git a/apps/tron_app/tron_main.c b/apps/tron_app/tron_main.c new file mode 100644 index 00000000..e69de29b diff --git a/apps/tron_app/tron_priv.h b/apps/tron_app/tron_priv.h new file mode 100644 index 00000000..c50df3b5 --- /dev/null +++ b/apps/tron_app/tron_priv.h @@ -0,0 +1,59 @@ +/** + * @file tron_priv.h + * @author Cypherock X1 Team + * @brief Support for tron app internal operations + * This file is defined to separate TRON's internal use functions, + * flows, common APIs + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef TRON_PRIV_H +#define TRON_PRIV_H +/***************************************************************************** + * INCLUDES + *****************************************************************************/ +#include +#include + +#include "tron_context.h" +//#include "solana_txn_helpers.h" +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Handler for NEAR public key derivation. + * @details This flow expects BTC_GET_PUBLIC_KEY_REQUEST_INITIATE_TAG as initial + * query, otherwise the flow is aborted + * + * @param query object for address public key query + */ +void tron_get_pub_keys(tron_query_t *query); + +/** + * @brief Handler for NEAR sign transaction function + * + * @param query Buffer containing USB query received from host + */ +void tron_sign_transaction(tron_query_t *query); + + + + + +#endif /* TRON_PRIV_H */ + diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c new file mode 100644 index 00000000..e69de29b diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c new file mode 100644 index 00000000..e69de29b diff --git a/common/proto-options/google/protobuf/any.options b/common/proto-options/google/protobuf/any.options new file mode 100644 index 00000000..c88410ed --- /dev/null +++ b/common/proto-options/google/protobuf/any.options @@ -0,0 +1,2 @@ +google.protobuf.Any.type_url max_size:64 +google.protobuf.Any.value max_size:64 diff --git a/common/proto-options/tron/contract.options b/common/proto-options/tron/contract.options new file mode 100644 index 00000000..eedff96c --- /dev/null +++ b/common/proto-options/tron/contract.options @@ -0,0 +1,63 @@ +# Address size is 21 + +tron.AccountUpdateContract.owner_address max_size: 21, fixed_length: true + +tron.TransferContract.owner_address max_size: 21, fixed_length: true +tron.TransferContract.to_address max_size: 21, fixed_length: true + +tron.TransferAssetContract.asset_name max_size: 16 +tron.TransferAssetContract.owner_address max_size: 21, fixed_length: true +tron.TransferAssetContract.to_address max_size: 21, fixed_length: true + +tron.VoteWitnessContract.owner_address max_size: 21, fixed_length: true +tron.VoteWitnessContract.votes max_count: 5 # Assume 5 votes max +tron.VoteWitnessContract.Vote.vote_address max_size: 21, fixed_length: true +tron.VoteWitnessContract.support type: FT_IGNORE + +tron.FreezeBalanceContract.owner_address max_size: 21, fixed_length: true +tron.FreezeBalanceContract.receiver_address max_size: 21, fixed_length: true + +tron.UnfreezeBalanceContract.owner_address max_size: 21, fixed_length: true +tron.UnfreezeBalanceContract.receiver_address max_size: 21, fixed_length: true + +tron.FreezeBalanceV2Contract.owner_address max_size: 21, fixed_length: true +tron.UnfreezeBalanceV2Contract.owner_address max_size: 21, fixed_length: true + +tron.WithdrawExpireUnfreezeContract.owner_address max_size: 21, fixed_length: true + +tron.DelegateResourceContract.owner_address max_size: 21, fixed_length: true +tron.DelegateResourceContract.receiver_address max_size: 21, fixed_length: true + +tron.UnDelegateResourceContract.owner_address max_size: 21, fixed_length: true +tron.UnDelegateResourceContract.receiver_address max_size: 21, fixed_length: true + +tron.WithdrawBalanceContract.owner_address max_size: 21, fixed_length: true + +tron.ProposalCreateContract.owner_address max_size: 21, fixed_length: true +tron.ProposalCreateContract.parameters max_count: 10 + +tron.ProposalApproveContract.owner_address max_size: 21, fixed_length: true + +tron.ProposalDeleteContract.owner_address max_size: 21, fixed_length: true + +tron.TriggerSmartContract.owner_address max_size: 21, fixed_length: true +tron.TriggerSmartContract.contract_address max_size: 21, fixed_length: true +tron.TriggerSmartContract.data type: FT_CALLBACK + +tron.ExchangeCreateContract.owner_address max_size: 21, fixed_length: true +tron.ExchangeCreateContract.first_token_id max_size: 8 +tron.ExchangeCreateContract.second_token_id max_size: 8 + +tron.ExchangeInjectContract.owner_address max_size: 21, fixed_length: true +tron.ExchangeInjectContract.token_id max_size: 8 + +tron.ExchangeWithdrawContract.owner_address max_size: 21, fixed_length: true +tron.ExchangeWithdrawContract.token_id max_size: 8 + +tron.ExchangeTransactionContract.owner_address max_size: 21, fixed_length: true +tron.ExchangeTransactionContract.token_id max_size: 8 + +tron.AccountPermissionUpdateContract.owner_address max_size: 21, fixed_length: true +tron.AccountPermissionUpdateContract.owner type: FT_IGNORE +tron.AccountPermissionUpdateContract.witness type: FT_IGNORE +tron.AccountPermissionUpdateContract.actives type: FT_IGNORE diff --git a/common/proto-options/tron/tron.options b/common/proto-options/tron/tron.options new file mode 100644 index 00000000..e956f572 --- /dev/null +++ b/common/proto-options/tron/tron.options @@ -0,0 +1,13 @@ +tron.Transaction.raw.contract max_count: 1 +tron.Transaction.raw.ref_block_bytes type: FT_IGNORE +tron.Transaction.raw.ref_block_num type: FT_IGNORE +tron.Transaction.raw.ref_block_hash type: FT_IGNORE +tron.Transaction.raw.expiration type: FT_IGNORE +tron.Transaction.raw.auths type: FT_IGNORE +tron.Transaction.raw.scripts type: FT_IGNORE +tron.Transaction.raw.timestamp type: FT_IGNORE + +tron.Key.address max_size: 21, fixed_length: true + +tron.Permission.keys max_count: 3 # Assume 3 max keys +tron.Permission.operations max_size: 32, fixed_length: true From 4422e4b3f5c7ff84f1262c7de680d6ff300c555b Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Sun, 21 Apr 2024 16:11:28 +0530 Subject: [PATCH 02/22] feat (app): Updated user vfxn and txn checks --- apps/tron_app/tron_main.c | 150 +++++ apps/tron_app/tron_main.h | 45 ++ apps/tron_app/tron_priv.h | 41 +- apps/tron_app/tron_pub_key.c | 473 ++++++++++++++++ apps/tron_app/tron_sign_txn.c | 527 ++++++++++++++++++ apps/tron_app/tron_txn_helpers.c | 119 ++++ apps/tron_app/tron_txn_helpers.h | 76 +++ common/core/app_registry.h | 2 +- common/core/core_flow_init.c | 2 + .../tron/get_public_keys.options | 5 + common/proto-options/tron/sign_txn.options | 5 + utilities/cmake/firmware/firmware.cmake | 3 +- 12 files changed, 1432 insertions(+), 16 deletions(-) create mode 100644 apps/tron_app/tron_main.h create mode 100644 apps/tron_app/tron_txn_helpers.c create mode 100644 apps/tron_app/tron_txn_helpers.h create mode 100644 common/proto-options/tron/get_public_keys.options create mode 100644 common/proto-options/tron/sign_txn.options diff --git a/apps/tron_app/tron_main.c b/apps/tron_app/tron_main.c index e69de29b..9222948f 100644 --- a/apps/tron_app/tron_main.c +++ b/apps/tron_app/tron_main.c @@ -0,0 +1,150 @@ +/** + * @file tron_main.c + * @author Cypherock X1 Team + * @brief A common entry point to various Tolana coin actions supported. + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "tron_main.h" + +#include "tron_api.h" +#include "tron_priv.h" +#include "status_api.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ +/** + * @brief Entry point for the TRON application of the X1 vault. It is invoked + * by the X1 vault firmware, as soon as there is a USB request raised for the + * tron app. + * + * @param usb_evt The USB event which triggered invocation of the bitcoin app + */ +void tron_main(usb_event_t usb_evt, const void *app_config); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ +static const cy_app_desc_t tron_app_desc = {.id = 18, + .version = + { + .major = 1, + .minor = 0, + .patch = 0, + }, + .app = tron_main, + .app_config = NULL}; + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ +void tron_main(usb_event_t usb_evt, const void *app_config) { + tron_query_t query = TRON_QUERY_INIT_DEFAULT; + + if (false == decode_tron_query(usb_evt.p_msg, usb_evt.msg_size, &query)) { + return; + } + + /* Set status to CORE_DEVICE_IDLE_STATE_USB to indicate host that we are now + * servicing a USB initiated command */ + core_status_set_idle_state(CORE_DEVICE_IDLE_STATE_USB); + + switch ((uint8_t)query.which_request) { + case TRON_QUERY_GET_PUBLIC_KEYS_TAG: + case TRON_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG: { + tron_get_pub_keys(&query); + break; + } + case TRON_QUERY_SIGN_TXN_TAG: { + tron_sign_transaction(&query); + break; + } + + default: { + /* In case we ever encounter invalid query, convey to the host app */ + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_QUERY); + } break; + } + + return; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ +const cy_app_desc_t *get_tron_app_desc() { + return &tron_app_desc; +} \ No newline at end of file diff --git a/apps/tron_app/tron_main.h b/apps/tron_app/tron_main.h new file mode 100644 index 00000000..7f5ac726 --- /dev/null +++ b/apps/tron_app/tron_main.h @@ -0,0 +1,45 @@ +/** + * @file tron_main.h + * @author Cypherock X1 Team + * @brief Header file for a common entry point to various Tron coin actions + supported. + * @details + + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + */ + +#ifndef TRON_MAIN_H +#define TRON_MAIN_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "app_registry.h" +#include "events.h" +#include "tron_context.h" +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ +/** + * @brief Returns the config for Tron chain app descriptors + * + * @return A const reference to cy_app_desc_t + */ +const cy_app_desc_t *get_tron_app_desc(); +#endif /* TRON_MAIN_H */ diff --git a/apps/tron_app/tron_priv.h b/apps/tron_app/tron_priv.h index c50df3b5..7b43e2db 100644 --- a/apps/tron_app/tron_priv.h +++ b/apps/tron_app/tron_priv.h @@ -2,7 +2,7 @@ * @file tron_priv.h * @author Cypherock X1 Team * @brief Support for tron app internal operations - * This file is defined to separate TRON's internal use functions, + * This file is defined to separate tron's internal use functions, * flows, common APIs * @copyright Copyright (c) 2023 HODL TECH PTE LTD *
You may obtain a copy of license at -#include +#include "events.h" +#include "tron_api.h" #include "tron_context.h" -//#include "solana_txn_helpers.h" +#include + /***************************************************************************** * MACROS AND DEFINES *****************************************************************************/ @@ -25,8 +27,20 @@ /***************************************************************************** * TYPEDEFS *****************************************************************************/ +typedef struct { + /** + * The structure holds the wallet information of the transaction. + * @note Populated by solana_handle_initiate_query() + */ + tron_sign_txn_initiate_request_t init_info; + // remembers the allocated buffer for holding complete unsigned transaction + uint8_t *transaction; + // decoded raw txn + tron_transaction_raw_t *raw_txn; + +} tron_txn_context_t; /***************************************************************************** * EXPORTED VARIABLES *****************************************************************************/ @@ -36,24 +50,23 @@ *****************************************************************************/ /** - * @brief Handler for NEAR public key derivation. - * @details This flow expects BTC_GET_PUBLIC_KEY_REQUEST_INITIATE_TAG as initial - * query, otherwise the flow is aborted + * @brief Handler for getting public keys for TRON. + * @details This flow expects TRON_GET_PUBLIC_KEYS_REQUEST_INITIATE_TAG as + * initial query, otherwise the flow is aborted * - * @param query object for address public key query + * @param query Reference to the decoded query struct from the host app */ void tron_get_pub_keys(tron_query_t *query); /** - * @brief Handler for NEAR sign transaction function + * @brief Handler for signing a transaction on tron. + * @details The expected request type is TRON_SIGN_TXN_REQUEST_INITIATE_TAG. The + * function controls the complete data exchange with host, user prompts and + * confirmations for signing an TRON based transaction. * - * @param query Buffer containing USB query received from host + * @param query Reference to the decoded query struct from the host app */ void tron_sign_transaction(tron_query_t *query); - - - - #endif /* TRON_PRIV_H */ diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index e69de29b..a413f83d 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -0,0 +1,473 @@ +/** + * @file tron_pub_key.c + * @author Cypherock X1 Team + * @brief Generates public key for Tron derivations. + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at
https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include + +#include "reconstruct_wallet_flow.h" +#include "tron_api.h" +//#include "solana_helpers.h" +#include "tron_priv.h" +#include "status_api.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" +#include "wallet_list.h" +#include "sha3.h" +#include "base58.h" +#include "bip32.h" +#include "coin_utils.h" +#include "curves.h" +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Checks if the provided query contains expected request. + * @details The function performs the check on the request type and if the check + * fails, then it will send an error to the host TRON app and return false. + * + * @param query Reference to an instance of tron_query_t containing query + * received from host app + * @param which_request The expected request type enum + * + * @return bool Indicating if the check succeeded or failed + * @retval true If the query contains the expected request + * @retval false If the query does not contain the expected request + */ +STATIC bool check_which_request(const tron_query_t *query, + pb_size_t which_request); +/** + * @brief Validates all the derivation paths received in the request from host + * @details The function validates each path entry in the request. If any + * invalid path is detected, the function will send an error to the host and + * return false. + * + * @param request Reference to an instance of tron_get_public_keys_request_t + * @return bool Indicating if the verification passed or failed + * @retval true If all the derivation path entries are valid + * @retval false If any of the derivation path entries are invalid + */ +STATIC bool validate_request_data(tron_get_public_keys_request_t *request, + const pb_size_t which_request); +/** + * @details The function provides a public key. It accepts NULL for output + * parameter and handles accordingly. The function also manages all the terminal + * errors during derivation/encoding, in which case it will return false and + * send a relevant error to the host closing the request-response pair. All the + * errors/invalid cases are conveyed to the host as unknown_error = 1 because we + * expect the data validation was success. + * + * @param seed Reference to the wallet seed generated from X1 Card + * @param path Derivation path of the node to be derived + * @param path_length Expected length of the provided derivation path + * @param public_key Storage location for raw uncompressed public key + * + * @retval false If derivation failed + */ +STATIC bool get_public_key(const uint8_t *seed, + const uint32_t *path, + uint32_t path_length, + uint8_t *public_key); + +/** + * @brief Derives a list of public key corresponding to the provided list of + * derivation paths. + * @details The function expects the size of list for derivation paths and + * location for storing derived public keys to be a match with provided count. + * + * @param paths Reference to the list of + * tron_get_public_keys_derivation_path_t + * @param count Number of derivation paths in the list and consequently, + * sufficient space in memory for storing derived public keys. + * @param seed Reference to a const array containing the seed + * @param public_keys Reference to the location to store all the public keys to + * be derived + * + * @return bool Indicating if the complete public keys list was derived + * @retval true If all the requested public keys were derived. + * @retval false If the public key derivation failed. This could be due to + * invalid derivation path. + */ +STATIC bool fill_public_keys( + const tron_get_public_keys_derivation_path_t *paths, + const uint8_t *seed, + uint8_t public_keys[][TRON_PUB_KEY_SIZE], + pb_size_t count); + +/** + * @brief The function sends public keys for the requested batch + * @details The function determines the batch size from the static struct + * member declaration of nanopb options. The function batches the result based + * on the definition and sends the result. The function expects that the entire + * list of public keys requested is already derived and provided to this + * function as public_keys. The function will return false if either the query + * was wrong or a P0 event is occurred. In case of wrong query, the function + * also sends an error to the host app. + * + * @param query Reference to an instance of tron_query_t + * @param public_keys Reference to list of derived public keys to be sent to the + * host + * @param count Number of public key entries in the list of public keys + * + * @return bool Indicating if the public keys were exported completely to the + * host + * @retval true If all the requested public keys were exported to the host app + * @retval false If the export was interrupted by a P0 event or an invalid query + * was received from the host app. + */ +static bool send_public_keys(tron_query_t *query, + const uint8_t public_keys[][TRON_PUB_KEY_SIZE], + const size_t count, + const pb_size_t which_request, + const pb_size_t which_response); +/** + * @brief Helper function to take user consent before exporting public keys to + * the host. Uses an appropriate message template based on the query request + * received from the host. + * + * @param which_request The type of request received from host + * @param wallet_name The name of the wallet on which the request needs to be + * performed + * @return true If the user accepted the request + * @return false If the user rejected or any P0 event occurred during the + * confirmation. + */ +static bool get_user_consent(const pb_size_t which_request, + const char *wallet_name); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +STATIC bool check_which_request(const tron_query_t *query, + pb_size_t which_request) { + if (which_request != query->get_public_keys.which_request) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +STATIC bool validate_request_data(tron_get_public_keys_request_t *request, + const pb_size_t which_request) { + bool status = true; + + if (0 == request->initiate.derivation_paths_count) { + // request does not have any derivation paths, invalid request + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = false; + } + + if (TRON_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG == which_request && + 1 < request->initiate.derivation_paths_count) { + // `TRON_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG` request contains more + // than one derivation path which is not expected + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = false; + } + + tron_get_public_keys_derivation_path_t *path = NULL; + pb_size_t count = request->initiate.derivation_paths_count; + for (pb_size_t index = 0; index < count; index++) { + path = &request->initiate.derivation_paths[index]; + //TODO: + /* + if (!tron_derivation_path_guard(path->path, path->path_count)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = false; + break; + } + */ + } + + return status; +} + +STATIC bool get_public_key(const uint8_t *seed, + const uint32_t *path, + uint32_t path_length, + uint8_t *public_key) { + HDNode node = {0}; + + if (!derive_hdnode_from_path(path, path_length, SECP256K1_NAME, seed, &node)) { + // send unknown error; unknown failure reason + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 1); + memzero(&node, sizeof(HDNode)); + return false; + } + + if (NULL != public_key) { + ecdsa_uncompress_pubkey( + get_curve_by_name(SECP256K1_NAME)->params, node.public_key, public_key); + } + + memzero(&node, sizeof(HDNode)); + return true; +} + +static bool fill_public_keys(const tron_get_public_keys_derivation_path_t *paths, + const uint8_t *seed, + uint8_t public_keys[][TRON_PUB_KEY_SIZE], + pb_size_t count) { + for (pb_size_t index = 0; index < count; index++) { + const tron_get_public_keys_derivation_path_t *path = &paths[index]; + if (!get_public_key( + seed, path->path, path->path_count, public_keys[index])) { + return false; + } + } + return true; +} + +static bool send_public_keys(tron_query_t *query, + const uint8_t public_keys[][TRON_PUB_KEY_SIZE], + const size_t count, + const pb_size_t which_request, + const pb_size_t which_response) { + tron_result_t response = init_tron_result(which_response); + tron_get_public_keys_result_response_t *result = + &response.get_public_keys.result; + static const size_t batch_limit = + sizeof(response.get_public_keys.result.public_keys) / TRON_PUB_KEY_SIZE; + size_t remaining = count; + + response.get_public_keys.which_response = + TRON_GET_PUBLIC_KEYS_RESPONSE_RESULT_TAG; + + while (true) { + // send response as batched list of public keys + size_t batch_size = CY_MIN(batch_limit, remaining); + result->public_keys_count = batch_size; + + memcpy(response.get_public_keys.result.public_keys, + public_keys[count - remaining], + batch_size * TRON_PUB_KEY_SIZE); + + tron_send_result(&response); + remaining -= batch_size; + if (0 == remaining) { + break; + } + + if (!tron_get_query(query, which_request) || + !check_which_request(query, + TRON_GET_PUBLIC_KEYS_REQUEST_FETCH_NEXT_TAG)) { + return false; + } + } + return true; +} + +static bool get_user_consent(const pb_size_t which_request, + const char *wallet_name) { + char msg[100] = ""; + + if (TRON_QUERY_GET_PUBLIC_KEYS_TAG == which_request) { + snprintf( + msg, sizeof(msg), UI_TEXT_ADD_ACCOUNT_PROMPT, "Tron", wallet_name); + } else { + snprintf(msg, + sizeof(msg), + UI_TEXT_RECEIVE_TOKEN_PROMPT, + TRON_LUNIT, + TRON_NAME, + wallet_name); + } + + return core_scroll_page(NULL, msg, tron_send_error); +} + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ +void tron_get_pub_keys(tron_query_t *query) { + char wallet_name[NAME_SIZE] = ""; + uint8_t seed[64] = {0}; + + const pb_size_t which_request = query->which_request; + tron_get_public_keys_intiate_request_t *init_req = NULL; + pb_size_t which_response = TRON_RESULT_COMMON_ERROR_TAG; + + if (TRON_QUERY_GET_PUBLIC_KEYS_TAG == which_request) { + which_response = TRON_RESULT_GET_PUBLIC_KEYS_TAG; + init_req = &query->get_public_keys.initiate; + } else { + which_response = TRON_RESULT_GET_USER_VERIFIED_PUBLIC_KEY_TAG; + init_req = &query->get_user_verified_public_key.initiate; + } + + uint8_t public_keys[sizeof(init_req->derivation_paths) / + sizeof(tron_get_public_keys_derivation_path_t)] + [TRON_PUB_KEY_SIZE] = {0}; + + if (!check_which_request(query, + TRON_GET_PUBLIC_KEYS_REQUEST_INITIATE_TAG) || + !validate_request_data(&query->get_public_keys, which_request) || + !get_wallet_name_by_id(query->get_public_keys.initiate.wallet_id, + (uint8_t *)wallet_name, + tron_send_error)) { + return; + } + + // Take user consent to export public key for the wallet + if (!get_user_consent(which_request, wallet_name)) { + return; + } + + set_app_flow_status(TRON_GET_PUBLIC_KEYS_STATUS_CONFIRM); + + if (!reconstruct_seed(query->get_public_keys.initiate.wallet_id, + &seed[0], + tron_send_error)) { + memzero(seed, sizeof(seed)); + return; + } + + set_app_flow_status(TRON_GET_PUBLIC_KEYS_STATUS_SEED_GENERATED); + delay_scr_init(ui_text_processing, DELAY_SHORT); + + bool status = fill_public_keys(init_req->derivation_paths, + seed, + public_keys, + init_req->derivation_paths_count); + + // Clear seed as soon as it is not needed + memzero(seed, sizeof(seed)); + + if (!status) { + // send unknown error; do not know failure reason + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 1); + return; + } + + if (TRON_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG == which_request) { + char main_address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = ""; + + // gen Address: + uint8_t initial_address[1 + 20] = {0}; //initial address + initial_address[0] = 0x41; + uint8_t public_key_digest[32]; + //#define USE_KECCAK 1 + //No iteration in public_keys[i]? + keccak_256(public_keys[0], TRON_PUB_KEY_SIZE, public_key_digest); //compare with reference + + // extract last 20 bytes + // address = 41||sha3[12,32) + for(int i = 12;i < 32;i++){ + initial_address[i - 12 + 1] = public_key_digest[i]; + } + + if(!base58_encode_check(initial_address, 1 + 20, HASHER_SHA2D, main_address, TRON_ACCOUNT_ADDRESS_LENGTH + 1)){ + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return; + } + + if (!core_scroll_page(ui_text_receive_on, main_address, tron_send_error)) { + return; + } + + set_app_flow_status(TRON_GET_PUBLIC_KEYS_STATUS_VERIFY); + } + + if (!send_public_keys(query, + public_keys, + init_req->derivation_paths_count, + which_request, + which_response)) { + return; + } + + delay_scr_init(ui_text_check_cysync_app, DELAY_TIME); +} \ No newline at end of file diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index e69de29b..ebfba37f 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -0,0 +1,527 @@ +/** + * @file tron_sign_txn.c + * @author Cypherock X1 Team + * @brief Tron chain transaction signing logic + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "reconstruct_wallet_flow.h" +#include "tron_api.h" +#include "sha2.h" +#include "tron_priv.h" +#include "status_api.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" +#include "wallet_list.h" +#include "curves.h" +#include +#include +#include +#include +#include + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Checks if the provided query contains expected request. + * @details The function performs the check on the request type and if the check + * fails, then it will send an error to the host bitcoin app and return false. + * + * @param query Reference to an instance of tron_query_t containing query + * received from host app + * @param which_request The expected request type enum + * + * @return bool Indicating if the check succeeded or failed + * @retval true If the query contains the expected request + * @retval false If the query does not contain the expected request + */ +static bool check_which_request(const tron_query_t *query, + pb_size_t which_request); + +/** + * @brief Validates the derivation path received in the request from host + * @details The function validates the provided account derivation path in the + * request. If invalid path is detected, the function will send an error to the + * host and return false. + * + * @param request Reference to an instance of tron_sign_txn_request_t + * @return bool Indicating if the verification passed or failed + * @retval true If all the derivation path entries are valid + * @retval false If any of the derivation path entries are invalid + */ +static bool validate_request_data(const tron_sign_txn_request_t *request); + +/** + * @brief The function prepares and sends empty responses + * + * @param which_response Constant value for the response type to be sent + */ +static void send_response(pb_size_t which_response); + +/** + * @brief Takes already received and decoded query for the user confirmation. + * @details The function will verify if the query contains the TRON_SIGN_TXN + * type of request. Additionally, the wallet-id is validated for sanity and the + * derivation path for the account is also validated. After the validations, + * user is prompted about the action for confirmation. The function returns true + * indicating all the validation and user confirmation was a success. + * + * @param query Constant reference to the decoded query received from the host + * + * @return bool Indicating if the function actions succeeded or failed + * @retval true If all the validation and user confirmation was positive + * @retval false If any of the validation or user confirmation was negative + */ +STATIC bool tron_handle_initiate_query(const tron_query_t *query); + +/** + * @brief Fetches complete raw transaction to be signed for verification + * @details The function will try to fetch the transaction by referring to the + * declared size in tron_txn_context. The function will store complete + * transaction into tron_txn_context.transaction. + * + * @param query Reference to an instance of tron_query_t for storing the + * transient transaction chunks. + * + * @return bool Indicating if the whole transaction received and verified + * @retval true If all the transaction was fetched and verified + * @retval false If the transaction failed verification or wasn't fetched + */ +STATIC bool tron_fetch_valid_transaction(tron_query_t *query); + +/** + * @brief Aggregates user consent for the transaction info + * @details The function decodes the receiver address along with the + * corresponding transfer value in SOL. + * + * + * @return bool Indicating if the user confirmed the transaction + * @retval true If user confirmed the receiver address along with + * the corresponding value. + * @retval false Immediate return if any of the confirmation is disapproved + */ +STATIC bool tron_get_user_verification(); + +/** + * @brief Fetches seed for generating public and private key + * @details The function internally calls wallet reconstruction sub-flow to get + * access to the seed. + * + * @param query Reference to an instance of tron_query_t to store transient + * request from the host + * @param seed_out seed recontructed from wallet + * @return bool Indicating if signature for the provided transaction was + * successfully generated + * @retval true If all the seed is generated without any error + * @retval false If seed failed to generate + */ +STATIC bool fetch_seed(tron_query_t *query, uint8_t *seed_out); + +/** + * @brief Sends the generated signature to the host + * @details The function internally updates the unsigned transaction with a + * recent blockhash and signs the transaction before sending to the host + * + * @param query Reference to an instance of tron_query_t to store transient + * request from the host + * @param seed seed reconstructed from wallet + * @param sig Reference to the struct having the signature components + * @return bool Indicating if the signature is sent to the host + * @retval true If the signature was sent to host successfully + * @retval false If the host responded with unknown/wrong query + */ +static bool send_signature(tron_query_t *query, + uint8_t *seed, + tron_sign_txn_signature_response_t *sig); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +STATIC tron_txn_context_t *tron_txn_context = NULL; + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +static bool check_which_request(const tron_query_t *query, + pb_size_t which_request) { + if (which_request != query->sign_txn.which_request) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +static bool validate_request_data(const tron_sign_txn_request_t *request) { + bool status = true; + + if (!tron_derivation_path_guard(request->initiate.derivation_path, + request->initiate.derivation_path_count)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = false; + } + + return status; +} + +static void send_response(const pb_size_t which_response) { + tron_result_t result = init_tron_result(TRON_RESULT_SIGN_TXN_TAG); + result.sign_txn.which_response = which_response; + tron_send_result(&result); +} + +STATIC bool tron_handle_initiate_query(const tron_query_t *query) { + char wallet_name[NAME_SIZE] = ""; + char msg[100] = ""; + + if (!check_which_request(query, TRON_SIGN_TXN_REQUEST_INITIATE_TAG) || + !validate_request_data(&query->sign_txn) || + !get_wallet_name_by_id(query->sign_txn.initiate.wallet_id, + (uint8_t *)wallet_name, + tron_send_error)) { + return false; + } + + snprintf(msg, + sizeof(msg), + UI_TEXT_SEND_TOKEN_PROMPT, + TRON_LUNIT, + TRON_NAME, + wallet_name); + // Take user consent to sign the transaction for the wallet + if (!core_confirmation(msg, tron_send_error)) { + return false; + } + + set_app_flow_status(TRON_SIGN_TXN_STATUS_CONFIRM); + send_response(TRON_SIGN_TXN_RESPONSE_CONFIRMATION_TAG); + // show processing screen for a minimum duration (additional time will add due + // to actual processing) + delay_scr_init(ui_text_processing, DELAY_SHORT); + return true; +} + +STATIC bool tron_fetch_valid_transaction(tron_query_t *query) { + uint32_t size = 0; + tron_result_t response = init_tron_result(TRON_RESULT_SIGN_TXN_TAG); + uint32_t total_size = tron_txn_context->init_info.transaction_size; + const tron_sign_txn_data_t *txn_data = &query->sign_txn.txn_data; + const common_chunk_payload_t *payload = &txn_data->chunk_payload; + const common_chunk_payload_chunk_t *chunk = &txn_data->chunk_payload.chunk; + + // allocate memory for storing transaction + tron_txn_context->transaction = (uint8_t *)malloc(total_size); + while (1) { + if (!tron_get_query(query, TRON_QUERY_SIGN_TXN_TAG) || + !check_which_request(query, TRON_SIGN_TXN_REQUEST_TXN_DATA_TAG)) { + return false; + } + + if (!txn_data->has_chunk_payload || + payload->chunk_index >= payload->total_chunks || + size + payload->chunk.size > total_size) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return false; + } + + memcpy(&tron_txn_context->transaction[size], chunk->bytes, chunk->size); + size += chunk->size; + // Send chunk ack to host + response.sign_txn.which_response = + TRON_SIGN_TXN_RESPONSE_DATA_ACCEPTED_TAG; + response.sign_txn.data_accepted.has_chunk_ack = true; + response.sign_txn.data_accepted.chunk_ack.chunk_index = + payload->chunk_index; + tron_send_result(&response); + + if (0 == payload->remaining_size || + payload->chunk_index + 1 == payload->total_chunks) { + break; + } + } + + // make sure all chunks were received + if (size != total_size) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return false; + } + + // decode and verify the received transaction + if (0 != tron_byte_array_to_raw_txn( + tron_txn_context->transaction, + total_size, + &tron_txn_context->raw_txn) || + 0 != + tron_validate_unsigned_txn(&tron_txn_context->raw_txn)) { + return false; + } + + return true; +} + +STATIC bool extract_contract_info(tron_transaction_raw *raw_txn, + int64_t *amount, + uint8_t *to_address, + uint8_t *owner_address) { + if (!(raw_txn->contract_count > 0)){ + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return false; + } + + tron_transaction_contract contract = raw_txn->contract[0]; // Example for the first contract + + tron_transfer_contract_t transfer_contract = TRON_TRANSFER_CONTRACT_INIT_DEFAULT; + + // TODO: Add switch-cases for more contract types + switch (contract.type) { + case tron_Transaction_Contract_ContractType_TransferContract: + google_protobuf_any_t any = contract.parameter; + pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); + + if(!pb_decode(&stream, TRON_TRANSFER_CONTRACT_FIELDS, &transfer_contract)){ + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + + default: + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + *amount = transfer_contract->amount; + *to_address = transfer_contract->to_address; + *owner_address = transfer_contract->owner_address; + + return true; +} + + + +STATIC bool tron_get_user_verification() { + uint8_t to_address[TRON_ACCOUNT_ADDRESS_LENGTH] = {0}; + uint8_t owner_address[TRON_ACCOUNT_ADDRESS_LENGTH] = {0}; + int64_t amount = 0; + char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; + // extract raw + if(!extract_contract_info(tron_txn_context->raw_txn, + &amount, + to_address, + owner_address)){ + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + + } + // verify recipient address; + if (!base58_encode_check(to_address, + 1 + 20, + HASHER_SHA2D, + address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return false; + } + + if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { + return false; + } + + // verify recipient amount + uint8_t amount_hex[8]; + char amount_string[40] = {'\0'}, amount_decimal_string[30] = {'\0'}; + char display[100] ={'\0'}; + + dec_to_hex(amount, amount_hex, 8); + if(!convert_byte_array_to_decimal_string( 8, + 0, + amount_string, + amount_decimal_string)){ + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 1); + return false; + } + snprintf(display, + sizeof(display), + UI_TEXT_VERIFY_AMOUNT, + amount_decimal_string, + TRON_LUNIT); + if (!core_confirmation(display, tron_send_error)) { + return false; + } + + set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); + return true; +} + +STATIC bool fetch_seed(tron_query_t *query, uint8_t *seed_out) { + if (!tron_get_query(query, TRON_QUERY_SIGN_TXN_TAG) || + !check_which_request(query, TRON_SIGN_TXN_REQUEST_VERIFY_TAG)) { + return false; + } + + if (!reconstruct_seed(tron_txn_context->init_info.wallet_id, + seed_out, + tron_send_error)) { + memzero(seed_out, sizeof(seed_out)); + return false; + } + set_app_flow_status(TRON_SIGN_TXN_STATUS_SEED_GENERATED); + send_response(TRON_SIGN_TXN_RESPONSE_VERIFY_TAG); + return true; +} + +static bool send_signature(tron_query_t *query, + uint8_t *seed, + tron_sign_txn_signature_response_t *sig) { + HDNode hdnode = {0}; + const size_t depth = tron_txn_context->init_info.derivation_path_count; + const uint32_t *hd_path = tron_txn_context->init_info.derivation_path; + + tron_result_t result = init_tron_result(TRON_RESULT_SIGN_TXN_TAG); + result.sign_txn.which_response = TRON_SIGN_TXN_RESPONSE_SIGNATURE_TAG; + if (!tron_get_query(query, TRON_QUERY_SIGN_TXN_TAG) || + !check_which_request(query, TRON_SIGN_TXN_REQUEST_SIGNATURE_TAG)) { + return false; + } + + // recieve latest blockhash + uint8_t tron_latest_blockhash[TRON_BLOCKHASH_LENGTH] = {0}; + memcpy(tron_latest_blockhash, + query->sign_txn.signature.blockhash, + TRON_BLOCKHASH_LENGTH); + + // update unsigned transaction with latest blockhash + int update_status = tron_update_blockhash_in_byte_array( + tron_txn_context->transaction, tron_latest_blockhash); + if (update_status != SOL_OK) + return false; + + // sign updated transaction + if (!derive_hdnode_from_path(hd_path, depth, ED25519_NAME, seed, &hdnode)) + return false; + + ed25519_sign(tron_txn_context->transaction, + tron_txn_context->init_info.transaction_size, + hdnode.private_key, + hdnode.public_key + 1, + sig->signature); + + memzero(&hdnode, sizeof(hdnode)); + memzero(seed, sizeof(seed)); + + memcpy(&result.sign_txn.signature, + sig, + sizeof(tron_sign_txn_signature_response_t)); + + tron_send_result(&result); + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +void tron_sign_transaction(tron_query_t *query) { + tron_txn_context = + (tron_txn_context_t *)malloc(sizeof(tron_txn_context_t)); + memzero(tron_txn_context, sizeof(tron_txn_context_t)); + tron_sign_txn_signature_response_t sig = {0}; + uint8_t seed[64] = {0}; + + if (tron_handle_initiate_query(query) && + tron_fetch_valid_transaction(query) && tron_get_user_verification() && + fetch_seed(query, seed) && send_signature(query, seed, &sig)) { + delay_scr_init(ui_text_check_cysync, DELAY_TIME); + } + + memzero(seed, sizeof(seed)); + + if (NULL != tron_txn_context->transaction) { + free(tron_txn_context->transaction); + } + if (NULL != tron_txn_context) { + free(tron_txn_context); + tron_txn_context = NULL; + } +} \ No newline at end of file diff --git a/apps/tron_app/tron_txn_helpers.c b/apps/tron_app/tron_txn_helpers.c new file mode 100644 index 00000000..c5c772be --- /dev/null +++ b/apps/tron_app/tron_txn_helpers.c @@ -0,0 +1,119 @@ +/** + * @file tron_txn_helpers.c + * @author Cypherock X1 Team + * @brief Helper implementation for interpreting and signing tron + * transactions + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ +#include "tron_txn_helpers.h" +#include "tron_priv.h" +#include +#include + +#include +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ +int tron_byte_array_to_raw_txn(uint8_t *byte_array, + size_t size, + tron_transaction_raw_t *raw_txn){ + if (byte_array == NULL || raw_txn == NULL) + return 1; + memzero(raw_txn, sizeof(tron_transaction_raw_t)); + + pb_istream_t stream = pb_istream_from_buffer(byte_array, size); + raw_txn = TRON_TRANSACTION_RAW_INIT_ZERO; + + if(!pb_decode(&stream, TRON_TRANSACTION_RAW_FIELDS, &raw_txn)){ + return -1; + } +} + +int tron_validate_unsigned_txn(tron_transaction_raw_t *raw_txn) { + //TODO: + return 0; +} + diff --git a/apps/tron_app/tron_txn_helpers.h b/apps/tron_app/tron_txn_helpers.h new file mode 100644 index 00000000..7bd3cead --- /dev/null +++ b/apps/tron_app/tron_txn_helpers.h @@ -0,0 +1,76 @@ +/** + * @file tron_txn_helpers.h + * @author Cypherock X1 Team + * @brief Helper apis for interpreting and signing tron transactions + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ + +#ifndef TRON_TXN_HELPERS_H +#define TRON_TXN_HELPERS_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include +#include "tron_txn_helpers.h" +#include "tron_priv.h" + +#include "utils.h" + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ +#define TRON_NAME "Tron" +#define TRON_LUNIT "TRX" //To Confirm +#define TRON_PUB_KEY_SIZE 65 +#define TRON_ACCOUNT_ADDRESS_LENGTH 34 + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ +/** + * @brief Convert byte array representation of unsigned transaction to + * solana_unsigned_txn. + * @details + * + * @param [in] byte_array Byte array of unsigned transaction. + * @param [in] byte_array_size Size of byte array. + * @param [out] utxn Pointer to the solana_unsigned_txn + * instance to store the transaction details. + * + * @return Status of conversion + * @retval 0 if successful + * @retval -1 if unsuccessful + * + * @see + * @since v1.0.0 + * + * @note + */ +int tron_byte_array_to_raw_txn(uint8_t *byte_array, + size_t size, + tron_transaction_raw_t *raw_txn); + +/** + * @brief Validate the deserialized unsigned transaction + * + * @param utxn Pointer to the solana_unsigned_txn instance to validate the + * transaction + * @return 0 if validation succeeded + * @return -1 if validation failed + */ +int tron_validate_unsigned_txn(const tron_transaction_raw_t *raw_txn); + + +#endif diff --git a/common/core/app_registry.h b/common/core/app_registry.h index 8bc572fb..cc8b80d7 100644 --- a/common/core/app_registry.h +++ b/common/core/app_registry.h @@ -23,7 +23,7 @@ * MACROS AND DEFINES *****************************************************************************/ -#define REGISTRY_MAX_APPS 18 +#define REGISTRY_MAX_APPS 19 /***************************************************************************** * TYPEDEFS diff --git a/common/core/core_flow_init.c b/common/core/core_flow_init.c index afecb734..2bc719aa 100644 --- a/common/core/core_flow_init.c +++ b/common/core/core_flow_init.c @@ -82,6 +82,7 @@ #include "polygon_app.h" #include "restricted_app.h" #include "solana_main.h" +#include "tron_main.h" /***************************************************************************** * EXTERN VARIABLES @@ -177,4 +178,5 @@ void core_init_app_registry() { registry_add_app(get_avalanche_app_desc()); registry_add_app(get_optimism_app_desc()); registry_add_app(get_arbitrum_app_desc()); + registry_add_app(get_tron_app_desc()); } \ No newline at end of file diff --git a/common/proto-options/tron/get_public_keys.options b/common/proto-options/tron/get_public_keys.options new file mode 100644 index 00000000..8a0d15b5 --- /dev/null +++ b/common/proto-options/tron/get_public_keys.options @@ -0,0 +1,5 @@ +# Options for file common/cypherock-common/proto/tron/get_public_key.proto +tron.GetPublicKeysDerivationPath.path type:FT_STATIC max_count:5 fixed_length:true +tron.GetPublicKeysIntiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true +tron.GetPublicKeysIntiateRequest.derivation_paths type:FT_STATIC max_count:100 fixed_length:true +tron.GetPublicKeysResultResponse.public_keys type:FT_STATIC max_size:65 max_count:10 fixed_length:true diff --git a/common/proto-options/tron/sign_txn.options b/common/proto-options/tron/sign_txn.options new file mode 100644 index 00000000..ca8a3d59 --- /dev/null +++ b/common/proto-options/tron/sign_txn.options @@ -0,0 +1,5 @@ +# Options for file common/cypherock-common/proto/tron/sign_txn.proto +tron.SignTxnInitiateRequest.walletId type:FT_STATIC max_size:32 fixed_length:true +tron.SignTxnInitiateRequest.derivationPath type:FT_STATIC max_count:4 fixed_length:true +tron.SignTxnSignatureResponse.signature type:FT_STATIC max_size:64 fixed_length:true +tron.SignTxnSignatureRequest.blockhash type:FT_STATIC max_size:32 fixed_length:true diff --git a/utilities/cmake/firmware/firmware.cmake b/utilities/cmake/firmware/firmware.cmake index 8a67d969..962e7a23 100644 --- a/utilities/cmake/firmware/firmware.cmake +++ b/utilities/cmake/firmware/firmware.cmake @@ -57,7 +57,8 @@ target_include_directories(${EXECUTABLE} PRIVATE apps/evm_family/arbitrum apps/near_app apps/solana_app - + apps/tron_app + src/ src/menu src/wallet From a7252b262cc50f3815abcfd2e38f180c4af02108 Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Sun, 21 Apr 2024 22:28:06 +0530 Subject: [PATCH 03/22] fix (app): Fixed logical bugs --- apps/tron_app/tron_pub_key.c | 2 +- apps/tron_app/tron_sign_txn.c | 81 +++++++++++------------------------ 2 files changed, 25 insertions(+), 58 deletions(-) diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index a413f83d..ad75d2bb 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -65,7 +65,7 @@ #include "reconstruct_wallet_flow.h" #include "tron_api.h" -//#include "solana_helpers.h" +#include "tron_txn_helpers.h" #include "tron_priv.h" #include "status_api.h" #include "ui_core_confirm.h" diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index ebfba37f..fd656519 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -74,6 +74,9 @@ #include #include #include +#include "hasher.h" +#include +#include "base58.h" /***************************************************************************** * EXTERN VARIABLES @@ -329,16 +332,16 @@ STATIC bool tron_fetch_valid_transaction(tron_query_t *query) { if (0 != tron_byte_array_to_raw_txn( tron_txn_context->transaction, total_size, - &tron_txn_context->raw_txn) || + tron_txn_context->raw_txn) || 0 != - tron_validate_unsigned_txn(&tron_txn_context->raw_txn)) { + tron_validate_unsigned_txn(tron_txn_context->raw_txn)) { return false; } return true; } -STATIC bool extract_contract_info(tron_transaction_raw *raw_txn, +STATIC bool extract_contract_info(tron_transaction_raw_t *raw_txn, int64_t *amount, uint8_t *to_address, uint8_t *owner_address) { @@ -348,14 +351,16 @@ STATIC bool extract_contract_info(tron_transaction_raw *raw_txn, return false; } - tron_transaction_contract contract = raw_txn->contract[0]; // Example for the first contract + tron_transaction_contract_t contract = raw_txn->contract[0]; // Example for the first contract tron_transfer_contract_t transfer_contract = TRON_TRANSFER_CONTRACT_INIT_DEFAULT; - + google_protobuf_any_t any = contract.parameter; + int state = memcmp(any.type_url, "type.googleapis.com/protocol.TransferContract", 64); // TODO: Add switch-cases for more contract types - switch (contract.type) { - case tron_Transaction_Contract_ContractType_TransferContract: - google_protobuf_any_t any = contract.parameter; + switch (state) { + // case protocol_Transaction_Contract_ContractType_TransferContract: + case 0: + { pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); if(!pb_decode(&stream, TRON_TRANSFER_CONTRACT_FIELDS, &transfer_contract)){ @@ -364,15 +369,18 @@ STATIC bool extract_contract_info(tron_transaction_raw *raw_txn, return false; } - default: + amount = &transfer_contract.amount; + to_address = (uint8_t *)transfer_contract.to_address; + owner_address = (uint8_t *)transfer_contract.owner_address; + } + + default: tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, ERROR_DATA_FLOW_INVALID_REQUEST); return false; } - *amount = transfer_contract->amount; - *to_address = transfer_contract->to_address; - *owner_address = transfer_contract->owner_address; + return true; } @@ -417,7 +425,8 @@ STATIC bool tron_get_user_verification() { if(!convert_byte_array_to_decimal_string( 8, 0, amount_string, - amount_decimal_string)){ + amount_decimal_string, + sizeof(amount_decimal_string))){ tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 1); return false; } @@ -451,50 +460,8 @@ STATIC bool fetch_seed(tron_query_t *query, uint8_t *seed_out) { return true; } -static bool send_signature(tron_query_t *query, - uint8_t *seed, - tron_sign_txn_signature_response_t *sig) { - HDNode hdnode = {0}; - const size_t depth = tron_txn_context->init_info.derivation_path_count; - const uint32_t *hd_path = tron_txn_context->init_info.derivation_path; - - tron_result_t result = init_tron_result(TRON_RESULT_SIGN_TXN_TAG); - result.sign_txn.which_response = TRON_SIGN_TXN_RESPONSE_SIGNATURE_TAG; - if (!tron_get_query(query, TRON_QUERY_SIGN_TXN_TAG) || - !check_which_request(query, TRON_SIGN_TXN_REQUEST_SIGNATURE_TAG)) { - return false; - } - - // recieve latest blockhash - uint8_t tron_latest_blockhash[TRON_BLOCKHASH_LENGTH] = {0}; - memcpy(tron_latest_blockhash, - query->sign_txn.signature.blockhash, - TRON_BLOCKHASH_LENGTH); - - // update unsigned transaction with latest blockhash - int update_status = tron_update_blockhash_in_byte_array( - tron_txn_context->transaction, tron_latest_blockhash); - if (update_status != SOL_OK) - return false; - - // sign updated transaction - if (!derive_hdnode_from_path(hd_path, depth, ED25519_NAME, seed, &hdnode)) - return false; - - ed25519_sign(tron_txn_context->transaction, - tron_txn_context->init_info.transaction_size, - hdnode.private_key, - hdnode.public_key + 1, - sig->signature); - - memzero(&hdnode, sizeof(hdnode)); - memzero(seed, sizeof(seed)); - - memcpy(&result.sign_txn.signature, - sig, - sizeof(tron_sign_txn_signature_response_t)); - - tron_send_result(&result); +static bool send_signature() { + return true; } From 746f91f14d3cc2d8a35ee11539597816a6378e07 Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Mon, 22 Apr 2024 03:17:51 +0530 Subject: [PATCH 04/22] fix (app): Compiler errors, successful build --- apps/tron_app/tron_pub_key.c | 2 +- apps/tron_app/tron_sign_txn.c | 81 ++++++++++++++++++---- apps/tron_app/tron_txn_helpers.c | 6 +- common/proto-options/tron/sign_txn.options | 3 +- 4 files changed, 71 insertions(+), 21 deletions(-) diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index ad75d2bb..3a2b46f4 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -439,7 +439,7 @@ void tron_get_pub_keys(tron_query_t *query) { uint8_t initial_address[1 + 20] = {0}; //initial address initial_address[0] = 0x41; uint8_t public_key_digest[32]; - //#define USE_KECCAK 1 + //No iteration in public_keys[i]? keccak_256(public_keys[0], TRON_PUB_KEY_SIZE, public_key_digest); //compare with reference diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index fd656519..45db0721 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -77,6 +77,10 @@ #include "hasher.h" #include #include "base58.h" +#include "secp256k1.h" +#include "ecdsa.h" +#include "coin_utils.h" + /***************************************************************************** * EXTERN VARIABLES @@ -136,7 +140,9 @@ static void send_response(pb_size_t which_response); * type of request. Additionally, the wallet-id is validated for sanity and the * derivation path for the account is also validated. After the validations, * user is prompted about the action for confirmation. The function returns true - * indicating all the validation and user confirmation was a success. + * indicating all the validation and user confirmation was a success. The + * function also duplicates the data from query into the tron_txn_context for + * further processing. * * @param query Constant reference to the decoded query received from the host * @@ -164,7 +170,7 @@ STATIC bool tron_fetch_valid_transaction(tron_query_t *query); /** * @brief Aggregates user consent for the transaction info * @details The function decodes the receiver address along with the - * corresponding transfer value in SOL. + * corresponding transfer value in TRX. * * * @return bool Indicating if the user confirmed the transaction @@ -234,8 +240,10 @@ static bool check_which_request(const tron_query_t *query, static bool validate_request_data(const tron_sign_txn_request_t *request) { bool status = true; - if (!tron_derivation_path_guard(request->initiate.derivation_path, - request->initiate.derivation_path_count)) { + if ( + /*!tron_derivation_path_guard(request->initiate.derivation_path, + request->initiate.derivation_path_count) + */ false) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, ERROR_DATA_FLOW_INVALID_DATA); status = false; @@ -272,6 +280,9 @@ STATIC bool tron_handle_initiate_query(const tron_query_t *query) { if (!core_confirmation(msg, tron_send_error)) { return false; } + memcpy(&tron_txn_context->init_info, + &query->sign_txn.initiate, + sizeof(tron_sign_txn_initiate_request_t)); set_app_flow_status(TRON_SIGN_TXN_STATUS_CONFIRM); send_response(TRON_SIGN_TXN_RESPONSE_CONFIRMATION_TAG); @@ -353,14 +364,13 @@ STATIC bool extract_contract_info(tron_transaction_raw_t *raw_txn, tron_transaction_contract_t contract = raw_txn->contract[0]; // Example for the first contract - tron_transfer_contract_t transfer_contract = TRON_TRANSFER_CONTRACT_INIT_DEFAULT; - google_protobuf_any_t any = contract.parameter; - int state = memcmp(any.type_url, "type.googleapis.com/protocol.TransferContract", 64); // TODO: Add switch-cases for more contract types - switch (state) { - // case protocol_Transaction_Contract_ContractType_TransferContract: - case 0: + switch (contract.type) { + + case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { + tron_transfer_contract_t transfer_contract = TRON_TRANSFER_CONTRACT_INIT_DEFAULT; + google_protobuf_any_t any = contract.parameter; pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); if(!pb_decode(&stream, TRON_TRANSFER_CONTRACT_FIELDS, &transfer_contract)){ @@ -375,13 +385,13 @@ STATIC bool extract_contract_info(tron_transaction_raw_t *raw_txn, } default: + { tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, ERROR_DATA_FLOW_INVALID_REQUEST); return false; - } - - + } + } return true; } @@ -460,11 +470,52 @@ STATIC bool fetch_seed(tron_query_t *query, uint8_t *seed_out) { return true; } -static bool send_signature() { - +static bool send_signature(tron_query_t *query, + uint8_t *seed, + tron_sign_txn_signature_response_t *sig) { + HDNode hdnode = {0}; + const size_t depth = tron_txn_context->init_info.derivation_path_count; + const uint32_t *hd_path = tron_txn_context->init_info.derivation_path; + + tron_result_t result = init_tron_result(TRON_RESULT_SIGN_TXN_TAG); + result.sign_txn.which_response = TRON_SIGN_TXN_RESPONSE_SIGNATURE_TAG; + if (!tron_get_query(query, TRON_QUERY_SIGN_TXN_TAG) || + !check_which_request(query, TRON_SIGN_TXN_REQUEST_SIGNATURE_TAG)) { + return false; + } + + // Hash the raw data using sha256. This gives you the Transaction ID. + uint8_t txid[SHA256_DIGEST_LENGTH] = {0}; + + sha256_Raw(tron_txn_context->transaction, + tron_txn_context->init_info.transaction_size, + txid); + + // sign transaction + if (!derive_hdnode_from_path(hd_path, depth, SECP256K1_NAME, seed, &hdnode)) + return false; + + uint8_t v_value = 0; + ecdsa_sign_digest(&secp256k1, + hdnode.private_key, + txid, + sig->signature, + &v_value, + NULL); + sig->signature[64] = v_value; + + memzero(&hdnode, sizeof(hdnode)); + memzero(seed, sizeof(seed)); + + memcpy(&result.sign_txn.signature, + sig, + sizeof(tron_sign_txn_signature_response_t)); + + tron_send_result(&result); return true; } + /***************************************************************************** * GLOBAL FUNCTIONS *****************************************************************************/ diff --git a/apps/tron_app/tron_txn_helpers.c b/apps/tron_app/tron_txn_helpers.c index c5c772be..ab19df98 100644 --- a/apps/tron_app/tron_txn_helpers.c +++ b/apps/tron_app/tron_txn_helpers.c @@ -105,14 +105,14 @@ int tron_byte_array_to_raw_txn(uint8_t *byte_array, memzero(raw_txn, sizeof(tron_transaction_raw_t)); pb_istream_t stream = pb_istream_from_buffer(byte_array, size); - raw_txn = TRON_TRANSACTION_RAW_INIT_ZERO; + //*raw_txn = TRON_TRANSACTION_RAW_INIT_ZERO; - if(!pb_decode(&stream, TRON_TRANSACTION_RAW_FIELDS, &raw_txn)){ + if(!pb_decode(&stream, TRON_TRANSACTION_RAW_FIELDS, raw_txn)){ return -1; } } -int tron_validate_unsigned_txn(tron_transaction_raw_t *raw_txn) { +int tron_validate_unsigned_txn(const tron_transaction_raw_t *raw_txn) { //TODO: return 0; } diff --git a/common/proto-options/tron/sign_txn.options b/common/proto-options/tron/sign_txn.options index ca8a3d59..4c5123eb 100644 --- a/common/proto-options/tron/sign_txn.options +++ b/common/proto-options/tron/sign_txn.options @@ -1,5 +1,4 @@ # Options for file common/cypherock-common/proto/tron/sign_txn.proto tron.SignTxnInitiateRequest.walletId type:FT_STATIC max_size:32 fixed_length:true tron.SignTxnInitiateRequest.derivationPath type:FT_STATIC max_count:4 fixed_length:true -tron.SignTxnSignatureResponse.signature type:FT_STATIC max_size:64 fixed_length:true -tron.SignTxnSignatureRequest.blockhash type:FT_STATIC max_size:32 fixed_length:true +tron.SignTxnSignatureResponse.signature type:FT_STATIC max_size:65 fixed_length:true \ No newline at end of file From 1bdb57381afe591355bdce67579210aefdb0fac4 Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Tue, 23 Apr 2024 20:15:53 +0530 Subject: [PATCH 05/22] feat (app): Gen pubkey and sign txn tested --- apps/tron_app/tron_sign_txn.c | 27 +++++++++++++++------------ apps/tron_app/tron_txn_helpers.c | 2 ++ apps/tron_app/tron_txn_helpers.h | 1 + 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index 45db0721..00bc5752 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -339,11 +339,12 @@ STATIC bool tron_fetch_valid_transaction(tron_query_t *query) { return false; } + tron_txn_context->raw_txn = (tron_transaction_raw_t *)malloc(sizeof(tron_transaction_raw_t)); // decode and verify the received transaction if (0 != tron_byte_array_to_raw_txn( tron_txn_context->transaction, total_size, - tron_txn_context->raw_txn) || + tron_txn_context->raw_txn) || 0 != tron_validate_unsigned_txn(tron_txn_context->raw_txn)) { return false; @@ -368,7 +369,7 @@ STATIC bool extract_contract_info(tron_transaction_raw_t *raw_txn, switch (contract.type) { case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: - { + { tron_transfer_contract_t transfer_contract = TRON_TRANSFER_CONTRACT_INIT_DEFAULT; google_protobuf_any_t any = contract.parameter; pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); @@ -377,29 +378,31 @@ STATIC bool extract_contract_info(tron_transaction_raw_t *raw_txn, tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, ERROR_DATA_FLOW_DECODING_FAILED); return false; + } - amount = &transfer_contract.amount; - to_address = (uint8_t *)transfer_contract.to_address; - owner_address = (uint8_t *)transfer_contract.owner_address; + memcpy(amount, &transfer_contract.amount, sizeof(int64_t)); + memcpy(to_address, (uint8_t *)transfer_contract.to_address, TRON_INITIAL_ADDRESS_LENGTH); + memcpy(owner_address, (uint8_t *)transfer_contract.owner_address, TRON_INITIAL_ADDRESS_LENGTH); + break; } default: - { + { tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, ERROR_DATA_FLOW_INVALID_REQUEST); return false; } } - return true; + return true; } STATIC bool tron_get_user_verification() { - uint8_t to_address[TRON_ACCOUNT_ADDRESS_LENGTH] = {0}; - uint8_t owner_address[TRON_ACCOUNT_ADDRESS_LENGTH] = {0}; + uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; + uint8_t owner_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; int64_t amount = 0; char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; // extract raw @@ -454,8 +457,7 @@ STATIC bool tron_get_user_verification() { } STATIC bool fetch_seed(tron_query_t *query, uint8_t *seed_out) { - if (!tron_get_query(query, TRON_QUERY_SIGN_TXN_TAG) || - !check_which_request(query, TRON_SIGN_TXN_REQUEST_VERIFY_TAG)) { + if (!tron_get_query(query, TRON_QUERY_SIGN_TXN_TAG)) { return false; } @@ -465,8 +467,8 @@ STATIC bool fetch_seed(tron_query_t *query, uint8_t *seed_out) { memzero(seed_out, sizeof(seed_out)); return false; } + set_app_flow_status(TRON_SIGN_TXN_STATUS_SEED_GENERATED); - send_response(TRON_SIGN_TXN_RESPONSE_VERIFY_TAG); return true; } @@ -513,6 +515,7 @@ static bool send_signature(tron_query_t *query, tron_send_result(&result); return true; + } diff --git a/apps/tron_app/tron_txn_helpers.c b/apps/tron_app/tron_txn_helpers.c index ab19df98..a32dd222 100644 --- a/apps/tron_app/tron_txn_helpers.c +++ b/apps/tron_app/tron_txn_helpers.c @@ -110,6 +110,8 @@ int tron_byte_array_to_raw_txn(uint8_t *byte_array, if(!pb_decode(&stream, TRON_TRANSACTION_RAW_FIELDS, raw_txn)){ return -1; } + + return 0; } int tron_validate_unsigned_txn(const tron_transaction_raw_t *raw_txn) { diff --git a/apps/tron_app/tron_txn_helpers.h b/apps/tron_app/tron_txn_helpers.h index 7bd3cead..5fdf604c 100644 --- a/apps/tron_app/tron_txn_helpers.h +++ b/apps/tron_app/tron_txn_helpers.h @@ -27,6 +27,7 @@ #define TRON_NAME "Tron" #define TRON_LUNIT "TRX" //To Confirm #define TRON_PUB_KEY_SIZE 65 +#define TRON_INITIAL_ADDRESS_LENGTH 21 #define TRON_ACCOUNT_ADDRESS_LENGTH 34 /***************************************************************************** From 97a14210f88266ea869dc4779188436e400fa880 Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Wed, 24 Apr 2024 16:07:05 +0530 Subject: [PATCH 06/22] fix (app): Minor bug, temp fix --- apps/tron_app/tron_priv.h | 4 +- apps/tron_app/tron_sign_txn.c | 194 +++++++++++++++------------------- 2 files changed, 90 insertions(+), 108 deletions(-) diff --git a/apps/tron_app/tron_priv.h b/apps/tron_app/tron_priv.h index 7b43e2db..a9584ffd 100644 --- a/apps/tron_app/tron_priv.h +++ b/apps/tron_app/tron_priv.h @@ -15,10 +15,11 @@ * INCLUDES *****************************************************************************/ +#include + #include "events.h" #include "tron_api.h" #include "tron_context.h" -#include /***************************************************************************** * MACROS AND DEFINES @@ -69,4 +70,3 @@ void tron_get_pub_keys(tron_query_t *query); void tron_sign_transaction(tron_query_t *query); #endif /* TRON_PRIV_H */ - diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index 00bc5752..846852f4 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -60,27 +60,27 @@ * INCLUDES *****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "base58.h" +#include "coin_utils.h" +#include "curves.h" +#include "ecdsa.h" +#include "hasher.h" #include "reconstruct_wallet_flow.h" -#include "tron_api.h" +#include "secp256k1.h" #include "sha2.h" -#include "tron_priv.h" #include "status_api.h" +#include "tron_api.h" +#include "tron_priv.h" #include "ui_core_confirm.h" #include "ui_screens.h" #include "wallet_list.h" -#include "curves.h" -#include -#include -#include -#include -#include -#include "hasher.h" -#include -#include "base58.h" -#include "secp256k1.h" -#include "ecdsa.h" -#include "coin_utils.h" - /***************************************************************************** * EXTERN VARIABLES @@ -230,7 +230,7 @@ static bool check_which_request(const tron_query_t *query, pb_size_t which_request) { if (which_request != query->sign_txn.which_request) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_REQUEST); + ERROR_DATA_FLOW_INVALID_REQUEST); return false; } @@ -241,11 +241,12 @@ static bool validate_request_data(const tron_sign_txn_request_t *request) { bool status = true; if ( - /*!tron_derivation_path_guard(request->initiate.derivation_path, - request->initiate.derivation_path_count) - */ false) { + /*!tron_derivation_path_guard(request->initiate.derivation_path, + request->initiate.derivation_path_count) + */ + false) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); + ERROR_DATA_FLOW_INVALID_DATA); status = false; } @@ -312,15 +313,14 @@ STATIC bool tron_fetch_valid_transaction(tron_query_t *query) { payload->chunk_index >= payload->total_chunks || size + payload->chunk.size > total_size) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); + ERROR_DATA_FLOW_INVALID_DATA); return false; } memcpy(&tron_txn_context->transaction[size], chunk->bytes, chunk->size); size += chunk->size; // Send chunk ack to host - response.sign_txn.which_response = - TRON_SIGN_TXN_RESPONSE_DATA_ACCEPTED_TAG; + response.sign_txn.which_response = TRON_SIGN_TXN_RESPONSE_DATA_ACCEPTED_TAG; response.sign_txn.data_accepted.has_chunk_ack = true; response.sign_txn.data_accepted.chunk_ack.chunk_index = payload->chunk_index; @@ -335,90 +335,87 @@ STATIC bool tron_fetch_valid_transaction(tron_query_t *query) { // make sure all chunks were received if (size != total_size) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); + ERROR_DATA_FLOW_INVALID_DATA); return false; } - tron_txn_context->raw_txn = (tron_transaction_raw_t *)malloc(sizeof(tron_transaction_raw_t)); + tron_txn_context->raw_txn = + (tron_transaction_raw_t *)malloc(sizeof(tron_transaction_raw_t)); // decode and verify the received transaction - if (0 != tron_byte_array_to_raw_txn( - tron_txn_context->transaction, - total_size, - tron_txn_context->raw_txn) || - 0 != - tron_validate_unsigned_txn(tron_txn_context->raw_txn)) { + if (0 != tron_byte_array_to_raw_txn(tron_txn_context->transaction, + total_size, + tron_txn_context->raw_txn) || + 0 != tron_validate_unsigned_txn(tron_txn_context->raw_txn)) { return false; } return true; } -STATIC bool extract_contract_info(tron_transaction_raw_t *raw_txn, - int64_t *amount, - uint8_t *to_address, +STATIC bool extract_contract_info(tron_transaction_raw_t *raw_txn, + int64_t *amount, + uint8_t *to_address, uint8_t *owner_address) { - if (!(raw_txn->contract_count > 0)){ - tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); - return false; - } - - tron_transaction_contract_t contract = raw_txn->contract[0]; // Example for the first contract - - // TODO: Add switch-cases for more contract types - switch (contract.type) { - - case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: - { - tron_transfer_contract_t transfer_contract = TRON_TRANSFER_CONTRACT_INIT_DEFAULT; - google_protobuf_any_t any = contract.parameter; - pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); - - if(!pb_decode(&stream, TRON_TRANSFER_CONTRACT_FIELDS, &transfer_contract)){ - tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); - return false; - - } - - memcpy(amount, &transfer_contract.amount, sizeof(int64_t)); - memcpy(to_address, (uint8_t *)transfer_contract.to_address, TRON_INITIAL_ADDRESS_LENGTH); - memcpy(owner_address, (uint8_t *)transfer_contract.owner_address, TRON_INITIAL_ADDRESS_LENGTH); - break; - } + if (!(raw_txn->contract_count > 0)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return false; + } - default: - { - tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, - ERROR_DATA_FLOW_INVALID_REQUEST); - return false; + tron_transaction_contract_t contract = + raw_txn->contract[0]; // Example for the first contract + + // TODO: Add switch-cases for more contract types + switch (contract.type) { + case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { + tron_transfer_contract_t transfer_contract = + TRON_TRANSFER_CONTRACT_INIT_DEFAULT; + google_protobuf_any_t any = contract.parameter; + pb_istream_t stream = + pb_istream_from_buffer(any.value.bytes, any.value.size); + + if (!pb_decode( + &stream, TRON_TRANSFER_CONTRACT_FIELDS, &transfer_contract)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; } + memcpy(amount, &transfer_contract.amount, sizeof(int64_t)); + memcpy(to_address, + (uint8_t *)transfer_contract.to_address, + TRON_INITIAL_ADDRESS_LENGTH); + memcpy(owner_address, + (uint8_t *)transfer_contract.owner_address, + TRON_INITIAL_ADDRESS_LENGTH); + break; + } + + default: { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; } - return true; + } + return true; } - - STATIC bool tron_get_user_verification() { uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; uint8_t owner_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; int64_t amount = 0; char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; // extract raw - if(!extract_contract_info(tron_txn_context->raw_txn, - &amount, - to_address, - owner_address)){ - tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); + if (!extract_contract_info( + tron_txn_context->raw_txn, &amount, to_address, owner_address)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); return false; - } // verify recipient address; if (!base58_encode_check(to_address, - 1 + 20, - HASHER_SHA2D, + 1 + 20, + HASHER_SHA2D, address, TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); @@ -430,24 +427,17 @@ STATIC bool tron_get_user_verification() { } // verify recipient amount - uint8_t amount_hex[8]; - char amount_string[40] = {'\0'}, amount_decimal_string[30] = {'\0'}; - char display[100] ={'\0'}; - - dec_to_hex(amount, amount_hex, 8); - if(!convert_byte_array_to_decimal_string( 8, - 0, - amount_string, - amount_decimal_string, - sizeof(amount_decimal_string))){ - tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 1); - return false; - } + char amount_decimal_string[30] = {'\0'}; + char display[100] = {'\0'}; + + sprintf(display, "%lli", amount); + /* snprintf(display, sizeof(display), UI_TEXT_VERIFY_AMOUNT, amount_decimal_string, TRON_LUNIT); + */ if (!core_confirmation(display, tron_send_error)) { return false; } @@ -461,9 +451,8 @@ STATIC bool fetch_seed(tron_query_t *query, uint8_t *seed_out) { return false; } - if (!reconstruct_seed(tron_txn_context->init_info.wallet_id, - seed_out, - tron_send_error)) { + if (!reconstruct_seed( + tron_txn_context->init_info.wallet_id, seed_out, tron_send_error)) { memzero(seed_out, sizeof(seed_out)); return false; } @@ -498,12 +487,8 @@ static bool send_signature(tron_query_t *query, return false; uint8_t v_value = 0; - ecdsa_sign_digest(&secp256k1, - hdnode.private_key, - txid, - sig->signature, - &v_value, - NULL); + ecdsa_sign_digest( + &secp256k1, hdnode.private_key, txid, sig->signature, &v_value, NULL); sig->signature[64] = v_value; memzero(&hdnode, sizeof(hdnode)); @@ -515,17 +500,14 @@ static bool send_signature(tron_query_t *query, tron_send_result(&result); return true; - } - /***************************************************************************** * GLOBAL FUNCTIONS *****************************************************************************/ void tron_sign_transaction(tron_query_t *query) { - tron_txn_context = - (tron_txn_context_t *)malloc(sizeof(tron_txn_context_t)); + tron_txn_context = (tron_txn_context_t *)malloc(sizeof(tron_txn_context_t)); memzero(tron_txn_context, sizeof(tron_txn_context_t)); tron_sign_txn_signature_response_t sig = {0}; uint8_t seed[64] = {0}; From 5ae54447292614500e75406f8c175cf45769fc0f Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Wed, 24 Apr 2024 17:00:13 +0530 Subject: [PATCH 07/22] fix (app): Formatting fixes --- apps/tron_app/tron_api.c | 16 ++++---- apps/tron_app/tron_api.h | 12 +++--- apps/tron_app/tron_main.c | 20 +++++----- apps/tron_app/tron_pub_key.c | 64 +++++++++++++++++--------------- apps/tron_app/tron_sign_txn.c | 2 +- apps/tron_app/tron_txn_helpers.c | 32 ++++++++-------- apps/tron_app/tron_txn_helpers.h | 7 ++-- 7 files changed, 79 insertions(+), 74 deletions(-) diff --git a/apps/tron_app/tron_api.c b/apps/tron_app/tron_api.c index ff084747..61e6334a 100644 --- a/apps/tron_app/tron_api.c +++ b/apps/tron_app/tron_api.c @@ -102,11 +102,11 @@ * GLOBAL FUNCTIONS *****************************************************************************/ bool decode_tron_query(const uint8_t *data, - uint16_t data_size, - tron_query_t *query_out) { + uint16_t data_size, + tron_query_t *query_out) { if (NULL == data || NULL == query_out || 0 == data_size) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); + ERROR_DATA_FLOW_DECODING_FAILED); return false; } @@ -122,16 +122,16 @@ bool decode_tron_query(const uint8_t *data, /* Send error to host if status is false*/ if (false == status) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); + ERROR_DATA_FLOW_DECODING_FAILED); } return status; } bool encode_tron_result(const tron_result_t *result, - uint8_t *buffer, - uint16_t max_buffer_len, - size_t *bytes_written_out) { + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out) { if (NULL == result || NULL == buffer || NULL == bytes_written_out) return false; @@ -151,7 +151,7 @@ bool encode_tron_result(const tron_result_t *result, bool check_tron_query(const tron_query_t *query, pb_size_t exp_query_tag) { if ((NULL == query) || (exp_query_tag != query->which_request)) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_QUERY); + ERROR_DATA_FLOW_INVALID_QUERY); return false; } return true; diff --git a/apps/tron_app/tron_api.h b/apps/tron_app/tron_api.h index 16c88e27..240b95dc 100644 --- a/apps/tron_app/tron_api.h +++ b/apps/tron_app/tron_api.h @@ -14,8 +14,8 @@ * INCLUDES *****************************************************************************/ -#include #include +#include /***************************************************************************** * MACROS AND DEFINES @@ -42,8 +42,8 @@ * @return bool True if decoding was successful, else false */ bool decode_tron_query(const uint8_t *data, - uint16_t data_size, - tron_query_t *query_out); + uint16_t data_size, + tron_query_t *query_out); /** * @brief Encodes the TRON result with `TRON_RESULT_FIELDS` to byte-stream @@ -56,9 +56,9 @@ bool decode_tron_query(const uint8_t *data, * @return bool True if decoding was successful, else false */ bool encode_tron_result(const tron_result_t *result, - uint8_t *buffer, - uint16_t max_buffer_len, - size_t *bytes_written_out); + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out); /** * @brief This API checks if the `which_request` field of the query of type diff --git a/apps/tron_app/tron_main.c b/apps/tron_app/tron_main.c index 9222948f..ed557a99 100644 --- a/apps/tron_app/tron_main.c +++ b/apps/tron_app/tron_main.c @@ -62,9 +62,9 @@ #include "tron_main.h" +#include "status_api.h" #include "tron_api.h" #include "tron_priv.h" -#include "status_api.h" /***************************************************************************** * EXTERN VARIABLES @@ -98,14 +98,14 @@ void tron_main(usb_event_t usb_evt, const void *app_config); * STATIC VARIABLES *****************************************************************************/ static const cy_app_desc_t tron_app_desc = {.id = 18, - .version = - { - .major = 1, - .minor = 0, - .patch = 0, - }, - .app = tron_main, - .app_config = NULL}; + .version = + { + .major = 1, + .minor = 0, + .patch = 0, + }, + .app = tron_main, + .app_config = NULL}; /***************************************************************************** * STATIC FUNCTIONS @@ -135,7 +135,7 @@ void tron_main(usb_event_t usb_evt, const void *app_config) { default: { /* In case we ever encounter invalid query, convey to the host app */ tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_QUERY); + ERROR_DATA_FLOW_INVALID_QUERY); } break; } diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index 3a2b46f4..a4fe5738 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -63,19 +63,19 @@ #include #include +#include "base58.h" +#include "bip32.h" +#include "coin_utils.h" +#include "curves.h" #include "reconstruct_wallet_flow.h" +#include "sha3.h" +#include "status_api.h" #include "tron_api.h" -#include "tron_txn_helpers.h" #include "tron_priv.h" -#include "status_api.h" +#include "tron_txn_helpers.h" #include "ui_core_confirm.h" #include "ui_screens.h" #include "wallet_list.h" -#include "sha3.h" -#include "base58.h" -#include "bip32.h" -#include "coin_utils.h" -#include "curves.h" /***************************************************************************** * EXTERN VARIABLES *****************************************************************************/ @@ -222,7 +222,7 @@ STATIC bool check_which_request(const tron_query_t *query, pb_size_t which_request) { if (which_request != query->get_public_keys.which_request) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_REQUEST); + ERROR_DATA_FLOW_INVALID_REQUEST); return false; } @@ -236,7 +236,7 @@ STATIC bool validate_request_data(tron_get_public_keys_request_t *request, if (0 == request->initiate.derivation_paths_count) { // request does not have any derivation paths, invalid request tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); + ERROR_DATA_FLOW_INVALID_DATA); status = false; } @@ -245,7 +245,7 @@ STATIC bool validate_request_data(tron_get_public_keys_request_t *request, // `TRON_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG` request contains more // than one derivation path which is not expected tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); + ERROR_DATA_FLOW_INVALID_DATA); status = false; } @@ -253,7 +253,7 @@ STATIC bool validate_request_data(tron_get_public_keys_request_t *request, pb_size_t count = request->initiate.derivation_paths_count; for (pb_size_t index = 0; index < count; index++) { path = &request->initiate.derivation_paths[index]; - //TODO: + // TODO: /* if (!tron_derivation_path_guard(path->path, path->path_count)) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, @@ -273,7 +273,8 @@ STATIC bool get_public_key(const uint8_t *seed, uint8_t *public_key) { HDNode node = {0}; - if (!derive_hdnode_from_path(path, path_length, SECP256K1_NAME, seed, &node)) { + if (!derive_hdnode_from_path( + path, path_length, SECP256K1_NAME, seed, &node)) { // send unknown error; unknown failure reason tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 1); memzero(&node, sizeof(HDNode)); @@ -289,10 +290,11 @@ STATIC bool get_public_key(const uint8_t *seed, return true; } -static bool fill_public_keys(const tron_get_public_keys_derivation_path_t *paths, - const uint8_t *seed, - uint8_t public_keys[][TRON_PUB_KEY_SIZE], - pb_size_t count) { +static bool fill_public_keys( + const tron_get_public_keys_derivation_path_t *paths, + const uint8_t *seed, + uint8_t public_keys[][TRON_PUB_KEY_SIZE], + pb_size_t count) { for (pb_size_t index = 0; index < count; index++) { const tron_get_public_keys_derivation_path_t *path = &paths[index]; if (!get_public_key( @@ -347,8 +349,7 @@ static bool get_user_consent(const pb_size_t which_request, char msg[100] = ""; if (TRON_QUERY_GET_PUBLIC_KEYS_TAG == which_request) { - snprintf( - msg, sizeof(msg), UI_TEXT_ADD_ACCOUNT_PROMPT, "Tron", wallet_name); + snprintf(msg, sizeof(msg), UI_TEXT_ADD_ACCOUNT_PROMPT, "Tron", wallet_name); } else { snprintf(msg, sizeof(msg), @@ -392,8 +393,7 @@ void tron_get_pub_keys(tron_query_t *query) { sizeof(tron_get_public_keys_derivation_path_t)] [TRON_PUB_KEY_SIZE] = {0}; - if (!check_which_request(query, - TRON_GET_PUBLIC_KEYS_REQUEST_INITIATE_TAG) || + if (!check_which_request(query, TRON_GET_PUBLIC_KEYS_REQUEST_INITIATE_TAG) || !validate_request_data(&query->get_public_keys, which_request) || !get_wallet_name_by_id(query->get_public_keys.initiate.wallet_id, (uint8_t *)wallet_name, @@ -436,22 +436,28 @@ void tron_get_pub_keys(tron_query_t *query) { char main_address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = ""; // gen Address: - uint8_t initial_address[1 + 20] = {0}; //initial address + uint8_t initial_address[1 + 20] = {0}; // initial address initial_address[0] = 0x41; uint8_t public_key_digest[32]; - - //No iteration in public_keys[i]? - keccak_256(public_keys[0], TRON_PUB_KEY_SIZE, public_key_digest); //compare with reference + + // No iteration in public_keys[i]? + keccak_256(public_keys[0], + TRON_PUB_KEY_SIZE, + public_key_digest); // compare with reference // extract last 20 bytes // address = 41||sha3[12,32) - for(int i = 12;i < 32;i++){ - initial_address[i - 12 + 1] = public_key_digest[i]; + for (int i = 12; i < 32; i++) { + initial_address[i - 12 + 1] = public_key_digest[i]; } - if(!base58_encode_check(initial_address, 1 + 20, HASHER_SHA2D, main_address, TRON_ACCOUNT_ADDRESS_LENGTH + 1)){ - tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); - return; + if (!base58_encode_check(initial_address, + 1 + 20, + HASHER_SHA2D, + main_address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return; } if (!core_scroll_page(ui_text_receive_on, main_address, tron_send_error)) { diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index 846852f4..27bc36a9 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -427,7 +427,7 @@ STATIC bool tron_get_user_verification() { } // verify recipient amount - char amount_decimal_string[30] = {'\0'}; + // char amount_decimal_string[30] = {'\0'}; char display[100] = {'\0'}; sprintf(display, "%lli", amount); diff --git a/apps/tron_app/tron_txn_helpers.c b/apps/tron_app/tron_txn_helpers.c index a32dd222..8a70b34b 100644 --- a/apps/tron_app/tron_txn_helpers.c +++ b/apps/tron_app/tron_txn_helpers.c @@ -61,11 +61,12 @@ * INCLUDES *****************************************************************************/ #include "tron_txn_helpers.h" -#include "tron_priv.h" -#include -#include +#include #include +#include + +#include "tron_priv.h" /***************************************************************************** * EXTERN VARIABLES *****************************************************************************/ @@ -99,23 +100,22 @@ *****************************************************************************/ int tron_byte_array_to_raw_txn(uint8_t *byte_array, size_t size, - tron_transaction_raw_t *raw_txn){ - if (byte_array == NULL || raw_txn == NULL) - return 1; - memzero(raw_txn, sizeof(tron_transaction_raw_t)); + tron_transaction_raw_t *raw_txn) { + if (byte_array == NULL || raw_txn == NULL) + return 1; + memzero(raw_txn, sizeof(tron_transaction_raw_t)); - pb_istream_t stream = pb_istream_from_buffer(byte_array, size); - //*raw_txn = TRON_TRANSACTION_RAW_INIT_ZERO; + pb_istream_t stream = pb_istream_from_buffer(byte_array, size); + //*raw_txn = TRON_TRANSACTION_RAW_INIT_ZERO; - if(!pb_decode(&stream, TRON_TRANSACTION_RAW_FIELDS, raw_txn)){ - return -1; - } + if (!pb_decode(&stream, TRON_TRANSACTION_RAW_FIELDS, raw_txn)) { + return -1; + } - return 0; + return 0; } int tron_validate_unsigned_txn(const tron_transaction_raw_t *raw_txn) { - //TODO: - return 0; + // TODO: + return 0; } - diff --git a/apps/tron_app/tron_txn_helpers.h b/apps/tron_app/tron_txn_helpers.h index 5fdf604c..05e82d20 100644 --- a/apps/tron_app/tron_txn_helpers.h +++ b/apps/tron_app/tron_txn_helpers.h @@ -16,16 +16,16 @@ #include #include -#include "tron_txn_helpers.h" -#include "tron_priv.h" +#include "tron_priv.h" +#include "tron_txn_helpers.h" #include "utils.h" /***************************************************************************** * MACROS AND DEFINES *****************************************************************************/ #define TRON_NAME "Tron" -#define TRON_LUNIT "TRX" //To Confirm +#define TRON_LUNIT "TRX" // To Confirm #define TRON_PUB_KEY_SIZE 65 #define TRON_INITIAL_ADDRESS_LENGTH 21 #define TRON_ACCOUNT_ADDRESS_LENGTH 34 @@ -73,5 +73,4 @@ int tron_byte_array_to_raw_txn(uint8_t *byte_array, */ int tron_validate_unsigned_txn(const tron_transaction_raw_t *raw_txn); - #endif From 11f4aab943bda68ef2455700287859ed378d99dd Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Tue, 30 Apr 2024 14:47:57 +0530 Subject: [PATCH 08/22] feat (app): Add derivation path tron feat (app): Add derivation path tron --- apps/tron_app/tron_helpers.c | 123 ++++++++++++++++++ apps/tron_app/tron_helpers.h | 57 ++++++++ apps/tron_app/tron_priv.h | 2 +- apps/tron_app/tron_pub_key.c | 40 +++--- apps/tron_app/tron_sign_txn.c | 11 +- apps/tron_app/tron_txn_helpers.c | 1 - apps/tron_app/tron_txn_helpers.h | 11 +- common/cypherock-common | 2 +- .../tron/get_public_keys.options | 2 +- utilities/cmake/simulator/simulator.cmake | 1 + 10 files changed, 215 insertions(+), 35 deletions(-) create mode 100644 apps/tron_app/tron_helpers.c create mode 100644 apps/tron_app/tron_helpers.h diff --git a/apps/tron_app/tron_helpers.c b/apps/tron_app/tron_helpers.c new file mode 100644 index 00000000..bee9ffc7 --- /dev/null +++ b/apps/tron_app/tron_helpers.c @@ -0,0 +1,123 @@ +/** + * @file tron_helpers.c + * @author Cypherock X1 Team + * @brief Utilities specific to Tron chains + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "tron_helpers.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +bool tron_derivation_path_guard(const uint32_t *path, uint8_t levels) { + bool status = false; + if (levels < 3) + return status; + + uint32_t purpose = path[0], coin = path[1], account = path[2]; + + switch (levels) { + case 3: { // m/44'/195'/0' + status = (purpose == TRON_PURPOSE_INDEX && coin == TRON_COIN_INDEX && + account == TRON_ACCOUNT_INDEX); + } break; + + case 5: { // m/44'/195'/0'/0/i + uint32_t change = path[3]; + uint32_t address = path[4]; + status = (purpose == TRON_PURPOSE_INDEX && coin == TRON_COIN_INDEX && + account == TRON_ACCOUNT_INDEX && change == TRON_CHANGE_INDEX && + is_non_hardened(address)); + } break; + + default: + break; + } + + return status; +} diff --git a/apps/tron_app/tron_helpers.h b/apps/tron_app/tron_helpers.h new file mode 100644 index 00000000..c95df038 --- /dev/null +++ b/apps/tron_app/tron_helpers.h @@ -0,0 +1,57 @@ +/** + * @file tron_helpers.h + * @author Cypherock X1 Team + * @brief Utilities api definitions for TRON chains + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef TRON_HELPERS_H +#define TRON_HELPERS_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include +#include + +#include "coin_utils.h" + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ +#define TRON_PURPOSE_INDEX 0x8000002C +#define TRON_COIN_INDEX 0x80000405 +#define TRON_ACCOUNT_INDEX 0x80000000 +#define TRON_CHANGE_INDEX 0x0 +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Verifies the derivation path. + * @details The function supports checking derivation paths for HD wallets + * Types of derivations: + * address: m/44'/195'/0'/0/i + * address: m/44'/195'/0' + * + * @param[in] path The derivation path as an uint32 array + * @param[in] depth The number of levels in the derivation path + * + * @return bool Indicates if the provided derivation path is valid + * @retval true if the derivation path is valid + * @retval false otherwise + */ +bool tron_derivation_path_guard(const uint32_t *path, uint8_t levels); + +#endif // TRON_HELPERS_H \ No newline at end of file diff --git a/apps/tron_app/tron_priv.h b/apps/tron_app/tron_priv.h index a9584ffd..16248d81 100644 --- a/apps/tron_app/tron_priv.h +++ b/apps/tron_app/tron_priv.h @@ -31,7 +31,7 @@ typedef struct { /** * The structure holds the wallet information of the transaction. - * @note Populated by solana_handle_initiate_query() + * @note Populated by tron_handle_initiate_query() */ tron_sign_txn_initiate_request_t init_info; diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index a4fe5738..6f92049d 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -162,7 +162,7 @@ STATIC bool get_public_key(const uint8_t *seed, STATIC bool fill_public_keys( const tron_get_public_keys_derivation_path_t *paths, const uint8_t *seed, - uint8_t public_keys[][TRON_PUB_KEY_SIZE], + uint8_t public_keys[][TRON_PUB_KEY_SIZE_PLUS_ONE], pb_size_t count); /** @@ -186,11 +186,12 @@ STATIC bool fill_public_keys( * @retval false If the export was interrupted by a P0 event or an invalid query * was received from the host app. */ -static bool send_public_keys(tron_query_t *query, - const uint8_t public_keys[][TRON_PUB_KEY_SIZE], - const size_t count, - const pb_size_t which_request, - const pb_size_t which_response); +static bool send_public_keys( + tron_query_t *query, + const uint8_t public_keys[][TRON_PUB_KEY_SIZE_PLUS_ONE], + const size_t count, + const pb_size_t which_request, + const pb_size_t which_response); /** * @brief Helper function to take user consent before exporting public keys to * the host. Uses an appropriate message template based on the query request @@ -293,7 +294,7 @@ STATIC bool get_public_key(const uint8_t *seed, static bool fill_public_keys( const tron_get_public_keys_derivation_path_t *paths, const uint8_t *seed, - uint8_t public_keys[][TRON_PUB_KEY_SIZE], + uint8_t public_keys[][TRON_PUB_KEY_SIZE_PLUS_ONE], pb_size_t count) { for (pb_size_t index = 0; index < count; index++) { const tron_get_public_keys_derivation_path_t *path = &paths[index]; @@ -305,16 +306,18 @@ static bool fill_public_keys( return true; } -static bool send_public_keys(tron_query_t *query, - const uint8_t public_keys[][TRON_PUB_KEY_SIZE], - const size_t count, - const pb_size_t which_request, - const pb_size_t which_response) { +static bool send_public_keys( + tron_query_t *query, + const uint8_t public_keys[][TRON_PUB_KEY_SIZE_PLUS_ONE], + const size_t count, + const pb_size_t which_request, + const pb_size_t which_response) { tron_result_t response = init_tron_result(which_response); tron_get_public_keys_result_response_t *result = &response.get_public_keys.result; static const size_t batch_limit = - sizeof(response.get_public_keys.result.public_keys) / TRON_PUB_KEY_SIZE; + sizeof(response.get_public_keys.result.public_keys) / + TRON_PUB_KEY_SIZE_PLUS_ONE; size_t remaining = count; response.get_public_keys.which_response = @@ -327,7 +330,7 @@ static bool send_public_keys(tron_query_t *query, memcpy(response.get_public_keys.result.public_keys, public_keys[count - remaining], - batch_size * TRON_PUB_KEY_SIZE); + batch_size * TRON_PUB_KEY_SIZE_PLUS_ONE); tron_send_result(&response); remaining -= batch_size; @@ -391,7 +394,7 @@ void tron_get_pub_keys(tron_query_t *query) { uint8_t public_keys[sizeof(init_req->derivation_paths) / sizeof(tron_get_public_keys_derivation_path_t)] - [TRON_PUB_KEY_SIZE] = {0}; + [TRON_PUB_KEY_SIZE_PLUS_ONE] = {0}; if (!check_which_request(query, TRON_GET_PUBLIC_KEYS_REQUEST_INITIATE_TAG) || !validate_request_data(&query->get_public_keys, which_request) || @@ -436,14 +439,13 @@ void tron_get_pub_keys(tron_query_t *query) { char main_address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = ""; // gen Address: - uint8_t initial_address[1 + 20] = {0}; // initial address + uint8_t initial_address[1 + 20] = {0}; initial_address[0] = 0x41; uint8_t public_key_digest[32]; + // Drop the '04' from pubkey // No iteration in public_keys[i]? - keccak_256(public_keys[0], - TRON_PUB_KEY_SIZE, - public_key_digest); // compare with reference + keccak_256(&public_keys[0][1], TRON_PUB_KEY_SIZE, public_key_digest); // extract last 20 bytes // address = 41||sha3[12,32) diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index 27bc36a9..825c5f9b 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -77,6 +77,7 @@ #include "sha2.h" #include "status_api.h" #include "tron_api.h" +#include "tron_helpers.h" #include "tron_priv.h" #include "ui_core_confirm.h" #include "ui_screens.h" @@ -240,11 +241,8 @@ static bool check_which_request(const tron_query_t *query, static bool validate_request_data(const tron_sign_txn_request_t *request) { bool status = true; - if ( - /*!tron_derivation_path_guard(request->initiate.derivation_path, - request->initiate.derivation_path_count) - */ - false) { + if (!tron_derivation_path_guard(request->initiate.derivation_path, + request->initiate.derivation_path_count)) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, ERROR_DATA_FLOW_INVALID_DATA); status = false; @@ -362,8 +360,7 @@ STATIC bool extract_contract_info(tron_transaction_raw_t *raw_txn, return false; } - tron_transaction_contract_t contract = - raw_txn->contract[0]; // Example for the first contract + tron_transaction_contract_t contract = raw_txn->contract[0]; // TODO: Add switch-cases for more contract types switch (contract.type) { diff --git a/apps/tron_app/tron_txn_helpers.c b/apps/tron_app/tron_txn_helpers.c index 8a70b34b..58c37352 100644 --- a/apps/tron_app/tron_txn_helpers.c +++ b/apps/tron_app/tron_txn_helpers.c @@ -106,7 +106,6 @@ int tron_byte_array_to_raw_txn(uint8_t *byte_array, memzero(raw_txn, sizeof(tron_transaction_raw_t)); pb_istream_t stream = pb_istream_from_buffer(byte_array, size); - //*raw_txn = TRON_TRANSACTION_RAW_INIT_ZERO; if (!pb_decode(&stream, TRON_TRANSACTION_RAW_FIELDS, raw_txn)) { return -1; diff --git a/apps/tron_app/tron_txn_helpers.h b/apps/tron_app/tron_txn_helpers.h index 05e82d20..efb5d2fb 100644 --- a/apps/tron_app/tron_txn_helpers.h +++ b/apps/tron_app/tron_txn_helpers.h @@ -25,8 +25,9 @@ * MACROS AND DEFINES *****************************************************************************/ #define TRON_NAME "Tron" -#define TRON_LUNIT "TRX" // To Confirm -#define TRON_PUB_KEY_SIZE 65 +#define TRON_LUNIT "TRX" +#define TRON_PUB_KEY_SIZE 64 // ECDSA's x+y coordinates only +#define TRON_PUB_KEY_SIZE_PLUS_ONE 65 #define TRON_INITIAL_ADDRESS_LENGTH 21 #define TRON_ACCOUNT_ADDRESS_LENGTH 34 @@ -42,12 +43,12 @@ *****************************************************************************/ /** * @brief Convert byte array representation of unsigned transaction to - * solana_unsigned_txn. + * tron_unsigned_txn. * @details * * @param [in] byte_array Byte array of unsigned transaction. * @param [in] byte_array_size Size of byte array. - * @param [out] utxn Pointer to the solana_unsigned_txn + * @param [out] utxn Pointer to the tron_unsigned_txn * instance to store the transaction details. * * @return Status of conversion @@ -66,7 +67,7 @@ int tron_byte_array_to_raw_txn(uint8_t *byte_array, /** * @brief Validate the deserialized unsigned transaction * - * @param utxn Pointer to the solana_unsigned_txn instance to validate the + * @param utxn Pointer to the tron_unsigned_txn instance to validate the * transaction * @return 0 if validation succeeded * @return -1 if validation failed diff --git a/common/cypherock-common b/common/cypherock-common index d8a29c30..da546059 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit d8a29c30226807044f7bc9b5a79c997826b2271a +Subproject commit da546059a3185822a9272b196424ee62c589eadd diff --git a/common/proto-options/tron/get_public_keys.options b/common/proto-options/tron/get_public_keys.options index 8a0d15b5..7fca2bfa 100644 --- a/common/proto-options/tron/get_public_keys.options +++ b/common/proto-options/tron/get_public_keys.options @@ -1,4 +1,4 @@ -# Options for file common/cypherock-common/proto/tron/get_public_key.proto +# Options for file common/cypherock-common/proto/tron/get_public_keys.proto tron.GetPublicKeysDerivationPath.path type:FT_STATIC max_count:5 fixed_length:true tron.GetPublicKeysIntiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true tron.GetPublicKeysIntiateRequest.derivation_paths type:FT_STATIC max_count:100 fixed_length:true diff --git a/utilities/cmake/simulator/simulator.cmake b/utilities/cmake/simulator/simulator.cmake index 9b78a9a8..bf77da09 100644 --- a/utilities/cmake/simulator/simulator.cmake +++ b/utilities/cmake/simulator/simulator.cmake @@ -54,6 +54,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE apps/near_app apps/solana_app + apps/tron_app src/ src/menu From 4a2f262db7e9b987f4664df9d944fd58285949a9 Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Thu, 9 May 2024 14:32:43 +0530 Subject: [PATCH 09/22] fix (app): Minor fixes --- apps/tron_app/tron_helpers.h | 2 +- apps/tron_app/tron_pub_key.c | 8 ++++---- common/proto-options/tron/sign_txn.options | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/tron_app/tron_helpers.h b/apps/tron_app/tron_helpers.h index c95df038..005e932e 100644 --- a/apps/tron_app/tron_helpers.h +++ b/apps/tron_app/tron_helpers.h @@ -23,7 +23,7 @@ * MACROS AND DEFINES *****************************************************************************/ #define TRON_PURPOSE_INDEX 0x8000002C -#define TRON_COIN_INDEX 0x80000405 +#define TRON_COIN_INDEX 0x800000C3 #define TRON_ACCOUNT_INDEX 0x80000000 #define TRON_CHANGE_INDEX 0x0 /***************************************************************************** diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index 6f92049d..9c8f95e0 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -71,11 +71,13 @@ #include "sha3.h" #include "status_api.h" #include "tron_api.h" +#include "tron_helpers.h" #include "tron_priv.h" #include "tron_txn_helpers.h" #include "ui_core_confirm.h" #include "ui_screens.h" #include "wallet_list.h" + /***************************************************************************** * EXTERN VARIABLES *****************************************************************************/ @@ -254,15 +256,13 @@ STATIC bool validate_request_data(tron_get_public_keys_request_t *request, pb_size_t count = request->initiate.derivation_paths_count; for (pb_size_t index = 0; index < count; index++) { path = &request->initiate.derivation_paths[index]; - // TODO: - /* + if (!tron_derivation_path_guard(path->path, path->path_count)) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); + ERROR_DATA_FLOW_INVALID_DATA); status = false; break; } - */ } return status; diff --git a/common/proto-options/tron/sign_txn.options b/common/proto-options/tron/sign_txn.options index 4c5123eb..b92f7b74 100644 --- a/common/proto-options/tron/sign_txn.options +++ b/common/proto-options/tron/sign_txn.options @@ -1,4 +1,4 @@ # Options for file common/cypherock-common/proto/tron/sign_txn.proto tron.SignTxnInitiateRequest.walletId type:FT_STATIC max_size:32 fixed_length:true -tron.SignTxnInitiateRequest.derivationPath type:FT_STATIC max_count:4 fixed_length:true +tron.SignTxnInitiateRequest.derivationPath type:FT_STATIC max_count:5 fixed_length:true tron.SignTxnSignatureResponse.signature type:FT_STATIC max_size:65 fixed_length:true \ No newline at end of file From 83bf9bf778f7c9f1f3058f67d76e7daf333f1ebd Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Sat, 11 May 2024 16:31:05 +0530 Subject: [PATCH 10/22] fix (ci): Pass checks and code quality --- apps/tron_app/tron_pub_key.c | 14 +++++++------- apps/tron_app/tron_sign_txn.c | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index 9c8f95e0..7f6bcbca 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -107,7 +107,7 @@ * @retval true If the query contains the expected request * @retval false If the query does not contain the expected request */ -STATIC bool check_which_request(const tron_query_t *query, +static bool check_which_request(const tron_query_t *query, pb_size_t which_request); /** * @brief Validates all the derivation paths received in the request from host @@ -120,7 +120,7 @@ STATIC bool check_which_request(const tron_query_t *query, * @retval true If all the derivation path entries are valid * @retval false If any of the derivation path entries are invalid */ -STATIC bool validate_request_data(tron_get_public_keys_request_t *request, +static bool validate_request_data(tron_get_public_keys_request_t *request, const pb_size_t which_request); /** * @details The function provides a public key. It accepts NULL for output @@ -137,7 +137,7 @@ STATIC bool validate_request_data(tron_get_public_keys_request_t *request, * * @retval false If derivation failed */ -STATIC bool get_public_key(const uint8_t *seed, +static bool get_public_key(const uint8_t *seed, const uint32_t *path, uint32_t path_length, uint8_t *public_key); @@ -161,7 +161,7 @@ STATIC bool get_public_key(const uint8_t *seed, * @retval false If the public key derivation failed. This could be due to * invalid derivation path. */ -STATIC bool fill_public_keys( +static bool fill_public_keys( const tron_get_public_keys_derivation_path_t *paths, const uint8_t *seed, uint8_t public_keys[][TRON_PUB_KEY_SIZE_PLUS_ONE], @@ -221,7 +221,7 @@ static bool get_user_consent(const pb_size_t which_request, * STATIC FUNCTIONS *****************************************************************************/ -STATIC bool check_which_request(const tron_query_t *query, +static bool check_which_request(const tron_query_t *query, pb_size_t which_request) { if (which_request != query->get_public_keys.which_request) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, @@ -232,7 +232,7 @@ STATIC bool check_which_request(const tron_query_t *query, return true; } -STATIC bool validate_request_data(tron_get_public_keys_request_t *request, +static bool validate_request_data(tron_get_public_keys_request_t *request, const pb_size_t which_request) { bool status = true; @@ -268,7 +268,7 @@ STATIC bool validate_request_data(tron_get_public_keys_request_t *request, return status; } -STATIC bool get_public_key(const uint8_t *seed, +static bool get_public_key(const uint8_t *seed, const uint32_t *path, uint32_t path_length, uint8_t *public_key) { diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index 825c5f9b..af0994dc 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -194,7 +194,7 @@ STATIC bool tron_get_user_verification(); * @retval true If all the seed is generated without any error * @retval false If seed failed to generate */ -STATIC bool fetch_seed(tron_query_t *query, uint8_t *seed_out); +static bool fetch_seed(tron_query_t *query, uint8_t *seed_out); /** * @brief Sends the generated signature to the host @@ -424,17 +424,17 @@ STATIC bool tron_get_user_verification() { } // verify recipient amount - // char amount_decimal_string[30] = {'\0'}; + char amount_decimal_string[30] = {'\0'}; char display[100] = {'\0'}; - sprintf(display, "%lli", amount); - /* + snprintf( + amount_decimal_string, sizeof(amount_decimal_string), "%lli", amount); snprintf(display, sizeof(display), UI_TEXT_VERIFY_AMOUNT, amount_decimal_string, TRON_LUNIT); - */ + if (!core_confirmation(display, tron_send_error)) { return false; } @@ -443,7 +443,7 @@ STATIC bool tron_get_user_verification() { return true; } -STATIC bool fetch_seed(tron_query_t *query, uint8_t *seed_out) { +static bool fetch_seed(tron_query_t *query, uint8_t *seed_out) { if (!tron_get_query(query, TRON_QUERY_SIGN_TXN_TAG)) { return false; } From 8488ad17364e769a51431bfedfa0b00e0b83876c Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Tue, 4 Jun 2024 12:49:52 +0530 Subject: [PATCH 11/22] feat(app): Tron tokens --- apps/tron_app/tron_context.h | 2 + apps/tron_app/tron_contracts.c | 256 ++++++++++++++++++ apps/tron_app/tron_sign_txn.c | 90 +----- .../proto-options/google/protobuf/any.options | 4 +- 4 files changed, 264 insertions(+), 88 deletions(-) create mode 100644 apps/tron_app/tron_contracts.c diff --git a/apps/tron_app/tron_context.h b/apps/tron_app/tron_context.h index 03814b3d..2610ef08 100644 --- a/apps/tron_app/tron_context.h +++ b/apps/tron_app/tron_context.h @@ -14,6 +14,7 @@ *****************************************************************************/ #include #include +#include /***************************************************************************** * MACROS AND DEFINES @@ -34,5 +35,6 @@ typedef struct { /***************************************************************************** * GLOBAL FUNCTION PROTOTYPES *****************************************************************************/ +bool extract_contract_info(tron_transaction_raw_t *raw_txn); #endif /* TRON_CONTEXT_H */ diff --git a/apps/tron_app/tron_contracts.c b/apps/tron_app/tron_contracts.c new file mode 100644 index 00000000..abb47c3a --- /dev/null +++ b/apps/tron_app/tron_contracts.c @@ -0,0 +1,256 @@ +/** + * @file tron_contracts.c + * @author Cypherock X1 Team + * @brief Tron chain contract parsing logic + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "base58.h" +#include "coin_utils.h" +#include "curves.h" +#include "ecdsa.h" +#include "hasher.h" +#include "secp256k1.h" +#include "sha2.h" +#include "status_api.h" +#include "tron_api.h" +#include "tron_helpers.h" +#include "tron_priv.h" +#include "tron_txn_helpers.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" +#include "wallet_list.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +static bool transfer_contract_txn(tron_transaction_raw_t *raw_txn, + tron_transaction_contract_t *contract) { + uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; + // uint8_t owner_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; + int64_t amount = 0; + char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; + + tron_transfer_contract_t transfer_contract = + TRON_TRANSFER_CONTRACT_INIT_DEFAULT; + google_protobuf_any_t any = contract->parameter; + pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); + + if (!pb_decode(&stream, TRON_TRANSFER_CONTRACT_FIELDS, &transfer_contract)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + memcpy(&amount, &transfer_contract.amount, sizeof(int64_t)); + memcpy(to_address, + (uint8_t *)transfer_contract.to_address, + TRON_INITIAL_ADDRESS_LENGTH); + + // verify recipient address; + if (!base58_encode_check(to_address, + 1 + 20, + HASHER_SHA2D, + address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return false; + } + + if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { + return false; + } + + // verify recipient amount + char amount_string[30] = {'\0'}; + char display[100] = {'\0'}; + + snprintf(amount_string, sizeof(amount_string), "%lli", amount); + snprintf(display, + sizeof(display), + UI_TEXT_VERIFY_AMOUNT, + amount_string, + TRON_LUNIT); + + if (!core_confirmation(display, tron_send_error)) { + return false; + } + + set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); + return true; +} + +static bool trigger_smart_contract_txn(tron_transaction_raw_t *raw_txn, + tron_transaction_contract_t *contract) { + tron_trigger_smart_contract_t trigger_smc_contract = + TRON_TRIGGER_SMART_CONTRACT_INIT_DEFAULT; + google_protobuf_any_t any = contract->parameter; + pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); + + if (!pb_decode( + &stream, TRON_TRANSFER_CONTRACT_FIELDS, &trigger_smc_contract)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + + uint8_t contract_address[TRON_INITIAL_ADDRESS_LENGTH]; + char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; + int64_t call_value; + int64_t call_token_value; + int64_t token_id; + uint8_t data[68]; + memcpy(contract_address, + (uint8_t *)trigger_smc_contract.contract_address, + TRON_INITIAL_ADDRESS_LENGTH); + memcpy(&call_value, &trigger_smc_contract.call_value, sizeof(int64_t)); + memcpy(&call_token_value, + &trigger_smc_contract.call_token_value, + sizeof(int64_t)); + memcpy(&token_id, &trigger_smc_contract.token_id, sizeof(int64_t)); + // memcpy(data, (uint8_t *)trigger_smc_contract.data, 68); + + // verify recipient address + if (!base58_encode_check(contract_address, + 1 + 20, + HASHER_SHA2D, + address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return false; + } + + if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { + return false; + } + + // verify recipient amount + // if (!core_scroll_page("DATA FIELD", (char *)data, tron_send_error)) { + // return false; + // } + + set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +bool extract_contract_info(tron_transaction_raw_t *raw_txn) { + if (!(raw_txn->contract_count > 0)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return false; + } + + tron_transaction_contract_t contract = raw_txn->contract[0]; + + // TODO: Add switch-cases for more contract types + switch (contract.type) { + case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { + if (!transfer_contract_txn(raw_txn, &contract)) { + return false; + } + break; + } + case TRON_TRANSACTION_CONTRACT_TRIGGER_SMART_CONTRACT: { + if (!trigger_smart_contract_txn(raw_txn, &contract)) { + return false; + } + break; + } + default: { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + } + return true; +} diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index af0994dc..abb10065 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -77,11 +77,13 @@ #include "sha2.h" #include "status_api.h" #include "tron_api.h" +#include "tron_context.h" #include "tron_helpers.h" #include "tron_priv.h" #include "ui_core_confirm.h" #include "ui_screens.h" #include "wallet_list.h" +//#include "tron_contracts.c" /***************************************************************************** * EXTERN VARIABLES @@ -336,7 +338,6 @@ STATIC bool tron_fetch_valid_transaction(tron_query_t *query) { ERROR_DATA_FLOW_INVALID_DATA); return false; } - tron_txn_context->raw_txn = (tron_transaction_raw_t *)malloc(sizeof(tron_transaction_raw_t)); // decode and verify the received transaction @@ -350,96 +351,13 @@ STATIC bool tron_fetch_valid_transaction(tron_query_t *query) { return true; } -STATIC bool extract_contract_info(tron_transaction_raw_t *raw_txn, - int64_t *amount, - uint8_t *to_address, - uint8_t *owner_address) { - if (!(raw_txn->contract_count > 0)) { - tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); - return false; - } - - tron_transaction_contract_t contract = raw_txn->contract[0]; - - // TODO: Add switch-cases for more contract types - switch (contract.type) { - case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { - tron_transfer_contract_t transfer_contract = - TRON_TRANSFER_CONTRACT_INIT_DEFAULT; - google_protobuf_any_t any = contract.parameter; - pb_istream_t stream = - pb_istream_from_buffer(any.value.bytes, any.value.size); - - if (!pb_decode( - &stream, TRON_TRANSFER_CONTRACT_FIELDS, &transfer_contract)) { - tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); - return false; - } - - memcpy(amount, &transfer_contract.amount, sizeof(int64_t)); - memcpy(to_address, - (uint8_t *)transfer_contract.to_address, - TRON_INITIAL_ADDRESS_LENGTH); - memcpy(owner_address, - (uint8_t *)transfer_contract.owner_address, - TRON_INITIAL_ADDRESS_LENGTH); - break; - } - - default: { - tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, - ERROR_DATA_FLOW_INVALID_REQUEST); - return false; - } - } - return true; -} - STATIC bool tron_get_user_verification() { - uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; - uint8_t owner_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; - int64_t amount = 0; - char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; // extract raw - if (!extract_contract_info( - tron_txn_context->raw_txn, &amount, to_address, owner_address)) { + if (!extract_contract_info(tron_txn_context->raw_txn)) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, ERROR_DATA_FLOW_DECODING_FAILED); return false; } - // verify recipient address; - if (!base58_encode_check(to_address, - 1 + 20, - HASHER_SHA2D, - address, - TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { - tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); - return false; - } - - if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { - return false; - } - - // verify recipient amount - char amount_decimal_string[30] = {'\0'}; - char display[100] = {'\0'}; - - snprintf( - amount_decimal_string, sizeof(amount_decimal_string), "%lli", amount); - snprintf(display, - sizeof(display), - UI_TEXT_VERIFY_AMOUNT, - amount_decimal_string, - TRON_LUNIT); - - if (!core_confirmation(display, tron_send_error)) { - return false; - } - - set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); return true; } @@ -472,7 +390,7 @@ static bool send_signature(tron_query_t *query, return false; } - // Hash the raw data using sha256. This gives you the Transaction ID. + // Hash the raw data using sha256. This gives us the Transaction ID. uint8_t txid[SHA256_DIGEST_LENGTH] = {0}; sha256_Raw(tron_txn_context->transaction, diff --git a/common/proto-options/google/protobuf/any.options b/common/proto-options/google/protobuf/any.options index c88410ed..a23f60b6 100644 --- a/common/proto-options/google/protobuf/any.options +++ b/common/proto-options/google/protobuf/any.options @@ -1,2 +1,2 @@ -google.protobuf.Any.type_url max_size:64 -google.protobuf.Any.value max_size:64 +google.protobuf.Any.type_url max_size:200 +google.protobuf.Any.value max_size:200 From c81f0124914d67277725d86f25ff58de1382ec32 Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Mon, 10 Jun 2024 14:24:50 +0530 Subject: [PATCH 12/22] feat(app): Abi decode and trc10 --- apps/tron_app/tron_contracts.c | 107 +++++++++++--- .../coin_support/tron_parse_txn/abi_extract.c | 132 ++++++++++++++++++ .../coin_support/tron_parse_txn/abi_extract.h | 102 ++++++++++++++ .../proto-options/google/protobuf/any.options | 4 +- common/proto-options/tron/contract.options | 2 +- utilities/cmake/firmware/firmware.cmake | 1 + utilities/cmake/simulator/simulator.cmake | 1 + 7 files changed, 325 insertions(+), 24 deletions(-) create mode 100644 common/coin_support/tron_parse_txn/abi_extract.c create mode 100644 common/coin_support/tron_parse_txn/abi_extract.h diff --git a/apps/tron_app/tron_contracts.c b/apps/tron_app/tron_contracts.c index abb47c3a..4187bc40 100644 --- a/apps/tron_app/tron_contracts.c +++ b/apps/tron_app/tron_contracts.c @@ -67,6 +67,7 @@ #include #include +#include "abi_extract.h" #include "base58.h" #include "coin_utils.h" #include "curves.h" @@ -111,8 +112,7 @@ * STATIC FUNCTIONS *****************************************************************************/ -static bool transfer_contract_txn(tron_transaction_raw_t *raw_txn, - tron_transaction_contract_t *contract) { +static bool transfer_contract_txn(tron_transaction_contract_t *contract) { uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; // uint8_t owner_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; int64_t amount = 0; @@ -166,15 +166,14 @@ static bool transfer_contract_txn(tron_transaction_raw_t *raw_txn, return true; } -static bool trigger_smart_contract_txn(tron_transaction_raw_t *raw_txn, - tron_transaction_contract_t *contract) { +static bool trigger_smart_contract_txn(tron_transaction_contract_t *contract) { tron_trigger_smart_contract_t trigger_smc_contract = TRON_TRIGGER_SMART_CONTRACT_INIT_DEFAULT; google_protobuf_any_t any = contract->parameter; pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); if (!pb_decode( - &stream, TRON_TRANSFER_CONTRACT_FIELDS, &trigger_smc_contract)) { + &stream, TRON_TRIGGER_SMART_CONTRACT_FIELDS, &trigger_smc_contract)) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, ERROR_DATA_FLOW_DECODING_FAILED); return false; @@ -182,21 +181,12 @@ static bool trigger_smart_contract_txn(tron_transaction_raw_t *raw_txn, uint8_t contract_address[TRON_INITIAL_ADDRESS_LENGTH]; char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; - int64_t call_value; - int64_t call_token_value; - int64_t token_id; uint8_t data[68]; memcpy(contract_address, (uint8_t *)trigger_smc_contract.contract_address, TRON_INITIAL_ADDRESS_LENGTH); - memcpy(&call_value, &trigger_smc_contract.call_value, sizeof(int64_t)); - memcpy(&call_token_value, - &trigger_smc_contract.call_token_value, - sizeof(int64_t)); - memcpy(&token_id, &trigger_smc_contract.token_id, sizeof(int64_t)); - // memcpy(data, (uint8_t *)trigger_smc_contract.data, 68); - - // verify recipient address + memcpy(data, (uint8_t *)trigger_smc_contract.data, 68); + if (!base58_encode_check(contract_address, 1 + 20, HASHER_SHA2D, @@ -205,15 +195,84 @@ static bool trigger_smart_contract_txn(tron_transaction_raw_t *raw_txn, tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); return false; } + // store contract address + ui_display_node *ui_node = ui_create_display_node( + ui_text_verify_address, 15, address, sizeof(address)); + + // populate display node with remaining + // TODO: recognize both types of function hash + // transfer() and approve() + ui_node->next = extract_data(data); + // check(verification) + // ifnot display warning + // USE LEDGER + if (NULL == ui_node->next) { + return false; + } + + while (NULL != ui_node) { + if (!core_scroll_page(ui_node->title, ui_node->value, tron_send_error)) { + return false; + } + ui_node = ui_node->next; + } + + cy_free(); + set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); + return true; +} + +static bool transfer_asset_contract_txn(tron_transaction_contract_t *contract) { + tron_transfer_asset_contract_t tac_contract = + TRON_TRANSFER_ASSET_CONTRACT_INIT_DEFAULT; + google_protobuf_any_t any = contract->parameter; + pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); + + if (!pb_decode(&stream, TRON_TRANSFER_ASSET_CONTRACT_FIELDS, &tac_contract)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + + uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; + int64_t amount = 0; + char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; + + memcpy(&amount, &tac_contract.amount, sizeof(int64_t)); + memcpy(to_address, + (uint8_t *)tac_contract.to_address, + TRON_INITIAL_ADDRESS_LENGTH); + + // verify recipient address; + if (!base58_encode_check(to_address, + 1 + 20, + HASHER_SHA2D, + address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return false; + } if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { return false; } // verify recipient amount - // if (!core_scroll_page("DATA FIELD", (char *)data, tron_send_error)) { - // return false; - // } + char amount_string[30] = {'\0'}; + char display[100] = {'\0'}; + + snprintf(amount_string, sizeof(amount_string), "%lli", amount); + snprintf(display, + sizeof(display), + UI_TEXT_VERIFY_AMOUNT, + amount_string, + TRON_LUNIT); + + if (!core_confirmation(display, tron_send_error)) { + return false; + } + // TODO: DISPLAY ASSET NAME/TOKEN ID + // tac_ set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); return true; @@ -235,13 +294,19 @@ bool extract_contract_info(tron_transaction_raw_t *raw_txn) { // TODO: Add switch-cases for more contract types switch (contract.type) { case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { - if (!transfer_contract_txn(raw_txn, &contract)) { + if (!transfer_contract_txn(&contract)) { return false; } break; } case TRON_TRANSACTION_CONTRACT_TRIGGER_SMART_CONTRACT: { - if (!trigger_smart_contract_txn(raw_txn, &contract)) { + if (!trigger_smart_contract_txn(&contract)) { + return false; + } + break; + } + case TRON_TRANSACTION_CONTRACT_TRANSFER_ASSET_CONTRACT: { + if (!transfer_asset_contract_txn(&contract)) { return false; } break; diff --git a/common/coin_support/tron_parse_txn/abi_extract.c b/common/coin_support/tron_parse_txn/abi_extract.c new file mode 100644 index 00000000..c5376313 --- /dev/null +++ b/common/coin_support/tron_parse_txn/abi_extract.c @@ -0,0 +1,132 @@ +/** + * @file abi_extract.c + * @author Cypherock X1 Team + * @brief Tron chain abi extract logic + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "abi_extract.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +ui_display_node *extract_data(uint8_t *data) { + uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; + to_address[0] = 0x41; + uint8_t amount[32]; + memcpy(to_address + 1, data + 4 + (32 - 20), 20); + memcpy(amount, data + 4 + 32, 32); + + char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; + // receipent address + if (!base58_encode_check(to_address, + 1 + 20, + HASHER_SHA2D, + address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return NULL; + } + ui_display_node *ui_node = ui_create_display_node( + "Datatype:address\0", 25, address, sizeof(address)); + ui_display_node *head = ui_node; + + // receipent amount + char staticBufferInUTF8[200]; + memzero(staticBufferInUTF8, sizeof(staticBufferInUTF8)); + byte_array_to_hex_string(amount, 32, &(staticBufferInUTF8[0]), 65); + convert_byte_array_to_decimal_string( + 64, 0, &(staticBufferInUTF8[0]), &(staticBufferInUTF8[100]), 100); + + (ui_node)->next = ui_create_display_node( + "Datatype:uint256\0", 25, &(staticBufferInUTF8[100]), 100); + + ui_node = (ui_node)->next; + (ui_node)->next = NULL; + + return head; +} diff --git a/common/coin_support/tron_parse_txn/abi_extract.h b/common/coin_support/tron_parse_txn/abi_extract.h new file mode 100644 index 00000000..dc0b50c2 --- /dev/null +++ b/common/coin_support/tron_parse_txn/abi_extract.h @@ -0,0 +1,102 @@ +/** + * @file abi_extract.h + * @author Cypherock X1 Team + * @brief Tron chain abi extract logic + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "base58.h" +#include "coin_utils.h" +#include "curves.h" +#include "ecdsa.h" +#include "hasher.h" +#include "secp256k1.h" +#include "sha2.h" +#include "status_api.h" +#include "tron_api.h" +#include "tron_helpers.h" +#include "tron_priv.h" +#include "tron_txn_helpers.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" +#include "wallet_list.h" + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +ui_display_node *extract_data(uint8_t *data); diff --git a/common/proto-options/google/protobuf/any.options b/common/proto-options/google/protobuf/any.options index a23f60b6..37b66e73 100644 --- a/common/proto-options/google/protobuf/any.options +++ b/common/proto-options/google/protobuf/any.options @@ -1,2 +1,2 @@ -google.protobuf.Any.type_url max_size:200 -google.protobuf.Any.value max_size:200 +google.protobuf.Any.type_url max_size:64 +google.protobuf.Any.value max_size:116 diff --git a/common/proto-options/tron/contract.options b/common/proto-options/tron/contract.options index eedff96c..3a1d775b 100644 --- a/common/proto-options/tron/contract.options +++ b/common/proto-options/tron/contract.options @@ -42,7 +42,7 @@ tron.ProposalDeleteContract.owner_address max_size: 21, fixed_length: true tron.TriggerSmartContract.owner_address max_size: 21, fixed_length: true tron.TriggerSmartContract.contract_address max_size: 21, fixed_length: true -tron.TriggerSmartContract.data type: FT_CALLBACK +tron.TriggerSmartContract.data max_size: 68, fixed_length: true tron.ExchangeCreateContract.owner_address max_size: 21, fixed_length: true tron.ExchangeCreateContract.first_token_id max_size: 8 diff --git a/utilities/cmake/firmware/firmware.cmake b/utilities/cmake/firmware/firmware.cmake index 962e7a23..f35609e2 100644 --- a/utilities/cmake/firmware/firmware.cmake +++ b/utilities/cmake/firmware/firmware.cmake @@ -111,6 +111,7 @@ target_include_directories(${EXECUTABLE} PRIVATE common/logger common/coin_support common/coin_support/eth_sign_data + common/coin_support/tron_parse_txn common/flash common/Firewall common/core diff --git a/utilities/cmake/simulator/simulator.cmake b/utilities/cmake/simulator/simulator.cmake index bf77da09..9a6aea28 100644 --- a/utilities/cmake/simulator/simulator.cmake +++ b/utilities/cmake/simulator/simulator.cmake @@ -108,6 +108,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE common/logger common/coin_support common/coin_support/eth_sign_data + common/coin_support/tron_parse_txn common/flash common/Firewall common/core From 6302848ab351398d70597258060dc97128130b9e Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Fri, 14 Jun 2024 07:09:05 +0530 Subject: [PATCH 13/22] fix(app): Device specific tron decoding --- apps/tron_app/tron_contracts.c | 333 +------------- apps/tron_app/tron_contracts.h | 14 + apps/tron_app/tron_parse_contracts.c | 426 ++++++++++++++++++ apps/tron_app/tron_sign_txn.c | 9 +- apps/tron_app/tron_txn_helpers.h | 2 + .../coin_support/tron_parse_txn/abi_extract.c | 17 + .../coin_support/tron_parse_txn/abi_extract.h | 2 +- .../tron_parse_txn/tron/contract.proto | 238 ++++++++++ .../tron/google/protobuf/any.proto | 154 +++++++ .../tron_parse_txn/tron/tron.proto | 161 +++++++ .../{ => tron}/google/protobuf/any.options | 2 +- common/proto-options/tron/sign_txn.options | 4 +- utilities/proto/generate-protob.sh | 7 +- 13 files changed, 1041 insertions(+), 328 deletions(-) create mode 100644 apps/tron_app/tron_contracts.h create mode 100644 apps/tron_app/tron_parse_contracts.c create mode 100644 common/coin_support/tron_parse_txn/tron/contract.proto create mode 100644 common/coin_support/tron_parse_txn/tron/google/protobuf/any.proto create mode 100644 common/coin_support/tron_parse_txn/tron/tron.proto rename common/proto-options/{ => tron}/google/protobuf/any.options (51%) diff --git a/apps/tron_app/tron_contracts.c b/apps/tron_app/tron_contracts.c index 4187bc40..06a87b78 100644 --- a/apps/tron_app/tron_contracts.c +++ b/apps/tron_app/tron_contracts.c @@ -1,321 +1,22 @@ -/** - * @file tron_contracts.c - * @author Cypherock X1 Team - * @brief Tron chain contract parsing logic - * @copyright Copyright (c) 2023 HODL TECH PTE LTD - *
You may obtain a copy of license at https://mitcc.org/ - * - ****************************************************************************** - * @attention - * - * (c) Copyright 2023 by HODL TECH PTE LTD - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject - * to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * - * "Commons Clause" License Condition v1.0 - * - * The Software is provided to you by the Licensor under the License, - * as defined below, subject to the following condition. - * - * Without limiting other conditions in the License, the grant of - * rights under the License will not include, and the License does not - * grant to you, the right to Sell the Software. - * - * For purposes of the foregoing, "Sell" means practicing any or all - * of the rights granted to you under the License to provide to third - * parties, for a fee or other consideration (including without - * limitation fees for hosting or consulting/ support services related - * to the Software), a product or service whose value derives, entirely - * or substantially, from the functionality of the Software. Any license - * notice or attribution required by the License must also include - * this Commons Clause License Condition notice. - * - * Software: All X1Wallet associated files. - * License: MIT - * Licensor: HODL TECH PTE LTD - * - ****************************************************************************** - */ - -/***************************************************************************** - * INCLUDES - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "abi_extract.h" -#include "base58.h" -#include "coin_utils.h" -#include "curves.h" -#include "ecdsa.h" -#include "hasher.h" -#include "secp256k1.h" -#include "sha2.h" -#include "status_api.h" -#include "tron_api.h" -#include "tron_helpers.h" -#include "tron_priv.h" -#include "tron_txn_helpers.h" -#include "ui_core_confirm.h" -#include "ui_screens.h" -#include "wallet_list.h" - -/***************************************************************************** - * EXTERN VARIABLES - *****************************************************************************/ - -/***************************************************************************** - * PRIVATE MACROS AND DEFINES - *****************************************************************************/ - -/***************************************************************************** - * PRIVATE TYPEDEFS - *****************************************************************************/ - -/***************************************************************************** - * STATIC FUNCTION PROTOTYPES - *****************************************************************************/ - -/***************************************************************************** - * STATIC VARIABLES - *****************************************************************************/ +#include /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ -/***************************************************************************** - * STATIC FUNCTIONS - *****************************************************************************/ - -static bool transfer_contract_txn(tron_transaction_contract_t *contract) { - uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; - // uint8_t owner_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; - int64_t amount = 0; - char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; - - tron_transfer_contract_t transfer_contract = - TRON_TRANSFER_CONTRACT_INIT_DEFAULT; - google_protobuf_any_t any = contract->parameter; - pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); - - if (!pb_decode(&stream, TRON_TRANSFER_CONTRACT_FIELDS, &transfer_contract)) { - tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); - return false; - } - memcpy(&amount, &transfer_contract.amount, sizeof(int64_t)); - memcpy(to_address, - (uint8_t *)transfer_contract.to_address, - TRON_INITIAL_ADDRESS_LENGTH); - - // verify recipient address; - if (!base58_encode_check(to_address, - 1 + 20, - HASHER_SHA2D, - address, - TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { - tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); - return false; - } - - if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { - return false; - } - - // verify recipient amount - char amount_string[30] = {'\0'}; - char display[100] = {'\0'}; - - snprintf(amount_string, sizeof(amount_string), "%lli", amount); - snprintf(display, - sizeof(display), - UI_TEXT_VERIFY_AMOUNT, - amount_string, - TRON_LUNIT); - - if (!core_confirmation(display, tron_send_error)) { - return false; - } - - set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); - return true; -} - -static bool trigger_smart_contract_txn(tron_transaction_contract_t *contract) { - tron_trigger_smart_contract_t trigger_smc_contract = - TRON_TRIGGER_SMART_CONTRACT_INIT_DEFAULT; - google_protobuf_any_t any = contract->parameter; - pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); - - if (!pb_decode( - &stream, TRON_TRIGGER_SMART_CONTRACT_FIELDS, &trigger_smc_contract)) { - tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); - return false; - } - - uint8_t contract_address[TRON_INITIAL_ADDRESS_LENGTH]; - char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; - uint8_t data[68]; - memcpy(contract_address, - (uint8_t *)trigger_smc_contract.contract_address, - TRON_INITIAL_ADDRESS_LENGTH); - memcpy(data, (uint8_t *)trigger_smc_contract.data, 68); - - if (!base58_encode_check(contract_address, - 1 + 20, - HASHER_SHA2D, - address, - TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { - tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); - return false; - } - // store contract address - ui_display_node *ui_node = ui_create_display_node( - ui_text_verify_address, 15, address, sizeof(address)); - - // populate display node with remaining - // TODO: recognize both types of function hash - // transfer() and approve() - ui_node->next = extract_data(data); - // check(verification) - // ifnot display warning - // USE LEDGER - if (NULL == ui_node->next) { - return false; - } - - while (NULL != ui_node) { - if (!core_scroll_page(ui_node->title, ui_node->value, tron_send_error)) { - return false; - } - ui_node = ui_node->next; - } - - cy_free(); - set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); - return true; -} - -static bool transfer_asset_contract_txn(tron_transaction_contract_t *contract) { - tron_transfer_asset_contract_t tac_contract = - TRON_TRANSFER_ASSET_CONTRACT_INIT_DEFAULT; - google_protobuf_any_t any = contract->parameter; - pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); - - if (!pb_decode(&stream, TRON_TRANSFER_ASSET_CONTRACT_FIELDS, &tac_contract)) { - tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); - return false; - } - - uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; - int64_t amount = 0; - char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; - - memcpy(&amount, &tac_contract.amount, sizeof(int64_t)); - memcpy(to_address, - (uint8_t *)tac_contract.to_address, - TRON_INITIAL_ADDRESS_LENGTH); - - // verify recipient address; - if (!base58_encode_check(to_address, - 1 + 20, - HASHER_SHA2D, - address, - TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { - tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); - return false; - } - - if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { - return false; - } - - // verify recipient amount - char amount_string[30] = {'\0'}; - char display[100] = {'\0'}; - - snprintf(amount_string, sizeof(amount_string), "%lli", amount); - snprintf(display, - sizeof(display), - UI_TEXT_VERIFY_AMOUNT, - amount_string, - TRON_LUNIT); - - if (!core_confirmation(display, tron_send_error)) { - return false; - } - // TODO: DISPLAY ASSET NAME/TOKEN ID - // tac_ - - set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); - return true; -} - -/***************************************************************************** - * GLOBAL FUNCTIONS - *****************************************************************************/ - -bool extract_contract_info(tron_transaction_raw_t *raw_txn) { - if (!(raw_txn->contract_count > 0)) { - tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); - return false; - } - - tron_transaction_contract_t contract = raw_txn->contract[0]; - - // TODO: Add switch-cases for more contract types - switch (contract.type) { - case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { - if (!transfer_contract_txn(&contract)) { - return false; - } - break; - } - case TRON_TRANSACTION_CONTRACT_TRIGGER_SMART_CONTRACT: { - if (!trigger_smart_contract_txn(&contract)) { - return false; - } - break; - } - case TRON_TRANSACTION_CONTRACT_TRANSFER_ASSET_CONTRACT: { - if (!transfer_asset_contract_txn(&contract)) { - return false; - } - break; - } - default: { - tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, - ERROR_DATA_FLOW_INVALID_REQUEST); - return false; - } - } - return true; -} +// a9059cbb -> transfer(address,uint256) +// 095ea7b3 -> approve(address,uint256) +const uint8_t selector[TRC20_FUNCTION_SELECTOR_COUNT][4] = { + {0xA9, 0x05, 0x9C, 0xBB}}; //, {0x09, 0x5E, 0xA7, 0xB3}}; + +const trc20_contracts_t trc20_contracts[TRC20_WHITELISTED_CONTRACTS_COUNT] = { + // 0chain + {{0x41, 0xEA, 0x51, 0x34, 0x2D, 0xAB, 0xBB, 0x92, 0x8A, 0xE1, 0xE5, + 0x76, 0xBD, 0x39, 0xEF, 0xF8, 0xAA, 0xF0, 0x70, 0xA8, 0xC6}, + "USDT", // TESTNET + 6}, + // 0x + {{0xe4, 0x1d, 0x24, 0x89, 0x57, 0x1d, 0x32, 0x21, 0x89, 0x24, + 0x6d, 0xaf, 0xa5, 0xeb, 0xde, 0x1f, 0x46, 0x99, 0xf4, 0x98}, + "ZRX", + 18}}; \ No newline at end of file diff --git a/apps/tron_app/tron_contracts.h b/apps/tron_app/tron_contracts.h new file mode 100644 index 00000000..4cb744ec --- /dev/null +++ b/apps/tron_app/tron_contracts.h @@ -0,0 +1,14 @@ +#include + +typedef struct trc20_contracts { + /// 20-byte hex coded public address of the contract + const uint8_t address[TRON_INITIAL_ADDRESS_LENGTH]; + /// Symbol (short alphabetical representation) of the contract token + const char *symbol; + /// Decimal value used to display the amount in token transfer in token units + const uint8_t decimal; +} trc20_contracts_t; + +/// Number of entries in whitelisted contracts list +#define TRC20_WHITELISTED_CONTRACTS_COUNT 2 +#define TRC20_FUNCTION_SELECTOR_COUNT 1 \ No newline at end of file diff --git a/apps/tron_app/tron_parse_contracts.c b/apps/tron_app/tron_parse_contracts.c new file mode 100644 index 00000000..574666ad --- /dev/null +++ b/apps/tron_app/tron_parse_contracts.c @@ -0,0 +1,426 @@ +/** + * @file tron_contracts.c + * @author Cypherock X1 Team + * @brief Tron chain contract parsing logic + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "abi_extract.h" +#include "base58.h" +#include "coin_utils.h" +#include "curves.h" +#include "ecdsa.h" +#include "hasher.h" +#include "secp256k1.h" +#include "sha2.h" +#include "status_api.h" +#include "tron_api.h" +#include "tron_contracts.h" +#include "tron_helpers.h" +#include "tron_priv.h" +#include "tron_txn_helpers.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" +#include "wallet_list.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/** + * @brief Whitelisted contracts with respective token symbol + * @details A map of Tron contract addresses with their token symbols. These + * will enable the device to verify the TRC20 token transaction in a + * user-friendly manner. + * + * @see erc20_contracts_t + */ +extern const trc20_contracts_t trc20_contracts[]; + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ +static bool is_token_whitelisted(const uint8_t *address, + const trc20_contracts_t **contract) { + const trc20_contracts_t *match = NULL; + bool status = false; + for (int16_t i = 0; i < TRC20_WHITELISTED_CONTRACTS_COUNT; i++) { + if (memcmp(address, + trc20_contracts[i].address, + TRON_INITIAL_ADDRESS_LENGTH) == 0) { + match = &trc20_contracts[i]; + status = true; + break; + } + } + + if (NULL != contract) { + *contract = match; + } + return status; +} + +static bool parse_whitelist(uint8_t *data, + const uint8_t *contract_address, + bool *status) { + const trc20_contracts_t *contract; + if (!is_token_whitelisted(contract_address, &contract)) { + *status = 0; + return true; + } + + *status = 1; + char msg[100] = ""; + snprintf(msg, sizeof(msg), "Send \n%s on \n%s", contract->symbol, TRON_NAME); + if (!core_confirmation(msg, tron_send_error)) { + return false; + } + + uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; + to_address[0] = 0x41; + uint8_t amount[32]; + + // address is initial_address without '0x41' (20 Bytes) + memcpy(to_address + 1, data + 4 + (32 - 20), 20); + memcpy(amount, data + 4 + 32, 32); + + // receipent address + char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; + if (!base58_encode_check(to_address, + 1 + 20, + HASHER_SHA2D, + address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return false; + } + + if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { + return false; + } + + // receipent amount + char staticBufferInUTF8[200]; + memzero(staticBufferInUTF8, sizeof(staticBufferInUTF8)); + byte_array_to_hex_string(amount, 32, &(staticBufferInUTF8[0]), 65); + convert_byte_array_to_decimal_string(64, + contract->decimal, + &(staticBufferInUTF8[0]), + &(staticBufferInUTF8[100]), + 100); + + char display_amount[200] = ""; + snprintf(display_amount, + sizeof(msg), + UI_TEXT_VERIFY_AMOUNT, + &(staticBufferInUTF8[100]), + contract->symbol); + if (!core_confirmation(display_amount, tron_send_error)) { + return false; + } + + return true; +} + +static bool parse_unverified(uint8_t *data, uint8_t *contract_address) { + char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; + if (!base58_encode_check(contract_address, + 1 + 20, + HASHER_SHA2D, + address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return false; + } + + // store contract address + ui_display_node *ui_node = ui_create_display_node( + ui_text_verify_address, 15, address, sizeof(address)); + // store head node + ui_display_node *curr_head = ui_node; + + // stringify data for user verification + // create display nodes + ui_node->next = extract_data(data); + if (NULL == ui_node->next) { + return false; + } + + // Contract Unverifed, Display warning + delay_scr_init(ui_text_unverified_contract, DELAY_TIME); + + while (NULL != curr_head) { + if (!core_scroll_page( + curr_head->title, curr_head->value, tron_send_error)) { + return false; + } + curr_head = curr_head->next; + } + + cy_free(); + return true; +} +static bool transfer_contract_txn(tron_transaction_contract_t *contract) { + uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; + // uint8_t owner_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; + int64_t amount = 0; + char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; + + tron_transfer_contract_t transfer_contract = + TRON_TRANSFER_CONTRACT_INIT_DEFAULT; + google_protobuf_any_t any = contract->parameter; + pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); + + if (!pb_decode(&stream, TRON_TRANSFER_CONTRACT_FIELDS, &transfer_contract)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + memcpy(&amount, &transfer_contract.amount, sizeof(int64_t)); + memcpy(to_address, + (uint8_t *)transfer_contract.to_address, + TRON_INITIAL_ADDRESS_LENGTH); + + // verify recipient address; + if (!base58_encode_check(to_address, + 1 + 20, + HASHER_SHA2D, + address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return false; + } + + if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { + return false; + } + + // verify recipient amount + char amount_string[30] = {'\0'}; + char display[100] = {'\0'}; + + snprintf(amount_string, sizeof(amount_string), "%lli", amount); + snprintf(display, + sizeof(display), + UI_TEXT_VERIFY_AMOUNT, + amount_string, + TRON_LUNIT); + + if (!core_confirmation(display, tron_send_error)) { + return false; + } + + set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); + return true; +} + +static bool trigger_smart_contract_txn(tron_transaction_contract_t *contract) { + tron_trigger_smart_contract_t trigger_smc_contract = + TRON_TRIGGER_SMART_CONTRACT_INIT_DEFAULT; + google_protobuf_any_t any = contract->parameter; + pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); + + if (!pb_decode( + &stream, TRON_TRIGGER_SMART_CONTRACT_FIELDS, &trigger_smc_contract)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + + // cpy details + uint8_t contract_address[TRON_INITIAL_ADDRESS_LENGTH]; + uint8_t data[68]; + memcpy(contract_address, + (uint8_t *)trigger_smc_contract.contract_address, + TRON_INITIAL_ADDRESS_LENGTH); + memcpy(data, (uint8_t *)trigger_smc_contract.data, 68); + + // user verification + bool is_verified = 0; + if (!parse_whitelist(data, contract_address, &is_verified)) { + return false; + } + if (0 == is_verified && (!parse_unverified(data, contract_address))) { + return false; + } + + set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); + return true; +} + +static bool transfer_asset_contract_txn(tron_transaction_contract_t *contract) { + tron_transfer_asset_contract_t tac_contract = + TRON_TRANSFER_ASSET_CONTRACT_INIT_DEFAULT; + google_protobuf_any_t any = contract->parameter; + pb_istream_t stream = pb_istream_from_buffer(any.value.bytes, any.value.size); + + if (!pb_decode(&stream, TRON_TRANSFER_ASSET_CONTRACT_FIELDS, &tac_contract)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + + uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; + int64_t amount = 0; + char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; + + memcpy(&amount, &tac_contract.amount, sizeof(int64_t)); + memcpy(to_address, + (uint8_t *)tac_contract.to_address, + TRON_INITIAL_ADDRESS_LENGTH); + + // verify recipient address; + if (!base58_encode_check(to_address, + 1 + 20, + HASHER_SHA2D, + address, + TRON_ACCOUNT_ADDRESS_LENGTH + 1)) { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return false; + } + + if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { + return false; + } + + // verify recipient amount + char amount_string[30] = {'\0'}; + char display[100] = {'\0'}; + + snprintf(amount_string, sizeof(amount_string), "%lli", amount); + snprintf( + display, sizeof(display), UI_TEXT_VERIFY_AMOUNT, amount_string, "TOKENS"); + + if (!core_confirmation(display, tron_send_error)) { + return false; + } + // TODO: DISPLAY ASSET NAME/TOKEN ID + // tac_ + + set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +bool extract_contract_info(tron_transaction_raw_t *raw_txn) { + if (!(raw_txn->contract_count > 0)) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return false; + } + + tron_transaction_contract_t contract = raw_txn->contract[0]; + + // TODO: Add switch-cases for more contract types + switch (contract.type) { + case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { + if (!transfer_contract_txn(&contract)) { + return false; + } + break; + } + case TRON_TRANSACTION_CONTRACT_TRIGGER_SMART_CONTRACT: { + if (!trigger_smart_contract_txn(&contract)) { + return false; + } + break; + } + case TRON_TRANSACTION_CONTRACT_TRANSFER_ASSET_CONTRACT: { + if (!transfer_asset_contract_txn(&contract)) { + return false; + } + break; + } + default: { + tron_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + } + return true; +} diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index abb10065..4e49a8b5 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -60,9 +60,9 @@ * INCLUDES *****************************************************************************/ -#include #include #include +#include #include #include #include @@ -271,12 +271,7 @@ STATIC bool tron_handle_initiate_query(const tron_query_t *query) { return false; } - snprintf(msg, - sizeof(msg), - UI_TEXT_SEND_TOKEN_PROMPT, - TRON_LUNIT, - TRON_NAME, - wallet_name); + snprintf(msg, sizeof(msg), UI_TEXT_SIGN_TXN_PROMPT, TRON_NAME, wallet_name); // Take user consent to sign the transaction for the wallet if (!core_confirmation(msg, tron_send_error)) { return false; diff --git a/apps/tron_app/tron_txn_helpers.h b/apps/tron_app/tron_txn_helpers.h index efb5d2fb..3dcde44a 100644 --- a/apps/tron_app/tron_txn_helpers.h +++ b/apps/tron_app/tron_txn_helpers.h @@ -29,11 +29,13 @@ #define TRON_PUB_KEY_SIZE 64 // ECDSA's x+y coordinates only #define TRON_PUB_KEY_SIZE_PLUS_ONE 65 #define TRON_INITIAL_ADDRESS_LENGTH 21 +#define TRON_INITIAL_ADDRESS_LENGTH_MINUS_ONE 20 #define TRON_ACCOUNT_ADDRESS_LENGTH 34 /***************************************************************************** * TYPEDEFS *****************************************************************************/ + /***************************************************************************** * EXPORTED VARIABLES *****************************************************************************/ diff --git a/common/coin_support/tron_parse_txn/abi_extract.c b/common/coin_support/tron_parse_txn/abi_extract.c index c5376313..af1a7a2f 100644 --- a/common/coin_support/tron_parse_txn/abi_extract.c +++ b/common/coin_support/tron_parse_txn/abi_extract.c @@ -62,10 +62,13 @@ #include "abi_extract.h" +#include "tron_contracts.h" + /***************************************************************************** * EXTERN VARIABLES *****************************************************************************/ +extern const uint8_t selector[][4]; /***************************************************************************** * PRIVATE MACROS AND DEFINES *****************************************************************************/ @@ -98,9 +101,23 @@ ui_display_node *extract_data(uint8_t *data) { uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; to_address[0] = 0x41; uint8_t amount[32]; + uint8_t function_selector[4] = {0}; + + memcpy(function_selector, data, 4); + // address is initial_address without '0x41' (20 Bytes) memcpy(to_address + 1, data + 4 + (32 - 20), 20); memcpy(amount, data + 4 + 32, 32); + // check function selector + for (int i = 0; i < TRC20_FUNCTION_SELECTOR_COUNT; i++) { + bool is_valid = 0; + if (memcmp(function_selector, selector[i], 4) == 0) { + is_valid = 1; + } + if (!is_valid) { + return NULL; + } + } char address[TRON_ACCOUNT_ADDRESS_LENGTH + 1] = {0}; // receipent address if (!base58_encode_check(to_address, diff --git a/common/coin_support/tron_parse_txn/abi_extract.h b/common/coin_support/tron_parse_txn/abi_extract.h index dc0b50c2..3826c4be 100644 --- a/common/coin_support/tron_parse_txn/abi_extract.h +++ b/common/coin_support/tron_parse_txn/abi_extract.h @@ -60,9 +60,9 @@ * INCLUDES *****************************************************************************/ -#include #include #include +#include #include #include #include diff --git a/common/coin_support/tron_parse_txn/tron/contract.proto b/common/coin_support/tron_parse_txn/tron/contract.proto new file mode 100644 index 00000000..71ba5fd5 --- /dev/null +++ b/common/coin_support/tron_parse_txn/tron/contract.proto @@ -0,0 +1,238 @@ +/* + * java-tron is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-tron is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +syntax = "proto3"; + +package tron; + +import "tron/tron.proto"; + +message AccountCreateContract { + bytes owner_address = 1; + bytes account_address = 2; + AccountType type = 3; +} + +// Update account name. Account name is not unique now. +message AccountUpdateContract { + bytes account_name = 1; + bytes owner_address = 2; +} + +message TransferContract { + bytes owner_address = 1; + bytes to_address = 2; + int64 amount = 3; +} + +message TransferAssetContract { + bytes asset_name = 1; + bytes owner_address = 2; + bytes to_address = 3; + int64 amount = 4; +} + + +message VoteAssetContract { + bytes owner_address = 1; + repeated bytes vote_address = 2; + bool support = 3; + int32 count = 5; +} + +message VoteWitnessContract { + message Vote { + bytes vote_address = 1; + int64 vote_count = 2; + } + bytes owner_address = 1; + repeated Vote votes = 2; + bool support = 3; +} + +message WitnessCreateContract { + bytes owner_address = 1; + bytes url = 2; +} + +message WitnessUpdateContract { + bytes owner_address = 1; + bytes update_url = 12; +} + +message AssetIssueContract { + message FrozenSupply { + int64 frozen_amount = 1; + int64 frozen_days = 2; + } + bytes owner_address = 1; + bytes name = 2; + bytes abbr = 3; + int64 total_supply = 4; + repeated FrozenSupply frozen_supply = 5; + int32 trx_num = 6; + int32 num = 8; + int64 start_time = 9; + int64 end_time = 10; + int32 vote_score = 16; + bytes description = 20; + bytes url = 21; + int64 free_asset_net_limit = 22; + int64 public_free_asset_net_limit = 23; + int64 public_free_asset_net_usage = 24; + int64 public_latest_free_net_time = 25; +} + +message ParticipateAssetIssueContract { + bytes owner_address = 1; + bytes to_address = 2; + bytes asset_name = 3; // the name of target asset + int64 amount = 4; // the amount of drops +} + +message DeployContract { + bytes owner_address = 1; + bytes script = 2; +} + +enum ResourceCode { + BANDWIDTH = 0x00; + ENERGY = 0x01; +} + +message FreezeBalanceContract { + bytes owner_address = 1; + int64 frozen_balance = 2; + int64 frozen_duration = 3; + + ResourceCode resource = 10; + bytes receiver_address = 15; +} + +message UnfreezeBalanceContract { + bytes owner_address = 1; + + ResourceCode resource = 10; + bytes receiver_address = 15; +} + +message FreezeBalanceV2Contract { + bytes owner_address = 1; + int64 frozen_balance = 2; + ResourceCode resource = 3; +} + +message UnfreezeBalanceV2Contract { + bytes owner_address = 1; + int64 unfreeze_balance = 2; + ResourceCode resource = 3; +} + +message WithdrawExpireUnfreezeContract { + bytes owner_address = 1; +} + +message DelegateResourceContract { + bytes owner_address = 1; + ResourceCode resource = 2; + int64 balance = 3; + bytes receiver_address = 4; + bool lock = 5; +} + +message UnDelegateResourceContract { + bytes owner_address = 1; + ResourceCode resource = 2; + int64 balance = 3; + bytes receiver_address = 4; +} + +message UnfreezeAssetContract { + bytes owner_address = 1; +} + +message WithdrawBalanceContract { + bytes owner_address = 1; +} + +message UpdateAssetContract { + bytes owner_address = 1; + bytes description = 2; + bytes url = 3; + int64 new_limit = 4; + int64 new_public_limit = 5; +} + +message ProposalCreateContract { + bytes owner_address = 1; + map parameters = 2; +} + +message ProposalApproveContract { + bytes owner_address = 1; + int64 proposal_id = 2; + bool is_add_approval = 3; // add or remove approval +} + +message ProposalDeleteContract { + bytes owner_address = 1; + int64 proposal_id = 2; +} + +message TriggerSmartContract { + bytes owner_address = 1; + bytes contract_address = 2; + int64 call_value = 3; + bytes data = 4; + int64 call_token_value = 5; + int64 token_id = 6; +} + +message ExchangeCreateContract { + bytes owner_address = 1; + bytes first_token_id = 2; + int64 first_token_balance = 3; + bytes second_token_id = 4; + int64 second_token_balance = 5; +} + +message ExchangeInjectContract { + bytes owner_address = 1; + int64 exchange_id = 2; + bytes token_id = 3; + int64 quant = 4; +} + +message ExchangeWithdrawContract { + bytes owner_address = 1; + int64 exchange_id = 2; + bytes token_id = 3; + int64 quant = 4; +} + +message ExchangeTransactionContract { + bytes owner_address = 1; + int64 exchange_id = 2; + bytes token_id = 3; + int64 quant = 4; + int64 expected = 5; +} + +message AccountPermissionUpdateContract { + bytes owner_address = 1; + Permission owner = 2; // Empty is invalidate + Permission witness = 3; // Can be empty + repeated Permission actives = 4; // Empty is invalidate + } \ No newline at end of file diff --git a/common/coin_support/tron_parse_txn/tron/google/protobuf/any.proto b/common/coin_support/tron_parse_txn/tron/google/protobuf/any.proto new file mode 100644 index 00000000..49329425 --- /dev/null +++ b/common/coin_support/tron_parse_txn/tron/google/protobuf/any.proto @@ -0,0 +1,154 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "github.com/golang/protobuf/ptypes/any"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "AnyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// Example 4: Pack and unpack a message in Go +// +// foo := &pb.Foo{...} +// any, err := ptypes.MarshalAny(foo) +// ... +// foo := &pb.Foo{} +// if err := ptypes.UnmarshalAny(any, foo); err != nil { +// ... +// } +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name that uniquely identifies the type of the serialized + // protocol buffer message. The last segment of the URL's path must represent + // the fully qualified name of the type (as in + // `path/google.protobuf.Duration`). The name should be in a canonical form + // (e.g., leading "." is not accepted). + // + // In practice, teams usually precompile into the binary all types that they + // expect it to use in the context of Any. However, for URLs which use the + // scheme `http`, `https`, or no scheme, one can optionally set up a type + // server that maps type URLs to message definitions as follows: + // + // * If no scheme is provided, `https` is assumed. + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Note: this functionality is not currently available in the official + // protobuf release, and it is not used for type URLs beginning with + // type.googleapis.com. + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + string type_url = 1; + + // Must be a valid serialized protocol buffer of the above specified type. + bytes value = 2; +} diff --git a/common/coin_support/tron_parse_txn/tron/tron.proto b/common/coin_support/tron_parse_txn/tron/tron.proto new file mode 100644 index 00000000..6820ea43 --- /dev/null +++ b/common/coin_support/tron_parse_txn/tron/tron.proto @@ -0,0 +1,161 @@ +syntax = "proto3"; + +import "tron/google/protobuf/any.proto"; + +package tron; + +enum AccountType { + Normal = 0; + AssetIssue = 1; + Contract = 2; +} + +// Exchange +message Exchange { + int64 exchange_id = 1; + bytes creator_address = 2; + int64 create_time = 3; + bytes first_token_id = 6; + int64 first_token_balance = 7; + bytes second_token_id = 8; + int64 second_token_balance = 9; +} + +// AccountId, (name, address) use name, (null, address) use address, (name, null) use name, +message AccountId { + bytes name = 1; + bytes address = 2; +} + +message authority { + AccountId account = 1; + bytes permission_name = 2; +} + +message Transaction { + message Contract { + enum ContractType { + AccountCreateContract = 0; + TransferContract = 1; + TransferAssetContract = 2; + VoteAssetContract = 3; + VoteWitnessContract = 4; + WitnessCreateContract = 5; + AssetIssueContract = 6; + WitnessUpdateContract = 8; + ParticipateAssetIssueContract = 9; + AccountUpdateContract = 10; + FreezeBalanceContract = 11; + UnfreezeBalanceContract = 12; + WithdrawBalanceContract = 13; + UnfreezeAssetContract = 14; + UpdateAssetContract = 15; + ProposalCreateContract = 16; + ProposalApproveContract = 17; + ProposalDeleteContract = 18; + SetAccountIdContract = 19; + CustomContract = 20; + // BuyStorageContract = 21; + // BuyStorageBytesContract = 22; + // SellStorageContract = 23; + CreateSmartContract = 30; + TriggerSmartContract = 31; + GetContract = 32; + UpdateSettingContract = 33; + ExchangeCreateContract = 41; + ExchangeInjectContract = 42; + ExchangeWithdrawContract = 43; + ExchangeTransactionContract = 44; + UpdateEnergyLimitContract = 45; + AccountPermissionUpdateContract = 46; + ClearABIContract = 48; + UpdateBrokerageContract = 49; + FreezeBalanceV2Contract = 54; + UnfreezeBalanceV2Contract = 55; + WithdrawExpireUnfreezeContract = 56; + DelegateResourceContract = 57; + UnDelegateResourceContract = 58; + } + ContractType type = 1; + google.protobuf.Any parameter = 2; + bytes provider = 3; + bytes ContractName = 4; + int32 Permission_id = 5; + } + + message Result { + enum code { + SUCESS = 0; + FAILED = 1; + } + enum contractResult { + DEFAULT = 0; + SUCCESS = 1; + REVERT = 2; + BAD_JUMP_DESTINATION = 3; + OUT_OF_MEMORY = 4; + PRECOMPILED_CONTRACT = 5; + STACK_TOO_SMALL = 6; + STACK_TOO_LARGE = 7; + ILLEGAL_OPERATION = 8; + STACK_OVERFLOW = 9; + OUT_OF_ENERGY = 10; + OUT_OF_TIME = 11; + JVM_STACK_OVER_FLOW = 12; + UNKNOWN = 13; + TRANSFER_FAILED = 14; + } + int64 fee = 1; + code ret = 2; + contractResult contractRet = 3; + + string assetIssueID = 14; + int64 withdraw_amount = 15; + int64 unfreeze_amount = 16; + int64 exchange_received_amount = 18; + int64 exchange_inject_another_amount = 19; + int64 exchange_withdraw_another_amount = 20; + int64 exchange_id = 21; + } + + message raw { + bytes ref_block_bytes = 1; + int64 ref_block_num = 3; + bytes ref_block_hash = 4; + int64 expiration = 8; + repeated authority auths = 9; + // data not used + bytes custom_data = 10; + //only support size = 1, repeated list here for extension + repeated Contract contract = 11; + // scripts not used + bytes scripts = 12; + int64 timestamp = 14; + int64 fee_limit = 18; + } + + raw raw_data = 1; + // only support size = 1, repeated list here for muti-sig extension + repeated bytes signature = 2; + repeated Result ret = 5; +} + +message Key { + bytes address = 1; + int64 weight = 2; +} + +message Permission { + enum PermissionType { + Owner = 0; + Witness = 1; + Active = 2; + } + PermissionType type = 1; + int32 id = 2; //Owner id=0, Witness id=1, Active id start by 2 + string permission_name = 3; + int64 threshold = 4; + int32 parent_id = 5; + bytes operations = 6; //1 bit 1 contract + repeated Key keys = 7; +} diff --git a/common/proto-options/google/protobuf/any.options b/common/proto-options/tron/google/protobuf/any.options similarity index 51% rename from common/proto-options/google/protobuf/any.options rename to common/proto-options/tron/google/protobuf/any.options index 37b66e73..e5c9f8f2 100644 --- a/common/proto-options/google/protobuf/any.options +++ b/common/proto-options/tron/google/protobuf/any.options @@ -1,2 +1,2 @@ google.protobuf.Any.type_url max_size:64 -google.protobuf.Any.value max_size:116 +google.protobuf.Any.value max_size:116 \ No newline at end of file diff --git a/common/proto-options/tron/sign_txn.options b/common/proto-options/tron/sign_txn.options index b92f7b74..2d0bcb97 100644 --- a/common/proto-options/tron/sign_txn.options +++ b/common/proto-options/tron/sign_txn.options @@ -1,4 +1,4 @@ # Options for file common/cypherock-common/proto/tron/sign_txn.proto -tron.SignTxnInitiateRequest.walletId type:FT_STATIC max_size:32 fixed_length:true -tron.SignTxnInitiateRequest.derivationPath type:FT_STATIC max_count:5 fixed_length:true +tron.SignTxnInitiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true +tron.SignTxnInitiateRequest.derivation_path type:FT_STATIC max_count:5 fixed_length:true tron.SignTxnSignatureResponse.signature type:FT_STATIC max_size:65 fixed_length:true \ No newline at end of file diff --git a/utilities/proto/generate-protob.sh b/utilities/proto/generate-protob.sh index 59f156d7..18b7bced 100755 --- a/utilities/proto/generate-protob.sh +++ b/utilities/proto/generate-protob.sh @@ -9,8 +9,11 @@ PYTHON_VERSION="$(python3 --version)" || exit 1 OUTPUT_DIR="$(pwd)/generated/proto" PROTO_SRC="$(pwd)/common/cypherock-common/proto" OPTIONS_DIR="$(pwd)/common/proto-options/" +# Path for tron-specific device protocol structures +PROTO_TRON="$(pwd)/common/coin_support/tron_parse_txn/" test -d "${PROTO_SRC}" +test -d "${PROTO_TRON}" test -f "${NANOPB_GEN}" echo -e "Detected ${PYTHON_VERSION} (at $(which python3))" @@ -24,4 +27,6 @@ cd "${PROTO_SRC}" # btc.error.proto) as it would result into a collision. # By using <> format instead of "proto/" helps because in future, relocation # of generated files would not require updating this parameter. -python3 "${NANOPB_GEN}" -q --generated-include-format "#include <%s>" --proto-path="${PROTO_SRC}" --options-path="${OPTIONS_DIR}" $(find "${PROTO_SRC}" -name "*.proto") --output-dir="${OUTPUT_DIR}" --c-style -s anonymous_oneof:true -s long_names:false \ No newline at end of file +python3 "${NANOPB_GEN}" -q --generated-include-format "#include <%s>" --proto-path="${PROTO_SRC}" --options-path="${OPTIONS_DIR}" $(find "${PROTO_SRC}" -name "*.proto") --output-dir="${OUTPUT_DIR}" --c-style -s anonymous_oneof:true -s long_names:false +# generate tron files +python3 "${NANOPB_GEN}" -q --generated-include-format "#include <%s>" --proto-path="${PROTO_TRON}" --options-path="${OPTIONS_DIR}" $(find "${PROTO_TRON}" -name "*.proto") --output-dir="${OUTPUT_DIR}" --c-style -s anonymous_oneof:true -s long_names:false \ No newline at end of file From 4f552c10108ce11aa35d054a463e7c64a9551e7c Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Sat, 15 Jun 2024 11:00:53 +0530 Subject: [PATCH 14/22] fix(app): Decimal places trx --- apps/tron_app/tron_contracts.c | 45 ++- apps/tron_app/tron_contracts.h | 2 +- apps/tron_app/tron_parse_contracts.c | 13 +- .../tron_parse_txn/tron/contract.proto | 372 +++++++++--------- .../tron_parse_txn/tron/tron.proto | 96 ++--- .../tron/google/protobuf/any.options | 4 +- 6 files changed, 281 insertions(+), 251 deletions(-) diff --git a/apps/tron_app/tron_contracts.c b/apps/tron_app/tron_contracts.c index 06a87b78..dc7e7948 100644 --- a/apps/tron_app/tron_contracts.c +++ b/apps/tron_app/tron_contracts.c @@ -10,13 +10,42 @@ const uint8_t selector[TRC20_FUNCTION_SELECTOR_COUNT][4] = { {0xA9, 0x05, 0x9C, 0xBB}}; //, {0x09, 0x5E, 0xA7, 0xB3}}; const trc20_contracts_t trc20_contracts[TRC20_WHITELISTED_CONTRACTS_COUNT] = { - // 0chain - {{0x41, 0xEA, 0x51, 0x34, 0x2D, 0xAB, 0xBB, 0x92, 0x8A, 0xE1, 0xE5, - 0x76, 0xBD, 0x39, 0xEF, 0xF8, 0xAA, 0xF0, 0x70, 0xA8, 0xC6}, - "USDT", // TESTNET + // USDT + {{0x41, 0xA6, 0x14, 0xF8, 0x03, 0xB6, 0xFD, 0x78, 0x09, 0x86, 0xA4, + 0x2C, 0x78, 0xEC, 0x9C, 0x7F, 0x77, 0xE6, 0xDE, 0xD1, 0x3C}, + "USDT", 6}, // 0x - {{0xe4, 0x1d, 0x24, 0x89, 0x57, 0x1d, 0x32, 0x21, 0x89, 0x24, - 0x6d, 0xaf, 0xa5, 0xeb, 0xde, 0x1f, 0x46, 0x99, 0xf4, 0x98}, - "ZRX", - 18}}; \ No newline at end of file + {{0x41, 0x34, 0x87, 0xb6, 0x3d, 0x30, 0xb5, 0xb2, 0xc8, 0x7f, 0xb7, + 0xff, 0xa8, 0xbc, 0xfa, 0xde, 0x38, 0xea, 0xac, 0x1a, 0xbe}, + "USDC", + 6}, + {{0x41, 0x94, 0xf2, 0x4e, 0x99, 0x2c, 0xa0, 0x4b, 0x49, 0xc6, 0xf2, + 0xa2, 0x75, 0x30, 0x76, 0xef, 0x89, 0x38, 0xed, 0x4d, 0xaa}, + "USDD", + 18}, + {{0x41, 0x03, 0x20, 0x17, 0x41, 0x1f, 0x46, 0x63, 0xb3, 0x17, 0xfe, + 0x77, 0xc2, 0x57, 0xd2, 0x8d, 0x5c, 0xd1, 0xb2, 0x6e, 0x3d}, + "BTT", + 18}, + {{0x41, 0xce, 0xbd, 0xe7, 0x10, 0x77, 0xb8, 0x30, 0xb9, 0x58, 0xc8, + 0xda, 0x17, 0xbc, 0xdd, 0xee, 0xb8, 0x5d, 0x0b, 0xcf, 0x25}, + "TUSD", + 18}, + {{0x41, 0x3d, 0xfe, 0x63, 0x7b, 0x2b, 0x9a, 0xe4, 0x19, 0x0a, 0x45, + 0x8b, 0x5f, 0x3e, 0xfc, 0x19, 0x69, 0xaf, 0xe2, 0x78, 0x19}, + "NFT", + 6}, + {{0x41, 0x18, 0xfd, 0x06, 0x26, 0xda, 0xf3, 0xaf, 0x02, 0x38, 0x9a, + 0xef, 0x3e, 0xd8, 0x7d, 0xb9, 0xc3, 0x3f, 0x63, 0x8f, 0xfa}, + "JST", + 18}, + {{0x41, 0x74, 0x47, 0x2E, 0x7D, 0x35, 0x39, 0x5A, 0x6B, 0x5A, 0xDD, + 0x42, 0x7E, 0xEC, 0xB7, 0xF4, 0xB6, 0x2A, 0xD2, 0xB0, 0x71}, + "WIN", + 6}, + {{0x41, 0x89, 0x1c, 0xdb, 0x91, 0xd1, 0x49, 0xf2, 0x3b, 0x1a, 0x45, + 0xd9, 0xc5, 0xca, 0x78, 0xa8, 0x8d, 0x0c, 0xb4, 0x4c, 0x18}, + "WTRX", + 6}, +}; \ No newline at end of file diff --git a/apps/tron_app/tron_contracts.h b/apps/tron_app/tron_contracts.h index 4cb744ec..8c80575e 100644 --- a/apps/tron_app/tron_contracts.h +++ b/apps/tron_app/tron_contracts.h @@ -10,5 +10,5 @@ typedef struct trc20_contracts { } trc20_contracts_t; /// Number of entries in whitelisted contracts list -#define TRC20_WHITELISTED_CONTRACTS_COUNT 2 +#define TRC20_WHITELISTED_CONTRACTS_COUNT 9 #define TRC20_FUNCTION_SELECTOR_COUNT 1 \ No newline at end of file diff --git a/apps/tron_app/tron_parse_contracts.c b/apps/tron_app/tron_parse_contracts.c index 574666ad..2dbe7ba2 100644 --- a/apps/tron_app/tron_parse_contracts.c +++ b/apps/tron_app/tron_parse_contracts.c @@ -279,9 +279,11 @@ static bool transfer_contract_txn(tron_transaction_contract_t *contract) { // verify recipient amount char amount_string[30] = {'\0'}; - char display[100] = {'\0'}; + double decimal_amount = (double)amount; + decimal_amount *= 1e-6; + snprintf(amount_string, sizeof(amount_string), "%.6f", decimal_amount); - snprintf(amount_string, sizeof(amount_string), "%lli", amount); + char display[100] = {'\0'}; snprintf(display, sizeof(display), UI_TEXT_VERIFY_AMOUNT, @@ -361,6 +363,8 @@ static bool transfer_asset_contract_txn(tron_transaction_contract_t *contract) { return false; } + delay_scr_init(ui_text_unverified_contract, DELAY_TIME); + if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { return false; } @@ -370,14 +374,12 @@ static bool transfer_asset_contract_txn(tron_transaction_contract_t *contract) { char display[100] = {'\0'}; snprintf(amount_string, sizeof(amount_string), "%lli", amount); - snprintf( - display, sizeof(display), UI_TEXT_VERIFY_AMOUNT, amount_string, "TOKENS"); + snprintf(display, sizeof(display), "Verify amount\n%s", amount_string); if (!core_confirmation(display, tron_send_error)) { return false; } // TODO: DISPLAY ASSET NAME/TOKEN ID - // tac_ set_app_flow_status(TRON_SIGN_TXN_STATUS_VERIFY); return true; @@ -396,7 +398,6 @@ bool extract_contract_info(tron_transaction_raw_t *raw_txn) { tron_transaction_contract_t contract = raw_txn->contract[0]; - // TODO: Add switch-cases for more contract types switch (contract.type) { case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { if (!transfer_contract_txn(&contract)) { diff --git a/common/coin_support/tron_parse_txn/tron/contract.proto b/common/coin_support/tron_parse_txn/tron/contract.proto index 71ba5fd5..deb1ff22 100644 --- a/common/coin_support/tron_parse_txn/tron/contract.proto +++ b/common/coin_support/tron_parse_txn/tron/contract.proto @@ -19,17 +19,17 @@ package tron; import "tron/tron.proto"; -message AccountCreateContract { - bytes owner_address = 1; - bytes account_address = 2; - AccountType type = 3; -} - -// Update account name. Account name is not unique now. -message AccountUpdateContract { - bytes account_name = 1; - bytes owner_address = 2; -} +// message AccountCreateContract { +// bytes owner_address = 1; +// bytes account_address = 2; +// AccountType type = 3; +// } + +// // Update account name. Account name is not unique now. +// message AccountUpdateContract { +// bytes account_name = 1; +// bytes owner_address = 2; +// } message TransferContract { bytes owner_address = 1; @@ -45,151 +45,151 @@ message TransferAssetContract { } -message VoteAssetContract { - bytes owner_address = 1; - repeated bytes vote_address = 2; - bool support = 3; - int32 count = 5; -} - -message VoteWitnessContract { - message Vote { - bytes vote_address = 1; - int64 vote_count = 2; - } - bytes owner_address = 1; - repeated Vote votes = 2; - bool support = 3; -} - -message WitnessCreateContract { - bytes owner_address = 1; - bytes url = 2; -} - -message WitnessUpdateContract { - bytes owner_address = 1; - bytes update_url = 12; -} - -message AssetIssueContract { - message FrozenSupply { - int64 frozen_amount = 1; - int64 frozen_days = 2; - } - bytes owner_address = 1; - bytes name = 2; - bytes abbr = 3; - int64 total_supply = 4; - repeated FrozenSupply frozen_supply = 5; - int32 trx_num = 6; - int32 num = 8; - int64 start_time = 9; - int64 end_time = 10; - int32 vote_score = 16; - bytes description = 20; - bytes url = 21; - int64 free_asset_net_limit = 22; - int64 public_free_asset_net_limit = 23; - int64 public_free_asset_net_usage = 24; - int64 public_latest_free_net_time = 25; -} - -message ParticipateAssetIssueContract { - bytes owner_address = 1; - bytes to_address = 2; - bytes asset_name = 3; // the name of target asset - int64 amount = 4; // the amount of drops -} - -message DeployContract { - bytes owner_address = 1; - bytes script = 2; -} +// message VoteAssetContract { +// bytes owner_address = 1; +// repeated bytes vote_address = 2; +// bool support = 3; +// int32 count = 5; +// } + +// message VoteWitnessContract { +// message Vote { +// bytes vote_address = 1; +// int64 vote_count = 2; +// } +// bytes owner_address = 1; +// repeated Vote votes = 2; +// bool support = 3; +// } + +// message WitnessCreateContract { +// bytes owner_address = 1; +// bytes url = 2; +// } + +// message WitnessUpdateContract { +// bytes owner_address = 1; +// bytes update_url = 12; +// } + +// message AssetIssueContract { +// message FrozenSupply { +// int64 frozen_amount = 1; +// int64 frozen_days = 2; +// } +// bytes owner_address = 1; +// bytes name = 2; +// bytes abbr = 3; +// int64 total_supply = 4; +// repeated FrozenSupply frozen_supply = 5; +// int32 trx_num = 6; +// int32 num = 8; +// int64 start_time = 9; +// int64 end_time = 10; +// int32 vote_score = 16; +// bytes description = 20; +// bytes url = 21; +// int64 free_asset_net_limit = 22; +// int64 public_free_asset_net_limit = 23; +// int64 public_free_asset_net_usage = 24; +// int64 public_latest_free_net_time = 25; +// } + +// message ParticipateAssetIssueContract { +// bytes owner_address = 1; +// bytes to_address = 2; +// bytes asset_name = 3; // the name of target asset +// int64 amount = 4; // the amount of drops +// } + +// message DeployContract { +// bytes owner_address = 1; +// bytes script = 2; +// } enum ResourceCode { BANDWIDTH = 0x00; ENERGY = 0x01; } -message FreezeBalanceContract { - bytes owner_address = 1; - int64 frozen_balance = 2; - int64 frozen_duration = 3; - - ResourceCode resource = 10; - bytes receiver_address = 15; -} - -message UnfreezeBalanceContract { - bytes owner_address = 1; - - ResourceCode resource = 10; - bytes receiver_address = 15; -} - -message FreezeBalanceV2Contract { - bytes owner_address = 1; - int64 frozen_balance = 2; - ResourceCode resource = 3; -} - -message UnfreezeBalanceV2Contract { - bytes owner_address = 1; - int64 unfreeze_balance = 2; - ResourceCode resource = 3; -} - -message WithdrawExpireUnfreezeContract { - bytes owner_address = 1; -} - -message DelegateResourceContract { - bytes owner_address = 1; - ResourceCode resource = 2; - int64 balance = 3; - bytes receiver_address = 4; - bool lock = 5; -} - -message UnDelegateResourceContract { - bytes owner_address = 1; - ResourceCode resource = 2; - int64 balance = 3; - bytes receiver_address = 4; -} - -message UnfreezeAssetContract { - bytes owner_address = 1; -} - -message WithdrawBalanceContract { - bytes owner_address = 1; -} - -message UpdateAssetContract { - bytes owner_address = 1; - bytes description = 2; - bytes url = 3; - int64 new_limit = 4; - int64 new_public_limit = 5; -} - -message ProposalCreateContract { - bytes owner_address = 1; - map parameters = 2; -} - -message ProposalApproveContract { - bytes owner_address = 1; - int64 proposal_id = 2; - bool is_add_approval = 3; // add or remove approval -} - -message ProposalDeleteContract { - bytes owner_address = 1; - int64 proposal_id = 2; -} +// message FreezeBalanceContract { +// bytes owner_address = 1; +// int64 frozen_balance = 2; +// int64 frozen_duration = 3; + +// ResourceCode resource = 10; +// bytes receiver_address = 15; +// } + +// message UnfreezeBalanceContract { +// bytes owner_address = 1; + +// ResourceCode resource = 10; +// bytes receiver_address = 15; +// } + +// message FreezeBalanceV2Contract { +// bytes owner_address = 1; +// int64 frozen_balance = 2; +// ResourceCode resource = 3; +// } + +// message UnfreezeBalanceV2Contract { +// bytes owner_address = 1; +// int64 unfreeze_balance = 2; +// ResourceCode resource = 3; +// } + +// message WithdrawExpireUnfreezeContract { +// bytes owner_address = 1; +// } + +// message DelegateResourceContract { +// bytes owner_address = 1; +// ResourceCode resource = 2; +// int64 balance = 3; +// bytes receiver_address = 4; +// bool lock = 5; +// } + +// message UnDelegateResourceContract { +// bytes owner_address = 1; +// ResourceCode resource = 2; +// int64 balance = 3; +// bytes receiver_address = 4; +// } + +// message UnfreezeAssetContract { +// bytes owner_address = 1; +// } + +// message WithdrawBalanceContract { +// bytes owner_address = 1; +// } + +// message UpdateAssetContract { +// bytes owner_address = 1; +// bytes description = 2; +// bytes url = 3; +// int64 new_limit = 4; +// int64 new_public_limit = 5; +// } + +// message ProposalCreateContract { +// bytes owner_address = 1; +// map parameters = 2; +// } + +// message ProposalApproveContract { +// bytes owner_address = 1; +// int64 proposal_id = 2; +// bool is_add_approval = 3; // add or remove approval +// } + +// message ProposalDeleteContract { +// bytes owner_address = 1; +// int64 proposal_id = 2; +// } message TriggerSmartContract { bytes owner_address = 1; @@ -200,39 +200,39 @@ message TriggerSmartContract { int64 token_id = 6; } -message ExchangeCreateContract { - bytes owner_address = 1; - bytes first_token_id = 2; - int64 first_token_balance = 3; - bytes second_token_id = 4; - int64 second_token_balance = 5; -} - -message ExchangeInjectContract { - bytes owner_address = 1; - int64 exchange_id = 2; - bytes token_id = 3; - int64 quant = 4; -} - -message ExchangeWithdrawContract { - bytes owner_address = 1; - int64 exchange_id = 2; - bytes token_id = 3; - int64 quant = 4; -} - -message ExchangeTransactionContract { - bytes owner_address = 1; - int64 exchange_id = 2; - bytes token_id = 3; - int64 quant = 4; - int64 expected = 5; -} - -message AccountPermissionUpdateContract { - bytes owner_address = 1; - Permission owner = 2; // Empty is invalidate - Permission witness = 3; // Can be empty - repeated Permission actives = 4; // Empty is invalidate - } \ No newline at end of file +// message ExchangeCreateContract { +// bytes owner_address = 1; +// bytes first_token_id = 2; +// int64 first_token_balance = 3; +// bytes second_token_id = 4; +// int64 second_token_balance = 5; +// } + +// message ExchangeInjectContract { +// bytes owner_address = 1; +// int64 exchange_id = 2; +// bytes token_id = 3; +// int64 quant = 4; +// } + +// message ExchangeWithdrawContract { +// bytes owner_address = 1; +// int64 exchange_id = 2; +// bytes token_id = 3; +// int64 quant = 4; +// } + +// message ExchangeTransactionContract { +// bytes owner_address = 1; +// int64 exchange_id = 2; +// bytes token_id = 3; +// int64 quant = 4; +// int64 expected = 5; +// } + +// message AccountPermissionUpdateContract { +// bytes owner_address = 1; +// Permission owner = 2; // Empty is invalidate +// Permission witness = 3; // Can be empty +// repeated Permission actives = 4; // Empty is invalidate +// } \ No newline at end of file diff --git a/common/coin_support/tron_parse_txn/tron/tron.proto b/common/coin_support/tron_parse_txn/tron/tron.proto index 6820ea43..6436cb18 100644 --- a/common/coin_support/tron_parse_txn/tron/tron.proto +++ b/common/coin_support/tron_parse_txn/tron/tron.proto @@ -4,22 +4,22 @@ import "tron/google/protobuf/any.proto"; package tron; -enum AccountType { - Normal = 0; - AssetIssue = 1; - Contract = 2; -} +// enum AccountType { +// Normal = 0; +// AssetIssue = 1; +// Contract = 2; +// } -// Exchange -message Exchange { - int64 exchange_id = 1; - bytes creator_address = 2; - int64 create_time = 3; - bytes first_token_id = 6; - int64 first_token_balance = 7; - bytes second_token_id = 8; - int64 second_token_balance = 9; -} +// // Exchange +// message Exchange { +// int64 exchange_id = 1; +// bytes creator_address = 2; +// int64 create_time = 3; +// bytes first_token_id = 6; +// int64 first_token_balance = 7; +// bytes second_token_id = 8; +// int64 second_token_balance = 9; +// } // AccountId, (name, address) use name, (null, address) use address, (name, null) use name, message AccountId { @@ -38,43 +38,43 @@ message Transaction { AccountCreateContract = 0; TransferContract = 1; TransferAssetContract = 2; - VoteAssetContract = 3; - VoteWitnessContract = 4; - WitnessCreateContract = 5; - AssetIssueContract = 6; - WitnessUpdateContract = 8; - ParticipateAssetIssueContract = 9; - AccountUpdateContract = 10; - FreezeBalanceContract = 11; - UnfreezeBalanceContract = 12; - WithdrawBalanceContract = 13; - UnfreezeAssetContract = 14; - UpdateAssetContract = 15; - ProposalCreateContract = 16; - ProposalApproveContract = 17; - ProposalDeleteContract = 18; - SetAccountIdContract = 19; - CustomContract = 20; + // VoteAssetContract = 3; + // VoteWitnessContract = 4; + // WitnessCreateContract = 5; + // AssetIssueContract = 6; + // WitnessUpdateContract = 8; + // ParticipateAssetIssueContract = 9; + // AccountUpdateContract = 10; + // FreezeBalanceContract = 11; + // UnfreezeBalanceContract = 12; + // WithdrawBalanceContract = 13; + // UnfreezeAssetContract = 14; + // UpdateAssetContract = 15; + // ProposalCreateContract = 16; + // ProposalApproveContract = 17; + // ProposalDeleteContract = 18; + // SetAccountIdContract = 19; + // CustomContract = 20; // BuyStorageContract = 21; // BuyStorageBytesContract = 22; // SellStorageContract = 23; - CreateSmartContract = 30; + // CreateSmartContract = 30; TriggerSmartContract = 31; - GetContract = 32; - UpdateSettingContract = 33; - ExchangeCreateContract = 41; - ExchangeInjectContract = 42; - ExchangeWithdrawContract = 43; - ExchangeTransactionContract = 44; - UpdateEnergyLimitContract = 45; - AccountPermissionUpdateContract = 46; - ClearABIContract = 48; - UpdateBrokerageContract = 49; - FreezeBalanceV2Contract = 54; - UnfreezeBalanceV2Contract = 55; - WithdrawExpireUnfreezeContract = 56; - DelegateResourceContract = 57; - UnDelegateResourceContract = 58; + // GetContract = 32; + // UpdateSettingContract = 33; + // ExchangeCreateContract = 41; + // ExchangeInjectContract = 42; + // ExchangeWithdrawContract = 43; + // ExchangeTransactionContract = 44; + // UpdateEnergyLimitContract = 45; + // AccountPermissionUpdateContract = 46; + // ClearABIContract = 48; + // UpdateBrokerageContract = 49; + // FreezeBalanceV2Contract = 54; + // UnfreezeBalanceV2Contract = 55; + // WithdrawExpireUnfreezeContract = 56; + // DelegateResourceContract = 57; + // UnDelegateResourceContract = 58; } ContractType type = 1; google.protobuf.Any parameter = 2; diff --git a/common/proto-options/tron/google/protobuf/any.options b/common/proto-options/tron/google/protobuf/any.options index e5c9f8f2..ff0f0f6b 100644 --- a/common/proto-options/tron/google/protobuf/any.options +++ b/common/proto-options/tron/google/protobuf/any.options @@ -1,2 +1,2 @@ -google.protobuf.Any.type_url max_size:64 -google.protobuf.Any.value max_size:116 \ No newline at end of file +google.protobuf.Any.type_url max_size:100 +google.protobuf.Any.value max_size:200 \ No newline at end of file From 059712575cfd4717508f9feb9d7894774d7cac6e Mon Sep 17 00:00:00 2001 From: vrockz747 Date: Mon, 17 Jun 2024 00:32:34 +0530 Subject: [PATCH 15/22] chore(app): Comments and prototypes --- apps/tron_app/tron_context.h | 6 ++ apps/tron_app/tron_contracts.c | 97 ++++++++++++++++++- apps/tron_app/tron_contracts.h | 40 +++++++- apps/tron_app/tron_parse_contracts.c | 46 ++++++++- .../coin_support/tron_parse_txn/abi_extract.c | 1 + .../coin_support/tron_parse_txn/abi_extract.h | 13 +++ .../tron_parse_txn/tron/contract.proto | 2 +- 7 files changed, 194 insertions(+), 11 deletions(-) diff --git a/apps/tron_app/tron_context.h b/apps/tron_app/tron_context.h index 2610ef08..539bd75e 100644 --- a/apps/tron_app/tron_context.h +++ b/apps/tron_app/tron_context.h @@ -35,6 +35,12 @@ typedef struct { /***************************************************************************** * GLOBAL FUNCTION PROTOTYPES *****************************************************************************/ +/** + * @brief Function for handling the parameter field of tron txns + * + * @param[in] raw_txn: tron raw transaction + * @return bool True if decoding was successful, else false + */ bool extract_contract_info(tron_transaction_raw_t *raw_txn); #endif /* TRON_CONTEXT_H */ diff --git a/apps/tron_app/tron_contracts.c b/apps/tron_app/tron_contracts.c index dc7e7948..90acfbbe 100644 --- a/apps/tron_app/tron_contracts.c +++ b/apps/tron_app/tron_contracts.c @@ -1,21 +1,100 @@ +/** + * @file TRON_contracts.c + * @author Cypherock X1 Team + * @brief TRON whitelisted contracts list + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + #include +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ // a9059cbb -> transfer(address,uint256) -// 095ea7b3 -> approve(address,uint256) const uint8_t selector[TRC20_FUNCTION_SELECTOR_COUNT][4] = { - {0xA9, 0x05, 0x9C, 0xBB}}; //, {0x09, 0x5E, 0xA7, 0xB3}}; + {0xA9, 0x05, 0x9C, 0xBB}}; const trc20_contracts_t trc20_contracts[TRC20_WHITELISTED_CONTRACTS_COUNT] = { - // USDT {{0x41, 0xA6, 0x14, 0xF8, 0x03, 0xB6, 0xFD, 0x78, 0x09, 0x86, 0xA4, 0x2C, 0x78, 0xEC, 0x9C, 0x7F, 0x77, 0xE6, 0xDE, 0xD1, 0x3C}, "USDT", 6}, - // 0x {{0x41, 0x34, 0x87, 0xb6, 0x3d, 0x30, 0xb5, 0xb2, 0xc8, 0x7f, 0xb7, 0xff, 0xa8, 0xbc, 0xfa, 0xde, 0x38, 0xea, 0xac, 0x1a, 0xbe}, "USDC", @@ -48,4 +127,12 @@ const trc20_contracts_t trc20_contracts[TRC20_WHITELISTED_CONTRACTS_COUNT] = { 0xd9, 0xc5, 0xca, 0x78, 0xa8, 0x8d, 0x0c, 0xb4, 0x4c, 0x18}, "WTRX", 6}, -}; \ No newline at end of file +}; + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ diff --git a/apps/tron_app/tron_contracts.h b/apps/tron_app/tron_contracts.h index 8c80575e..7fdf4811 100644 --- a/apps/tron_app/tron_contracts.h +++ b/apps/tron_app/tron_contracts.h @@ -1,7 +1,33 @@ +/** + * @file tron_contracts.h + * @author Cypherock X1 Team + * @brief TRON contract related definitions and types + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef TRON_CONTRACTS_H +#define TRON_CONTRACTS_H +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + #include +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +// Number of entries in whitelisted contracts list +#define TRC20_WHITELISTED_CONTRACTS_COUNT 9 +#define TRC20_FUNCTION_SELECTOR_COUNT 1 + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + typedef struct trc20_contracts { - /// 20-byte hex coded public address of the contract + /// 21-byte hex coded public address of the contract const uint8_t address[TRON_INITIAL_ADDRESS_LENGTH]; /// Symbol (short alphabetical representation) of the contract token const char *symbol; @@ -9,6 +35,12 @@ typedef struct trc20_contracts { const uint8_t decimal; } trc20_contracts_t; -/// Number of entries in whitelisted contracts list -#define TRC20_WHITELISTED_CONTRACTS_COUNT 9 -#define TRC20_FUNCTION_SELECTOR_COUNT 1 \ No newline at end of file +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +#endif // TRON_CONTRACTS_H diff --git a/apps/tron_app/tron_parse_contracts.c b/apps/tron_app/tron_parse_contracts.c index 2dbe7ba2..bea49e59 100644 --- a/apps/tron_app/tron_parse_contracts.c +++ b/apps/tron_app/tron_parse_contracts.c @@ -95,7 +95,7 @@ * will enable the device to verify the TRC20 token transaction in a * user-friendly manner. * - * @see erc20_contracts_t + * @see trc20_contracts_t */ extern const trc20_contracts_t trc20_contracts[]; @@ -110,6 +110,46 @@ extern const trc20_contracts_t trc20_contracts[]; /***************************************************************************** * STATIC FUNCTION PROTOTYPES *****************************************************************************/ +/** + * @brief Checks if the provided token address is whitelisted and return the + * matching contract instance. + * + * @param address Reference to the buffer containing the token address + * @param contract Pointer to store the matched contract address instance + * + * @return bool Indicating if the provided token address is whitelisted + * @return true If the address matches to an entry in the whitelist + * @return false If the address does not match to an entry in the whitelist + */ +static bool is_token_whitelisted(const uint8_t *address, + const trc20_contracts_t **contract); + +/** + * @brief User verification case when token is whitelisted + * + * @param data ABI encoded data field of tron txn + * @param contract_address contract address of current txn + * @param status Indicates the result of is_token_whitelisted + * + * @return bool Indicating parsing and verification status + * @return true If parsing and user verification successful + * @return false If parsing error or user denial + */ +static bool parse_whitelist(uint8_t *data, + const uint8_t *contract_address, + bool *status); + +/** + * @brief User verification case when token is not whitelisted + * + * @param data ABI encoded data field of tron txn + * @param contract_address contract address of current txn + * + * @return bool Indicating parsing and verification status + * @return true If parsing and user verification successful + * @return false If parsing error or user denial + */ +static bool parse_unverified(uint8_t *data, uint8_t *contract_address); /***************************************************************************** * STATIC VARIABLES @@ -242,6 +282,7 @@ static bool parse_unverified(uint8_t *data, uint8_t *contract_address) { cy_free(); return true; } + static bool transfer_contract_txn(tron_transaction_contract_t *contract) { uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; // uint8_t owner_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; @@ -400,18 +441,21 @@ bool extract_contract_info(tron_transaction_raw_t *raw_txn) { switch (contract.type) { case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { + // Transfer TRX type if (!transfer_contract_txn(&contract)) { return false; } break; } case TRON_TRANSACTION_CONTRACT_TRIGGER_SMART_CONTRACT: { + // TRC20 type if (!trigger_smart_contract_txn(&contract)) { return false; } break; } case TRON_TRANSACTION_CONTRACT_TRANSFER_ASSET_CONTRACT: { + // TRC10 type if (!transfer_asset_contract_txn(&contract)) { return false; } diff --git a/common/coin_support/tron_parse_txn/abi_extract.c b/common/coin_support/tron_parse_txn/abi_extract.c index af1a7a2f..32979802 100644 --- a/common/coin_support/tron_parse_txn/abi_extract.c +++ b/common/coin_support/tron_parse_txn/abi_extract.c @@ -69,6 +69,7 @@ *****************************************************************************/ extern const uint8_t selector[][4]; + /***************************************************************************** * PRIVATE MACROS AND DEFINES *****************************************************************************/ diff --git a/common/coin_support/tron_parse_txn/abi_extract.h b/common/coin_support/tron_parse_txn/abi_extract.h index 3826c4be..00d2ead5 100644 --- a/common/coin_support/tron_parse_txn/abi_extract.h +++ b/common/coin_support/tron_parse_txn/abi_extract.h @@ -98,5 +98,18 @@ /***************************************************************************** * GLOBAL FUNCTION PROTOTYPES *****************************************************************************/ +/** + * @brief This function converts ABI value to UTF8 format + * to be displayed on the LED display for user verification for tron txns. + * This function creates and returns a UI node of type ui_display_node. + * Important thing to note here is that it only supports static Abi type data. + * If the Abi data is dynamic, it must be broken down into static data and then + * stringified. + * + * @param data Pointer to Abi data to be stringified + * + * @return ui_display_node: This function returns pointer to the UI node which + * can be displayed by the caller. + */ ui_display_node *extract_data(uint8_t *data); diff --git a/common/coin_support/tron_parse_txn/tron/contract.proto b/common/coin_support/tron_parse_txn/tron/contract.proto index deb1ff22..50e4557a 100644 --- a/common/coin_support/tron_parse_txn/tron/contract.proto +++ b/common/coin_support/tron_parse_txn/tron/contract.proto @@ -17,7 +17,7 @@ syntax = "proto3"; package tron; -import "tron/tron.proto"; +//import "tron/tron.proto"; // message AccountCreateContract { // bytes owner_address = 1; From f5a89ce9faca89bce959ee718db0aa76d7dfdebe Mon Sep 17 00:00:00 2001 From: Vaibhav Sethia Date: Mon, 17 Jun 2024 13:25:52 +0530 Subject: [PATCH 16/22] fix(app): Merge conflicts --- common/cypherock-common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cypherock-common b/common/cypherock-common index da546059..79e2f03a 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit da546059a3185822a9272b196424ee62c589eadd +Subproject commit 79e2f03a5d16c4ce8cbb50b472620034f984d735 From d27a9c17796b4b01ddadac7f8bc11c1eca993ebe Mon Sep 17 00:00:00 2001 From: Vaibhav Sethia Date: Thu, 20 Jun 2024 17:55:34 +0530 Subject: [PATCH 17/22] fix(app): Review changes --- apps/tron_app/tron_contracts.c | 61 +++++++++++++++++++++++++++++++- apps/tron_app/tron_contracts.h | 2 +- apps/tron_app/tron_helpers.c | 2 ++ apps/tron_app/tron_helpers.h | 4 ++- apps/tron_app/tron_pub_key.c | 36 +++++++++---------- apps/tron_app/tron_txn_helpers.c | 11 +++++- apps/tron_app/tron_txn_helpers.h | 4 +-- 7 files changed, 93 insertions(+), 27 deletions(-) diff --git a/apps/tron_app/tron_contracts.c b/apps/tron_app/tron_contracts.c index 90acfbbe..7215707d 100644 --- a/apps/tron_app/tron_contracts.c +++ b/apps/tron_app/tron_contracts.c @@ -1,5 +1,5 @@ /** - * @file TRON_contracts.c + * @file tron_contracts.c * @author Cypherock X1 Team * @brief TRON whitelisted contracts list * @copyright Copyright (c) 2023 HODL TECH PTE LTD @@ -91,42 +91,101 @@ const uint8_t selector[TRC20_FUNCTION_SELECTOR_COUNT][4] = { {0xA9, 0x05, 0x9C, 0xBB}}; const trc20_contracts_t trc20_contracts[TRC20_WHITELISTED_CONTRACTS_COUNT] = { + // Tether USD {{0x41, 0xA6, 0x14, 0xF8, 0x03, 0xB6, 0xFD, 0x78, 0x09, 0x86, 0xA4, 0x2C, 0x78, 0xEC, 0x9C, 0x7F, 0x77, 0xE6, 0xDE, 0xD1, 0x3C}, "USDT", 6}, + // USD Coin {{0x41, 0x34, 0x87, 0xb6, 0x3d, 0x30, 0xb5, 0xb2, 0xc8, 0x7f, 0xb7, 0xff, 0xa8, 0xbc, 0xfa, 0xde, 0x38, 0xea, 0xac, 0x1a, 0xbe}, "USDC", 6}, + // Decentralized USD {{0x41, 0x94, 0xf2, 0x4e, 0x99, 0x2c, 0xa0, 0x4b, 0x49, 0xc6, 0xf2, 0xa2, 0x75, 0x30, 0x76, 0xef, 0x89, 0x38, 0xed, 0x4d, 0xaa}, "USDD", 18}, + // BitTorrent {{0x41, 0x03, 0x20, 0x17, 0x41, 0x1f, 0x46, 0x63, 0xb3, 0x17, 0xfe, 0x77, 0xc2, 0x57, 0xd2, 0x8d, 0x5c, 0xd1, 0xb2, 0x6e, 0x3d}, "BTT", 18}, + // TrueUSD {{0x41, 0xce, 0xbd, 0xe7, 0x10, 0x77, 0xb8, 0x30, 0xb9, 0x58, 0xc8, 0xda, 0x17, 0xbc, 0xdd, 0xee, 0xb8, 0x5d, 0x0b, 0xcf, 0x25}, "TUSD", 18}, + // APENFT {{0x41, 0x3d, 0xfe, 0x63, 0x7b, 0x2b, 0x9a, 0xe4, 0x19, 0x0a, 0x45, 0x8b, 0x5f, 0x3e, 0xfc, 0x19, 0x69, 0xaf, 0xe2, 0x78, 0x19}, "NFT", 6}, + // JUST {{0x41, 0x18, 0xfd, 0x06, 0x26, 0xda, 0xf3, 0xaf, 0x02, 0x38, 0x9a, 0xef, 0x3e, 0xd8, 0x7d, 0xb9, 0xc3, 0x3f, 0x63, 0x8f, 0xfa}, "JST", 18}, + // WINkLink {{0x41, 0x74, 0x47, 0x2E, 0x7D, 0x35, 0x39, 0x5A, 0x6B, 0x5A, 0xDD, 0x42, 0x7E, 0xEC, 0xB7, 0xF4, 0xB6, 0x2A, 0xD2, 0xB0, 0x71}, "WIN", 6}, + // Wrapped TRX {{0x41, 0x89, 0x1c, 0xdb, 0x91, 0xd1, 0x49, 0xf2, 0x3b, 0x1a, 0x45, 0xd9, 0xc5, 0xca, 0x78, 0xa8, 0x8d, 0x0c, 0xb4, 0x4c, 0x18}, "WTRX", 6}, + // Staked USDT + {{0x41, 0xc2, 0x91, 0xf8, 0x08, 0xee, 0x3b, 0xc3, 0xda, 0xd2, 0xa2, + 0x8e, 0x9d, 0x4d, 0x3c, 0x84, 0xd9, 0xa7, 0xd7, 0xca, 0xed}, + "stUSDT", + 18}, + // SUNOLD + {{0x41, 0x6b, 0x51, 0x51, 0x32, 0x03, 0x59, 0xec, 0x18, 0xb0, 0x86, + 0x07, 0xc7, 0x0a, 0x3b, 0x74, 0x39, 0xaf, 0x62, 0x6a, 0xa3}, + "SUNOLD", + 18}, + // SUN + {{0x41, 0xb4, 0xa4, 0x28, 0xab, 0x70, 0x92, 0xc2, 0xf1, 0x39, 0x5f, + 0x37, 0x6c, 0xe2, 0x97, 0x03, 0x3b, 0x3b, 0xb4, 0x46, 0xc1}, + "SUN", + 18}, + // JUST Stablecoin + {{0x41, 0x83, 0x42, 0x95, 0x92, 0x1a, 0x48, 0x8d, 0x9d, 0x42, 0xb4, + 0xb3, 0x02, 0x1e, 0xd1, 0xa3, 0xc3, 0x9f, 0xb0, 0xf0, 0x3e}, + "USDJ", + 18}, + // EthereumOLD + {{0x41, 0x53, 0x90, 0x83, 0x08, 0xf4, 0xaa, 0x22, 0x0f, 0xb1, 0x0d, + 0x77, 0x8b, 0x5d, 0x1b, 0x34, 0x48, 0x9c, 0xd6, 0xed, 0xfc}, + "ETHOLD", + 18}, + // Ethereum + {{0x41, 0xa7, 0xa5, 0x72, 0xf6, 0xd8, 0xb4, 0xca, 0x29, 0x1b, 0x93, + 0x53, 0xcf, 0x26, 0x58, 0x0a, 0xbe, 0xd7, 0x4f, 0x3e, 0x31}, + "ETH", + 18}, + // Wrapped BTC + {{0x41, 0xef, 0xc2, 0x30, 0xe1, 0x25, 0xc2, 0x4d, 0xe3, 0x5f, 0x62, + 0x90, 0xaf, 0xca, 0xfa, 0x28, 0xd5, 0x0b, 0x43, 0x65, 0x36}, + "WBTC", + 8}, + // Bitcoin + {{0x41, 0x84, 0x71, 0x69, 0x14, 0xc0, 0xfd, 0xf7, 0x11, 0x0a, 0x44, + 0x03, 0x0d, 0x04, 0xd0, 0xc4, 0x92, 0x35, 0x04, 0xd9, 0xcc}, + "BTC", + 8}, + // Wrapped BTT + {{0x41, 0x6a, 0x63, 0x37, 0xae, 0x47, 0xa0, 0x9a, 0xea, 0x0b, 0xbd, + 0x4f, 0xae, 0xb2, 0x3c, 0xa9, 0x43, 0x49, 0xc7, 0xb7, 0x74}, + "WBTT", + 6}, + // HTX + {{0x41, 0xca, 0x03, 0x03, 0xe8, 0xb9, 0xa7, 0x38, 0x12, 0x17, 0x77, + 0x11, 0x6d, 0xce, 0xa4, 0x19, 0xfe, 0x52, 0x4f, 0x27, 0x1a}, + "HTX", + 18}, }; /***************************************************************************** diff --git a/apps/tron_app/tron_contracts.h b/apps/tron_app/tron_contracts.h index 7fdf4811..f1ea52e9 100644 --- a/apps/tron_app/tron_contracts.h +++ b/apps/tron_app/tron_contracts.h @@ -19,7 +19,7 @@ *****************************************************************************/ // Number of entries in whitelisted contracts list -#define TRC20_WHITELISTED_CONTRACTS_COUNT 9 +#define TRC20_WHITELISTED_CONTRACTS_COUNT 19 #define TRC20_FUNCTION_SELECTOR_COUNT 1 /***************************************************************************** diff --git a/apps/tron_app/tron_helpers.c b/apps/tron_app/tron_helpers.c index bee9ffc7..ca1af6cc 100644 --- a/apps/tron_app/tron_helpers.c +++ b/apps/tron_app/tron_helpers.c @@ -107,6 +107,8 @@ bool tron_derivation_path_guard(const uint32_t *path, uint8_t levels) { account == TRON_ACCOUNT_INDEX); } break; + // TODO: 4 levels not supported yet + case 5: { // m/44'/195'/0'/0/i uint32_t change = path[3]; uint32_t address = path[4]; diff --git a/apps/tron_app/tron_helpers.h b/apps/tron_app/tron_helpers.h index 005e932e..c6506c5b 100644 --- a/apps/tron_app/tron_helpers.h +++ b/apps/tron_app/tron_helpers.h @@ -22,10 +22,12 @@ /***************************************************************************** * MACROS AND DEFINES *****************************************************************************/ + #define TRON_PURPOSE_INDEX 0x8000002C #define TRON_COIN_INDEX 0x800000C3 #define TRON_ACCOUNT_INDEX 0x80000000 -#define TRON_CHANGE_INDEX 0x0 +#define TRON_CHANGE_INDEX 0x00000000 + /***************************************************************************** * TYPEDEFS *****************************************************************************/ diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index 7f6bcbca..45624b04 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -164,7 +164,7 @@ static bool get_public_key(const uint8_t *seed, static bool fill_public_keys( const tron_get_public_keys_derivation_path_t *paths, const uint8_t *seed, - uint8_t public_keys[][TRON_PUB_KEY_SIZE_PLUS_ONE], + uint8_t public_keys[][TRON_PUB_KEY_SIZE], pb_size_t count); /** @@ -188,12 +188,11 @@ static bool fill_public_keys( * @retval false If the export was interrupted by a P0 event or an invalid query * was received from the host app. */ -static bool send_public_keys( - tron_query_t *query, - const uint8_t public_keys[][TRON_PUB_KEY_SIZE_PLUS_ONE], - const size_t count, - const pb_size_t which_request, - const pb_size_t which_response); +static bool send_public_keys(tron_query_t *query, + const uint8_t public_keys[][TRON_PUB_KEY_SIZE], + const size_t count, + const pb_size_t which_request, + const pb_size_t which_response); /** * @brief Helper function to take user consent before exporting public keys to * the host. Uses an appropriate message template based on the query request @@ -294,7 +293,7 @@ static bool get_public_key(const uint8_t *seed, static bool fill_public_keys( const tron_get_public_keys_derivation_path_t *paths, const uint8_t *seed, - uint8_t public_keys[][TRON_PUB_KEY_SIZE_PLUS_ONE], + uint8_t public_keys[][TRON_PUB_KEY_SIZE], pb_size_t count) { for (pb_size_t index = 0; index < count; index++) { const tron_get_public_keys_derivation_path_t *path = &paths[index]; @@ -306,18 +305,16 @@ static bool fill_public_keys( return true; } -static bool send_public_keys( - tron_query_t *query, - const uint8_t public_keys[][TRON_PUB_KEY_SIZE_PLUS_ONE], - const size_t count, - const pb_size_t which_request, - const pb_size_t which_response) { +static bool send_public_keys(tron_query_t *query, + const uint8_t public_keys[][TRON_PUB_KEY_SIZE], + const size_t count, + const pb_size_t which_request, + const pb_size_t which_response) { tron_result_t response = init_tron_result(which_response); tron_get_public_keys_result_response_t *result = &response.get_public_keys.result; static const size_t batch_limit = - sizeof(response.get_public_keys.result.public_keys) / - TRON_PUB_KEY_SIZE_PLUS_ONE; + sizeof(response.get_public_keys.result.public_keys) / TRON_PUB_KEY_SIZE; size_t remaining = count; response.get_public_keys.which_response = @@ -330,7 +327,7 @@ static bool send_public_keys( memcpy(response.get_public_keys.result.public_keys, public_keys[count - remaining], - batch_size * TRON_PUB_KEY_SIZE_PLUS_ONE); + batch_size * TRON_PUB_KEY_SIZE); tron_send_result(&response); remaining -= batch_size; @@ -394,7 +391,7 @@ void tron_get_pub_keys(tron_query_t *query) { uint8_t public_keys[sizeof(init_req->derivation_paths) / sizeof(tron_get_public_keys_derivation_path_t)] - [TRON_PUB_KEY_SIZE_PLUS_ONE] = {0}; + [TRON_PUB_KEY_SIZE] = {0}; if (!check_which_request(query, TRON_GET_PUBLIC_KEYS_REQUEST_INITIATE_TAG) || !validate_request_data(&query->get_public_keys, which_request) || @@ -444,8 +441,7 @@ void tron_get_pub_keys(tron_query_t *query) { uint8_t public_key_digest[32]; // Drop the '04' from pubkey - // No iteration in public_keys[i]? - keccak_256(&public_keys[0][1], TRON_PUB_KEY_SIZE, public_key_digest); + keccak_256(&public_keys[0][1], TRON_PUB_KEY_SIZE - 1, public_key_digest); // extract last 20 bytes // address = 41||sha3[12,32) diff --git a/apps/tron_app/tron_txn_helpers.c b/apps/tron_app/tron_txn_helpers.c index 58c37352..08fd4faf 100644 --- a/apps/tron_app/tron_txn_helpers.c +++ b/apps/tron_app/tron_txn_helpers.c @@ -115,6 +115,15 @@ int tron_byte_array_to_raw_txn(uint8_t *byte_array, } int tron_validate_unsigned_txn(const tron_transaction_raw_t *raw_txn) { - // TODO: + if (NULL == raw_txn || NULL == raw_txn->contract) { + return 1; + } + + if (raw_txn->contract_count != 1) { + tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return 1; + } + return 0; } diff --git a/apps/tron_app/tron_txn_helpers.h b/apps/tron_app/tron_txn_helpers.h index 3dcde44a..0474ddb5 100644 --- a/apps/tron_app/tron_txn_helpers.h +++ b/apps/tron_app/tron_txn_helpers.h @@ -26,10 +26,8 @@ *****************************************************************************/ #define TRON_NAME "Tron" #define TRON_LUNIT "TRX" -#define TRON_PUB_KEY_SIZE 64 // ECDSA's x+y coordinates only -#define TRON_PUB_KEY_SIZE_PLUS_ONE 65 +#define TRON_PUB_KEY_SIZE 65 #define TRON_INITIAL_ADDRESS_LENGTH 21 -#define TRON_INITIAL_ADDRESS_LENGTH_MINUS_ONE 20 #define TRON_ACCOUNT_ADDRESS_LENGTH 34 /***************************************************************************** From 61ab6dc9f358327f2ccd07a44a66eb066901d5b0 Mon Sep 17 00:00:00 2001 From: Vaibhav Sethia Date: Tue, 25 Jun 2024 15:52:46 +0530 Subject: [PATCH 18/22] fix(app): Btc utxo parser temp fix --- apps/btc_family/btc_txn_helpers.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/btc_family/btc_txn_helpers.c b/apps/btc_family/btc_txn_helpers.c index bb3546ed..699879f8 100644 --- a/apps/btc_family/btc_txn_helpers.c +++ b/apps/btc_family/btc_txn_helpers.c @@ -390,6 +390,19 @@ static void update_locktime(btc_verify_input_t *verify_input_data, return; } } + +// TODO: cover uint32_t and uint64_t numbers +static int64_t varint_decode(const uint8_t *raw_txn_chunk, int32_t *offset) { + uint8_t first_byte = raw_txn_chunk[*offset]; + if (first_byte < 0xFD) { + return first_byte; + } else { + uint8_t result[2]; + memcpy(result, raw_txn_chunk + *offset + 1, 2); + *offset += 2; + return U16_READ_LE_ARRAY(result); + } +} /***************************************************************************** * GLOBAL FUNCTIONS *****************************************************************************/ @@ -442,9 +455,13 @@ int btc_verify_input(const uint8_t *raw_txn_chunk, } case SCRIPT_LENGTH_CASE: { - if (offset + raw_txn_chunk[offset] + 1 + 4 > CHUNK_SIZE) { + // Added partial solution to var-int decode, fixing PRF#7276 + // https://app.clickup.com/t/9002019994/PRF-7276 + // refer to: + int64_t script_length = varint_decode(raw_txn_chunk, &offset); + if (offset + script_length + 1 + 4 > CHUNK_SIZE) { verify_input_data->prev_offset = - (offset + raw_txn_chunk[offset] + 1 + 4) - CHUNK_SIZE; + (offset + script_length + 1 + 4) - CHUNK_SIZE; update_hash( verify_input_data, raw_txn_chunk, chunk_index, CHUNK_SIZE); verify_input_data->input_parse = @@ -452,7 +469,7 @@ int btc_verify_input(const uint8_t *raw_txn_chunk, verify_input_data->input_index++; return 4; } else { - offset += (raw_txn_chunk[offset] + 1 + 4); + offset += (script_length + 1 + 4); } break; } From 4311f74c29f63116e3739ded1e81c6f4598fd6f4 Mon Sep 17 00:00:00 2001 From: Vaibhav Sethia Date: Tue, 25 Jun 2024 16:21:27 +0530 Subject: [PATCH 19/22] chore(app): Update comments --- apps/btc_family/btc_txn_helpers.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/btc_family/btc_txn_helpers.c b/apps/btc_family/btc_txn_helpers.c index 699879f8..7e40adef 100644 --- a/apps/btc_family/btc_txn_helpers.c +++ b/apps/btc_family/btc_txn_helpers.c @@ -391,12 +391,16 @@ static void update_locktime(btc_verify_input_t *verify_input_data, } } -// TODO: cover uint32_t and uint64_t numbers +// TODO: Add chunking condition for varint decode +// refer: https://app.clickup.com/t/9002019994/PRF-7288 static int64_t varint_decode(const uint8_t *raw_txn_chunk, int32_t *offset) { uint8_t first_byte = raw_txn_chunk[*offset]; if (first_byte < 0xFD) { return first_byte; } else { + // TODO: var-int varies between 1-9 bytes + // current implementation supports decoding + // upto 3 bytes only uint8_t result[2]; memcpy(result, raw_txn_chunk + *offset + 1, 2); *offset += 2; @@ -427,7 +431,7 @@ int btc_verify_input(const uint8_t *raw_txn_chunk, // store the number of inputs in the raw_txn verify_input_data->count = raw_txn_chunk[offset++]; // TODO: Improve varint decode. - // size of variable containing ip-count/op-count + // size of variable containing script size and ip-count/op-count // varies (1-9 Bytes) depending on its value. // refer: // https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer @@ -455,9 +459,6 @@ int btc_verify_input(const uint8_t *raw_txn_chunk, } case SCRIPT_LENGTH_CASE: { - // Added partial solution to var-int decode, fixing PRF#7276 - // https://app.clickup.com/t/9002019994/PRF-7276 - // refer to: int64_t script_length = varint_decode(raw_txn_chunk, &offset); if (offset + script_length + 1 + 4 > CHUNK_SIZE) { verify_input_data->prev_offset = From 0ae738393c485dd5a62fd44cf7257bec9e3ebd3c Mon Sep 17 00:00:00 2001 From: Parnika Cypherock <39666569+VeronicaGupta@users.noreply.github.com> Date: Wed, 26 Jun 2024 18:52:33 +0530 Subject: [PATCH 20/22] chore: Add confirmation page --- src/constant_texts.c | 3 ++- src/constant_texts.h | 3 +++ src/wallet/delete_wallet_flow.c | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/constant_texts.c b/src/constant_texts.c index a88b9ac3..1daf819d 100644 --- a/src/constant_texts.c +++ b/src/constant_texts.c @@ -479,7 +479,8 @@ const char *ui_text_sync_wallets_next_steps = "Sync each wallet in next steps"; const char *ui_text_corrupted_card_contact_support = "Corrupted card! Contact support"; const char *ui_text_incompatible_card_version = - "Incompatible card version! Contact support"; + "Incompatible card version! Contact suppsnprintf(msg, sizeof(msg), " + "UI_TEXT_SIGN_TXN_PROMPT, TRON_NAME, wallet_name);ort"; const char *ui_text_card_error_contact_support = "Contact support & share the device logs"; const char *ui_text_device_and_card_not_paired = diff --git a/src/constant_texts.h b/src/constant_texts.h index 2a777880..af5be9c8 100644 --- a/src/constant_texts.h +++ b/src/constant_texts.h @@ -17,6 +17,9 @@ #define UI_TEXT_CARD_TAPPED "Card #%d Tapped" #define UI_TEXT_TAP_CARD_TO_TEST \ "Place any card below the device to test card tapping" +#define UI_TEXT_PERMANENTLY_DELETE \ + "This will permanently delete %s wallet\nfrom your device and all cards. " \ + "Confirm?" #define UI_TEXT_ENTER_WORD "Enter Word # %d" #define UI_TEXT_IS_WORD "Is Word #%d\n%s" #define UI_TEXT_TAP_CARD "Tap card #%d" diff --git a/src/wallet/delete_wallet_flow.c b/src/wallet/delete_wallet_flow.c index 426c11c9..d27cd489 100644 --- a/src/wallet/delete_wallet_flow.c +++ b/src/wallet/delete_wallet_flow.c @@ -134,6 +134,16 @@ static bool get_pin_input() { void delete_wallet_flow(const Flash_Wallet *flash_wallet) { ASSERT(NULL != flash_wallet); + char confimation_display[100]; + snprintf(confimation_display, + sizeof(confimation_display), + UI_TEXT_PERMANENTLY_DELETE, + flash_wallet->wallet_name); + + if (!core_scroll_page(NULL, confimation_display, NULL)) { + return; + } + if (!core_scroll_page( NULL, ui_text_need_all_x1cards_to_delete_wallet_entirely, NULL)) { return; From 691fa68b35849c05f5e51664be99e176fe96fa52 Mon Sep 17 00:00:00 2001 From: Parnika Cypherock <39666569+VeronicaGupta@users.noreply.github.com> Date: Wed, 26 Jun 2024 18:57:03 +0530 Subject: [PATCH 21/22] chore: Text removed --- src/constant_texts.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/constant_texts.c b/src/constant_texts.c index 1daf819d..a88b9ac3 100644 --- a/src/constant_texts.c +++ b/src/constant_texts.c @@ -479,8 +479,7 @@ const char *ui_text_sync_wallets_next_steps = "Sync each wallet in next steps"; const char *ui_text_corrupted_card_contact_support = "Corrupted card! Contact support"; const char *ui_text_incompatible_card_version = - "Incompatible card version! Contact suppsnprintf(msg, sizeof(msg), " - "UI_TEXT_SIGN_TXN_PROMPT, TRON_NAME, wallet_name);ort"; + "Incompatible card version! Contact support"; const char *ui_text_card_error_contact_support = "Contact support & share the device logs"; const char *ui_text_device_and_card_not_paired = From 038d2747e7344eccfc032f33d1e3e083b1b4eeb7 Mon Sep 17 00:00:00 2001 From: Parnika Cypherock <39666569+VeronicaGupta@users.noreply.github.com> Date: Thu, 27 Jun 2024 18:04:14 +0530 Subject: [PATCH 22/22] chore: Version bunp v.0.6.768 (feature++) --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 0393026f..2aba5c15 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:002:001 +firmware version=000:006:003:000 hardware version=000:001:000:000 magic number=45227A01