Skip to content

Commit

Permalink
flex porting
Browse files Browse the repository at this point in the history
  • Loading branch information
tdejoigny-ledger committed May 19, 2024
1 parent 6dd470c commit cf05623
Show file tree
Hide file tree
Showing 44 changed files with 111 additions and 69 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ build/
dist/
*.manifest
*.spec

# Temporary directory with snapshots taken during test runs
tests/snapshots-tmp/

# Virtual env for sideload (macOS and Windows)
ledger/
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to this project will be documented in this file.

## 2.0.0 - 2024-05-01

- Support of Flex device

## 1.7.6 - 2021-03-30

- Support of Monero client version `0.17.2.*`
Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ include $(BOLOS_SDK)/Makefile.defines
APPNAME = "Monero"

# Application version
APPVERSION_M = 1
APPVERSION_N = 9
APPVERSION_M = 2
APPVERSION_N = 0
APPVERSION_P = 0
APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)"

Expand All @@ -43,6 +43,7 @@ ICON_NANOS = icons/app_monero_16px.gif
ICON_NANOX = icons/app_monero_14px.gif
ICON_NANOSP = icons/app_monero_14px.gif
ICON_STAX = icons/app_monero_32px.gif
ICON_FLEX = icons/app_monero_40px.gif

# Application allowed derivation curves.
CURVE_APP_LOAD_PARAMS = secp256k1
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Monero Ledger App

Monero wallet application for Ledger Nano S and Nano X.
Monero wallet application for all Ledger devices.

## Install

Expand Down
Binary file added icons/app_monero_40px.gif
Loading
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]
pytest_directory = "./tests/"
2 changes: 1 addition & 1 deletion src/monero_nvram.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "monero_api.h"
#include "monero_vars.h"

#if defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX)
#if defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX) || defined(TARGET_FLEX)
const monero_nv_state_t N_state_pic;
#else
monero_nv_state_t N_state_pic;
Expand Down
27 changes: 17 additions & 10 deletions src/monero_ux_stax.c → src/monero_ux_nbgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static void release_context(void) {
/* -------------------------------- INFO UX --------------------------------- */

void ui_menu_show_tx_aborted(void) {
nbgl_useCaseStatus("Transaction\ncancelled", false, ui_menu_main_display);
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_REJECTED, ui_menu_main_display);
}

void ui_menu_show_security_error(void) {
Expand Down Expand Up @@ -103,7 +103,7 @@ unsigned int ui_menu_transaction_start(void) {
}

unsigned int ui_menu_transaction_signed(void) {
nbgl_useCaseStatus("TRANSACTION\nSIGNED", true, ui_menu_main_display);
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_SIGNED, ui_menu_main_display);
return 0;
}

