Skip to content

Commit

Permalink
support for Stax
Browse files Browse the repository at this point in the history
  • Loading branch information
ftheirs committed Nov 23, 2023
1 parent b6a7886 commit 56c2b74
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 72 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/guidelines_enforcer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ name: Ensure compliance with Ledger guidelines

on:
workflow_dispatch:
# push:
# branches:
# - master
# - main
# - develop
# pull_request:
push:
branches:
- master
- main
- develop
pull_request:

jobs:
guidelines_enforcer:
name: Call Ledger guidelines_enforcer
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_guidelines_enforcer.yml@v1
with:
relative_app_directory: app
run_for_devices: '["nanos", "nanosp", "nanox"]'
run_for_devices: '["nanos", "nanosp", "nanox", "stax"]'
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "deps/nanos-secure-sdk"]
path = deps/nanos-secure-sdk
url = https://github.com/LedgerHQ/nanos-secure-sdk
[submodule "deps/ledger-secure-sdk"]
path = deps/ledger-secure-sdk
url = https://github.com/LedgerHQ/ledger-secure-sdk
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ TESTS_JS_DIR = $(CURDIR)/js
ifeq ($(BOLOS_SDK),)
# In this case, there is not predefined SDK and we run dockerized
# When not using the SDK, we override and build the XL complete app

SUBSTRATE_PARSER_FULL ?= 1
ZXLIB_COMPILE_STAX ?= 1
include $(CURDIR)/deps/ledger-zxlib/dockerized_build.mk

else
Expand Down
4 changes: 2 additions & 2 deletions app/src/common/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include <string.h>
#include "zxmacros.h"

#if defined(TARGET_NANOX) || defined(TARGET_NANOS2)
#if defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX)
#define RAM_BUFFER_SIZE 8192
#define FLASH_BUFFER_SIZE 16384
#elif defined(TARGET_NANOS)
Expand All @@ -37,7 +37,7 @@ typedef struct {
uint8_t buffer[FLASH_BUFFER_SIZE];
} storage_t;

#if defined(TARGET_NANOS) || defined(TARGET_NANOX) || defined(TARGET_NANOS2)
#if defined(TARGET_NANOS) || defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX)
storage_t NV_CONST N_appdata_impl __attribute__((aligned(64)));
#define N_appdata (*(NV_VOLATILE storage_t *)PIC(&N_appdata_impl))
#endif
Expand Down
12 changes: 6 additions & 6 deletions app/src/crypto_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "bolos_target.h"
#endif

