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

Memo hotfix #17

Merged
merged 3 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 4 additions & 4 deletions .github/workflows/ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest

container:
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:d5bfe2e793f15a826971ae9de2adcad524df3e8e
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:3.19.0

steps:
- name: Clone
Expand All @@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest

container:
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:d5bfe2e793f15a826971ae9de2adcad524df3e8e
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:3.19.0

steps:
- name: Clone
Expand All @@ -50,7 +50,7 @@ jobs:
runs-on: ubuntu-latest

container:
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:d5bfe2e793f15a826971ae9de2adcad524df3e8e
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:3.19.0

steps:
- name: Clone
Expand All @@ -72,7 +72,7 @@ jobs:
needs: job_nanoS_build_debug

container:
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:d5bfe2e793f15a826971ae9de2adcad524df3e8e
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:3.19.0

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

APPVERSION_M = 1
APPVERSION_N = 0
APPVERSION_P = 6
APPVERSION_P = 7

NANOS_ID = 1
WORDS = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
Expand Down
2 changes: 1 addition & 1 deletion MakefileContainer.mk
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ifneq ($(BOLOS_SDK),)
$(error Containerized build, BOLOS_SDK should be empty)
endif

APP_BUILDER_IMAGE = ledger-app-builder:d5bfe2e793f15a826971ae9de2adcad524df3e8e
APP_BUILDER_IMAGE = ledger-app-builder:3.19.0

default_target: build

Expand Down
2 changes: 1 addition & 1 deletion MakefileSpeculos.mk
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# limitations under the License.
#*******************************************************************************

SPECULOS_IMAGE = speculos:sha-6a34680
SPECULOS_IMAGE = speculos:6409e73ba640fbec2e46dfae7ae0f18887a7ee42

define run_announce
@perl -e 'use Time::HiRes; use POSIX; $$ts = sprintf qq[%f], Time::HiRes::time(); ($$f) = $$ts =~ m~(\....)~; printf qq[%s%s %s make: %s\n], POSIX::strftime("%H:%M:%S", gmtime), $$f, q[-] x 126, $$ARGV[0];' "$(1)"
Expand Down
36 changes: 17 additions & 19 deletions ledgerjs-fio/src/interactions/transactionTemplates/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,30 +413,28 @@ export function ADD_STORAGE_CHECK(check: VALUE_STORAGE_COMPARE, c: Command): Com
}
}

