Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sgl/flex porting #256

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PATH_SLIP21_APP_LOAD_PARAMS = "LEDGER-Wallet policy"
APPVERSION_M = 2
APPVERSION_N = 2
APPVERSION_P = 2
APPVERSION_SUFFIX = # if not empty, appended at the end. Do not add a dash.
APPVERSION_SUFFIX = flex

ifeq ($(APPVERSION_SUFFIX),)
APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)"
Expand Down Expand Up @@ -109,6 +109,7 @@ ICON_NANOS = icons/nanos_app_bitcoin.gif
ICON_NANOX = icons/nanox_app_bitcoin.gif
ICON_NANOSP = icons/nanox_app_bitcoin.gif
ICON_STAX = icons/stax_app_bitcoin.gif
ICON_FLEX = icons/flex_app_bitcoin.gif

########################################
# Application communication interfaces #
Expand Down
Binary file added icons/flex_app_bitcoin.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion ledger_app.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[app]
build_directory = "./"
sdk = "C"
devices = ["nanos", "nanox", "nanos+", "stax"]
devices = ["nanos", "nanox", "nanos+", "stax", "flex"]

[tests]
unit_directory = "./unit-tests/"
Expand Down
56 changes: 43 additions & 13 deletions ragger_bitcoin/ragger_instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,38 +42,56 @@ def navigate_end_of_flow(self, save_screenshot=True):
self.new_request("Processing", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_TAP,
save_screenshot=save_screenshot)

