diff --git a/app/Makefile b/app/Makefile index 79736d02..0d59df97 100755 --- a/app/Makefile +++ b/app/Makefile @@ -22,15 +22,9 @@ endif MY_DIR := $(dir $(lastword $(MAKEFILE_LIST))) -include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.installer_script - -include $(BOLOS_SDK)/Makefile.defines - # Set the default value for PRODUCTION_BUILD to 0 if not already defined PRODUCTION_BUILD ?= 1 -$(info ************ PENUMBRA_NAME = [$(TARGET_NAME)]) - # Display whether this is a production build or for internal use ifeq ($(PRODUCTION_BUILD), 1) $(info ************ PRODUCTION_BUILD = [PRODUCTION BUILD]) @@ -39,9 +33,8 @@ else endif # Display whether swap functionality is enabled or not -ifdef HAVE_SWAP +ifeq ($(ENABLE_SWAP), 1) $(info ************ HAVE_SWAP = [ENABLED]) - DEFINES += HAVE_SWAP=$(HAVE_SWAP) else $(info ************ HAVE_SWAP = [DISABLED]) endif @@ -55,6 +48,9 @@ ifndef COIN COIN=UM endif +VARIANT_PARAM=COIN +VARIANT_VALUES=$(COIN) + include $(CURDIR)/Makefile.version $(info COIN = [$(COIN)]) @@ -78,12 +74,7 @@ $(info PATHS LIST = $(APPPATH)) APP_LOAD_PARAMS = --curve secp256k1 $(COMMON_LOAD_PARAMS) --path $(APPPATH) INCLUDES_PATH += $(CURDIR)/src/protobuf - -ifeq ($(TARGET_NAME),TARGET_NANOS) - APP_STACK_MIN_SIZE := 1600 -else - APP_STACK_MIN_SIZE := 1752 -endif +INCLUDES_PATH += $(CURDIR)/src/common # Flag to compile all Penumbra actions FULL_APP ?= 0 @@ -92,45 +83,30 @@ DEFINES += FULL_APP $(info ************ FULL APP ENABLED ************) endif -include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.devices - -$(info TARGET_NAME = [$(TARGET_NAME)]) -$(info ICONNAME = [$(ICONNAME)]) - -ifndef ICONNAME -$(error ICONNAME is not set) -endif - -ifeq ($(TARGET_NAME),TARGET_NANOS) RUST_TARGET:=thumbv6m-none-eabi -endif - -ifeq ($(TARGET_NAME),TARGET_NANOX) -RUST_TARGET:=thumbv6m-none-eabi -endif -ifeq ($(TARGET_NAME),TARGET_NANOS2) -#RUST_TARGET:=thumbv8m.main-none-eabi -RUST_TARGET:=thumbv6m-none-eabi -endif - -ifeq ($(TARGET_NAME),TARGET_STAX) -RUST_TARGET:=thumbv6m-none-eabi -endif +$(info ************ RUST_TARGET = [$(RUST_TARGET)]) -ifeq ($(TARGET_NAME),TARGET_FLEX) -RUST_TARGET:=thumbv6m-none-eabi -endif +include $(BOLOS_SDK)/Makefile.target -$(info ************ RUST_TARGET = [$(RUST_TARGET)]) +include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.devices include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.platform + APP_SOURCE_PATH += $(CURDIR)/rust/include CFLAGS += -Wvla LDFLAGS += -z muldefs LDLIBS += -lm -lgcc -lc LDLIBS += -L$(MY_DIR)rust/target/$(RUST_TARGET)/release -lrslib +include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.installer_script + +$(info TARGET_NAME = [$(TARGET_NAME)]) +$(info ICONNAME = [$(ICONNAME)]) + +ifndef ICONNAME +$(error ICONNAME is not set) +endif ifeq ($(DEBUG), 1) CFLAGS += -O3 -Os -Wno-unknown-pragmas -Wno-unused-parameter -g @@ -157,18 +133,13 @@ rust_clean: clean: rust_clean -include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.side_loading -# Import generic rules from the SDK -include $(BOLOS_SDK)/Makefile.rules +# make rust a prerequisite for all object files +$(OBJECT_FILES): rust #add dependency on custom makefile filename dep/%.d: %.c Makefile -.PHONY: listvariants -listvariants: - @echo VARIANTS COIN UM - .PHONY: version version: @echo "v$(APPVERSION)" > app.version diff --git a/app/rust/src/bolos.rs b/app/rust/src/bolos.rs index 854cb67d..c36405fe 100644 --- a/app/rust/src/bolos.rs +++ b/app/rust/src/bolos.rs @@ -55,7 +55,7 @@ impl RngCore for Trng { #[cfg(not(test))] fn fill_bytes(&mut self, dest: &mut [u8]) { - zlog("fill_bytes\x00".as_ref()); + zlog("fill_bytes\x00"); unsafe { cx_rng(dest.as_mut_ptr(), dest.len() as u32); diff --git a/app/rust/src/constants.rs b/app/rust/src/constants.rs index f4de0ace..54315958 100644 --- a/app/rust/src/constants.rs +++ b/app/rust/src/constants.rs @@ -31,6 +31,7 @@ pub const MAX_CLUE_SUBKEYS: usize = 10; pub const MAX_REWARDS: usize = 5; pub const EFFECT_HASH_LEN: usize = 64; +pub const UI_ADDRESS_LEN: usize = 37; // Nonces: pub const NONCE_LEN: usize = 12; diff --git a/app/rust/src/parser/memo.rs b/app/rust/src/parser/memo.rs index 0522a2f7..eace3674 100644 --- a/app/rust/src/parser/memo.rs +++ b/app/rust/src/parser/memo.rs @@ -16,18 +16,18 @@ use super::memo_plain_text::MemoPlaintextC; use super::symmetric::{PayloadKey, PayloadKind}; -use crate::constants::{MEMO_CIPHERTEXT_LEN_BYTES, MEMO_LEN_BYTES}; +use crate::constants::{MEMO_CIPHERTEXT_LEN_BYTES, MEMO_LEN_BYTES, UI_ADDRESS_LEN}; use crate::parser::bytes::BytesC; use crate::parser::effect_hash::{create_personalized_state, EffectHash}; use crate::utils::protobuf::encode_varint; use crate::ParserError; #[repr(C)] -#[derive(Default)] #[cfg_attr(any(feature = "derive-debug", test), derive(Debug))] pub struct MemoPlanC { pub plaintext: MemoPlaintextC, pub key: BytesC, + pub ui_address: [u8; UI_ADDRESS_LEN], } impl MemoPlanC { diff --git a/app/rust/src/parser/plans.rs b/app/rust/src/parser/plans.rs index c5eff103..5df6041f 100644 --- a/app/rust/src/parser/plans.rs +++ b/app/rust/src/parser/plans.rs @@ -183,7 +183,7 @@ pub unsafe extern "C" fn rs_output_action_hash( Ok(body_hash_bytes) => { let body_hash_array = body_hash_bytes.as_array(); let copy_len: usize = core::cmp::min(output.len(), body_hash_array.len()); - output[..copy_len].copy_from_slice(&body_hash_array[..copy_len]); + output[..copy_len].copy_from_slice(&body_hash_array[..copy_len]); } Err(err) => return err as u32, } @@ -453,6 +453,7 @@ mod tests { text: BytesC::default(), }, key: BytesC::from_slice(&memo_key_bytes), + ui_address: [0u8; 37], }; // Create dummy DetectionDataPlanC @@ -747,6 +748,7 @@ mod tests { text: BytesC::from_slice(&memo_plaintext), }, key: BytesC::from_slice(&memo_key_bytes), + ui_address: [0u8; 37], }; let memo_hash = dummy_memo_plan.effect_hash(); diff --git a/app/src/apdu_handler.c b/app/src/apdu_handler.c index 7c4db4be..e416165e 100644 --- a/app/src/apdu_handler.c +++ b/app/src/apdu_handler.c @@ -28,7 +28,6 @@ #include "parser_common.h" #include "tx.h" #include "view.h" -#include "view_internal.h" #include "zxformat.h" #include "zxmacros.h" @@ -110,12 +109,6 @@ __Z_INLINE bool process_chunk(__Z_UNUSED volatile uint32_t *tx, uint32_t rx, boo __Z_INLINE void handleGetAddr(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { zemu_log("handleGetAddr\n"); - // TODO: Check size for nanos -#if defined(TARGET_NANOS) - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); -#endif - extractHDPath(rx, OFFSET_DATA); const uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; @@ -145,12 +138,6 @@ __Z_INLINE void handleGetAddr(volatile uint32_t *flags, volatile uint32_t *tx, u __Z_INLINE void handleGetFVK(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { zemu_log("handleGetFVK\n"); - // TODO: Check size for nanos -#if defined(TARGET_NANOS) - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); -#endif - extractHDPath(rx, OFFSET_DATA); zxerr_t zxerr = app_fill_keys(); @@ -190,6 +177,7 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint THROW(APDU_CODE_OK); } + view_spinner_show("Processing..."); __Z_UNUSED const char *error_msg = tx_parse(); CHECK_APP_CANARY() if (error_msg != NULL) { @@ -211,14 +199,14 @@ __Z_INLINE void handle_getversion(__Z_UNUSED volatile uint32_t *flags, volatile G_io_apdu_buffer[0] = 0x01; #endif - G_io_apdu_buffer[1] = (LEDGER_MAJOR_VERSION >> 8) & 0xFF; - G_io_apdu_buffer[2] = (LEDGER_MAJOR_VERSION >> 0) & 0xFF; + G_io_apdu_buffer[1] = (MAJOR_VERSION >> 8) & 0xFF; + G_io_apdu_buffer[2] = (MAJOR_VERSION >> 0) & 0xFF; - G_io_apdu_buffer[3] = (LEDGER_MINOR_VERSION >> 8) & 0xFF; - G_io_apdu_buffer[4] = (LEDGER_MINOR_VERSION >> 0) & 0xFF; + G_io_apdu_buffer[3] = (MINOR_VERSION >> 8) & 0xFF; + G_io_apdu_buffer[4] = (MINOR_VERSION >> 0) & 0xFF; - G_io_apdu_buffer[5] = (LEDGER_PATCH_VERSION >> 8) & 0xFF; - G_io_apdu_buffer[6] = (LEDGER_PATCH_VERSION >> 0) & 0xFF; + G_io_apdu_buffer[5] = (PATCH_VERSION >> 8) & 0xFF; + G_io_apdu_buffer[6] = (PATCH_VERSION >> 0) & 0xFF; G_io_apdu_buffer[7] = !IS_UX_ALLOWED; diff --git a/app/src/constants.h b/app/src/constants.h index 7662f959..936ebe51 100644 --- a/app/src/constants.h +++ b/app/src/constants.h @@ -88,6 +88,8 @@ #define DEFAULT_CHAIN_ID "penumbra-1" +#define SHORT_ADDRESS_LEN sizeof(ADDR_BECH32_PREFIX) + SHORT_ADDRESS_VISIBLE_CHARS + sizeof(ELLIPSIS) + // Constant to use to allocate a buffer on the stack to hold the formatting of an output action #define OUTPUT_DISPLAY_MAX_LEN \ (VALUE_DISPLAY_MAX_LEN + SHORT_ADDRESS_VISIBLE_CHARS + sizeof(ELLIPSIS) + sizeof(ADDR_BECH32_PREFIX) + 6) // = 202 diff --git a/app/src/memo.c b/app/src/memo.c index 0e05ef04..e14db929 100644 --- a/app/src/memo.c +++ b/app/src/memo.c @@ -36,14 +36,11 @@ parser_error_t memo_getItem(const parser_context_t *ctx, uint8_t displayIdx, cha return err; } - char short_address[100] = {0}; switch (displayIdx) { case 0: if (ctx->tx_obj->plan.has_memo) { snprintf(outKey, outKeyLen, "Memo Sender Address"); - CHECK_ERROR(printTxAddress(&ctx->tx_obj->plan.memo.plaintext.return_address.inner, short_address, - sizeof(short_address))); - pageString(outVal, outValLen, (char *)short_address, pageIdx, pageCount); + pageString(outVal, outValLen, (char *)ctx->tx_obj->plan.memo.ui_address, pageIdx, pageCount); } else { snprintf(outKey, outKeyLen, "Memo"); snprintf(outVal, outValLen, "None"); diff --git a/app/src/parser.c b/app/src/parser.c index a2a6d2c7..1cfafc66 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -183,67 +183,64 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c } switch (ctx->tx_obj->actions_plan[action_idx].action_type) { case penumbra_core_transaction_v1_ActionPlan_spend_tag: - CHECK_ERROR(spend_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.spend, action_idx + 1, outKey, + CHECK_ERROR(spend_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.spend, action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_output_tag: - CHECK_ERROR(output_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.output, action_idx + 1, outKey, + CHECK_ERROR(output_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.output, action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_ics20_withdrawal_tag: CHECK_ERROR(ics20_withdrawal_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.ics20_withdrawal, - action_idx + 1, outKey, outKeyLen, outVal, outValLen, pageIdx, - pageCount)) + action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; #if defined(FULL_APP) case penumbra_core_transaction_v1_ActionPlan_swap_tag: - CHECK_ERROR(swap_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.swap, action_idx + 1, outKey, + CHECK_ERROR(swap_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.swap, action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; #endif case penumbra_core_transaction_v1_ActionPlan_delegate_tag: - CHECK_ERROR(delegate_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.delegate, action_idx + 1, - outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) + CHECK_ERROR(delegate_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.delegate, action_idx, outKey, + outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_undelegate_tag: - CHECK_ERROR(undelegate_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.undelegate, action_idx + 1, + CHECK_ERROR(undelegate_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.undelegate, action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_undelegate_claim_tag: CHECK_ERROR(undelegate_claim_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.undelegate_claim, - action_idx + 1, outKey, outKeyLen, outVal, outValLen, pageIdx, - pageCount)) + action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_delegator_vote_tag: CHECK_ERROR(delegator_vote_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.delegator_vote, - action_idx + 1, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) + action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_position_open_tag: CHECK_ERROR(position_open_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.position_open, - action_idx + 1, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) + action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_position_close_tag: CHECK_ERROR(position_close_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.position_close, - action_idx + 1, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) + action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_position_withdraw_tag: CHECK_ERROR(position_withdraw_getItem(ctx, &ctx->tx_obj->actions_plan[action_idx].action.position_withdraw, - action_idx + 1, outKey, outKeyLen, outVal, outValLen, pageIdx, - pageCount)) + action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_action_dutch_auction_schedule_tag: CHECK_ERROR(action_dutch_auction_schedule_getItem( - ctx, &ctx->tx_obj->actions_plan[action_idx].action.action_dutch_auction_schedule, action_idx + 1, outKey, + ctx, &ctx->tx_obj->actions_plan[action_idx].action.action_dutch_auction_schedule, action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_action_dutch_auction_end_tag: CHECK_ERROR(action_dutch_auction_end_getItem( - ctx, &ctx->tx_obj->actions_plan[action_idx].action.action_dutch_auction_end, action_idx + 1, outKey, + ctx, &ctx->tx_obj->actions_plan[action_idx].action.action_dutch_auction_end, action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; case penumbra_core_transaction_v1_ActionPlan_action_dutch_auction_withdraw_tag: CHECK_ERROR(action_dutch_auction_withdraw_getItem( - ctx, &ctx->tx_obj->actions_plan[action_idx].action.action_dutch_auction_withdraw, action_idx + 1, outKey, + ctx, &ctx->tx_obj->actions_plan[action_idx].action.action_dutch_auction_withdraw, action_idx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount)) break; default: diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 3936f627..41f06323 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -34,6 +34,7 @@ #include "protobuf/penumbra/core/transaction/v1/transaction.pb.h" #include "spend.h" #include "swap.h" +#include "ui_utils.h" #include "undelegate.h" #include "undelegate_claim.h" #include "zxformat.h" @@ -245,6 +246,30 @@ parser_error_t _read(parser_context_t *c, parser_tx_t *v) { v->plan.has_detection_data = request.has_detection_data; v->plan.actions.qty = actions_qty; + if (v->plan.has_memo) { + // Calculate UI memo address now to avoid delay in display + CHECK_ERROR(printTxAddress(&v->plan.memo.plaintext.return_address.inner, (char *)v->plan.memo.ui_address, + sizeof(v->plan.memo.ui_address))); + } + + // Calculate action addresses now to avoid delay in display + for (uint8_t i = 0; i < actions_qty; i++) { + switch (v->actions_plan[i].action_type) { + case penumbra_core_transaction_v1_ActionPlan_spend_tag: + CHECK_ERROR(printTxAddress(&v->actions_plan[i].action.spend.note.address.inner, + (char *)v->actions_plan[i].action.spend.ui_address, + sizeof(v->actions_plan[i].action.spend.ui_address))); + break; + case penumbra_core_transaction_v1_ActionPlan_output_tag: + CHECK_ERROR(printTxAddress(&v->actions_plan[i].action.output.dest_address.inner, + (char *)v->actions_plan[i].action.output.ui_address, + sizeof(v->actions_plan[i].action.output.ui_address))); + break; + default: + break; + } + } + return parser_ok; } diff --git a/app/src/parser_txdef.h b/app/src/parser_txdef.h index 36775eda..cd4c5f85 100644 --- a/app/src/parser_txdef.h +++ b/app/src/parser_txdef.h @@ -212,6 +212,7 @@ typedef struct { uint64_t position; bytes_t randomizer; bytes_t value_blinding; + uint8_t ui_address[SHORT_ADDRESS_LEN]; } spend_plan_t; typedef struct { @@ -219,6 +220,7 @@ typedef struct { address_plan_t dest_address; bytes_t rseed; bytes_t value_blinding; + uint8_t ui_address[SHORT_ADDRESS_LEN]; } output_plan_t; typedef struct { @@ -328,6 +330,7 @@ typedef struct { typedef struct { memo_plain_text_t plaintext; bytes_t key; + uint8_t ui_address[SHORT_ADDRESS_LEN]; } memo_plan_t; typedef struct { diff --git a/app/src/plan/action_dutch_auction_end.c b/app/src/plan/action_dutch_auction_end.c index c3ecbb70..3d7dc7ae 100644 --- a/app/src/plan/action_dutch_auction_end.c +++ b/app/src/plan/action_dutch_auction_end.c @@ -59,7 +59,7 @@ parser_error_t action_dutch_auction_end_getItem(const parser_context_t *ctx, char bufferUI[DUTCH_AUCTION_END_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(action_dutch_auction_end_printValue(ctx, action_dutch_auction_end, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/action_dutch_auction_schedule.c b/app/src/plan/action_dutch_auction_schedule.c index dfb82bf3..eb35d3ec 100644 --- a/app/src/plan/action_dutch_auction_schedule.c +++ b/app/src/plan/action_dutch_auction_schedule.c @@ -99,7 +99,7 @@ parser_error_t action_dutch_auction_schedule_getItem( char bufferUI[DUTCH_AUCTION_SCHEDULE_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(action_dutch_auction_schedule_printValue(ctx, action_dutch_auction_schedule, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/action_dutch_auction_withdraw.c b/app/src/plan/action_dutch_auction_withdraw.c index fee6af8b..fffbbf83 100644 --- a/app/src/plan/action_dutch_auction_withdraw.c +++ b/app/src/plan/action_dutch_auction_withdraw.c @@ -91,7 +91,7 @@ parser_error_t action_dutch_auction_withdraw_getItem( char bufferUI[DUTCH_AUCTION_WITHDRAW_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(action_dutch_auction_withdraw_printValue(ctx, action_dutch_auction_withdraw, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/delegate.c b/app/src/plan/delegate.c index 82b78fe1..ac3488cc 100644 --- a/app/src/plan/delegate.c +++ b/app/src/plan/delegate.c @@ -62,7 +62,7 @@ parser_error_t delegate_getItem(const parser_context_t *ctx, const delegate_plan char bufferUI[DELEGATE_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(delegate_printValue(ctx, delegate, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/delegator_vote.c b/app/src/plan/delegator_vote.c index d2dc0a5e..2df37a1a 100644 --- a/app/src/plan/delegator_vote.c +++ b/app/src/plan/delegator_vote.c @@ -113,7 +113,7 @@ parser_error_t delegator_vote_getItem(const parser_context_t *ctx, const delegat char bufferUI[DELEGATE_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(delegator_vote_printValue(ctx, delegator_vote, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/ics20_withdrawal.c b/app/src/plan/ics20_withdrawal.c index cc1c31a6..154f7710 100644 --- a/app/src/plan/ics20_withdrawal.c +++ b/app/src/plan/ics20_withdrawal.c @@ -65,7 +65,7 @@ parser_error_t ics20_withdrawal_getItem(const parser_context_t *ctx, const ics20 char bufferUI[ICS20_WITHDRAWAL_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(ics20_withdrawal_printValue(ctx, ics20_withdrawal, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/output.c b/app/src/plan/output.c index 49d8cc98..d74b039c 100644 --- a/app/src/plan/output.c +++ b/app/src/plan/output.c @@ -73,7 +73,7 @@ parser_error_t output_getItem(const parser_context_t *ctx, const output_plan_t * char bufferUI[OUTPUT_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(output_printValue(ctx, output, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); @@ -108,7 +108,7 @@ parser_error_t output_printValue(const parser_context_t *ctx, const output_plan_ written_value = strlen(outVal); // add address - CHECK_ERROR(printTxAddress(&output->dest_address.inner, outVal + written_value, outValLen - written_value)); + MEMCPY(outVal + written_value, &output->ui_address, SHORT_ADDRESS_LEN); return parser_ok; } diff --git a/app/src/plan/output.h b/app/src/plan/output.h index def75bbc..40a0de14 100644 --- a/app/src/plan/output.h +++ b/app/src/plan/output.h @@ -28,6 +28,7 @@ parser_error_t output_getNumItems(const parser_context_t *ctx, uint8_t *num_item parser_error_t output_getItem(const parser_context_t *ctx, const output_plan_t *output, uint8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t actionIdx, uint8_t *pageCount); parser_error_t output_printValue(const parser_context_t *ctx, const output_plan_t *output, char *outVal, uint16_t outValLen); + #ifdef __cplusplus } #endif diff --git a/app/src/plan/position_close.c b/app/src/plan/position_close.c index 84d5b627..47c311ff 100644 --- a/app/src/plan/position_close.c +++ b/app/src/plan/position_close.c @@ -57,7 +57,7 @@ parser_error_t position_close_getItem(const parser_context_t *ctx, const positio char bufferUI[POSITION_CLOSE_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(position_close_printValue(ctx, position_close, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/position_open.c b/app/src/plan/position_open.c index 0dfdd098..f562ae04 100644 --- a/app/src/plan/position_open.c +++ b/app/src/plan/position_open.c @@ -98,7 +98,7 @@ parser_error_t position_open_getItem(const parser_context_t *ctx, const position char bufferUI[POSITION_OPEN_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(position_open_printValue(ctx, position_open, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/position_withdraw.c b/app/src/plan/position_withdraw.c index 29812371..d3f26475 100644 --- a/app/src/plan/position_withdraw.c +++ b/app/src/plan/position_withdraw.c @@ -106,7 +106,7 @@ parser_error_t position_withdraw_getItem(const parser_context_t *ctx, const posi char bufferUI[POSITION_WITHDRAW_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(position_withdraw_printValue(ctx, position_withdraw, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/spend.c b/app/src/plan/spend.c index 40f08c1b..231a01f1 100644 --- a/app/src/plan/spend.c +++ b/app/src/plan/spend.c @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************/ +#include "spend.h" #include "note.h" #include "parser_pb_utils.h" @@ -63,6 +64,33 @@ parser_error_t decode_spend_plan(const bytes_t *data, spend_plan_t *output) { return parser_ok; } +parser_error_t spend_getNumItems(const parser_context_t *ctx, uint8_t *num_items) { + UNUSED(ctx); + // from spends we display only two items: + // - Spend 100 USDC + // - From Main Account + // all concatenated in a single string + *num_items = 1; + return parser_ok; +} + +parser_error_t spend_getItem(const parser_context_t *ctx, const spend_plan_t *spend, uint8_t actionIdx, char *outKey, + uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) { + parser_error_t err = parser_no_data; + + if (spend == NULL || outKey == NULL || outVal == NULL || outKeyLen == 0 || outValLen == 0) { + return err; + } + + char bufferUI[SPEND_DISPLAY_MAX_LEN] = {0}; + + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); + CHECK_ERROR(spend_printValue(ctx, spend, bufferUI, sizeof(bufferUI))); + pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); + + return parser_ok; +} + parser_error_t spend_printValue(const parser_context_t *ctx, const spend_plan_t *spend, char *outVal, uint16_t outValLen) { if (ctx == NULL || spend == NULL || outVal == NULL) { return parser_no_data; @@ -90,34 +118,7 @@ parser_error_t spend_printValue(const parser_context_t *ctx, const spend_plan_t written_value = strlen(outVal); // add address - CHECK_ERROR(printTxAddress(&spend->note.address.inner, outVal + written_value, outValLen - written_value)); - - return parser_ok; -} - -parser_error_t spend_getNumItems(const parser_context_t *ctx, uint8_t *num_items) { - UNUSED(ctx); - // from spends we display only two items: - // - Spend 100 USDC - // - From Main Account - // all concatenated in a single string - *num_items = 1; - return parser_ok; -} - -parser_error_t spend_getItem(const parser_context_t *ctx, const spend_plan_t *spend, uint8_t actionIdx, char *outKey, - uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) { - parser_error_t err = parser_no_data; - - if (spend == NULL || outKey == NULL || outVal == NULL || outKeyLen == 0 || outValLen == 0) { - return err; - } - - char bufferUI[SPEND_DISPLAY_MAX_LEN] = {0}; - - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); - CHECK_ERROR(spend_printValue(ctx, spend, bufferUI, sizeof(bufferUI))); - pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); + MEMCPY(outVal + written_value, &spend->ui_address, SHORT_ADDRESS_LEN); return parser_ok; } diff --git a/app/src/plan/swap.c b/app/src/plan/swap.c index 1847a00b..fd7eb2e9 100644 --- a/app/src/plan/swap.c +++ b/app/src/plan/swap.c @@ -108,7 +108,7 @@ parser_error_t swap_getItem(const parser_context_t *ctx, const swap_plan_t *swap char bufferUI[SWAP_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(swap_printValue(ctx, swap, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/undelegate.c b/app/src/plan/undelegate.c index 768665fc..00a061fe 100644 --- a/app/src/plan/undelegate.c +++ b/app/src/plan/undelegate.c @@ -69,7 +69,7 @@ parser_error_t undelegate_getItem(const parser_context_t *ctx, const undelegate_ char bufferUI[UNDELEGATE_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(undelegate_printValue(ctx, undelegate, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/plan/undelegate_claim.c b/app/src/plan/undelegate_claim.c index c4ce2210..62fef8ca 100644 --- a/app/src/plan/undelegate_claim.c +++ b/app/src/plan/undelegate_claim.c @@ -67,7 +67,7 @@ parser_error_t undelegate_claim_getItem(const parser_context_t *ctx, const undel char bufferUI[UNDELEGATE_DISPLAY_MAX_LEN] = {0}; - snprintf(outKey, outKeyLen, "Action_%d", actionIdx); + snprintf(outKey, outKeyLen, "Action_%d", actionIdx + 1); CHECK_ERROR(undelegate_claim_printValue(ctx, undelegate, bufferUI, sizeof(bufferUI))); pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); diff --git a/app/src/ui_utils.c b/app/src/ui_utils.c index 32e258e1..77b1811d 100644 --- a/app/src/ui_utils.c +++ b/app/src/ui_utils.c @@ -100,17 +100,11 @@ parser_error_t printShortAddress(const uint8_t *address, uint16_t address_len, c return err; } - // Calculate required length for short form - uint16_t prefix_and_sep_len = sizeof(ADDR_BECH32_PREFIX); // prefix + separator - uint16_t required_len = prefix_and_sep_len + SHORT_ADDRESS_VISIBLE_CHARS; - - // + ellipsis + null - if (out_len < required_len + sizeof(ELLIPSIS)) { + if (out_len < SHORT_ADDRESS_LEN) { return parser_unexpected_buffer_end; } - // Copy prefix + separator + visible chars - uint16_t truncate_pos = prefix_and_sep_len + SHORT_ADDRESS_VISIBLE_CHARS; + uint16_t truncate_pos = SHORT_ADDRESS_LEN - sizeof(ELLIPSIS); MEMZERO(out, out_len); MEMCPY(out, full_address, truncate_pos); diff --git a/deps/ledger-zxlib b/deps/ledger-zxlib index e988dc04..24cc70c4 160000 --- a/deps/ledger-zxlib +++ b/deps/ledger-zxlib @@ -1 +1 @@ -Subproject commit e988dc040d16459db99e8328135abf58a85ca7fc +Subproject commit 24cc70c432036bff55ffa809431218f89bda55f5 diff --git a/tests_zemu/tests/effect_hash.test.ts b/tests_zemu/tests/effect_hash.test.ts index 5d1587cd..0aa8a239 100644 --- a/tests_zemu/tests/effect_hash.test.ts +++ b/tests_zemu/tests/effect_hash.test.ts @@ -49,6 +49,7 @@ describe('Standard', function () { // Wait until we are not in the main menu await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) + await sim.waitForText('Review') await sim.compareSnapshotsAndApprove('.', `${m.prefix.toLowerCase()}-sign_${data.name}`) const signatureResponse = await signatureRequest diff --git a/tests_zemu/tests/testscases/actions.ts b/tests_zemu/tests/testscases/actions.ts index b9086187..21d6c74f 100644 --- a/tests_zemu/tests/testscases/actions.ts +++ b/tests_zemu/tests/testscases/actions.ts @@ -90,5 +90,5 @@ export const ACTIONS_TESTCASES: TestCase[] = [ blob: '0a9101ba038d010a220a20c8e835549a1ff640a5812680855d9f23d6ff06ebeed9e57dddca5e71806624b210f480db0a1a300a0a08f0a0aa93b1c3839a0c12220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a1022300a0a08fda0b3c49de6d1cb0912220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a10122a121b6566657774677a72736873796d6162777a6c78647a6b63642d30321a0b0a0908f4bfcfd98adebe042af1020acc020a520a500f0b7f44e8814645e90dcaf1a8b1d35f794483fd067037a4c9ad0a104c12b0dc4fa351bd73ea6b3a3b7fd8af874e987a3e5d4f6420a53d66bd022b6c97048fad6430718940efc32fbf5d7e9f36105f1212f501485a48387320582068646a2020206e207538686f52533331202063376e43356f68722050356c2031205638695341206920343161207520386c4a7a4b79662062334a3120206a6c3133685564795a374973394756202051722032203420206b3732476d6531203465616131206b48346549375420454c2020716b4e72583631203420414155206d30385076426e3745522062202052663955437220204534204f366e594643644a4f363972757333203972207935204d7331625a496f20205943363167612058592036672050206b6d5a20436244206f4e51305632203533772041396e6f4e31574938686e39664e204f7a4c3171201220e59b72f45b2a4ae19ff9f731d0b5bd45766de79e791901deebdbf090380ea29d', expected_effect_hash: '5a43389ca7f1beddea45593243f3d3074df09cbba250b5b2f29a0d9e13f4769b352d2b7cceb77264186754bad2b31513e08071f1714cc82f7b986ffc1c1d34b2', - } + }, ]