Skip to content

Commit c8d31ae

Browse files
authored
Merge pull request #224 from Zondax/dev
2 parents 2323a72 + 34ea581 commit c8d31ae

File tree

111 files changed

+356
-328
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+356
-328
lines changed

app/Makefile.version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ APPVERSION_M=2
33
# This is the minor version of this release
44
APPVERSION_N=4
55
# This is the patch version of this release
6-
APPVERSION_P=7
6+
APPVERSION_P=8

app/src/candid/candid_parser.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,11 @@ parser_error_t readCandidICRCTransfer(parser_tx_t *tx, const uint8_t *input, uin
345345
// Read to (Account)
346346
CHECK_PARSER_ERR(readCandidByte(&ctx, &icrc->account.has_owner))
347347
if (icrc->account.has_owner) {
348-
uint8_t ownerSize = 0;
349-
CHECK_PARSER_ERR(readCandidByte(&ctx, &ownerSize))
350-
if (ownerSize != DFINITY_PRINCIPAL_LEN) {
348+
CHECK_PARSER_ERR(readCandidByte(&ctx, &icrc->account.owner.len))
349+
if (icrc->account.owner.len > DFINITY_PRINCIPAL_LEN) {
351350
return parser_unexpected_value;
352351
}
353-
CHECK_PARSER_ERR(readCandidBytes(&ctx, icrc->account.owner, ownerSize))
352+
CHECK_PARSER_ERR(readCandidBytes(&ctx, icrc->account.owner.ptr, icrc->account.owner.len))
354353
}
355354

356355
CHECK_PARSER_ERR(readCandidByte(&ctx, &icrc->account.has_subaccount))
@@ -369,6 +368,10 @@ parser_error_t readCandidICRCTransfer(parser_tx_t *tx, const uint8_t *input, uin
369368
if (icrc->has_memo) {
370369
uint8_t tmp = 0;
371370
CHECK_PARSER_ERR(readCandidNat(&ctx, &icrc->memo.len))
371+
// should not be bigger than uint64
372+
if (icrc->memo.len > 8) {
373+
return parser_unexpected_value;
374+
}
372375

373376
icrc->memo.p = ctx.buffer + ctx.offset;
374377
for (uint64_t i = 0; i < icrc->memo.len; i++) {

app/src/candid/candid_types.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,14 @@ typedef struct {
220220
uint32_t dissolve_timestamp_seconds;
221221
} candid_IncreaseDissolveDelay_t;
222222

223+
typedef struct {
224+
uint8_t len;
225+
uint8_t ptr[30];
226+
} candid_Principal_t;
227+
223228
typedef struct {
224229
uint8_t has_principal;
225-
uint8_t principal[30];
230+
candid_Principal_t principal;
226231
} candid_AddRemoveHotkey_t;
227232

228233
typedef struct {
@@ -241,7 +246,7 @@ typedef struct {
241246
uint32_t percentage_to_spawn;
242247

243248
uint8_t has_controller;
244-
uint8_t new_controller[30];
249+
candid_Principal_t new_controller;
245250

246251
uint8_t has_nonce;
247252
uint64_t nonce;
@@ -298,12 +303,12 @@ typedef struct {
298303
sns_NeuronPermissionList_t permissionList;
299304

300305
uint8_t has_principal;
301-
uint8_t principal[30];
306+
candid_Principal_t principal;
302307
} sns_NeuronPermissions_t;
303308

304309
typedef struct {
305310
uint8_t has_owner;
306-
uint8_t owner[30];
311+
candid_Principal_t owner;
307312

308313
uint8_t has_subaccount;
309314
sizedBuffer_t subaccount;

app/src/candid/nns_parser.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,10 @@ __Z_INLINE parser_error_t readCommandSpawn(parser_context_t *ctx, candid_transac
144144
CHECK_PARSER_ERR(readCandidByte(ctx, &val->command.spawn.has_controller))
145145
if (val->command.spawn.has_controller) {
146146
uint8_t has_principal = 0;
147-
uint8_t principalSize = 0;
148147
CHECK_PARSER_ERR(readCandidByte(ctx, &has_principal))
149-
if(has_principal) {
150-
CHECK_PARSER_ERR(readCandidByte(ctx, &principalSize))
151-
CHECK_PARSER_ERR(readCandidBytes(ctx, val->command.spawn.new_controller, principalSize))
148+
if (has_principal) {
149+
CHECK_PARSER_ERR(readCandidByte(ctx, &val->command.spawn.new_controller.len))
150+
CHECK_PARSER_ERR(readCandidBytes(ctx, val->command.spawn.new_controller.ptr, val->command.spawn.new_controller.len))
152151
}
153152
}
154153

@@ -425,16 +424,15 @@ __Z_INLINE parser_error_t readOperationAddRemoveHotkey(parser_context_t *ctx, ca
425424
return parser_unexpected_value;
426425
}
427426
uint8_t has_principal = 0;
428-
uint8_t principalSize = 0;
429427
CHECK_PARSER_ERR(readCandidByte(ctx, &has_principal))
430428
if (!has_principal) {
431429
return parser_unexpected_value;
432430
}
433-
CHECK_PARSER_ERR(readCandidByte(ctx, &principalSize))
434-
if (principalSize != DFINITY_PRINCIPAL_LEN) {
431+
CHECK_PARSER_ERR(readCandidByte(ctx, &operation->hotkey.principal.len))
432+
if (operation->hotkey.principal.len > DFINITY_PRINCIPAL_LEN) {
435433
return parser_unexpected_value;
436434
}
437-
CHECK_PARSER_ERR(readCandidBytes(ctx, operation->hotkey.principal, principalSize))
435+
CHECK_PARSER_ERR(readCandidBytes(ctx, operation->hotkey.principal.ptr, operation->hotkey.principal.len))
438436

439437
return parser_ok;
440438
}

app/src/candid/sns_parser.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,13 @@ __Z_INLINE parser_error_t readSNSCommandNeuronPermissions(parser_context_t *ctx,
9191
CHECK_PARSER_ERR(readCandidByte(ctx, &val->has_principal))
9292
if (val->has_principal) {
9393
uint8_t has_principal = 0;
94-
uint8_t principalSize = 0;
9594
CHECK_PARSER_ERR(readCandidByte(ctx, &has_principal))
96-
if(has_principal) {
97-
CHECK_PARSER_ERR(readCandidByte(ctx, &principalSize))
98-
if (principalSize != DFINITY_PRINCIPAL_LEN) {
95+
if (has_principal) {
96+
CHECK_PARSER_ERR(readCandidByte(ctx, &val->principal.len))
97+
if (val->principal.len > DFINITY_PRINCIPAL_LEN) {
9998
return parser_unexpected_value;
10099
}
101-
CHECK_PARSER_ERR(readCandidBytes(ctx, val->principal, principalSize))
100+
CHECK_PARSER_ERR(readCandidBytes(ctx, val->principal.ptr, val->principal.len))
102101
}
103102
}
104103

@@ -290,14 +289,13 @@ __Z_INLINE parser_error_t readSNSCommandNeuronDisburse(parser_context_t *ctx, ca
290289
CHECK_PARSER_ERR(readCandidByte(ctx, &val->account.has_owner))
291290
if (val->account.has_owner) {
292291
uint8_t has_principal = 0;
293-
uint8_t principalSize = 0;
294292
CHECK_PARSER_ERR(readCandidByte(ctx, &has_principal))
295293
if (has_principal) {
296-
CHECK_PARSER_ERR(readCandidByte(ctx, &principalSize))
297-
if (principalSize != DFINITY_PRINCIPAL_LEN) {
294+
CHECK_PARSER_ERR(readCandidByte(ctx, &val->account.owner.len))
295+
if (val->account.owner.len > DFINITY_PRINCIPAL_LEN) {
298296
return parser_unexpected_value;
299297
}
300-
CHECK_PARSER_ERR(readCandidBytes(ctx, val->account.owner, principalSize))
298+
CHECK_PARSER_ERR(readCandidBytes(ctx, val->account.owner.ptr, val->account.owner.len))
301299
}
302300
}
303301

app/src/crypto.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -459,11 +459,33 @@ uint64_t change_endianness(uint64_t value) {
459459
return result;
460460
}
461461

462+
zxerr_t crypto_computeStakeSubaccount(const uint8_t *principal, uint16_t principalLen,
463+
const uint8_t *memo, uint16_t memoLen,
464+
uint8_t *subaccount, uint16_t subaccountLen) {
465+
if (principalLen > DFINITY_PRINCIPAL_LEN || subaccountLen < DFINITY_SUBACCOUNT_LEN ||
466+
memoLen > sizeof(uint64_t)) {
467+
return zxerr_invalid_crypto_settings;
468+
}
469+
470+
uint8_t preHash[1 + STAKEACCOUNT_PREFIX_SIZE + DFINITY_PRINCIPAL_LEN + sizeof(uint64_t)] = {0};
471+
uint16_t preHashLen = 0;
472+
preHash[0] = 0x0C;
473+
preHashLen++;
474+
memmove(preHash + preHashLen, "neuron-stake", STAKEACCOUNT_PREFIX_SIZE);
475+
preHashLen += STAKEACCOUNT_PREFIX_SIZE;
476+
memmove(preHash + preHashLen, principal, principalLen);
477+
preHashLen += principalLen;
478+
memmove(preHash + preHashLen, memo, memoLen);
479+
preHashLen += memoLen;
480+
481+
cx_hash_sha256((uint8_t *) preHash, preHashLen, subaccount, 32);
482+
return zxerr_ok;
483+
}
484+
462485
zxerr_t crypto_principalToStakeAccount(const uint8_t *principal, uint16_t principalLen,
463486
const uint64_t neuron_creation_memo,
464487
uint8_t *address, uint16_t maxoutLen) {
465-
if (principalLen != DFINITY_PRINCIPAL_LEN ||
466-
maxoutLen < DFINITY_ADDR_LEN) {
488+
if (principalLen > DFINITY_PRINCIPAL_LEN || maxoutLen < DFINITY_ADDR_LEN) {
467489
return zxerr_invalid_crypto_settings;
468490
}
469491
stake_account account;
@@ -472,7 +494,7 @@ zxerr_t crypto_principalToStakeAccount(const uint8_t *principal, uint16_t princi
472494
stake_account_pre_hash *pre_hash = &account.hash_fields.pre_hash;
473495
pre_hash->prefix_byte = 0x0C;
474496
MEMCPY(pre_hash->prefix_string, (uint8_t *) "neuron-stake", STAKEACCOUNT_PREFIX_SIZE);
475-
MEMCPY(pre_hash->principal, principal, DFINITY_PRINCIPAL_LEN);
497+
MEMCPY(pre_hash->principal, principal, principalLen);
476498
pre_hash->memo_be = change_endianness(neuron_creation_memo);
477499

478500
stake_account_hash *final_hash = &account.hash_fields.stake_hash;
@@ -525,19 +547,19 @@ zxerr_t crypto_computePrincipal(const uint8_t *pubKey, uint8_t *principal) {
525547
zxerr_t crypto_principalToSubaccount(const uint8_t *principal, uint16_t principalLen,
526548
const uint8_t *subAccount, uint16_t subaccountLen,
527549
uint8_t *address, uint16_t maxoutLen) {
528-
if (principalLen != DFINITY_PRINCIPAL_LEN || subaccountLen != DFINITY_SUBACCOUNT_LEN ||
550+
if (principalLen > DFINITY_PRINCIPAL_LEN || subaccountLen != DFINITY_SUBACCOUNT_LEN ||
529551
maxoutLen < DFINITY_ADDR_LEN) {
530552
return zxerr_invalid_crypto_settings;
531553
}
532554
uint8_t hashinput[SUBACCOUNT_PREFIX_SIZE + DFINITY_PRINCIPAL_LEN + DFINITY_SUBACCOUNT_LEN];
533555
MEMZERO(hashinput, sizeof(hashinput));
534556
hashinput[0] = 0x0a;
535557
MEMCPY(&hashinput[1], (uint8_t *) "account-id", SUBACCOUNT_PREFIX_SIZE - 1);
536-
MEMCPY(hashinput + SUBACCOUNT_PREFIX_SIZE, principal, DFINITY_PRINCIPAL_LEN);
537-
MEMCPY(hashinput + SUBACCOUNT_PREFIX_SIZE + DFINITY_PRINCIPAL_LEN, subAccount, DFINITY_SUBACCOUNT_LEN);
558+
MEMCPY(hashinput + SUBACCOUNT_PREFIX_SIZE, principal, principalLen);
559+
MEMCPY(hashinput + SUBACCOUNT_PREFIX_SIZE + principalLen, subAccount, DFINITY_SUBACCOUNT_LEN);
538560

539561
CHECK_ZXERR(
540-
hash_sha224(hashinput, SUBACCOUNT_PREFIX_SIZE + DFINITY_PRINCIPAL_LEN + DFINITY_SUBACCOUNT_LEN, address + 4,
562+
hash_sha224(hashinput, SUBACCOUNT_PREFIX_SIZE + principalLen + DFINITY_SUBACCOUNT_LEN, address + 4,
541563
(maxoutLen - 4)));
542564

543565
uint32_t crc = 0;

app/src/crypto.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ zxerr_t crypto_sign_combined(uint8_t *signatureBuffer,
6363

6464
zxerr_t crypto_getDigest(uint8_t *digest, txtype_e txtype);
6565

66+
zxerr_t crypto_computeStakeSubaccount(const uint8_t *principal, uint16_t principalLen,
67+
const uint8_t *memo, uint16_t memoLen,
68+
uint8_t *subaccount, uint16_t subaccountLen);
69+
6670
zxerr_t crypto_principalToStakeAccount(const uint8_t *principal, uint16_t principalLen,
6771
const uint64_t neuron_creation_memo,
6872
uint8_t *address, uint16_t maxoutLen);

app/src/parser_impl.c

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
********************************************************************************/
1616

1717
#include <zxmacros.h>
18+
#include "crypto.h"
1819
#include "parser_impl.h"
1920
#include "parser_txdef.h"
2021
#include "cbor.h"
@@ -286,10 +287,8 @@ parser_error_t getManageNeuronType(const parser_tx_t *v, manageNeuron_e *mn_type
286287
case Spawn:
287288
case Follow:
288289
case RegisterVote:
289-
case MergeMaturity: {
290290
*mn_type = command;
291291
return parser_ok;
292-
}
293292

294293
default: {
295294
return parser_unexpected_type;
@@ -702,23 +701,45 @@ parser_error_t _validateTx(__Z_UNUSED const parser_context_t *c, const parser_tx
702701
#endif
703702

704703
if (v->txtype == call && parser_tx_obj.special_transfer_type == neuron_stake_transaction) {
705-
const bool is_candid = v->tx_fields.call.method_type == candid_transfer;
706704
uint8_t to_hash[32] = {0};
707-
uint64_t memo = is_candid ? v->tx_fields.call.data.candid_transfer.memo
708-
: v->tx_fields.call.data.SendRequest.memo.memo;
709-
710-
711-
PARSER_ASSERT_OR_ERROR(
712-
zxerr_ok == crypto_principalToStakeAccount(sender, DFINITY_PRINCIPAL_LEN,
713-
memo, to_hash, sizeof(to_hash)),
714-
parser_unexpected_error);
715-
716-
const uint8_t *to = is_candid ? v->tx_fields.call.data.candid_transfer.to
717-
: v->tx_fields.call.data.SendRequest.to.hash;
718-
719-
if (memcmp(to_hash, to, DFINITY_ADDR_LEN) != 0) {
720-
zemu_log_stack("wrong data");
721-
return parser_invalid_address;
705+
if (v->tx_fields.call.method_type == candid_icrc_transfer) {
706+
const icrc_transfer_t *fields = &v->tx_fields.call.data.icrcTransfer;
707+
if (fields->icp_canister == 0 || fields->account.has_owner == 0 ||
708+
fields->account.has_subaccount == 0 ||
709+
fields->account.subaccount.len != DFINITY_SUBACCOUNT_LEN ||
710+
fields->has_memo == 0 || fields->memo.len == 0) {
711+
return parser_invalid_address;
712+
}
713+
// stands for rrkah-fqaaa-aaaaa-aaaaq-cai principal
714+
uint8_t governanceCanister[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01};
715+
if (fields->account.owner.len != sizeof(governanceCanister) ||
716+
memcmp(governanceCanister, fields->account.owner.ptr, 10) != 0) {
717+
zemu_log_stack("wrong principal");
718+
return parser_invalid_address;
719+
}
720+
PARSER_ASSERT_OR_ERROR(
721+
zxerr_ok == crypto_computeStakeSubaccount(sender, v->tx_fields.call.sender.len,
722+
fields->memo.p, fields->memo.len,
723+
to_hash, sizeof(to_hash)),
724+
parser_unexpected_error);
725+
if (memcmp(to_hash, fields->account.subaccount.p, DFINITY_SUBACCOUNT_LEN) != 0) {
726+
zemu_log_stack("wrong data");
727+
return parser_invalid_address;
728+
}
729+
} else {
730+
const bool is_candid = v->tx_fields.call.method_type == candid_transfer;
731+
uint64_t memo = is_candid ? v->tx_fields.call.data.candid_transfer.memo
732+
: v->tx_fields.call.data.SendRequest.memo.memo;
733+
const uint8_t *to = is_candid ? v->tx_fields.call.data.candid_transfer.to
734+
: v->tx_fields.call.data.SendRequest.to.hash;
735+
PARSER_ASSERT_OR_ERROR(
736+
zxerr_ok == crypto_principalToStakeAccount(sender, DFINITY_PRINCIPAL_LEN,
737+
memo, to_hash, sizeof(to_hash)),
738+
parser_unexpected_error);
739+
if (memcmp(to_hash, to, DFINITY_ADDR_LEN) != 0) {
740+
zemu_log_stack("wrong data");
741+
return parser_invalid_address;
742+
}
722743
}
723744
}
724745
return parser_ok;
@@ -746,7 +767,6 @@ uint8_t getNumItemsManageNeurons(__Z_UNUSED const parser_context_t *c, const par
746767
case Configure_AddHotKey :
747768
case Configure_RemoveHotkeyCandid:
748769
case Configure_AddHotkeyCandid:
749-
case MergeMaturity :
750770
case Configure_IncreaseDissolveDelay:
751771
case Configure_IncreaseDissolveDelayCandid:
752772
case Configure_ChangeAutoStakeMaturity:
@@ -841,10 +861,12 @@ uint8_t _getNumItems(__Z_UNUSED const parser_context_t *c, const parser_tx_t *v)
841861
case candid_icrc_transfer: {
842862
const call_t *call = &v->tx_fields.call;
843863
const bool icp_canisterId = call->data.icrcTransfer.icp_canister;
864+
const bool is_stake_tx = parser_tx_obj.special_transfer_type == neuron_stake_transaction;
844865

845866
// Canister ID will be display only when different to ICP
846867
// Fee will be display if available or default if Canister ID is ICP
847-
return 5 + (icp_canisterId ? 0 : 1) + ((call->data.icrcTransfer.has_fee || icp_canisterId) ? 1 : 0);
868+
// To account is only shown if tx is not stake
869+
return 4 + (icp_canisterId ? 0 : 1) + ((call->data.icrcTransfer.has_fee || icp_canisterId) ? 1 : 0) + (is_stake_tx ? 0 : 1);
848870
}
849871

850872
default:

0 commit comments

Comments
 (0)