From 572db734ca6f5b44c24814b345d8153599706a44 Mon Sep 17 00:00:00 2001 From: Xavier Chapron Date: Mon, 29 Jan 2024 16:52:43 +0100 Subject: [PATCH] src: Use nbgl sync API step 1 --- src/ui/nbgl_display_address.c | 66 ++++++++-------- src/ui/nbgl_display_transaction.c | 124 +++++++++++++----------------- 2 files changed, 82 insertions(+), 108 deletions(-) diff --git a/src/ui/nbgl_display_address.c b/src/ui/nbgl_display_address.c index 5f1bbfe8..b917e09c 100644 --- a/src/ui/nbgl_display_address.c +++ b/src/ui/nbgl_display_address.c @@ -36,53 +36,47 @@ #include "../transaction/types.h" #include "../menu.h" -static char g_address[43]; - -static void confirm_address_rejection(void) { - // display a status page and go back to main - validate_pubkey(false); - nbgl_useCaseStatus("Address verification\ncancelled", false, ui_menu_main); -} - -static void confirm_address_approval(void) { - // display a success status page and go back to main - validate_pubkey(true); - nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, ui_menu_main); -} - -static void review_choice(bool confirm) { - if (confirm) { - confirm_address_approval(); - } else { - confirm_address_rejection(); - } -} - -static void continue_review(void) { - nbgl_useCaseAddressConfirmation(g_address, review_choice); -} - int ui_display_address() { if (G_context.req_type != CONFIRM_ADDRESS || G_context.state != STATE_NONE) { G_context.state = STATE_NONE; return io_send_sw(SW_BAD_STATE); } - memset(g_address, 0, sizeof(g_address)); - uint8_t address[ADDRESS_LEN] = {0}; - if (!address_from_pubkey(G_context.pk_info.raw_public_key, address, sizeof(address))) { + + char address_str[43] = {0}; + uint8_t address_bin[ADDRESS_LEN] = {0}; + + if (!address_from_pubkey(G_context.pk_info.raw_public_key, address_bin, sizeof(address_bin))) { return io_send_sw(SW_DISPLAY_ADDRESS_FAIL); } - if (format_hex(address, sizeof(address), g_address, sizeof(g_address)) == -1) { + if (format_hex(address_bin, sizeof(address_bin), address_str, sizeof(address_str)) == -1) { return io_send_sw(SW_DISPLAY_ADDRESS_FAIL); } - nbgl_useCaseReviewStart(&C_app_boilerplate_64px, - "Verify BOL address", - NULL, - "Cancel", - continue_review, - confirm_address_rejection); + sync_nbgl_ret_t ret = sync_nbgl_useCaseAddressReview(address_str, + &C_app_boilerplate_64px, + "Verify BOL address", + NULL); + + if (ret == NBGL_SYNC_RET_SUCCESS) { + // display a status page and go back to main + validate_pubkey(true); + nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, ui_menu_main); + } else if (ret == NBGL_SYNC_RET_REJECTED) { + // display a status page and go back to main + validate_pubkey(false); + nbgl_useCaseStatus("Address verification\ncancelled", false, ui_menu_main); + } else { + io_send_sw(SW_BAD_STATE); + nbgl_useCaseStatus("Address verification\nissue", false, ui_menu_main); + } + + // Here we used async version of nbgl_useCaseStatus + // This means that upon end of timer or touch ui_menu_main will be called + // but in the meantime we return to app_main to process APDU. + // If an APDU is received before the timer ends, a new UX might be shown on + // the screen, and therefore the modal will be dismissed and its callback + // will never be called. return 0; } diff --git a/src/ui/nbgl_display_transaction.c b/src/ui/nbgl_display_transaction.c index 2396c8ce..463ae802 100755 --- a/src/ui/nbgl_display_transaction.c +++ b/src/ui/nbgl_display_transaction.c @@ -22,8 +22,7 @@ #include "os.h" #include "glyphs.h" -#include "os_io_seproxyhal.h" -#include "nbgl_use_case.h" +#include "nbgl_sync.h" #include "io.h" #include "bip32.h" #include "format.h" @@ -37,64 +36,9 @@ #include "../transaction/types.h" #include "../menu.h" -// Buffer where the transaction amount string is written -static char g_amount[30]; -// Buffer where the transaction address string is written -static char g_address[43]; - -static nbgl_layoutTagValue_t pairs[2]; -static nbgl_layoutTagValueList_t pairList; -static nbgl_pageInfoLongPress_t infoLongPress; - -static void confirm_transaction_rejection(void) { - // display a status page and go back to main - validate_transaction(false); - nbgl_useCaseStatus("Transaction rejected", false, ui_menu_main); -} - -static void ask_transaction_rejection_confirmation(void) { - // display a choice to confirm/cancel rejection - nbgl_useCaseConfirm("Reject transaction?", - NULL, - "Yes, Reject", - "Go back to transaction", - confirm_transaction_rejection); -} - -// called when long press button on 3rd page is long-touched or when reject footer is touched -static void review_choice(bool confirm) { - if (confirm) { - // display a status page and go back to main - validate_transaction(true); - nbgl_useCaseStatus("TRANSACTION\nSIGNED", true, ui_menu_main); - } else { - ask_transaction_rejection_confirmation(); - } -} - -static void review_continue(void) { - // Setup data to display - pairs[0].item = "Amount"; - pairs[0].value = g_amount; - pairs[1].item = "Address"; - pairs[1].value = g_address; - - // Setup list - pairList.nbMaxLinesForValue = 0; - pairList.nbPairs = 2; - pairList.pairs = pairs; - - // Info long press - infoLongPress.icon = &C_app_boilerplate_64px; - infoLongPress.text = "Sign transaction\nto send BOL"; - infoLongPress.longPressText = "Hold to sign"; - - nbgl_useCaseStaticReview(&pairList, &infoLongPress, "Reject transaction", review_choice); -} - // Public function to start the transaction review // - Check if the app is in the right state for transaction review -// - Format the amount and address strings in g_amount and g_address buffers +// - Format the amount and address strings in amount_str and address_str buffers // - Display the first screen of the transaction review int ui_display_transaction() { if (G_context.req_type != CONFIRM_TRANSACTION || G_context.state != STATE_PARSED) { @@ -102,30 +46,66 @@ int ui_display_transaction() { return io_send_sw(SW_BAD_STATE); } - // Format amount and address to g_amount and g_address buffers - memset(g_amount, 0, sizeof(g_amount)); - char amount[30] = {0}; - if (!format_fpu64(amount, - sizeof(amount), + // Buffer where the transaction amount string is written + char amount_str[30] = {0}; + // Buffer where the transaction address string is written + char address_str[43] = {0}; + + // Format amount and address to amount_str and address_str buffers + char amount_bin[30] = {0}; + if (!format_fpu64(amount_bin, + sizeof(amount_bin), G_context.tx_info.transaction.value, EXPONENT_SMALLEST_UNIT)) { return io_send_sw(SW_DISPLAY_AMOUNT_FAIL); } - snprintf(g_amount, sizeof(g_amount), "BOL %.*s", sizeof(amount), amount); - memset(g_address, 0, sizeof(g_address)); + snprintf(amount_str, sizeof(amount_str), "BOL %.*s", sizeof(amount_bin), amount_bin); - if (format_hex(G_context.tx_info.transaction.to, ADDRESS_LEN, g_address, sizeof(g_address)) == + if (format_hex(G_context.tx_info.transaction.to, ADDRESS_LEN, address_str, sizeof(address_str)) == -1) { return io_send_sw(SW_DISPLAY_ADDRESS_FAIL); } + nbgl_layoutTagValue_t pairs[2] = {0}; + nbgl_layoutTagValueList_t pairList = {0}; + + // Setup data to display + pairs[0].item = "Amount"; + pairs[0].value = amount_str; + pairs[1].item = "Address"; + pairs[1].value = address_str; + + // Setup list + pairList.nbMaxLinesForValue = 0; + pairList.nbPairs = 2; + pairList.pairs = pairs; + // Start review - nbgl_useCaseReviewStart(&C_app_boilerplate_64px, - "Review transaction\nto send BOL", - NULL, - "Reject transaction", - review_continue, - ask_transaction_rejection_confirmation); + sync_nbgl_ret_t ret = sync_nbgl_useCaseTransactionReview( + &pairList, + &C_app_boilerplate_64px, + "Review transaction\nto send BOL", + NULL, + "Sign transaction\nto send BOL"); + + if (ret == NBGL_SYNC_RET_SUCCESS) { + // display a status page and go back to main + validate_transaction(true); + sync_nbgl_useCaseStatus("TRANSACTION\nSIGNED", true); + } else if (ret == NBGL_SYNC_RET_REJECTED) { + // display a status page and go back to main + validate_transaction(false); + sync_nbgl_useCaseStatus("Transaction rejected", false); + } else { + io_send_sw(SW_BAD_STATE); + sync_nbgl_useCaseStatus("Transaction issue", false); + } + + // Here we used sync version of nbgl_useCaseStatus + // This means that upon reception of any APDU during + // sync_nbgl_useCaseStatus, we will stop the status display even if the + // received APDU doesn't need an UX flow to be answered. + ui_menu_main(); return 0; }