#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX)
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
#include "cx.h"
#include "cx_sha256.h"
#else
Expand All @@ -47,7 +47,7 @@ static zxerr_t crypto_publicKeyHash_ed25519(uint8_t *publicKeyHash, const uint8_

// Step 2. Hash the serialized public key with sha256.
uint8_t pkh[CX_SHA256_SIZE] = {0};
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX)
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
cx_hash_sha256((const uint8_t*) borshEncodedPubKey, PK_LEN_25519 + 1, pkh, CX_SHA256_SIZE);
#else
picohash_ctx_t ctx;
Expand Down Expand Up @@ -111,7 +111,7 @@ zxerr_t crypto_sha256(const uint8_t *input, uint16_t inputLen, uint8_t *output,

MEMZERO(output, outputLen);

#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX)
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
cx_hash_sha256(input, inputLen, output, CX_SHA256_SIZE);
#else
picohash_ctx_t ctx;
Expand All @@ -127,7 +127,7 @@ zxerr_t crypto_hashExtraDataSection(const section_t *extraData, uint8_t *output,
return zxerr_invalid_crypto_settings;
}

#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX)
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
cx_sha256_update(&sha256, &extraData->discriminant, 1);
Expand Down Expand Up @@ -159,7 +159,7 @@ zxerr_t crypto_hashDataSection(const section_t *data, uint8_t *output, uint32_t
return zxerr_no_data;
}

#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX)
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
cx_sha256_update(&sha256, &data->discriminant, 1);
Expand All @@ -185,7 +185,7 @@ zxerr_t crypto_hashCodeSection(const section_t *code, uint8_t *output, uint32_t
return zxerr_invalid_crypto_settings;
}

#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX)
#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
cx_sha256_update(&sha256, &code->discriminant, 1);
Expand Down
11 changes: 0 additions & 11 deletions app/src/parser_print_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,6 @@ static parser_error_t printAmount64( uint64_t amount, uint8_t amountDenom, const
return parser_ok;
}

parser_error_t printVPTypeHash(bytes_t *codeHash,
char *outVal, uint16_t outValLen,
uint8_t pageIdx, uint8_t *pageCount) {

char hexString[65] = {0};
array_to_hexstr((char*) hexString, sizeof(hexString), codeHash->ptr, codeHash->len);
pageString(outVal, outValLen, (const char*) hexString, pageIdx, pageCount);

return parser_ok;
}

parser_error_t decimal_to_string(int64_t num, uint32_t scale, char* strDec, size_t bufferSize) {

if (strDec == NULL || bufferSize == 0) {
Expand Down
4 changes: 0 additions & 4 deletions app/src/parser_print_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ parser_error_t printAmount( const uint256_t *amount, uint8_t amountDenom, const
char *outVal, uint16_t outValLen,
uint8_t pageIdx, uint8_t *pageCount);

parser_error_t printVPTypeHash(bytes_t *codeHash,
char *outVal, uint16_t outValLen,
uint8_t pageIdx, uint8_t *pageCount);

parser_error_t printPublicKey(const bytes_t *pubkey,
char *outVal, uint16_t outValLen,
uint8_t pageIdx, uint8_t *pageCount);
Expand Down
66 changes: 31 additions & 35 deletions app/src/parser_print_txn.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,7 @@ static parser_error_t printInitAccountTxn( const parser_context_t *ctx,
snprintf(outKey, outKeyLen, "VP type");
pageString(outVal, outValLen,ctx->tx_obj->initAccount.vp_type_text, pageIdx, pageCount);
if (app_mode_expert()) {
CHECK_ERROR(printVPTypeHash(&ctx->tx_obj->initAccount.vp_type_hash,
outVal, outValLen, pageIdx, pageCount))
pageStringHex(outVal, outValLen, (const char*)ctx->tx_obj->initAccount.vp_type_hash.ptr, ctx->tx_obj->initAccount.vp_type_hash.len, pageIdx, pageCount);
}
break;
default:
Expand Down Expand Up @@ -522,17 +521,12 @@ static parser_error_t printUpdateVPTxn(const parser_context_t *ctx,
break;
}
case 3: {
if (updateVp->has_threshold) {
snprintf(outKey, outKeyLen, "Threshold");
// Threshold value is less than 3 characters (uint8)
char strThreshold[3] = {0};
if (uint64_to_str(strThreshold, sizeof(strThreshold), updateVp->threshold) != NULL) {
return parser_unexpected_error;
}
pageString(outVal, outValLen, strThreshold, pageIdx, pageCount);
} else {
if (!updateVp->has_threshold) {
return parser_unexpected_error;
}
*pageCount = 1;
snprintf(outKey, outKeyLen, "Threshold");
snprintf(outVal, outValLen, "%d", updateVp->threshold);
break;
}
case 4:
Expand Down Expand Up @@ -560,6 +554,7 @@ static parser_error_t printInitValidatorTxn( const parser_context_t *ctx,
char *outVal, uint16_t outValLen,
uint8_t pageIdx, uint8_t *pageCount) {


const tx_init_validator_t *initValidator = &ctx->tx_obj->initValidator;
const uint32_t account_keys = initValidator->number_of_account_keys;

Expand All @@ -568,15 +563,12 @@ static parser_error_t printInitValidatorTxn( const parser_context_t *ctx,

if(adjustedDisplayIdx >= 10 && ctx->tx_obj->initValidator.description.ptr == NULL) {
adjustedDisplayIdx++;
displayIdx++;
}
if(adjustedDisplayIdx >= 11 && ctx->tx_obj->initValidator.website.ptr == NULL) {
adjustedDisplayIdx++;
displayIdx++;
}
if(adjustedDisplayIdx >= 12 && ctx->tx_obj->initValidator.discord_handle.ptr == NULL) {
adjustedDisplayIdx++;
displayIdx++;
}

switch (adjustedDisplayIdx) {
Expand All @@ -599,13 +591,9 @@ static parser_error_t printInitValidatorTxn( const parser_context_t *ctx,
break;
}
case 2: {
*pageCount = 1;
snprintf(outKey, outKeyLen, "Threshold");
// Threshold value is less than 3 characters (uint8)
char strThreshold[4] = {0};
if (uint64_to_str(strThreshold, sizeof(strThreshold), initValidator->threshold) != NULL) {
return parser_unexpected_error;
}
snprintf(outVal, outKeyLen, "%s", strThreshold);
snprintf(outVal, outValLen, "%d", initValidator->threshold);
break;
}
case 3: {
Expand All @@ -614,56 +602,63 @@ static parser_error_t printInitValidatorTxn( const parser_context_t *ctx,
CHECK_ERROR(printPublicKey(consensusKey, outVal, outValLen, pageIdx, pageCount));
break;
}
case 4:
case 4: {
snprintf(outKey, outKeyLen, "Ethereum cold key");
const bytes_t *ethColdKey = &ctx->tx_obj->initValidator.eth_cold_key;
pageStringHex(outVal, outValLen, (const char*) ethColdKey->ptr, ethColdKey->len, pageIdx, pageCount);
break;

case 5:
}
case 5: {
snprintf(outKey, outKeyLen, "Ethereum hot key");
const bytes_t *ethHotKey = &ctx->tx_obj->initValidator.eth_hot_key;
pageStringHex(outVal, outValLen, (const char*) ethHotKey->ptr, ethHotKey->len, pageIdx, pageCount);
break;

case 6:
}
case 6: {
snprintf(outKey, outKeyLen, "Protocol key");
const bytes_t *protocolKey = &ctx->tx_obj->initValidator.protocol_key;
CHECK_ERROR(printPublicKey(protocolKey, outVal, outValLen, pageIdx, pageCount));
break;
case 7:
}
case 7: {
snprintf(outKey, outKeyLen, "Commission rate");
CHECK_ERROR(printAmount(&ctx->tx_obj->initValidator.commission_rate, POS_DECIMAL_PRECISION, "", outVal, outValLen, pageIdx, pageCount))
break;
case 8:
}
case 8: {
snprintf(outKey, outKeyLen, "Maximum commission rate change");
CHECK_ERROR(printAmount(&ctx->tx_obj->initValidator.max_commission_rate_change, POS_DECIMAL_PRECISION, "", outVal, outValLen, pageIdx, pageCount))
break;
case 9:
}
case 9: {
snprintf(outKey, outKeyLen, "Email");
pageStringExt(outVal, outValLen, (const char*)ctx->tx_obj->initValidator.email.ptr, ctx->tx_obj->initValidator.email.len, pageIdx, pageCount);
break;
case 10:
}
case 10: {
snprintf(outKey, outKeyLen, "Description");
pageStringExt(outVal, outValLen, (const char*)ctx->tx_obj->initValidator.description.ptr, ctx->tx_obj->initValidator.description.len, pageIdx, pageCount);
break;
case 11:
}
case 11: {
snprintf(outKey, outKeyLen, "Website");
pageStringExt(outVal, outValLen, (const char*)ctx->tx_obj->initValidator.website.ptr, ctx->tx_obj->initValidator.website.len, pageIdx, pageCount);
break;
case 12:
}
case 12: {
snprintf(outKey, outKeyLen, "Discord handle");
pageStringExt(outVal, outValLen, (const char*)ctx->tx_obj->initValidator.discord_handle.ptr, ctx->tx_obj->initValidator.discord_handle.len, pageIdx, pageCount);
break;
case 13:
}
case 13: {
snprintf(outKey, outKeyLen, "Validator VP type");
pageString(outVal, outValLen,ctx->tx_obj->initValidator.vp_type_text, pageIdx, pageCount);
if (app_mode_expert()) {
CHECK_ERROR(printVPTypeHash(&ctx->tx_obj->initValidator.vp_type_hash,
outVal, outValLen, pageIdx, pageCount))
pageStringHex(outVal, outValLen, (const char*)ctx->tx_obj->initValidator.vp_type_hash.ptr, ctx->tx_obj->initValidator.vp_type_hash.len, pageIdx, pageCount);
}
break;
default:
}
default: {
if (!app_mode_expert()) {
return parser_display_idx_out_of_range;
}
Expand All @@ -678,6 +673,7 @@ static parser_error_t printInitValidatorTxn( const parser_context_t *ctx,
displayIdx--;
}
return printExpert(ctx, displayIdx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount);
}
}

return parser_ok;
Expand Down
1 change: 1 addition & 0 deletions deps/ledger-secure-sdk
Submodule ledger-secure-sdk added at e050ce
2 changes: 2 additions & 0 deletions tests_zemu/tests/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ export const APP_SEED = 'equip will roof matter pink blind book anxiety banner e
const APP_PATH_S = Resolve('../app/output/app_s.elf')
const APP_PATH_X = Resolve('../app/output/app_x.elf')
const APP_PATH_SP = Resolve('../app/output/app_s2.elf')
const APP_PATH_ST = Resolve('../app/output/app_stax.elf')

export const models: IDeviceModel[] = [
{ name: 'nanos', prefix: 'S', path: APP_PATH_S },
{ name: 'nanox', prefix: 'X', path: APP_PATH_X },
{ name: 'nanosp', prefix: 'SP', path: APP_PATH_SP },
{ name: 'stax', prefix: 'ST', path: APP_PATH_ST },
]

export const hdpath = `m/44'/877'/0'/0'/0'`
Expand Down
20 changes: 15 additions & 5 deletions tests_zemu/tests/standard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
******************************************************************************* */

import Zemu from '@zondax/zemu'
import Zemu, { ButtonKind, zondaxMainmenuNavigation } from '@zondax/zemu'
import { NamadaApp } from '@zondax/ledger-namada'
import { models, hdpath, defaultOptions } from './common'

Expand All @@ -36,8 +36,9 @@ describe('Standard', function () {
test.concurrent.each(models)('main menu', async function (m) {
const sim = new Zemu(m.path)
try {
const mainmenuNavigation = zondaxMainmenuNavigation(m.name)
await sim.start({ ...defaultOptions, model: m.name })
await sim.navigateAndCompareSnapshots('.', `${m.prefix.toLowerCase()}-mainmenu`, [1, 0, 0, 4, -5])
await sim.navigateAndCompareSnapshots('.', `${m.prefix.toLowerCase()}-mainmenu`, mainmenuNavigation.schedule)
} finally {
await sim.close()
}
Expand Down Expand Up @@ -91,7 +92,12 @@ describe('Standard', function () {
test.concurrent.each(models)('show address', async function (m) {
const sim = new Zemu(m.path)
try {
await sim.start({ ...defaultOptions, model: m.name })
await sim.start({
...defaultOptions,
model: m.name,
approveKeyword: m.name === 'stax' ? 'QR' : '',
approveAction: ButtonKind.ApproveTapButton,
})
const app = new NamadaApp(sim.getTransport())

const respRequest = app.showAddressAndPubKey(hdpath)
Expand Down Expand Up @@ -120,13 +126,17 @@ describe('Standard', function () {
test.concurrent.each(models)('show address - reject', async function (m) {
const sim = new Zemu(m.path)
try {
await sim.start({ ...defaultOptions, model: m.name })
await sim.start({
...defaultOptions,
model: m.name,
rejectKeyword: m.name === 'stax' ? 'QR' : '',
})
const app = new NamadaApp(sim.getTransport())

const respRequest = app.showAddressAndPubKey(hdpath)

await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot())
await sim.navigateAndCompareUntilText('.', `${m.prefix.toLowerCase()}-show_address_reject`, 'REJECT')
await sim.compareSnapshotsAndReject('.', `${m.prefix.toLowerCase()}-show_address_reject`)

const resp = await respRequest
console.log(resp)
Expand Down

0 comments on commit 56c2b74

Please sign in to comment.