export function COMMAND_APPEND_DATA_MEMO_HASH(memo?: VarlenAsciiString, hash?: VarlenAsciiString, offline_url?: VarlenAsciiString): Command {
var varData: Buffer = Buffer.from("");
if (memo === undefined) {
validate(hash !== undefined, InvalidDataReason.INVALID_HASH);
validate(offline_url !== undefined, InvalidDataReason.INVALID_OFFLINE_URL);
varData = Buffer.concat([
Buffer.from("0001", "hex"),
varuint32_to_buf(hash.length),
Buffer.from(hash),
Buffer.from("01", "hex"),
varuint32_to_buf(offline_url.length),
Buffer.from(offline_url),
])
function serializeOptionalString(str?: VarlenAsciiString): Buffer {
if (str === undefined) {
return Buffer.from("00", "hex")
}
else {
validate(hash === undefined, InvalidDataReason.INVALID_HASH);
validate(hash === undefined, InvalidDataReason.INVALID_OFFLINE_URL);
varData = Buffer.concat([
return Buffer.concat([
Buffer.from("01", "hex"),
varuint32_to_buf(memo.length),
Buffer.from(memo),
Buffer.from("0000", "hex"),
varuint32_to_buf(str.length),
Buffer.from(str),
])
}
}

export function COMMAND_APPEND_DATA_MEMO_HASH(memo?: VarlenAsciiString, hash?: VarlenAsciiString, offline_url?: VarlenAsciiString): Command {
validate((hash !== undefined && offline_url !== undefined) || (hash === undefined && offline_url === undefined), InvalidDataReason.INVALID_HASH);

const varData = Buffer.concat([
serializeOptionalString(memo),
serializeOptionalString(hash),
serializeOptionalString(offline_url),
])

return {
...defaultCommand,
command: COMMAND.APPEND_DATA,
Expand Down
154 changes: 60 additions & 94 deletions src/decodeDH.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,78 +122,62 @@ static void decodeNewfundsreqMemo_ui_runStep() {
}

enum {
DECODE_NEWFUNDSREQ_HASH_UI_STEP_MESSAGE1 = 250,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_MESSAGE2,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_PAYEE_PUBLIC_ADDRESS,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_AMOUNT,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_CHAIN_CODE,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_TOKEN_CODE,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_HASH,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_OFFLINE_URL,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_CONFIRM,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_RESPOND,
DECODE_NEWFUNDSREQ_HASH_UI_STEP_INVALID,
DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_MESSAGE1 = 250,
DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_MESSAGE2,
DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_PAYEE_PUBLIC_ADDRESS,
DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_AMOUNT,
DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_CHAIN_CODE,
DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_TOKEN_CODE,
DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_CONFIRM,
DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_RESPOND,
DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_INVALID,
};

static void decodeNewfundsreqHash_ui_runStep() {
static void decodeNewfundsreqNoMemo_ui_runStep() {
TRACE("UI step %d", ctx->ui_step);
ui_callback_fn_t *this_fn = decodeNewfundsreqHash_ui_runStep;
ui_callback_fn_t *this_fn = decodeNewfundsreqNoMemo_ui_runStep;

UI_STEP_BEGIN(ctx->ui_step, this_fn);

UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_MESSAGE1) {
UI_STEP(DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_MESSAGE1) {
ui_displayPaginatedText("Decrypt content", "", this_fn);
}
UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_MESSAGE2) {
UI_STEP(DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_MESSAGE2) {
ui_displayPaginatedText("Interpreting", "the message as Request funds", this_fn);
}
UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_PAYEE_PUBLIC_ADDRESS) {
UI_STEP(DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_PAYEE_PUBLIC_ADDRESS) {
ui_displayAsciiBufferScreen("Payee public address",
ctx->parsedContent.payee_public_address->data,
ctx->parsedContent.payee_public_address->length,
this_fn);
}
UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_AMOUNT) {
UI_STEP(DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_AMOUNT) {
ui_displayAsciiBufferScreen("Amount",
ctx->parsedContent.amount->data,
ctx->parsedContent.amount->length,
this_fn);
}
UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_CHAIN_CODE) {
UI_STEP(DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_CHAIN_CODE) {
ui_displayAsciiBufferScreen("Chain code",
ctx->parsedContent.chain_code->data,
ctx->parsedContent.chain_code->length,
this_fn);
}
UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_TOKEN_CODE) {
UI_STEP(DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_TOKEN_CODE) {
ui_displayAsciiBufferScreen("Token code",
ctx->parsedContent.token_code->data,
ctx->parsedContent.token_code->length,
this_fn);
}
UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_HASH) {
ASSERT(ctx->parsedContent.hash != NULL);
ui_displayAsciiBufferScreen("Hash",
ctx->parsedContent.hash->data,
ctx->parsedContent.hash->length,
this_fn);
}
UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_OFFLINE_URL) {
ASSERT(ctx->parsedContent.offline_url != NULL);
ui_displayAsciiBufferScreen("Offline URL",
ctx->parsedContent.offline_url->data,
ctx->parsedContent.offline_url->length,
this_fn);
}
UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_CONFIRM) {
UI_STEP(DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_CONFIRM) {
ui_displayPrompt("Confirm", "response", this_fn, dh_respond_with_user_reject);
}
UI_STEP(DECODE_NEWFUNDSREQ_HASH_UI_STEP_RESPOND) {
UI_STEP(DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_RESPOND) {
io_send_buf(SUCCESS, NULL, 0);
ui_displayBusy(); // needs to happen after I/O
ctx->stage = DECODE_STAGE_SEND_REST;
}
UI_STEP_END(DECODE_NEWFUNDSREQ_HASH_UI_STEP_INVALID);
UI_STEP_END(DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_INVALID);
}

// Parse newfundsreq data
Expand All @@ -210,18 +194,17 @@ static void decodeNewfundsreqUIFlow() {
readOptionalStringWithLength(&read, &ctx->parsedContent.hash);
readOptionalStringWithLength(&read, &ctx->parsedContent.offline_url);
VALIDATE(read == ctx->bufferLen, ERR_INVALID_DATA);
bool hasMemo = (ctx->parsedContent.memo != NULL);
bool hasHash = (ctx->parsedContent.hash != NULL);
bool hasOfflineUrl = (ctx->parsedContent.offline_url != NULL);
VALIDATE((hasHash && hasOfflineUrl) || (!hasHash && !hasOfflineUrl), ERR_INVALID_DATA);

if (ctx->parsedContent.memo != NULL && ctx->parsedContent.hash == NULL &&
ctx->parsedContent.offline_url == NULL) {
if (hasMemo) {
ctx->ui_step = DECODE_NEWFUNDSREQ_MEMO_UI_STEP_MESSAGE1;
decodeNewfundsreqMemo_ui_runStep();
} else if (ctx->parsedContent.memo == NULL && ctx->parsedContent.hash != NULL &&
ctx->parsedContent.offline_url != NULL) {
ctx->ui_step = DECODE_NEWFUNDSREQ_HASH_UI_STEP_MESSAGE1;
decodeNewfundsreqHash_ui_runStep();

} else {
THROW(ERR_INVALID_DATA);
ctx->ui_step = DECODE_NEWFUNDSREQ_NOMEMO_UI_STEP_MESSAGE1;
decodeNewfundsreqNoMemo_ui_runStep();
}
}

Expand Down Expand Up @@ -318,101 +301,85 @@ static void decodeRecordobtMemo_ui_runStep() {
}

enum {
DECODE_RECORDOBT_HASH_UI_STEP_MESSAGE1 = 350,
DECODE_RECORDOBT_HASH_UI_STEP_MESSAGE2,
DECODE_RECORDOBT_HASH_UI_STEP_PAYEE_PUBLIC_ADDRESS,
DECODE_RECORDOBT_HASH_UI_STEP_PAYER_PUBLIC_ADDRESS,
DECODE_RECORDOBT_HASH_UI_STEP_AMOUNT,
DECODE_RECORDOBT_HASH_UI_STEP_CHAIN_CODE,
DECODE_RECORDOBT_HASH_UI_STEP_TOKEN_CODE,
DECODE_RECORDOBT_HASH_UI_STEP_STATUS,
DECODE_RECORDOBT_HASH_UI_STEP_OBT_ID,
DECODE_RECORDOBT_HASH_UI_STEP_HASH,
DECODE_RECORDOBT_HASH_UI_STEP_OFFLINE_URL,
DECODE_RECORDOBT_HASH_UI_STEP_CONFIRM,
DECODE_RECORDOBT_HASH_UI_STEP_RESPOND,
DECODE_RECORDOBT_HASH_UI_STEP_INVALID,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_MESSAGE1 = 350,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_MESSAGE2,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_PAYEE_PUBLIC_ADDRESS,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_PAYER_PUBLIC_ADDRESS,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_AMOUNT,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_CHAIN_CODE,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_TOKEN_CODE,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_STATUS,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_OBT_ID,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_CONFIRM,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_RESPOND,
DECODE_RECORDOBT_NO_MEMO_UI_STEP_INVALID,
};

static void decodeRecordobtHash_ui_runStep() {
static void decodeRecordobtNoMemo_ui_runStep() {
TRACE("UI step %d", ctx->ui_step);
ui_callback_fn_t *this_fn = decodeRecordobtHash_ui_runStep;
ui_callback_fn_t *this_fn = decodeRecordobtNoMemo_ui_runStep;

UI_STEP_BEGIN(ctx->ui_step, this_fn);

UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_MESSAGE1) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_MESSAGE1) {
ui_displayPaginatedText("Decrypt content", "", this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_MESSAGE2) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_MESSAGE2) {
ui_displayPaginatedText("Interpreting",
"the message as Record other blockchain transaction metadata",
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_PAYEE_PUBLIC_ADDRESS) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_PAYEE_PUBLIC_ADDRESS) {
ui_displayAsciiBufferScreen("Payee public address",
ctx->parsedContent.payee_public_address->data,
ctx->parsedContent.payee_public_address->length,
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_PAYER_PUBLIC_ADDRESS) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_PAYER_PUBLIC_ADDRESS) {
ui_displayAsciiBufferScreen("Payer public address",
ctx->parsedContent.payer_public_address->data,
ctx->parsedContent.payer_public_address->length,
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_AMOUNT) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_AMOUNT) {
ui_displayAsciiBufferScreen("Amount",
ctx->parsedContent.amount->data,
ctx->parsedContent.amount->length,
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_CHAIN_CODE) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_CHAIN_CODE) {
ui_displayAsciiBufferScreen("Chain code",
ctx->parsedContent.chain_code->data,
ctx->parsedContent.chain_code->length,
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_TOKEN_CODE) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_TOKEN_CODE) {
ui_displayAsciiBufferScreen("Token code",
ctx->parsedContent.token_code->data,
ctx->parsedContent.token_code->length,
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_STATUS) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_STATUS) {
ui_displayAsciiBufferScreen("Status",
ctx->parsedContent.status->data,
ctx->parsedContent.status->length,
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_OBT_ID) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_OBT_ID) {
ui_displayAsciiBufferScreen("Obt ID",
ctx->parsedContent.obt_id->data,
ctx->parsedContent.obt_id->length,
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_HASH) {
ASSERT(ctx->parsedContent.hash != NULL);
ui_displayAsciiBufferScreen("Hash",
ctx->parsedContent.hash->data,
ctx->parsedContent.hash->length,
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_OFFLINE_URL) {
ASSERT(ctx->parsedContent.offline_url != NULL);
ui_displayAsciiBufferScreen("Offline URL",
ctx->parsedContent.offline_url->data,
ctx->parsedContent.offline_url->length,
this_fn);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_CONFIRM) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_CONFIRM) {
ui_displayPrompt("Confirm", "response", this_fn, dh_respond_with_user_reject);
}
UI_STEP(DECODE_RECORDOBT_HASH_UI_STEP_RESPOND) {
UI_STEP(DECODE_RECORDOBT_NO_MEMO_UI_STEP_RESPOND) {
io_send_buf(SUCCESS, NULL, 0);
ui_displayBusy(); // needs to happen after I/O
ctx->stage = DECODE_STAGE_SEND_REST;
}
UI_STEP_END(DECODE_RECORDOBT_HASH_UI_STEP_INVALID);
UI_STEP_END(DECODE_RECORDOBT_NO_MEMO_UI_STEP_INVALID);
}

// Parse newfundsreq data
Expand All @@ -432,18 +399,17 @@ static void decodeRecordobtUIFlow() {
readOptionalStringWithLength(&read, &ctx->parsedContent.hash);
readOptionalStringWithLength(&read, &ctx->parsedContent.offline_url);
VALIDATE(read == ctx->bufferLen, ERR_INVALID_DATA);
bool hasMemo = (ctx->parsedContent.memo != NULL);
bool hasHash = (ctx->parsedContent.hash != NULL);
bool hasOfflineUrl = (ctx->parsedContent.offline_url != NULL);
VALIDATE((hasHash && hasOfflineUrl) || (!hasHash && !hasOfflineUrl), ERR_INVALID_DATA);

if (ctx->parsedContent.memo != NULL && ctx->parsedContent.hash == NULL &&
ctx->parsedContent.offline_url == NULL) {
if (hasMemo) {
ctx->ui_step = DECODE_RECORDOBT_MEMO_UI_STEP_MESSAGE1;
decodeRecordobtMemo_ui_runStep();
} else if (ctx->parsedContent.memo == NULL && ctx->parsedContent.hash != NULL &&
ctx->parsedContent.offline_url != NULL) {
ctx->ui_step = DECODE_RECORDOBT_HASH_UI_STEP_MESSAGE1;
decodeRecordobtHash_ui_runStep();

} else {
THROW(ERR_INVALID_DATA);
ctx->ui_step = DECODE_RECORDOBT_NO_MEMO_UI_STEP_MESSAGE1;
decodeRecordobtNoMemo_ui_runStep();
}
}

Expand Down
Loading
Loading