Expand Down Expand Up @@ -193,6 +193,13 @@ void ui_menu_timelock_validation_display(unsigned int value __attribute__((unuse
}

/* ----------------------------- USER DEST/AMOUNT VALIDATION ----------------------------- */

#ifdef TARGET_FLEX
#define NEXT_PAGE_TEXT ("Swipe to continue")
#else
#define NEXT_PAGE_TEXT ("Tap to continue")
#endif

static void fill_amount_and_destination(void) {
transactionContext.tagValuePair[0].item = "Amount";
transactionContext.tagValuePair[0].value = G_monero_vstate.ux_amount;
Expand Down Expand Up @@ -225,7 +232,7 @@ static void continue_display(int token, unsigned char index) {
.navType = NAV_WITH_TAP,
.progressIndicator = true,
.navWithTap.backButton = false,
.navWithTap.nextPageText = "Tap to continue",
.navWithTap.nextPageText = NEXT_PAGE_TEXT,
.navWithTap.nextPageToken = CONTINUE_TOKEN,
.navWithTap.quitText = "Cancel",
.quitToken = QUIT_TOKEN,
Expand Down Expand Up @@ -265,7 +272,7 @@ static void display_previous_infos(bool last) {
.navType = NAV_WITH_TAP,
.progressIndicator = true,
.navWithTap.backButton = false,
.navWithTap.nextPageText = "Tap to continue",
.navWithTap.nextPageText = NEXT_PAGE_TEXT,
.navWithTap.nextPageToken = CONTINUE_TOKEN,
.navWithTap.quitText = "Cancel",
.quitToken = QUIT_TOKEN,
Expand Down Expand Up @@ -315,7 +322,7 @@ static void ui_menu_pubaddr_action_cancelled(void) {
monero_io_do(IO_RETURN_AFTER_TX);
}
G_monero_vstate.disp_addr_mode = 0;
nbgl_useCaseStatus("Address display\ncancelled", false, ui_menu_main_display);
nbgl_useCaseReviewStatus(STATUS_TYPE_ADDRESS_REJECTED, ui_menu_main_display);
}

void ui_menu_pubaddr_action(bool confirm) {
Expand All @@ -325,7 +332,7 @@ void ui_menu_pubaddr_action(bool confirm) {
monero_io_do(IO_RETURN_AFTER_TX);
}
G_monero_vstate.disp_addr_mode = 0;
nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, ui_menu_main_display);
nbgl_useCaseReviewStatus(STATUS_TYPE_ADDRESS_VERIFIED, ui_menu_main_display);
} else {
ui_menu_pubaddr_action_cancelled();
}
Expand Down Expand Up @@ -372,8 +379,8 @@ void display_account(void) {

transactionContext.tagValueList.pairs = transactionContext.tagValuePair;

nbgl_useCaseAddressConfirmationExt(G_monero_vstate.ux_address, ui_menu_pubaddr_action,
&transactionContext.tagValueList);
nbgl_useCaseAddressReview(G_monero_vstate.ux_address, &transactionContext.tagValueList,
&C_Monero_64px, "Review Address", NULL, ui_menu_pubaddr_action);
}

int ui_menu_any_pubaddr_display(unsigned int value __attribute__((unused)), unsigned char* pub_view,
Expand All @@ -388,8 +395,8 @@ int ui_menu_any_pubaddr_display(unsigned int value __attribute__((unused)), unsi
return error;
}

nbgl_useCaseReviewStart(&C_Monero_64px, "Review Address", "", "Cancel", display_account,
ui_menu_pubaddr_action_cancelled);
display_account();

return 0;
}

Expand Down
108 changes: 67 additions & 41 deletions src/monero_ux_stax_menu.c → src/monero_ux_nbgl_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ enum {
RESET_TOKEN,
ACCOUNT_CHOICE,
ACCOUNT_CHOICE_2,
ACCOUNT_CHOICE_3,
NETWORK_CHOICE
};

enum { MAIN_NET, STAGE_NET, TEST_NET, MAX_NET };

#define SETTING_INFO_NB 4
static const char* const infoTypes[] = {"Spec", "Version", "Developer", "Copyright"};
static const char* const infoContents[] = {XSTR(SPEC_VERSION), APPVERSION, "Ledger",
"(c) 2022 Ledger"};
"(c) 2024 Ledger"};

static const char* const barTexts[] = {"Select Account", "Select Network", "Reset"};
static const uint8_t tokens[] = {ACCOUNT_TOKEN, NETWORK_TOKEN, RESET_TOKEN};
Expand All @@ -83,32 +85,9 @@ static void update_account(void) {
G_monero_vstate.disp_addr_m = 0;
}

static bool settings_navigation_cb(uint8_t page, nbgl_pageContent_t* content) {
if (page == 0) {
content->type = BARS_LIST;
content->barsList.barTexts = barTexts;
content->barsList.tokens = tokens;
content->barsList.nbBars = 3;
content->barsList.tuneId = TUNE_TAP_CASUAL;
} else if (page == 1) {
content->type = INFOS_LIST;
content->infosList.nbInfos = 3;
content->infosList.infoTypes = infoTypes;
content->infosList.infoContents = infoContents;
} else if (page == 2) {
content->type = INFOS_LIST;
content->infosList.nbInfos = 1;
content->infosList.infoTypes = infoTypes + 3;
content->infosList.infoContents = infoContents + 3;
} else {
return false;
}
return true;
}

static bool account_settings_navigation_cb(uint8_t page, nbgl_pageContent_t* content) {
content->type = CHOICES_LIST;
content->choicesList.nbChoices = 5;
content->choicesList.nbChoices = 4;
content->choicesList.localized = false;
content->choicesList.tuneId = TUNE_TAP_CASUAL;

Expand All @@ -117,13 +96,22 @@ static bool account_settings_navigation_cb(uint8_t page, nbgl_pageContent_t* con
content->choicesList.names = accountNames;
content->choicesList.token = ACCOUNT_CHOICE;
} else if (page == 1) {
if (N_monero_pstate->account_id > 4) {
content->choicesList.initChoice = N_monero_pstate->account_id - 5;
if (N_monero_pstate->account_id > 3) {
content->choicesList.initChoice = N_monero_pstate->account_id - 4;
} else {
content->choicesList.initChoice = 5;
content->choicesList.initChoice = 4;
}
content->choicesList.names = accountNames + 5;
content->choicesList.names = accountNames + 4;
content->choicesList.token = ACCOUNT_CHOICE_2;
} else if (page == 2) {
content->choicesList.nbChoices = 2;
if (N_monero_pstate->account_id > 7) {
content->choicesList.initChoice = N_monero_pstate->account_id - 8;
} else {
content->choicesList.initChoice = 8;
}
content->choicesList.names = accountNames + 8;
content->choicesList.token = ACCOUNT_CHOICE_3;
} else {
return false;
}
Expand Down Expand Up @@ -164,12 +152,11 @@ static void resetCallback(void) {
}

static void account_settings_control_cb(int token, uint8_t index) {
UNUSED(index);
switch (token) {
case ACCOUNT_CHOICE_3:
case ACCOUNT_CHOICE_2:
index = index + 5;
__attribute__((fallthrough));
case ACCOUNT_CHOICE:
index = (token - ACCOUNT_CHOICE)*4 + index;
if (index <= 9) {
monero_nvm_write((void*)&N_monero_pstate->account_id, &index, sizeof(uint8_t));
monero_init();
Expand Down Expand Up @@ -209,11 +196,12 @@ static void network_settings_control_cb(int token, uint8_t index) {
}
}

static void settings_control_cb(int token, uint8_t index) {
static void settings_control_cb(int token, uint8_t index, int page) {
UNUSED(index);
UNUSED(page);
switch (token) {
case ACCOUNT_TOKEN:
nbgl_useCaseSettings("Select account", 0, 2, IS_TOUCHABLE, display_settings_menu,
nbgl_useCaseSettings("Select account", 0, 3, IS_TOUCHABLE, display_settings_menu,
account_settings_navigation_cb, account_settings_control_cb);
break;
case NETWORK_TOKEN:
Expand All @@ -231,12 +219,31 @@ static void settings_control_cb(int token, uint8_t index) {
}
}

static void display_settings_menu(void) {
nbgl_useCaseSettings("Monero settings", PAGE_START, NB_PAGE_SETTING, IS_TOUCHABLE,
ui_menu_main_display, settings_navigation_cb, settings_control_cb);
}
// info menu definition
static const nbgl_contentInfoList_t infoList = {
.nbInfos = SETTING_INFO_NB,
.infoTypes = infoTypes,
.infoContents = infoContents,
};

// settings menu definition
#define SETTING_CONTENTS_NB 1
static const nbgl_content_t contents[SETTING_CONTENTS_NB] = {
{.type = BARS_LIST,
.content.barsList.barTexts = barTexts,
.content.barsList.tokens = tokens,
.content.barsList.nbBars = 3,
.content.barsList.tuneId = TUNE_TAP_CASUAL,
.contentActionCallback = settings_control_cb}};


static const nbgl_genericContents_t settingContents = {.callbackCallNeeded = false,
.contentsList = contents,
.nbContents = SETTING_CONTENTS_NB};
static nbgl_homeAction_t homeAction;

static void display_home_and_settings(bool displayHome) {

void ui_menu_main_display(void) {
update_account();

explicit_bzero(G_monero_vstate.ux_address, sizeof(G_monero_vstate.ux_address));
Expand All @@ -247,8 +254,27 @@ void ui_menu_main_display(void) {
monero_base58_public_key(G_monero_vstate.ux_address, G_monero_vstate.A, G_monero_vstate.B, 0,
NULL);

nbgl_useCaseHomeExt("Monero", &C_Monero_64px, NULL, true, transactionContext.buffer,
display_account, display_settings_menu, app_exit);
homeAction.callback = display_account;
homeAction.icon = NULL;
homeAction.text = transactionContext.buffer;
nbgl_useCaseHomeAndSettings(APPNAME,
&C_Monero_64px,
NULL,
displayHome ? INIT_HOME_PAGE : 0,
&settingContents,
&infoList,
&homeAction,
app_exit);
}

static void display_settings_menu(void) {
// display settings page
display_home_and_settings(false);
}

void ui_menu_main_display(void) {
// display home page
display_home_and_settings(true);
}

/* --- INIT --- */
Expand Down
2 changes: 1 addition & 1 deletion src/monero_vars.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

extern monero_v_state_t G_monero_vstate;

#if defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX)
#if defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX) || defined(TARGET_FLEX)
extern const monero_nv_state_t N_state_pic;
#define N_monero_pstate ((volatile monero_nv_state_t *)PIC(&N_state_pic))
#else
Expand Down
13 changes: 6 additions & 7 deletions tests/monero_client/monero_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from .crypto.hmac import hmac_sha256
from .exception.device_error import DeviceError
from .utils.varint import encode_varint
from .utils.utils import get_nano_review_instructions, get_stax_review_instructions
from .utils.utils import get_nano_review_instructions
from pathlib import Path
from ragger.navigator import NavInsID, NavIns

Expand Down Expand Up @@ -229,16 +229,14 @@ def prefix_hash_init(self, backend, test_name, firmware, navigator, version: int
instructions = get_nano_review_instructions(1)
else:
instructions = [
NavIns(NavInsID.USE_CASE_REVIEW_TAP)
NavIns(NavInsID.SWIPE_CENTER_TO_LEFT)
]

with self.device.send_async(cla=PROTOCOL_VERSION,
ins=ins,
p1=1,
p2=0,
option=0,
payload=payload):

navigator.navigate_and_compare(TESTS_ROOT_DIR,
test_name + "_hash_init",
instructions)
Expand Down Expand Up @@ -458,7 +456,8 @@ def validate_prehash_update(self,
instructions = get_nano_review_instructions(3)
else:
instructions = [
NavIns(NavInsID.USE_CASE_REVIEW_TAP),

NavIns(NavInsID.SWIPE_CENTER_TO_LEFT),
NavIns(NavInsID.USE_CASE_REVIEW_TAP),
NavIns(NavInsID.USE_CASE_REVIEW_CONFIRM)
]
Expand All @@ -474,8 +473,8 @@ def validate_prehash_update(self,

navigator.navigate_and_compare(TESTS_ROOT_DIR,
test_name + "_prehash_update",
instructions,
screen_change_after_last_instruction=False)
instructions,
screen_change_after_last_instruction=False, timeout=10000)

sw, response = self.device.async_response() # type: int, bytes

Expand Down
Loading

0 comments on commit cf05623

Please sign in to comment.