def confirm_transaction(self, save_screenshot=True):
self.new_request("Sign", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_CONFIRM,
def review_start(self, output_count: int = 1, save_screenshot=True):
self.new_request("Review", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_TAP,
save_screenshot=save_screenshot)
self.new_request("TRANSACTION", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_STATUS_DISMISS,
for _ in range(0, output_count):
self.new_request("Amount", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_TAP,
save_screenshot=save_screenshot)
def review_fees(self, fees_on_same_request: bool = True, save_screenshot=True):
if fees_on_same_request:
self.same_request("Fees", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_TAP,
save_screenshot=save_screenshot)
else:
self.new_request("Fees", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_TAP,
save_screenshot=save_screenshot)

def same_request_confirm_transaction(self, save_screenshot=True):
def confirm_transaction(self, save_screenshot=True):
self.same_request("Sign", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_CONFIRM,
save_screenshot=save_screenshot)
self.new_request("TRANSACTION", NavInsID.USE_CASE_REVIEW_TAP,
self.new_request("Transaction", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_STATUS_DISMISS,
save_screenshot=save_screenshot)

def review_message(self, page_count=1, save_screenshot=True):
self.new_request("Review", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_REVIEW_TAP, save_screenshot=save_screenshot)
self.same_request("Message", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_REVIEW_TAP, save_screenshot=save_screenshot)
for _ in range(1, page_count):
self.new_request("Message", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_REVIEW_TAP, save_screenshot=save_screenshot)

def confirm_message(self, save_screenshot=True):
self.new_request("Sign", NavInsID.USE_CASE_REVIEW_TAP,
self.same_request("Sign", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_REVIEW_CONFIRM, save_screenshot=save_screenshot)
self.new_request("MESSAGE", NavInsID.USE_CASE_REVIEW_TAP,
self.new_request("Message", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_STATUS_DISMISS, save_screenshot=save_screenshot)

def confirm_wallet(self, save_screenshot=True):
self.new_request("Approve", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_CONFIRM,
self.new_request("Approve", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_CHOICE_CONFIRM,
save_screenshot=save_screenshot)
self.same_request("WALLET", NavInsID.USE_CASE_REVIEW_TAP,
self.same_request("Wallet", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_STATUS_DISMISS, save_screenshot=save_screenshot)

def reject_message(self, save_screenshot=True):
self.new_request("Sign", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_REJECT,
self.new_request("Review", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_REVIEW_TAP, save_screenshot=save_screenshot)
self.same_request("Message", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_REVIEW_REJECT,
save_screenshot=save_screenshot)
self.same_request("Reject", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_CHOICE_CONFIRM,
save_screenshot=save_screenshot)
self.new_request("MESSAGE", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_STATUS_DISMISS,
self.new_request("Message", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_STATUS_DISMISS,
save_screenshot=save_screenshot)

def warning_accept(self, save_screenshot=True):
Expand All @@ -84,6 +102,8 @@ def address_confirm(self, save_screenshot=True):
self.new_request("Confirm", NavInsID.USE_CASE_REVIEW_TAP,
NavInsID.USE_CASE_ADDRESS_CONFIRMATION_CONFIRM,
save_screenshot=save_screenshot)
self.same_request("Address verified", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.CANCEL_FOOTER_TAP,
save_screenshot=save_screenshot)

def choice_confirm(self, save_screenshot=True):
self.new_request("Approve", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_CHOICE_CONFIRM,
Expand All @@ -94,5 +114,15 @@ def choice_reject(self, save_screenshot=True):
save_screenshot=save_screenshot)

def footer_cancel(self, save_screenshot=True):
self.new_request("Approve", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.CANCEL_FOOTER_TAP,
self.new_request("Confirm", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.CANCEL_FOOTER_TAP,
save_screenshot=save_screenshot)
self.new_request("rejected", NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_STATUS_DISMISS,
save_screenshot=save_screenshot)

def status_dismiss(self, text, status_on_same_request=True, save_screenshot=True):
if status_on_same_request:
self.same_request(text, NavInsID.USE_CASE_REVIEW_TAP, NavInsID.CANCEL_FOOTER_TAP,
save_screenshot=save_screenshot)
else:
self.new_request(text, NavInsID.USE_CASE_REVIEW_TAP, NavInsID.USE_CASE_STATUS_DISMISS,
save_screenshot=save_screenshot)
2 changes: 2 additions & 0 deletions src/boilerplate/dispatcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ void apdu_dispatcher(command_descriptor_t const cmd_descriptors[],
// - background processing took long enough that the "Processing..." screen was shown.
bool is_ux_dirty = G_dispatcher_state.had_ux_flow || G_was_processing_screen_shown;
if (G_dispatcher_state.termination_cb != NULL && is_ux_dirty) {
#ifdef HAVE_BAGL
G_dispatcher_state.termination_cb();
#endif
G_was_processing_screen_shown = 0;
}

Expand Down
7 changes: 1 addition & 6 deletions src/handler/sign_message.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,7 @@ static bool display_message_content_and_confirm(dispatcher_context_t* dc,
message_chunk[total_chunk_len] = '\0';
}

if (!ui_display_path_and_message_content(dc,
(char*) path_str,
(char*) message_chunk,
(n_chunks - 1) / MESSAGE_CHUNK_PER_DISPLAY)) {
if (!ui_display_path_and_message_content(dc, (char*) path_str, (char*) message_chunk)) {
return false;
}
}
Expand Down Expand Up @@ -184,13 +181,11 @@ void handler_sign_message(dispatcher_context_t* dc, uint8_t protocol_version) {
n_chunks,
(uint8_t*) path_str)) {
SEND_SW(dc, SW_DENY);
ui_post_processing_confirm_message(dc, false);
return;
}
} else {
if (!ui_display_message_path_hash_and_confirm(dc, path_str, message_hash_str)) {
SEND_SW(dc, SW_DENY);
ui_post_processing_confirm_message(dc, false);
return;
}
}
Expand Down
13 changes: 1 addition & 12 deletions src/handler/sign_psbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -690,15 +690,10 @@ init_global_state(dispatcher_context_t *dc, sign_psbt_state_t *st) {
// If it's not a default wallet policy, ask the user for confirmation, and abort if they deny
if (!st->is_wallet_default && !ui_authorize_wallet_spend(dc, wallet_header.name)) {
SEND_SW(dc, SW_DENY);
ui_post_processing_confirm_wallet_spend(dc, false);
return false;
}

st->master_key_fingerprint = crypto_get_master_key_fingerprint();

if (!st->is_wallet_default) {
ui_post_processing_confirm_wallet_spend(dc, true);
}
return true;
}

Expand Down Expand Up @@ -1312,7 +1307,7 @@ process_outputs(dispatcher_context_t *dc, sign_psbt_state_t *st) {

if (!read_outputs(dc, st, &placeholder_info, true)) return false;

if (!G_swap_state.called_from_swap && !ui_transaction_prompt(dc, st->outputs.n_external)) {
if (!G_swap_state.called_from_swap && !ui_transaction_prompt(dc)) {
SEND_SW(dc, SW_DENY);
return false;
}
Expand Down Expand Up @@ -1370,7 +1365,6 @@ confirm_transaction(dispatcher_context_t *dc, sign_psbt_state_t *st) {
if (10 * fee >= st->inputs_total_amount && st->inputs_total_amount > 10000) {
if (!ui_warn_high_fee(dc)) {
SEND_SW(dc, SW_DENY);
ui_post_processing_confirm_transaction(dc, false);
return false;
}
}
Expand All @@ -1379,7 +1373,6 @@ confirm_transaction(dispatcher_context_t *dc, sign_psbt_state_t *st) {
bool is_self_transfer = st->outputs.n_external == 0;
if (!ui_validate_transaction(dc, COIN_COINID_SHORT, fee, is_self_transfer)) {
SEND_SW(dc, SW_DENY);
ui_post_processing_confirm_transaction(dc, false);
return false;
}
}
Expand Down Expand Up @@ -2474,10 +2467,6 @@ sign_transaction(dispatcher_context_t *dc,
return false;

if (!sign_transaction_input(dc, st, &hashes, &placeholder_info, &input, i)) {
if (!G_swap_state.called_from_swap) {
ui_post_processing_confirm_transaction(dc, false);
}

// we do not send a status word, since sign_transaction_input
// already does it on failure
return false;
Expand Down
60 changes: 27 additions & 33 deletions src/ui/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@

#include "./display.h"

#ifdef HAVE_BAGL
#define SET_UX_DIRTY true
#else
#define SET_UX_DIRTY false
#endif

// These globals are a workaround for a limitation of the UX library that
// does not allow to pass proper callbacks and context.

Expand Down Expand Up @@ -98,20 +104,19 @@ bool ui_display_pubkey(dispatcher_context_t *context,
ui_display_pubkey_suspicious_flow();
}

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_display_path_and_message_content(dispatcher_context_t *context,
const char *path_str,
const char *message_content,
uint8_t pageCount) {
const char *message_content) {
ui_path_and_message_state_t *state = (ui_path_and_message_state_t *) &g_ui_state;
strncpy(state->bip32_path_str, path_str, sizeof(state->bip32_path_str));
strncpy(state->message, message_content, sizeof(state->message));

ui_sign_message_content_flow(pageCount);
ui_sign_message_content_flow();

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_display_message_path_hash_and_confirm(dispatcher_context_t *context,
Expand All @@ -123,14 +128,14 @@ bool ui_display_message_path_hash_and_confirm(dispatcher_context_t *context,

ui_sign_message_path_hash_and_confirm_flow();

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_display_message_confirm(dispatcher_context_t *context) {
(void) context;
ui_sign_message_confirm_flow();

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_display_register_wallet(dispatcher_context_t *context,
Expand All @@ -145,7 +150,7 @@ bool ui_display_register_wallet(dispatcher_context_t *context,

ui_display_register_wallet_flow();

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_display_policy_map_cosigner_pubkey(dispatcher_context_t *context,
Expand Down Expand Up @@ -177,7 +182,7 @@ bool ui_display_policy_map_cosigner_pubkey(dispatcher_context_t *context,
}
ui_display_policy_map_cosigner_pubkey_flow();

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_display_wallet_address(dispatcher_context_t *context,
Expand All @@ -194,7 +199,7 @@ bool ui_display_wallet_address(dispatcher_context_t *context,
ui_display_receive_in_wallet_flow();
}

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_authorize_wallet_spend(dispatcher_context_t *context, const char *wallet_name) {
Expand All @@ -203,27 +208,27 @@ bool ui_authorize_wallet_spend(dispatcher_context_t *context, const char *wallet
strncpy(state->wallet_name, wallet_name, sizeof(state->wallet_name));
ui_display_spend_from_wallet_flow();

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_warn_external_inputs(dispatcher_context_t *context) {
ui_display_warning_external_inputs_flow();
return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_warn_unverified_segwit_inputs(dispatcher_context_t *context) {
ui_display_unverified_segwit_inputs_flows();
return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_warn_nondefault_sighash(dispatcher_context_t *context) {
ui_display_nondefault_sighash_flow();
return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_transaction_prompt(dispatcher_context_t *context, const int external_outputs_total_count) {
ui_display_transaction_prompt(external_outputs_total_count);
return io_ui_process(context, true);
bool ui_transaction_prompt(dispatcher_context_t *context) {
ui_display_transaction_prompt();
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_validate_output(dispatcher_context_t *context,
Expand All @@ -245,13 +250,13 @@ bool ui_validate_output(dispatcher_context_t *context,
ui_display_output_address_amount_flow(index);
}

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_warn_high_fee(dispatcher_context_t *context) {
ui_warn_high_fee_flow();

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

bool ui_validate_transaction(dispatcher_context_t *context,
Expand All @@ -264,7 +269,7 @@ bool ui_validate_transaction(dispatcher_context_t *context,

ui_accept_transaction_flow(is_self_transfer);

return io_ui_process(context, true);
return io_ui_process(context, SET_UX_DIRTY);
}

#ifdef HAVE_BAGL
Expand All @@ -274,12 +279,6 @@ bool ui_post_processing_confirm_wallet_registration(dispatcher_context_t *contex
return true;
}

bool ui_post_processing_confirm_wallet_spend(dispatcher_context_t *context, bool success) {
(void) context;
(void) success;
return true;
}

bool ui_post_processing_confirm_transaction(dispatcher_context_t *context, bool success) {
(void) context;
(void) success;
Expand All @@ -305,16 +304,11 @@ bool ui_post_processing_confirm_wallet_registration(dispatcher_context_t *contex
return true;
}

bool ui_post_processing_confirm_wallet_spend(dispatcher_context_t *context, bool success) {
ui_display_post_processing_confirm_wallet_spend(success);

return io_ui_process(context, success);
}

bool ui_post_processing_confirm_transaction(dispatcher_context_t *context, bool success) {
(void) context;
ui_display_post_processing_confirm_transaction(success);

return io_ui_process(context, success);
return true;
}

bool ui_post_processing_confirm_message(dispatcher_context_t *context, bool success) {
Expand Down