diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index 4efa19302..699258d87 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -34,6 +34,7 @@ #define PKCS_PREFIXED_PUBKEY_SIZE PKCS_PREFIX_SIZE + CONSTELLATION_PUB_KEY_SIZE #define SHA256_DIGEST_SIZE 32 #define BS58_ENCODED_SIZE 45 +#define CONSTELLATION_TXN_HASH_LENGTH 64 /***************************************************************************** * TYPEDEFS diff --git a/apps/constellation_app/constellation_helpers.c b/apps/constellation_app/constellation_helpers.c index 1eb8bc731..a15238dce 100644 --- a/apps/constellation_app/constellation_helpers.c +++ b/apps/constellation_app/constellation_helpers.c @@ -59,9 +59,12 @@ /***************************************************************************** * INCLUDES *****************************************************************************/ - #include "constellation_helpers.h" +#include +#include +#include + #include "coin_utils.h" #include "constellation_context.h" @@ -114,3 +117,149 @@ bool constellation_derivation_path_guard(const uint32_t *path, uint8_t levels) { return status; } + +/// Ref: +// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/transaction-v2.ts#L113 +size_t encode_txn(const constellation_transaction_t *txn, char *output) { + char temp[1024] = ""; + char buffer[32] = ""; + size_t output_len = 0; + + // Parent count (always "2") + strcat(temp, "2"); + output_len++; + + // Source address length and value + size_t src_length = strnlen(txn->source, CONSTELLATION_ACCOUNT_ADDRESS_SIZE); + size_t src_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", src_length); + strncat(temp, buffer, src_length_string_len); + strncat(temp, txn->source, src_length); + output_len += src_length_string_len + src_length; + + // Destination address length and value + size_t dest_length = + strnlen(txn->destination, CONSTELLATION_ACCOUNT_ADDRESS_SIZE); + size_t dest_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", dest_length); + strncat(temp, buffer, dest_length_string_len); + strncat(temp, txn->destination, dest_length); + output_len += dest_length_string_len + dest_length; + + // Amount length and value (hex string) + char hex_str_amount[16] = ""; + size_t hex_str_amount_length = + snprintf(hex_str_amount, sizeof(hex_str_amount), "%llx", txn->amount); + size_t hex_str_amount_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", hex_str_amount_length); + strncat(temp, buffer, hex_str_amount_length_string_len); + strncat(temp, hex_str_amount, hex_str_amount_length); + output_len += hex_str_amount_length_string_len + hex_str_amount_length; + + // Parent hash length and value + size_t parent_hash_length = + strnlen(txn->parent.hash, CONSTELLATION_TXN_HASH_LENGTH); + size_t parent_hash_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", parent_hash_length); + strncat(temp, buffer, parent_hash_length_string_len); + strncat(temp, txn->parent.hash, parent_hash_length); + output_len += parent_hash_length_string_len + parent_hash_length; + + // Ordinal length and value + char str_ordinal[32] = ""; + size_t str_ordinal_length = + snprintf(str_ordinal, sizeof(str_ordinal), "%lu", txn->parent.ordinal); + size_t str_ordinal_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", str_ordinal_length); + strncat(temp, buffer, str_ordinal_length_string_len); + strncat(temp, str_ordinal, str_ordinal_length); + output_len += str_ordinal_length_string_len + str_ordinal_length; + + // Fee length and value + char str_fee[32] = ""; + size_t str_fee_length = snprintf(str_fee, sizeof(str_fee), "%lu", txn->fee); + size_t str_fee_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", str_fee_length); + strncat(temp, buffer, str_fee_length_string_len); + strncat(temp, str_fee, str_fee_length); + output_len += str_fee_length_string_len + str_fee_length; + + // Salt length and value + size_t salt_length = strnlen(txn->salt, 16); + size_t salt_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", salt_length); + strncat(temp, buffer, salt_length_string_len); + strncat(temp, txn->salt, salt_length); + output_len += salt_length_string_len + salt_length; + + strncpy(output, temp, output_len); + + return output_len; +} + +// Encode a variable-length integer (similar to utf8Length in JS) +/// Ref: +// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/tx-encode.ts#L81 +void encode_var_length(uint32_t value, uint8_t *output, size_t *out_len) { + size_t position = 0; + + if (value < (1 << 6)) { + output[position++] = (value | 0x80); + } else if (value < (1 << 13)) { + output[position++] = ((value & 0x3F) | 0xC0); + output[position++] = (value >> 6); + } else if (value < (1 << 20)) { + output[position++] = ((value & 0x3F) | 0xC0); + output[position++] = ((value >> 6) | 0x80); + output[position++] = (value >> 13); + } else if (value < (1 << 27)) { + output[position++] = ((value & 0x3F) | 0xC0); + output[position++] = ((value >> 6) | 0x80); + output[position++] = ((value >> 13) | 0x80); + output[position++] = (value >> 20); + } else { + output[position++] = ((value & 0x3F) | 0xC0); + output[position++] = ((value >> 6) | 0x80); + output[position++] = ((value >> 13) | 0x80); + output[position++] = ((value >> 20) | 0x80); + output[position++] = (value >> 27); + } + *out_len = position; +} + +/// Ref: +// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/tx-encode.ts#L71 +void kryo_serialize(const char *msg, + size_t msg_len, + uint8_t *output, + size_t *out_len) { + uint8_t length_encoded[5] = {0}; + size_t len = 0; + + // Prefix is "03" + utf8Length(msg length + 1) + encode_var_length(msg_len + 1, length_encoded, &len); + + size_t index = 0; + output[index++] = 0x03; // Prefix "03" + + // Append length encoding + memcpy(&output[index], length_encoded, len); + index += len; + + // Append msg as raw bytes + memcpy(&output[index], msg, msg_len); + index += msg_len; + + *out_len = index; +} + +/// Ref: +// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/key-store.ts#L337 +void serialize_txn(const constellation_transaction_t *txn, + uint8_t *output, + size_t *output_len) { + char encoded_txn[1024] = ""; + size_t encoded_txn_len = encode_txn(txn, encoded_txn); + + kryo_serialize(encoded_txn, encoded_txn_len, output, output_len); +} \ No newline at end of file diff --git a/apps/constellation_app/constellation_helpers.h b/apps/constellation_app/constellation_helpers.h index ef9ff911f..35ed11faa 100644 --- a/apps/constellation_app/constellation_helpers.h +++ b/apps/constellation_app/constellation_helpers.h @@ -17,6 +17,8 @@ #include #include +#include "constellation/sign_txn.pb.h" + /***************************************************************************** * MACROS AND DEFINES *****************************************************************************/ @@ -49,4 +51,19 @@ */ bool constellation_derivation_path_guard(const uint32_t *path, uint8_t levels); +/** + * @brief Serializes a constellation_transaction_t. + * @details Encodes the transaction as per dag4.js library and + * serializes the encoded txn with kryo_serialize + * + * @param[in] txn The constellation_transaction_t to serialize + * @param[out] output The buffer to hold the serialized txn + * @param[out] output_len The length of the output serialized txn + * + * @return None + */ +void serialize_txn(const constellation_transaction_t *txn, + uint8_t *output, + size_t *output_len); + #endif // CONSTELLATION_HELPERS_H \ No newline at end of file diff --git a/apps/constellation_app/constellation_main.c b/apps/constellation_app/constellation_main.c index bec5ce24e..07ac3c27f 100644 --- a/apps/constellation_app/constellation_main.c +++ b/apps/constellation_app/constellation_main.c @@ -134,7 +134,7 @@ void constellation_main(usb_event_t usb_evt, break; } case CONSTELLATION_QUERY_SIGN_TXN_TAG: { - // constellation_sign_transaction(&query); + constellation_sign_transaction(&query); break; } default: { diff --git a/apps/constellation_app/constellation_priv.h b/apps/constellation_app/constellation_priv.h index f7eb7d35c..2e3cb95c1 100644 --- a/apps/constellation_app/constellation_priv.h +++ b/apps/constellation_app/constellation_priv.h @@ -21,6 +21,16 @@ /***************************************************************************** * TYPEDEFS *****************************************************************************/ +typedef struct { + /** + * The structure holds the wallet information of the transaction. + * @note Populated by constellation_handle_initiate_query() + */ + constellation_sign_txn_initiate_request_t init_info; + + const constellation_transaction_t *txn; + +} constellation_txn_context_t; /***************************************************************************** * EXPORTED VARIABLES diff --git a/apps/constellation_app/constellation_txn.c b/apps/constellation_app/constellation_txn.c new file mode 100644 index 000000000..716139a84 --- /dev/null +++ b/apps/constellation_app/constellation_txn.c @@ -0,0 +1,445 @@ +/** + * @file constellation_txn.c + * @author Cypherock X1 Team + * @brief Source file to handle transaction signing logic for CONSTELLATION + *protocol + * + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2024 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 "coin_utils.h" +#include "constellation/core.pb.h" +#include "constellation/sign_txn.pb.h" +#include "constellation_api.h" +#include "constellation_context.h" +#include "constellation_helpers.h" +#include "constellation_priv.h" +#include "reconstruct_wallet_flow.h" +#include "status_api.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" +#include "utils.h" +#include "wallet_list.h" +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ +typedef constellation_sign_txn_signature_response_signature_t der_sig_t; + +/***************************************************************************** + * 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 constellation_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 constellation_query_t *query, + pb_size_t which_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(const pb_size_t which_response); + +/** + * @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 constellation_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 constellation_sign_txn_request_t *request); + +/** + * @brief Takes already received and decoded query for the user confirmation. + * @details The function will verify if the query contains the + * CONSTELLATION_SIGN_TXN_REQUEST_INITIATE_TAG 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. The function also duplicates the data from + * query into the constellation_txn_context for further processing. + * + * @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 handle_initiate_query(const constellation_query_t *query); + +/** + * @brief Receives unsigned txn from the host. If reception is successful, it + * also parses the txn to ensure it's validity. + * @note In case of any failure, a corresponding message is conveyed to the host + * + * @param query Reference to buffer of type constellation_query_t + * @return true If the txn is received in the internal buffers and is valid + * @return false If the txn could not be received or it's validation failed + */ +static bool fetch_valid_input(constellation_query_t *query); + +/** + * @brief This function executes user verification flow of the unsigned txn + * received from the host. + * @details The user verification flow is different for different type of action + * types identified from the unsigned txn + * @note This function expected that the unsigned txn is parsed using the helper + * function as only few action types are supported currently. + * + * @return true If the user accepted the transaction display + * @return false If any user rejection occured or P0 event occured + */ +static bool get_user_verification(void); + +/** + * @brief Calculates ED25519 curve based signature over the digest of the user + * verified unsigned txn. + * @details Seed reconstruction takes place within this function + * + * @param signature_buffer Reference to buffer where the signature will be + * populated + * @return true If the signature was computed successfully + * @return false If signature could not be computed - maybe due to some error + * during seed reconstruction phase + */ +static bool sign_txn(der_sig_t *der_signature); + +/** + * @brief Sends signature of the CONSTELLATION unsigned txn to the host + * @details The function waits for the host to send a request of type + * CONSTELLATION_SIGN_TXN_REQUEST_SIGNATURE_TAG and sends the response + * + * @param query Reference to buffer of type constellation_query_t + * @param signature Reference to signature to be sent to the host + * @return true If the signature was sent successfully + * @return false If the signature could not be sent - maybe due to and P0 event + * or invalid request received from the host + */ +static bool send_signature(constellation_query_t *query, + const der_sig_t *der_signature); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ +static constellation_txn_context_t *constellation_txn_context = NULL; + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ +static bool check_which_request(const constellation_query_t *query, + pb_size_t which_request) { + if (which_request != query->sign_txn.which_request) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +static void send_response(const pb_size_t which_response) { + constellation_result_t result = + init_constellation_result(CONSTELLATION_RESULT_SIGN_TXN_TAG); + result.sign_txn.which_response = which_response; + constellation_send_result(&result); +} + +static bool validate_request_data( + const constellation_sign_txn_request_t *request) { + bool status = true; + + if (!constellation_derivation_path_guard( + request->initiate.derivation_path, + request->initiate.derivation_path_count)) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = false; + } + return status; +} + +static bool handle_initiate_query(const constellation_query_t *query) { + char wallet_name[NAME_SIZE] = ""; + char msg[100] = ""; + + // TODO: Handle wallet search failures - eg: Wallet ID not found, Wallet + // ID found but is invalid/locked wallet + if (!check_which_request(query, + CONSTELLATION_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, + constellation_send_error)) { + return false; + } + + snprintf(msg, + sizeof(msg), + UI_TEXT_SIGN_TXN_PROMPT, + CONSTELLATION_NAME, + wallet_name); + // Take user consent to sign transaction for the wallet + if (!core_confirmation(msg, constellation_send_error)) { + return false; + } + + set_app_flow_status(CONSTELLATION_SIGN_TXN_STATUS_CONFIRM); + memcpy(&constellation_txn_context->init_info, + &query->sign_txn.initiate, + sizeof(constellation_sign_txn_initiate_request_t)); + + send_response(CONSTELLATION_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 fetch_valid_input(constellation_query_t *query) { + if (!constellation_get_query(query, CONSTELLATION_QUERY_SIGN_TXN_TAG) && + !check_which_request(query, + CONSTELLATION_SIGN_TXN_REQUEST_TXN_DATA_TAG)) { + return false; + } + + const constellation_sign_txn_data_t *sign_txn_data = + &query->sign_txn.txn_data; + if (sign_txn_data->has_txn == false) { + return false; + } + + constellation_txn_context->txn = &sign_txn_data->txn; + + send_response(CONSTELLATION_SIGN_TXN_RESPONSE_UNSIGNED_TXN_ACCEPTED_TAG); + + return true; +} + +static bool get_user_verification(void) { + const constellation_transaction_t *txn = constellation_txn_context->txn; + + // verify recipient address + if (!core_scroll_page( + ui_text_verify_address, txn->destination, constellation_send_error)) { + return false; + } + + // verify recipient amount + char amount_string[30] = {'\0'}; + double decimal_amount = (double)txn->amount; + decimal_amount *= 1e-8; + snprintf(amount_string, sizeof(amount_string), "%.*g", 8, decimal_amount); + + char display[100] = {'\0'}; + snprintf(display, + sizeof(display), + UI_TEXT_VERIFY_AMOUNT, + amount_string, + ""); // We don't know the which transaction(coin or token and/or + // which token) is it, hence we don't know unit + + if (!core_confirmation(display, constellation_send_error)) { + return false; + } + + // verify fee + char fee_string[30] = {'\0'}; + double decimal_fee = (double)txn->fee; + decimal_fee *= 1e-8; + snprintf(fee_string, sizeof(fee_string), "%.*g", 8, decimal_fee); + + char fee_display[100] = {'\0'}; + snprintf( + fee_display, sizeof(fee_display), UI_TEXT_VERIFY_FEE, fee_string, ""); + + if (!core_confirmation(fee_display, constellation_send_error)) { + return false; + } + + set_app_flow_status(CONSTELLATION_SIGN_TXN_STATUS_VERIFY); + + return true; +} + +static bool sign_txn(der_sig_t *der_signature) { + uint8_t seed[64] = {0}; + if (!reconstruct_seed(constellation_txn_context->init_info.wallet_id, + seed, + constellation_send_error)) { + memzero(seed, sizeof(seed)); + // TODO: handle errors of reconstruction flow + return false; + } + + set_app_flow_status(CONSTELLATION_SIGN_TXN_STATUS_SEED_GENERATED); + + uint8_t serialized_txn[1024] = {0}; + size_t serialized_txn_len = 0; + serialize_txn( + constellation_txn_context->txn, serialized_txn, &serialized_txn_len); + + uint8_t sha256_digest[SHA256_DIGEST_LENGTH] = {0}; + sha256_Raw(serialized_txn, serialized_txn_len, sha256_digest); + + char sha256_hex_str[SHA256_DIGEST_LENGTH * 2 + 1] = ""; + byte_array_to_hex_string(sha256_digest, + sizeof(sha256_digest), + sha256_hex_str, + sizeof(sha256_hex_str)); + + uint8_t sha512_digest[SHA512_DIGEST_LENGTH] = {0}; + sha512_Raw((uint8_t *)sha256_hex_str, strlen(sha256_hex_str), sha512_digest); + + HDNode hdnode = {0}; + derive_hdnode_from_path( + constellation_txn_context->init_info.derivation_path, + constellation_txn_context->init_info.derivation_path_count, + SECP256K1_NAME, + seed, + &hdnode); + + uint8_t signature[64] = {0}; + ecdsa_sign_digest( + &secp256k1, hdnode.private_key, sha512_digest, signature, NULL, NULL); + + der_signature->size = ecdsa_sig_to_der(signature, der_signature->bytes); + + memzero(serialized_txn, sizeof(serialized_txn)); + memzero(sha256_digest, sizeof(sha256_digest)); + memzero(sha512_digest, sizeof(sha512_digest)); + memzero(seed, sizeof(seed)); + memzero(&hdnode, sizeof(hdnode)); + memzero(signature, sizeof(signature)); + + return true; +} + +static bool send_signature(constellation_query_t *query, + const der_sig_t *der_signature) { + constellation_result_t result = + init_constellation_result(CONSTELLATION_RESULT_SIGN_TXN_TAG); + result.sign_txn.which_response = + CONSTELLATION_SIGN_TXN_RESPONSE_SIGNATURE_TAG; + + if (!constellation_get_query(query, CONSTELLATION_QUERY_SIGN_TXN_TAG) || + !check_which_request(query, + CONSTELLATION_SIGN_TXN_REQUEST_SIGNATURE_TAG)) { + return false; + } + + memcpy( + &result.sign_txn.signature.signature, der_signature, sizeof(der_sig_t)); + + constellation_send_result(&result); + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +void constellation_sign_transaction(constellation_query_t *query) { + constellation_txn_context = (constellation_txn_context_t *)malloc( + sizeof(constellation_txn_context_t)); + memzero(constellation_txn_context, sizeof(constellation_txn_context_t)); + + der_sig_t der_signature = {0}; + + if (handle_initiate_query(query) && fetch_valid_input(query) && + get_user_verification() && sign_txn(&der_signature) && + send_signature(query, &der_signature)) { + delay_scr_init(ui_text_check_cysync, DELAY_TIME); + } + + if (constellation_txn_context) { + free(constellation_txn_context); + constellation_txn_context = NULL; + } +} \ No newline at end of file diff --git a/common/cypherock-common b/common/cypherock-common index be16ebadc..0e7d09873 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit be16ebadc9863206f3bd216d721363f229417eaa +Subproject commit 0e7d0987335a1707e2ca74faed8e540dc36d059a diff --git a/common/proto-options/constellation/sign_txn.options b/common/proto-options/constellation/sign_txn.options index 2b221fe2d..f8df5071c 100644 --- a/common/proto-options/constellation/sign_txn.options +++ b/common/proto-options/constellation/sign_txn.options @@ -2,3 +2,9 @@ constellation.SignTxnInitiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true constellation.SignTxnInitiateRequest.derivation_path type:FT_STATIC max_count:5 fixed_length:true constellation.SignTxnSignatureResponse.signature type:FT_STATIC max_size:72 fixed_length:false + +constellation.Transaction.source type:FT_STATIC max_size:41 fixed_length:true +constellation.Transaction.destination type:FT_STATIC max_size:41 fixed_length:true +constellation.Parent.hash type:FT_STATIC max_size:65 fixed_length:true +constellation.Transaction.salt type:FT_STATIC max_size:16 fixed_length:false + diff --git a/src/constant_texts.h b/src/constant_texts.h index 6da9cc898..71d7de5ca 100644 --- a/src/constant_texts.h +++ b/src/constant_texts.h @@ -56,6 +56,7 @@ #define UI_TEXT_PIN "PIN\n %s" #define UI_TEXT_VERIFY_DESTINATION_TAG "Verify Destination Tag\n%lu" #define UI_TEXT_VERIFY_PRIORITY_FEE "Verify Priority Fee\n%s\n%s" +#define UI_TEXT_VERIFY_FEE "Verify Fee\n%s\n%s" // product hash extern const char *product_hash;