From 096e055aad69c25d79680010fc2d29c672ecdbd4 Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Sun, 20 Feb 2022 16:19:41 +0100 Subject: [PATCH 1/5] add tip support --- CMakeLists.txt | 9 +- app/src/json/json_parser.c | 6 + app/src/parser.c | 109 ++++++++--- app/src/tx_display.c | 66 ++++--- app/src/tx_display.h | 1 + app/src/tx_parser.c | 15 +- app/src/tx_parser.h | 4 + cmake/conan/CMakeLists.txt | 5 +- conanfile.txt | 4 +- deps/ledger-zxlib/.circleci/config.yml | 19 -- deps/ledger-zxlib/include/segwit_addr.h | 2 +- deps/ledger-zxlib/include/utf8.h | 2 +- deps/ledger-zxlib/include/zxmacros.h | 4 + deps/ledger-zxlib/include/zxversion.h | 4 +- deps/ledger-zxlib/src/zxutils_ledger.c | 6 +- deps/ledger-zxlib/templates/Makefile.root | 2 +- tests/testcases/manual.json | 211 ++++++++++++++++++++++ tests/tx_parse.cpp | 13 +- tests_zemu/package.json | 6 +- 19 files changed, 387 insertions(+), 101 deletions(-) delete mode 100644 deps/ledger-zxlib/.circleci/config.yml diff --git a/CMakeLists.txt b/CMakeLists.txt index 48f97c65..d6728109 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,10 +95,10 @@ file(GLOB_RECURSE LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/formatting.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c - app/src/json/json_parser.c - app/src/tx_parser.c - app/src/tx_display.c - app/src/tx_validate.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/json/json_parser.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/tx_parser.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/tx_display.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/tx_validate.c ) add_library(app_lib STATIC @@ -138,6 +138,7 @@ target_link_libraries(unittests PRIVATE CONAN_PKG::jsoncpp) add_compile_definitions(TESTVECTORS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/") +add_compile_definitions(APP_TESTING=1) add_test(unittests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittests) set_tests_properties(unittests PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) diff --git a/app/src/json/json_parser.c b/app/src/json/json_parser.c index e6dbe513..e7adf3f5 100644 --- a/app/src/json/json_parser.c +++ b/app/src/json/json_parser.c @@ -36,6 +36,12 @@ parser_error_t json_parse(parsed_json_t *parsed_json, const char *buffer, uint16 parsed_json->tokens, MAX_NUMBER_OF_TOKENS); +#ifdef APP_TESTING + char tmpBuffer[100]; + snprintf(tmpBuffer, sizeof(tmpBuffer), "tokens: %d", num_tokens); + zemu_log(tmpBuffer); +#endif + if (num_tokens < 0) { switch (num_tokens) { case JSMN_ERROR_NOMEM: diff --git a/app/src/parser.c b/app/src/parser.c index e83dac35..fc04e0f8 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -55,12 +55,12 @@ parser_error_t parser_getNumItems(const parser_context_t *ctx __attribute__((unu return tx_display_numItems(num_items); } -__Z_INLINE bool_t parser_areEqual(uint16_t tokenidx, char *expected) { - if (parser_tx_obj.json.tokens[tokenidx].type != JSMN_STRING) { +__Z_INLINE bool_t parser_areEqual(uint16_t tokenIdx, char *expected) { + if (parser_tx_obj.json.tokens[tokenIdx].type != JSMN_STRING) { return bool_false; } - int32_t len = parser_tx_obj.json.tokens[tokenidx].end - parser_tx_obj.json.tokens[tokenidx].start; + int32_t len = parser_tx_obj.json.tokens[tokenIdx].end - parser_tx_obj.json.tokens[tokenIdx].start; if (len < 0) { return bool_false; } @@ -69,7 +69,7 @@ __Z_INLINE bool_t parser_areEqual(uint16_t tokenidx, char *expected) { return bool_false; } - const char *p = parser_tx_obj.tx + parser_tx_obj.json.tokens[tokenidx].start; + const char *p = parser_tx_obj.tx + parser_tx_obj.json.tokens[tokenIdx].start; for (int32_t i = 0; i < len; i++) { if (expected[i] != *(p + i)) { return bool_false; @@ -80,17 +80,25 @@ __Z_INLINE bool_t parser_areEqual(uint16_t tokenidx, char *expected) { } __Z_INLINE bool_t parser_isAmount(char *key) { - if (strcmp(key, "fee/amount") == 0) + if (strcmp(key, "fee/amount") == 0) { return bool_true; + } - if (strcmp(key, "msgs/inputs/coins") == 0) + if (strcmp(key, "msgs/inputs/coins") == 0) { return bool_true; + } - if (strcmp(key, "msgs/outputs/coins") == 0) + if (strcmp(key, "msgs/outputs/coins") == 0) { return bool_true; + } - if (strcmp(key, "msgs/value/amount") == 0) + if (strcmp(key, "msgs/value/amount") == 0) { return bool_true; + } + + if (strcmp(key, "tip/amount") == 0) { + return bool_true; + } return bool_false; } @@ -110,16 +118,12 @@ __Z_INLINE bool_t is_default_denom_base(const char *denom, uint8_t denom_len) { return bool_false; } -__Z_INLINE parser_error_t parser_formatAmount(uint16_t amountToken, - char *outVal, uint16_t outValLen, - uint8_t pageIdx, uint8_t *pageCount) { +__Z_INLINE parser_error_t parser_formatAmountItem(uint16_t amountToken, + char *outVal, uint16_t outValLen, + uint8_t pageIdx, uint8_t *pageCount) { *pageCount = 0; - if (parser_tx_obj.json.tokens[amountToken].type == JSMN_ARRAY) { - amountToken++; - } uint16_t numElements; - CHECK_PARSER_ERR(array_get_element_count(&parser_tx_obj.json, amountToken, &numElements)) if (numElements == 0) { @@ -128,17 +132,21 @@ __Z_INLINE parser_error_t parser_formatAmount(uint16_t amountToken, return parser_ok; } - if (numElements != 4) + if (numElements != 4) { return parser_unexpected_field; + } - if (parser_tx_obj.json.tokens[amountToken].type != JSMN_OBJECT) + if (parser_tx_obj.json.tokens[amountToken].type != JSMN_OBJECT) { return parser_unexpected_field; + } - if (!parser_areEqual(amountToken + 1u, "amount")) + if (!parser_areEqual(amountToken + 1u, "amount")) { return parser_unexpected_field; + } - if (!parser_areEqual(amountToken + 3u, "denom")) + if (!parser_areEqual(amountToken + 3u, "denom")) { return parser_unexpected_field; + } char bufferUI[160]; char tmpDenom[COIN_DENOM_MAXSIZE]; @@ -191,6 +199,62 @@ __Z_INLINE parser_error_t parser_formatAmount(uint16_t amountToken, return parser_ok; } +__Z_INLINE parser_error_t parser_formatAmount(uint16_t amountToken, + char *outVal, uint16_t outValLen, + uint8_t pageIdx, uint8_t *pageCount) { + ZEMU_LOGF(200, "[formatAmount] ------- pageidx %d", pageIdx) + + *pageCount = 0; + if (parser_tx_obj.json.tokens[amountToken].type != JSMN_ARRAY) { + return parser_formatAmountItem(amountToken, outVal, outValLen, pageIdx, pageCount); + } + + uint8_t totalPages = 0; + bool_t showItemSet = false; + uint8_t showPageIdx = pageIdx; + uint16_t showItemTokenIdx = 0; + + uint16_t numberAmounts; + CHECK_PARSER_ERR(array_get_element_count(&parser_tx_obj.json, amountToken, &numberAmounts)) + + // Count total subpagesCount and calculate correct page and TokenIdx + for (uint16_t i = 0; i < numberAmounts; i++) { + uint16_t itemTokenIdx; + uint8_t subpagesCount; + + CHECK_PARSER_ERR(array_get_nth_element(&parser_tx_obj.json, amountToken, i, &itemTokenIdx)); + CHECK_PARSER_ERR(parser_formatAmountItem(itemTokenIdx, outVal, outValLen, 0, &subpagesCount)); + totalPages += subpagesCount; + + ZEMU_LOGF(200, "[formatAmount] [%d] TokenIdx: %d - PageIdx: %d - Pages: %d - Total %d", i, itemTokenIdx, + showPageIdx, subpagesCount, totalPages) + + if (!showItemSet) { + if (showPageIdx < subpagesCount) { + showItemSet = true; + showItemTokenIdx = itemTokenIdx; + ZEMU_LOGF(200, "[formatAmount] [%d] [SET] TokenIdx %d - PageIdx: %d", i, showItemTokenIdx, + showPageIdx) + } else { + showPageIdx -= subpagesCount; + } + } + } + *pageCount = totalPages; + if (pageIdx > totalPages) { + return parser_unexpected_value; + } + + if (totalPages == 0) { + *pageCount = 1; + snprintf(outVal, outValLen, "Empty"); + return parser_ok; + } + + uint8_t dummy; + return parser_formatAmountItem(showItemTokenIdx, outVal, outValLen, showPageIdx, &dummy); +} + parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, char *outKey, uint16_t outKeyLen, @@ -221,10 +285,9 @@ parser_error_t parser_getItem(const parser_context_t *ctx, snprintf(outKey, outKeyLen, "%s", tmpKey); if (parser_isAmount(tmpKey)) { - CHECK_PARSER_ERR( - parser_formatAmount(ret_value_token_index, - outVal, outValLen, - pageIdx, pageCount)) + CHECK_PARSER_ERR(parser_formatAmount(ret_value_token_index, + outVal, outValLen, + pageIdx, pageCount)) } else { CHECK_PARSER_ERR(tx_getToken(ret_value_token_index, outVal, outValLen, diff --git a/app/src/tx_display.c b/app/src/tx_display.c index 15e57cd7..736c05d7 100644 --- a/app/src/tx_display.c +++ b/app/src/tx_display.c @@ -1,3 +1,5 @@ +#pragma clang diagnostic push +#pragma ide diagnostic ignored "misc-no-recursion" /******************************************************************************* * (c) 2018, 2019 Zondax GmbH * @@ -21,7 +23,7 @@ #include "parser_impl.h" #include -#define NUM_REQUIRED_ROOT_PAGES 6 +#define NUM_REQUIRED_ROOT_PAGES 7 const char *get_required_root_item(root_item_e i) { switch (i) { @@ -37,6 +39,8 @@ const char *get_required_root_item(root_item_e i) { return "memo"; case root_item_msgs: return "msgs"; + case root_item_tip: + return "tip"; default: return "?"; } @@ -44,6 +48,7 @@ const char *get_required_root_item(root_item_e i) { #pragma clang diagnostic push #pragma ide diagnostic ignored "bugprone-branch-clone" + __Z_INLINE uint8_t get_root_max_level(root_item_e i) { switch (i) { case root_item_chain_id: @@ -58,10 +63,13 @@ __Z_INLINE uint8_t get_root_max_level(root_item_e i) { return 2; case root_item_msgs: return 2; + case root_item_tip: + return 1; default: return 0; } } + #pragma clang diagnostic pop typedef struct { @@ -132,22 +140,32 @@ __Z_INLINE bool address_matches_own(char *addr) { return true; } +#define INDEXING_TMP_KEYSIZE 70 +#define INDEXING_TMP_VALUESIZE 70 +#define INDEXING_GROUPING_REF_TYPE_SIZE 70 +#define INDEXING_GROUPING_REF_FROM_SIZE 70 + parser_error_t tx_indexRootFields() { if (parser_tx_obj.flags.cache_valid) { return parser_ok; } +#ifdef APP_TESTING + zemu_log("tx_indexRootFields"); +#endif + // Clear cache MEMZERO(&display_cache, sizeof(display_cache_t)); - char tmp_key[70]; - char tmp_val[70]; + + char tmp_key[INDEXING_TMP_KEYSIZE]; + char tmp_val[INDEXING_TMP_VALUESIZE]; MEMZERO(&tmp_key, sizeof(tmp_key)); MEMZERO(&tmp_val, sizeof(tmp_val)); // Grouping references - char reference_msg_type[70]; + char reference_msg_type[INDEXING_GROUPING_REF_TYPE_SIZE]; + char reference_msg_from[INDEXING_GROUPING_REF_FROM_SIZE]; MEMZERO(&reference_msg_type, sizeof(reference_msg_type)); - char reference_msg_from[70]; MEMZERO(&reference_msg_from, sizeof(reference_msg_from)); parser_tx_obj.filter_msg_type_count = 0; @@ -203,7 +221,7 @@ parser_error_t tx_indexRootFields() { parser_tx_obj.query.out_val_len, 0, &pageCount)) - // ZEMU_LOGF(200, "[ZEMU] %s : %s", tmp_key, parser_tx_obj.query.out_val); + ZEMU_LOGF(200, "[ZEMU] %s : %s", tmp_key, parser_tx_obj.query.out_val) switch (root_item_idx) { case root_item_memo: { @@ -257,7 +275,7 @@ parser_error_t tx_indexRootFields() { parser_tx_obj.filter_msg_from_count++; } - // ZEMU_LOGF(200, "[ZEMU] %s [%d/%d]", tmp_key, parser_tx_obj.filter_msg_type_count, parser_tx_obj.filter_msg_from_count); + ZEMU_LOGF(200, "[ZEMU] %s [%d/%d]", tmp_key, parser_tx_obj.filter_msg_type_count, parser_tx_obj.filter_msg_from_count); break; } default: @@ -335,8 +353,11 @@ __Z_INLINE uint8_t get_subitem_count(root_item_e root_item) { break; case root_item_fee: if (!tx_is_expert_mode()) { - tmp_num_items -= 1; // Hide Gas field + tmp_num_items -= 3; // Hide Gas field } + case root_item_tip: + tmp_num_items += 0; + break; default: break; } @@ -443,53 +464,36 @@ static const key_subst_t key_substitutions[] = { {"memo", "Memo"}, {"fee/amount", "Fee"}, {"fee/gas", "Gas"}, + {"fee/granter", "Granter"}, + {"fee/payer", "Payer"}, {"msgs/type", "Type"}, - // FIXME: Are these obsolete?? multisend? + {"tip/amount", "Tip"}, + {"tip/tipper", "Tipper"}, + {"msgs/inputs/address", "Source Address"}, {"msgs/inputs/coins", "Source Coins"}, {"msgs/outputs/address", "Dest Address"}, {"msgs/outputs/coins", "Dest Coins"}, - // MsgSend {"msgs/value/from_address", "From"}, {"msgs/value/to_address", "To"}, {"msgs/value/amount", "Amount"}, - - // MsgDelegate {"msgs/value/delegator_address", "Delegator"}, {"msgs/value/validator_address", "Validator"}, - - // MsgUndelegate -// {"msgs/value/delegator_address", "Delegator"}, -// {"msgs/value/validator_address", "Validator"}, - - // MsgBeginRedelegate -// {"msgs/value/delegator_address", "Delegator"}, {"msgs/value/validator_src_address", "Validator Source"}, {"msgs/value/validator_dst_address", "Validator Dest"}, - - // MsgSubmitProposal {"msgs/value/description", "Description"}, {"msgs/value/initial_deposit/amount", "Deposit Amount"}, {"msgs/value/initial_deposit/denom", "Deposit Denom"}, {"msgs/value/proposal_type", "Proposal"}, {"msgs/value/proposer", "Proposer"}, {"msgs/value/title", "Title"}, - - // MsgDeposit {"msgs/value/depositer", "Sender"}, {"msgs/value/proposal_id", "Proposal ID"}, {"msgs/value/amount", "Amount"}, - - // MsgVote {"msgs/value/voter", "Description"}, -// {"msgs/value/proposal_id", "Proposal ID"}, {"msgs/value/option", "Option"}, - - // MsgWithdrawDelegationReward -// {"msgs/value/delegator_address", "Delegator"}, // duplicated -// {"msgs/value/validator_address", "Validator"}, // duplicated }; parser_error_t tx_display_make_friendly() { @@ -506,3 +510,5 @@ parser_error_t tx_display_make_friendly() { return parser_ok; } + +#pragma clang diagnostic pop diff --git a/app/src/tx_display.h b/app/src/tx_display.h index 2e51e5b3..d9ed8da7 100644 --- a/app/src/tx_display.h +++ b/app/src/tx_display.h @@ -31,6 +31,7 @@ typedef enum { root_item_msgs, root_item_memo, root_item_fee, + root_item_tip, } root_item_e; bool tx_is_expert_mode(); diff --git a/app/src/tx_parser.c b/app/src/tx_parser.c index 091a913c..806f7a22 100644 --- a/app/src/tx_parser.c +++ b/app/src/tx_parser.c @@ -1,3 +1,5 @@ +#pragma clang diagnostic push +#pragma ide diagnostic ignored "misc-no-recursion" /******************************************************************************* * (c) 2018, 2019 Zondax GmbH * @@ -33,10 +35,9 @@ __Z_INLINE void strcat_chunk_s(char *dst, uint16_t dst_max, const char *src_chun src_chunk_size = space_left; } + // Check bounds if (src_chunk_size > 0) { - // Check bounds - MEMCPY(dst + prev_size, src_chunk, src_chunk_size); - // terminate + MEMMOVE(dst + prev_size, src_chunk, src_chunk_size); *(dst + prev_size + src_chunk_size) = 0; } } @@ -79,7 +80,7 @@ parser_error_t tx_getToken(uint16_t token_index, // empty strings are considered the first page *pageCount = 1; if (inLen > 0) { - for (uint32_t i = 0; i < array_length(value_substitutions); i++) { + for (uint32_t i = 0; i < array_length(value_substitutions); i++) { const char *substStr = value_substitutions[i].str1; const size_t substStrLen = strlen(substStr); if (inLen == substStrLen && !MEMCMP(inValue, substStr, substStrLen)) { @@ -100,7 +101,7 @@ parser_error_t tx_getToken(uint16_t token_index, return parser_ok; } -__Z_INLINE void append_key_item(int16_t token_index) { +__Z_INLINE void append_key_item(uint16_t token_index) { if (*parser_tx_obj.query.out_key > 0) { // There is already something there, add separator strcat_chunk_s(parser_tx_obj.query.out_key, @@ -213,7 +214,7 @@ parser_error_t tx_traverse_find(uint16_t root_token_index, uint16_t *ret_value_t break; } case JSMN_ARRAY: { - for (int16_t i = 0; i < el_count; ++i) { + for (uint16_t i = 0; i < el_count; ++i) { uint16_t element_index; CHECK_PARSER_ERR(array_get_nth_element(&parser_tx_obj.json, root_token_index, i, @@ -240,3 +241,5 @@ parser_error_t tx_traverse_find(uint16_t root_token_index, uint16_t *ret_value_t return parser_query_no_results; } + +#pragma clang diagnostic pop diff --git a/app/src/tx_parser.h b/app/src/tx_parser.h index cc173023..3f08dd08 100644 --- a/app/src/tx_parser.h +++ b/app/src/tx_parser.h @@ -1,3 +1,5 @@ +#pragma clang diagnostic push +#pragma ide diagnostic ignored "modernize-deprecated-headers" /******************************************************************************* * (c) 2018, 2019 Zondax GmbH * @@ -63,3 +65,5 @@ __Z_INLINE bool is_msg_from_field(char *field_name) { #ifdef __cplusplus } #endif + +#pragma clang diagnostic pop diff --git a/cmake/conan/CMakeLists.txt b/cmake/conan/CMakeLists.txt index 70cf30ec..e8924378 100644 --- a/cmake/conan/CMakeLists.txt +++ b/cmake/conan/CMakeLists.txt @@ -9,4 +9,7 @@ include(${CMAKE_BINARY_DIR}/conan.cmake) conan_check(REQUIRED) -conan_cmake_run(CONANFILE conanfile.txt BASIC_SETUP CMAKE_TARGETS BUILD missing) +conan_cmake_run(CONANFILE conanfile.txt + BASIC_SETUP + CMAKE_TARGETS + BUILD missing) diff --git a/conanfile.txt b/conanfile.txt index 6df14337..9639b968 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -1,6 +1,6 @@ [requires] -jsoncpp/1.9.4 -fmt/7.1.3 +jsoncpp/1.9.5 +fmt/8.1.1 [generators] cmake diff --git a/deps/ledger-zxlib/.circleci/config.yml b/deps/ledger-zxlib/.circleci/config.yml deleted file mode 100644 index 56ef429b..00000000 --- a/deps/ledger-zxlib/.circleci/config.yml +++ /dev/null @@ -1,19 +0,0 @@ -version: 2 -jobs: - build: - docker: - - image: ubuntu:20.04 - steps: - - run: - name: Install dependencies - command: apt update && apt-get -y install build-essential git sudo wget cmake libssl-dev libgmp-dev autoconf libtool - - checkout - - run: git submodule update --init --recursive - - run: cmake . && make - - run: export GTEST_COLOR=1 && ctest -VV - -workflows: - version: 2 - build_all: - jobs: - - build diff --git a/deps/ledger-zxlib/include/segwit_addr.h b/deps/ledger-zxlib/include/segwit_addr.h index d03bb11d..f97bcfaf 100644 --- a/deps/ledger-zxlib/include/segwit_addr.h +++ b/deps/ledger-zxlib/include/segwit_addr.h @@ -89,7 +89,7 @@ int bech32_encode( * data_len: Pointer to a size_t that will be updated to be the number * of entries in data. * In: input: Pointer to a null-terminated Bech32 string. - * Returns 1 if succesful. + * Returns 1 if successful. */ int bech32_decode( char *hrp, diff --git a/deps/ledger-zxlib/include/utf8.h b/deps/ledger-zxlib/include/utf8.h index 80532eb6..fe2e8d9f 100644 --- a/deps/ledger-zxlib/include/utf8.h +++ b/deps/ledger-zxlib/include/utf8.h @@ -1,4 +1,4 @@ - /* The latest version of this library is available on GitHub; +/* The latest version of this library is available on GitHub; * https://github.com/sheredom/utf8.h */ /* This is free and unencumbered software released into the public domain. diff --git a/deps/ledger-zxlib/include/zxmacros.h b/deps/ledger-zxlib/include/zxmacros.h index 9d92469b..b5bf7e87 100644 --- a/deps/ledger-zxlib/include/zxmacros.h +++ b/deps/ledger-zxlib/include/zxmacros.h @@ -104,7 +104,11 @@ __Z_INLINE void zemu_log(__Z_UNUSED const char *msg) { } #endif +#if APP_TESTING #define ZEMU_LOGF(SIZE, ...) { char tmp[(SIZE)]; snprintf(tmp, (SIZE), __VA_ARGS__); zemu_log(tmp); } +#else +#define ZEMU_LOGF(SIZE, ...) {} +#endif #ifdef __cplusplus } diff --git a/deps/ledger-zxlib/include/zxversion.h b/deps/ledger-zxlib/include/zxversion.h index dace6c00..9c90a17f 100644 --- a/deps/ledger-zxlib/include/zxversion.h +++ b/deps/ledger-zxlib/include/zxversion.h @@ -16,5 +16,5 @@ #pragma once #define ZXLIB_MAJOR 10 -#define ZXLIB_MINOR 4 -#define ZXLIB_PATCH 6 +#define ZXLIB_MINOR 5 +#define ZXLIB_PATCH 0 diff --git a/deps/ledger-zxlib/src/zxutils_ledger.c b/deps/ledger-zxlib/src/zxutils_ledger.c index c57443d0..f849184a 100644 --- a/deps/ledger-zxlib/src/zxutils_ledger.c +++ b/deps/ledger-zxlib/src/zxutils_ledger.c @@ -4,7 +4,7 @@ #define NULL ((void *)0) #endif -// We implement a light mecanism in order to be able to retrieve the width of +// We implement a light mechanism in order to be able to retrieve the width of // nano S characters, in the two possible fonts: // - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, // - BAGL_FONT_OPEN_SANS_REGULAR_11px. @@ -114,7 +114,7 @@ const char nanos_characters_width[96] = { unsigned short zx_compute_line_width_light(const char* text, unsigned char text_length) { char current_char; unsigned short line_width = 0; - + if(text == NULL) { return 0xFFFF; } @@ -135,4 +135,4 @@ unsigned short zx_compute_line_width_light(const char* text, unsigned char text_ text++; } return line_width; -} \ No newline at end of file +} diff --git a/deps/ledger-zxlib/templates/Makefile.root b/deps/ledger-zxlib/templates/Makefile.root index 7c211328..566f6073 100644 --- a/deps/ledger-zxlib/templates/Makefile.root +++ b/deps/ledger-zxlib/templates/Makefile.root @@ -14,7 +14,7 @@ #* limitations under the License. #******************************************************************************** -# We use BOLOS_SDK to determine the develoment environment that is being used +# We use BOLOS_SDK to determine the development environment that is being used # BOLOS_SDK IS DEFINED We use the plain Makefile for Ledger # BOLOS_SDK NOT DEFINED We use a containerized build approach diff --git a/tests/testcases/manual.json b/tests/testcases/manual.json index 85e46528..b772d3ff 100644 --- a/tests/testcases/manual.json +++ b/tests/testcases/manual.json @@ -1517,5 +1517,216 @@ "6 | Fee : 0.000600 ATOM" ], "expert": false + }, + { + "name": "completeTransferWithTips", + "tx": { + "account_number": "0", + "chain_id": "cosmoshub-4", + "fee": { + "amount": [ + { + "amount": "5", + "denom": "feecoin1" + }, + { + "amount": "6", + "denom": "feecoin2" + } + ], + "gas": "10000", + "granter": "cosmosaccaddr1d9h8xxxGRANTER", + "payer": "cosmosaccaddr1d9h8qatxxPAYER" + }, + "memo": "testmemo", + "msgs": [ + { + "inputs": [ + { + "address": "cosmosaccaddr1d9h8qatxxINPUT", + "coins": [ + { + "amount": "10", + "denom": "atom" + } + ] + } + ], + "outputs": [ + { + "address": "cosmosaccaddr1da6hguxxOUTPUT", + "coins": [ + { + "amount": "10", + "denom": "atom" + } + ] + } + ] + } + ], + "sequence": "1", + "tip": { + "amount": [ + { + "amount": "65", + "denom": "tipcoin" + }, + { + "amount": "66", + "denom": "tipcoin2" + } + ], + "tipper": "cosmosaccaddr1d9h8qatxTIPPER" + } + }, + "parsingErr": "No error", + "validationErr": "No error", + "expected": [ + "0 | Chain ID : cosmoshub-4", + "1 | Account : 0", + "2 | Sequence : 1", + "3 | Source Address : cosmosaccaddr1d9h8qatxxINPUT", + "4 | Source Coins : 10 atom", + "5 | Dest Address : cosmosaccaddr1da6hguxxOUTPUT", + "6 | Dest Coins : 10 atom", + "7 | Memo : testmemo", + "8 | Fee [1/2] : 5 feecoin1", + "8 | Fee [2/2] : 6 feecoin2", + "9 | Gas : 10000", + "10 | Granter : cosmosaccaddr1d9h8xxxGRANTER", + "11 | Payer : cosmosaccaddr1d9h8qatxxPAYER", + "12 | Tip [1/2] : 65 tipcoin", + "12 | Tip [2/2] : 66 tipcoin2", + "13 | Tipper : cosmosaccaddr1d9h8qatxTIPPER" + ], + "expert": true + }, + { + "name": "completeTransferWithTipsBasic", + "tx": { + "account_number": "0", + "chain_id": "cosmoshub-4", + "fee": { + "amount": [ + { + "amount": "5", + "denom": "photon" + } + ], + "gas": "10000", + "granter": "cosmosaccaddr1d9h8xxxGRANTER", + "payer": "cosmosaccaddr1d9h8qatxxPAYER" + }, + "memo": "testmemo", + "msgs": [ + { + "inputs": [ + { + "address": "cosmosaccaddr1d9h8qatxxINPUT", + "coins": [ + { + "amount": "10", + "denom": "atom" + } + ] + } + ], + "outputs": [ + { + "address": "cosmosaccaddr1da6hguxxOUTPUT", + "coins": [ + { + "amount": "10", + "denom": "atom" + } + ] + } + ] + } + ], + "sequence": "1", + "tip": { + "amount": [ + { + "amount": "65", + "denom": "tipcoin" + }, + { + "amount": "66", + "denom": "tipcoin2" + } + ], + "tipper": "cosmosaccaddr1d9h8qatxTIPPER" + } + }, + "parsingErr": "No error", + "validationErr": "No error", + "expected": [ + "0 | Source Address : cosmosaccaddr1d9h8qatxxINPUT", + "1 | Source Coins : 10 atom", + "2 | Dest Address : cosmosaccaddr1da6hguxxOUTPUT", + "3 | Dest Coins : 10 atom", + "4 | Memo : testmemo", + "5 | Fee : 5 photon", + "6 | Tip [1/2] : 65 tipcoin", + "6 | Tip [2/2] : 66 tipcoin2", + "7 | Tipper : cosmosaccaddr1d9h8qatxTIPPER" + ], + "expert": false + }, + { + "name": "doubleFees", + "tx": { + "account_number": "0", + "chain_id": "cosmoshub-4", + "fee": { + "amount": [ + { + "amount": "5", + "denom": "feecoin1" + }, + { + "amount": "6", + "denom": "feecoin2" + } + ], + "gas": "10000", + "granter": "cosmosaccaddr1d9h8xxxGRANTER", + "payer": "cosmosaccaddr1d9h8qatxxPAYER" + }, + "memo": "", + "msgs": [], + "sequence": "1", + "tip": { + "amount": [ + { + "amount": "65", + "denom": "tipcoin" + }, + { + "amount": "66", + "denom": "tipcoin2" + } + ], + "tipper": "cosmosaccaddr1d9h8qatxTIPPER" + } + }, + "parsingErr": "No error", + "validationErr": "No error", + "expected": [ + "0 | Chain ID : cosmoshub-4", + "1 | Account : 0", + "2 | Sequence : 1", + "3 | Fee [1/2] : 5 feecoin1", + "3 | Fee [2/2] : 6 feecoin2", + "4 | Gas : 10000", + "5 | Granter : cosmosaccaddr1d9h8xxxGRANTER", + "6 | Payer : cosmosaccaddr1d9h8qatxxPAYER", + "7 | Tip [1/2] : 65 tipcoin", + "7 | Tip [2/2] : 66 tipcoin2", + "8 | Tipper : cosmosaccaddr1d9h8qatxTIPPER" + ], + "expert": true } ] diff --git a/tests/tx_parse.cpp b/tests/tx_parse.cpp index a865d8b3..19bb106c 100644 --- a/tests/tx_parse.cpp +++ b/tests/tx_parse.cpp @@ -22,6 +22,8 @@ #include "common.h" namespace { +#pragma clang diagnostic push +#pragma ide diagnostic ignored "ConstantParameter" parser_error_t tx_traverse(int16_t root_token_index, uint8_t *numChunks) { uint16_t ret_value_token_index = 0; parser_error_t err = tx_traverse_find(root_token_index, &ret_value_token_index); @@ -34,12 +36,13 @@ namespace { parser_tx_obj.query.out_val, parser_tx_obj.query.out_val_len, parser_tx_obj.query.page_index, numChunks); } +#pragma clang diagnostic pop TEST(TxParse, Tx_Traverse) { auto transaction = R"({"keyA":"123456", "keyB":"abcdefg", "keyC":""})"; parser_tx_obj.tx = transaction; - parser_tx_obj.flags.cache_valid = 0; + parser_tx_obj.flags.cache_valid = false; parser_error_t err = JSON_PARSE(&parser_tx_obj.json, parser_tx_obj.tx); ASSERT_EQ(err, parser_ok); @@ -104,7 +107,7 @@ namespace { auto transaction = R"({"keyA":"123456", "keyB":"abcdefg"})"; parser_tx_obj.tx = transaction; - parser_tx_obj.flags.cache_valid = 0; + parser_tx_obj.flags.cache_valid = false; parser_error_t err = JSON_PARSE(&parser_tx_obj.json, parser_tx_obj.tx); ASSERT_EQ(err, parser_ok); @@ -127,7 +130,7 @@ namespace { auto transaction = R"({"account_number":"0"})"; parser_tx_obj.tx = transaction; - parser_tx_obj.flags.cache_valid = 0; + parser_tx_obj.flags.cache_valid = false; parser_error_t err = JSON_PARSE(&parser_tx_obj.json, parser_tx_obj.tx); EXPECT_EQ(err, parser_ok); @@ -141,7 +144,7 @@ namespace { auto transaction = R"({"account_number":"0","chain_id":"test-chain-1","fee":{"amount":[{"amount":"5","denom":"photon"}],"gas":"10000"},"memo":"testmemo","msgs":[{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"amount":"10","denom":"atom"}]}]}],"sequence":"1"})"; parser_tx_obj.tx = transaction; - parser_tx_obj.flags.cache_valid = 0; + parser_tx_obj.flags.cache_valid = false; parser_error_t err = JSON_PARSE(&parser_tx_obj.json, parser_tx_obj.tx); EXPECT_EQ(err, parser_ok); @@ -155,7 +158,7 @@ namespace { R"({"account_number":"0","chain_id":"test-chain-1","fee":{"amount":[{"amount":"5","denom":"photon"}],"gas":"10000"},"memo":"testmemo","msgs":[{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"amount":"10","denom":"atom"}]}]},{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"amount":"10","denom":"atom"}]}]},{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"amount":"10","denom":"atom"}]}]},{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"amount":"10","denom":"atom"}]}]}],"sequence":"1"})"; parser_tx_obj.tx = transaction; - parser_tx_obj.flags.cache_valid = 0; + parser_tx_obj.flags.cache_valid = false; parser_error_t err = JSON_PARSE(&parser_tx_obj.json, parser_tx_obj.tx); EXPECT_EQ(err, parser_ok); diff --git a/tests_zemu/package.json b/tests_zemu/package.json index 3912446c..175bda64 100644 --- a/tests_zemu/package.json +++ b/tests_zemu/package.json @@ -18,8 +18,8 @@ "testSR25519": "jest --detectOpenHandles --runInBand tests/sr25519.test.ts" }, "dependencies": { - "ledger-cosmos-js": "^2.1.8", - "@zondax/zemu": "^0.24.1" + "@zondax/zemu": "^0.25.1", + "ledger-cosmos-js": "^2.1.8" }, "devDependencies": { "@types/jest": "^27.4.0", @@ -33,7 +33,7 @@ "eslint-plugin-import": "^2.25.4", "eslint-plugin-jest": "^26.1.0", "eslint-plugin-prettier": "^4.0.0", - "jest": "27.2.5", + "jest": "27.5.1", "jest-serial-runner": "^1.1.0", "jssha": "^3.2.0", "prettier": "^2.5.1", From 1d1362f99ebfe0d9fd3f8b26498e6488073c6dd7 Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Sun, 20 Feb 2022 17:29:39 +0100 Subject: [PATCH 2/5] add additional logging --- app/src/addr.c | 10 +++++++--- tests_zemu/tests/common.ts | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/src/addr.c b/app/src/addr.c index f300f8d2..b7461e94 100644 --- a/app/src/addr.c +++ b/app/src/addr.c @@ -26,8 +26,10 @@ zxerr_t addr_getNumItems(uint8_t *num_items) { zemu_log_stack("addr_getNumItems"); *num_items = 1; if (app_mode_expert()) { + zemu_log("num_items 2\n"); *num_items = 2; } + zemu_log("num_items 1\n"); return zxerr_ok; } @@ -35,26 +37,28 @@ zxerr_t addr_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) { - char buffer[300]; - snprintf(buffer, sizeof(buffer), "addr_getItem %d/%d", displayIdx, pageIdx); - zemu_log_stack(buffer); + ZEMU_LOGF(200, "[addr_getItem] %d/%d\n", displayIdx, pageIdx) switch (displayIdx) { case 0: snprintf(outKey, outKeyLen, "Address"); pageString(outVal, outValLen, (char *) (G_io_apdu_buffer + VIEW_ADDRESS_OFFSET_SECP256K1), pageIdx, pageCount); + ZEMU_LOGF(200, "[addr_getItem] pageCount %d\n", *pageCount) return zxerr_ok; case 1: { if (!app_mode_expert()) { return zxerr_no_data; } + char buffer[300]; snprintf(outKey, outKeyLen, "Path"); bip32_to_str(buffer, sizeof(buffer), hdPath, HDPATH_LEN_DEFAULT); pageString(outVal, outValLen, buffer, pageIdx, pageCount); + ZEMU_LOGF(200, "[addr_getItem] pageCount %d\n", *pageCount) return zxerr_ok; } default: + zemu_log("[addr_getItem] no data\n"); return zxerr_no_data; } } diff --git a/tests_zemu/tests/common.ts b/tests_zemu/tests/common.ts index 688a14f5..e51e1d2c 100644 --- a/tests_zemu/tests/common.ts +++ b/tests_zemu/tests/common.ts @@ -14,6 +14,7 @@ * limitations under the License. ******************************************************************************* */ import { DEFAULT_START_OPTIONS, DeviceModel } from '@zondax/zemu' +import {DEFAULT_KEY_DELAY} from "@zondax/zemu/src/constants"; const Resolve = require('path').resolve @@ -26,6 +27,7 @@ export const DEFAULT_OPTIONS = { ...DEFAULT_START_OPTIONS, logging: true, custom: `-s "${APP_SEED}"`, + pressDelay: 1500, X11: false, } From df7044a44bc52d51575167a23910bedace1b26ee Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Sun, 20 Feb 2022 17:30:22 +0100 Subject: [PATCH 3/5] bump version --- app/Makefile.version | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Makefile.version b/app/Makefile.version index 764e16bd..12225abb 100644 --- a/app/Makefile.version +++ b/app/Makefile.version @@ -1,6 +1,6 @@ # This is the `transaction_version` field of `Runtime` APPVERSION_M=2 # This is the `spec_version` field of `Runtime` -APPVERSION_N=32 +APPVERSION_N=33 # This is the patch version of this release -APPVERSION_P=1 +APPVERSION_P=0 From fbb4500e4e33dea9bf744a7b35ed71b2cf48b3bc Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Sun, 20 Feb 2022 18:01:28 +0100 Subject: [PATCH 4/5] fix version numbers --- tests_zemu/snapshots/s-mainmenu/00004.png | Bin 458 -> 448 bytes tests_zemu/snapshots/s-mainmenu/00011.png | Bin 458 -> 448 bytes tests_zemu/snapshots/x-mainmenu/00004.png | Bin 390 -> 381 bytes tests_zemu/snapshots/x-mainmenu/00011.png | Bin 390 -> 381 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests_zemu/snapshots/s-mainmenu/00004.png b/tests_zemu/snapshots/s-mainmenu/00004.png index 68c84dce3bf19021707357a3675f123ca9ec863e..d30003d0ba10e70c3fb04aef7be2b124eda0458b 100644 GIT binary patch delta 422 zcmV;X0a^aa1Hc22B!7oVL_t(|ob8#-5`!QNgkz_D{|EM95421gl1Q)$wELYL1Z#Ks zNg@#d003|z+e+K2TpxVYPjK)30zsBX?>G1|T@B!KIVroXv^-wz`9gFcW<&14TlheA z)JWXA{c;wCYeb~%Fu9NQ1TiXkFbS8efHWoftaRk2Vyde1w|^Yy=svI?bp}Mwz4|}w z_Y_tQtYb5swxEzhYUi@idFH^e(^Up!b;L!I#!`phwGZKlx{H{0&r@qp}f6j)?E zi(r}=Any4dK!5!xNzY=R2u4AEj@l3fIYY`qkkz<5YGC4FsC5i9{Bu!svqm|k2&Zw9 z{2*8hvQAxpBT}uhQrthIDGv~G?;ZnuN`@w;ng%<$@q`3dfM3OI!%>r$E7Tgs{2uiC z9+3F^AnMv;oL^Q;G*m7JE_Uuxw*{TF(#3}6d~&IbwI9kaKL7v#003Y}o`w3`?um3B QrT_o{07*qoM6N<$f_G}e+5i9m delta 432 zcmV;h0Z;zG1Ih!CB!7`fL_t(|ob8#*a>F1DMdeQO{~zpyyHLU?dKGYEz`bYXF<{_| zha?jL0000VAYMp>$E!e!;S zo~|9B^o86f@C=Y2m(t@_&L41b9kv(704k7Cs0c`|ee8n>rRTdl_ilhvme_#ea1=xo zJ&iLh44}$#8-GCkR#;DSPBeN!d5qfO1tm>vBB-*Lr5w{nFUa1yXSPC=%waeLb2CLz zlfGdLr7;&2-Maa-T~kFNZv6nFj+UY;4p8&_b=q>lHk}Vi7#wx9$jMV^+yQwOvyVh# znXa%KZZ)l4#{Caqx^IrVaBVU!PpdJNnahqQQ&M*XeJNG1|T@B!KIVroXv^-wz`9gFcW<&14TlheA z)JWXA{c;wCYeb~%Fu9NQ1TiXkFbS8efHWoftaRk2Vyde1w|^Yy=svI?bp}Mwz4|}w z_Y_tQtYb5swxEzhYUi@idFH^e(^Up!b;L!I#!`phwGZKlx{H{0&r@qp}f6j)?E zi(r}=Any4dK!5!xNzY=R2u4AEj@l3fIYY`qkkz<5YGC4FsC5i9{Bu!svqm|k2&Zw9 z{2*8hvQAxpBT}uhQrthIDGv~G?;ZnuN`@w;ng%<$@q`3dfM3OI!%>r$E7Tgs{2uiC z9+3F^AnMv;oL^Q;G*m7JE_Uuxw*{TF(#3}6d~&IbwI9kaKL7v#003Y}o`w3`?um3B QrT_o{07*qoM6N<$f_G}e+5i9m delta 432 zcmV;h0Z;zG1Ih!CB!7`fL_t(|ob8#*a>F1DMdeQO{~zpyyHLU?dKGYEz`bYXF<{_| zha?jL0000VAYMp>$E!e!;S zo~|9B^o86f@C=Y2m(t@_&L41b9kv(704k7Cs0c`|ee8n>rRTdl_ilhvme_#ea1=xo zJ&iLh44}$#8-GCkR#;DSPBeN!d5qfO1tm>vBB-*Lr5w{nFUa1yXSPC=%waeLb2CLz zlfGdLr7;&2-Maa-T~kFNZv6nFj+UY;4p8&_b=q>lHk}Vi7#wx9$jMV^+yQwOvyVh# znXa%KZZ)l4#{Caqx^IrVaBVU!PpdJNnahqQQ&M*XeJNwB$rQXHU#WAE}&fA-@MTZr5+ya+gp1a|{YNmc|!l3|`qGP@~5AS_`a`0H9 zUE(8oK?VdUa9_1*RoUJR=i}56}1@ljvMuzGxz4C3Fp^QST7T^|F#8 z{`KycR6Y6@NqULSdz|@l+JftgW7gVlyJ(sIWAEjNhS%pG9hay91j&);LZ4A>WtsxVEL|ap||IeVb2PMg-lP`tHb1ljZN_ z!gO!yeRT0Zgnp|vd$@?2>=>7s%-!O delta 363 zcmey%)W$qPrQX-m#WAE}&fA;OLWdN1S`$m|aQ==D`u2!fxj7~%CtLW-|9MurAIvRcwyDSS z*1x{Hwk~3#v!*fE`%urK*%u{O#jRw!FZtE)Sbey|tVvJTggoLq8}jzt{cVdU?XI+) zqvx2YJ!@6SGs}0+@;GPp7j5~s#d>P-tozniS$EW#SkBFIj@z~O)Z)cQ&i+q`mj1Y| zLVoX@#1l*EXZl@PQg4`*&>4C{=>Oqqw<_}09?!VG?@}P2W^eQ9-Iu0nOi%lM*SWm^ z@ax+bCl^dTw=*Tt@Z)lg{71XKO4w>?pFe+`?Z<03)(g$E^WSV>=$p1+Vt-tj-ruw< zty!TnXKwzb-je5S|EG@s#I630tIO9Fo$8ljMhcbs&n)#j|2#`r_IU?L)YH|^Wt~$( F696{ys`>x` diff --git a/tests_zemu/snapshots/x-mainmenu/00011.png b/tests_zemu/snapshots/x-mainmenu/00011.png index 9e7613c848af1348d3c6cee792ece406ede891ee..bf6d460e13422b22b5d6114481c1ec3430f1b04c 100644 GIT binary patch delta 354 zcmZo;{>wB$rQXHU#WAE}&fA-@MTZr5+ya+gp1a|{YNmc|!l3|`qGP@~5AS_`a`0H9 zUE(8oK?VdUa9_1*RoUJR=i}56}1@ljvMuzGxz4C3Fp^QST7T^|F#8 z{`KycR6Y6@NqULSdz|@l+JftgW7gVlyJ(sIWAEjNhS%pG9hay91j&);LZ4A>WtsxVEL|ap||IeVb2PMg-lP`tHb1ljZN_ z!gO!yeRT0Zgnp|vd$@?2>=>7s%-!O delta 363 zcmey%)W$qPrQX-m#WAE}&fA;OLWdN1S`$m|aQ==D`u2!fxj7~%CtLW-|9MurAIvRcwyDSS z*1x{Hwk~3#v!*fE`%urK*%u{O#jRw!FZtE)Sbey|tVvJTggoLq8}jzt{cVdU?XI+) zqvx2YJ!@6SGs}0+@;GPp7j5~s#d>P-tozniS$EW#SkBFIj@z~O)Z)cQ&i+q`mj1Y| zLVoX@#1l*EXZl@PQg4`*&>4C{=>Oqqw<_}09?!VG?@}P2W^eQ9-Iu0nOi%lM*SWm^ z@ax+bCl^dTw=*Tt@Z)lg{71XKO4w>?pFe+`?Z<03)(g$E^WSV>=$p1+Vt-tj-ruw< zty!TnXKwzb-je5S|EG@s#I630tIO9Fo$8ljMhcbs&n)#j|2#`r_IU?L)YH|^Wt~$( F696{ys`>x` From 6a64f58f703662c285f167eef314831f1e361d51 Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Sun, 20 Feb 2022 18:01:33 +0100 Subject: [PATCH 5/5] fix unit tests --- app/src/tx_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/tx_display.c b/app/src/tx_display.c index 736c05d7..ea7ed8ee 100644 --- a/app/src/tx_display.c +++ b/app/src/tx_display.c @@ -353,7 +353,7 @@ __Z_INLINE uint8_t get_subitem_count(root_item_e root_item) { break; case root_item_fee: if (!tx_is_expert_mode()) { - tmp_num_items -= 3; // Hide Gas field + tmp_num_items = 1; // Only Amount } case root_item_tip: tmp_num_items += 0;