Skip to content

Commit

Permalink
Merge pull request #167 from Zondax/improving_parser
Browse files Browse the repository at this point in the history
Improving parser
  • Loading branch information
jleni authored Aug 31, 2022
2 parents 81cb735 + 631a111 commit aa43058
Show file tree
Hide file tree
Showing 14 changed files with 181 additions and 48 deletions.
6 changes: 1 addition & 5 deletions app/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ all: bin/app.elf

include $(BOLOS_SDK)/Makefile.defines

#DEFINES += APP_SECRET_MODE_ENABLED

$(info ************ TARGET_NAME = [$(TARGET_NAME)])

ifeq ($(APP_TESTING),1)
Expand All @@ -54,9 +52,7 @@ ifndef COIN
COIN=ICP
endif

APPVERSION_M=2
APPVERSION_N=1
APPVERSION_P=0
include $(CURDIR)/Makefile.version

$(info COIN = [$(COIN)])

Expand Down
6 changes: 6 additions & 0 deletions app/Makefile.version
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# This is the major version of this release
APPVERSION_M=2
# This is the minor version of this release
APPVERSION_N=1
# This is the patch version of this release
APPVERSION_P=1
135 changes: 121 additions & 14 deletions app/src/candid/candid_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,55 @@
// Good reference: https://github.com/dfinity/agent-js/tree/main/packages/candid
// https://github.com/dfinity/candid/blob/master/spec/Candid.md#deserialisation

static uint16_t table_entry_point = 0;

typedef parser_error_t (*check_hash)(const uint64_t *hash, bool *found);

parser_error_t check_hash_method(const uint64_t *hash, bool *found) {
if(found == NULL || hash == NULL) {
return parser_unexpected_value;
}
*found = false;

switch (*hash)
{
case hash_command_Spawn:
case hash_command_Split:
case hash_command_Follow:
case hash_command_ClaimOrRefresh:
case hash_command_Configure:
case hash_command_RegisterVote:
case hash_command_Merge:
*found = true;
break;
}

return parser_ok;
}

parser_error_t check_hash_operation(const uint64_t *hash, bool *found) {
if(found == NULL || hash == NULL) {
return parser_unexpected_value;
}
*found = false;

switch (*hash)
{
// case hash_operation_Invalid:
// case hash_operation_IncreaseDissolveDelay:
// case hash_operation_StartDissolving:
// case hash_operation_StopDissolving:
// case hash_operation_AddHotKey:
// case hash_operation_RemoveHotKey:
// case hash_operation_JoinCommunityFund:
case hash_operation_SetDissolvedTimestamp:
*found = true;
break;
}

return parser_ok;
}

parser_error_t checkCandidMAGIC(parser_context_t *ctx) {
// Check DIDL magic bytes
if (ctx->bufferLen < 4) {
Expand Down Expand Up @@ -256,11 +305,8 @@ parser_error_t findCandidFieldHash(__Z_UNUSED parser_context_t *_ctx,
return parser_not_implemented;
}

parser_error_t readCandidTypeTable_Item(parser_context_t *ctx, __Z_UNUSED uint64_t typeIdx) {
int64_t ty;
CHECK_PARSER_ERR(readCandidType(ctx, &ty))

switch (ty) {
parser_error_t readCandidTypeTable_Item(parser_context_t *ctx, const int64_t *type, __Z_UNUSED uint64_t typeIdx) {
switch (*type) {
case Opt: {
zemu_log_stack("readCandidTypeTable::Opt");
CHECK_PARSER_ERR(readCandidTypeTable_Opt(ctx))
Expand Down Expand Up @@ -313,6 +359,19 @@ parser_error_t readCandidTypeTable_Item(parser_context_t *ctx, __Z_UNUSED uint64
return parser_ok;
}

parser_error_t getNextType(parser_context_t *ctx, const IDLTypes_e type, int64_t *ty, const uint64_t itemIdx) {
if(ty == NULL || ctx == NULL) {
return parser_unexpected_value;
}

CHECK_PARSER_ERR(readCandidType(ctx, ty))
if (type == *ty) {
return parser_ok;
}
CHECK_PARSER_ERR(readCandidTypeTable_Item(ctx, ty, itemIdx))
return parser_ok;
}

parser_error_t readCandidTypeTable(parser_context_t *ctx) {
ctx->tx_obj->candid_typetableSize = 0;
CHECK_PARSER_ERR(readCandidLEB128(ctx, &ctx->tx_obj->candid_typetableSize))
Expand All @@ -321,8 +380,11 @@ parser_error_t readCandidTypeTable(parser_context_t *ctx) {
return parser_value_out_of_range;
}

table_entry_point = ctx->offset;
int64_t type = 0;
for (uint64_t itemIdx = 0; itemIdx < ctx->tx_obj->candid_typetableSize; itemIdx++) {
CHECK_PARSER_ERR(readCandidTypeTable_Item(ctx, itemIdx))
CHECK_PARSER_ERR(readCandidType(ctx, &type))
CHECK_PARSER_ERR(readCandidTypeTable_Item(ctx, &type, itemIdx))
}

return parser_ok;
Expand All @@ -349,12 +411,54 @@ parser_error_t readCandidHeader(parser_context_t *ctx) {
ctx.offset = 0; \
ctx.tx_obj = __TX;


parser_error_t findHash(parser_context_t *ctx, check_hash check_function,
const uint8_t variant, uint64_t *hash) {
if(ctx == NULL || hash == NULL || check_function == NULL) {
return parser_unexpected_value;
}
ctx->offset = table_entry_point;

int64_t type = 0;
bool found = false;

for (uint64_t itemIdx = 0; itemIdx < ctx->tx_obj->candid_typetableSize; itemIdx++) {
CHECK_PARSER_ERR(getNextType(ctx, Variant, &type, itemIdx))
if (type == Variant) {
uint64_t objectLength;
CHECK_PARSER_ERR(readCandidLEB128(ctx, &objectLength))

for (uint64_t i = 0; i < objectLength; i++) {
int64_t dummyType;
CHECK_PARSER_ERR(readCandidLEB128(ctx, hash))
if (i == variant) {
CHECK_PARSER_ERR(check_function(hash, &found))
}
if(found) {
return parser_ok;
}

CHECK_PARSER_ERR(readCandidType(ctx, &dummyType))
}
}
}
return parser_type_not_found;
}

parser_error_t getHash(parser_context_t *ctx, check_hash check_function,
const uint8_t variant, uint64_t *hash) {
const uint16_t start = ctx->offset;
*hash = 0;
parser_error_t err = findHash(ctx, check_function, variant, hash);
ctx->offset = start;
return err;
}

parser_error_t readCandidManageNeuron(parser_tx_t *tx, const uint8_t *input, uint16_t inputSize) {
CREATE_CTX(ctx, tx, input, inputSize)
CHECK_PARSER_ERR(readCandidHeader(&ctx))

///
CHECK_PARSER_ERR(readAndCheckType(&ctx, 65))
CHECK_PARSER_ERR(readAndCheckType(&ctx, (tx->candid_typetableSize - 1)))
candid_ManageNeuron_t *val = &tx->tx_fields.call.data.candid_manageNeuron;

// Now read
Expand All @@ -366,13 +470,14 @@ parser_error_t readCandidManageNeuron(parser_tx_t *tx, const uint8_t *input, uin
CHECK_PARSER_ERR(readCandidByte(&ctx, &val->has_command))
if (val->has_command) {
CHECK_PARSER_ERR(readCandidNat(&ctx, &val->command.variant))
CHECK_PARSER_ERR(getHash(&ctx, check_hash_method, val->command.variant, &val->command.hash))

switch (val->command.variant) {
case command_Split: {
switch (val->command.hash) {
case hash_command_Split: {
CHECK_PARSER_ERR(readCandidNat64(&ctx, &val->command.split.amount_e8s))
break;
}
case command_Merge: {
case hash_command_Merge: {
CHECK_PARSER_ERR(readCandidByte(&ctx, &val->command.merge.has_source))
if (!val->command.merge.has_source) {
// https://github.com/Zondax/ledger-icp/issues/149
Expand All @@ -382,16 +487,18 @@ parser_error_t readCandidManageNeuron(parser_tx_t *tx, const uint8_t *input, uin
CHECK_PARSER_ERR(readCandidNat64(&ctx, &val->command.merge.source.id))
break;
}
case command_Configure: {
case hash_command_Configure: {
CHECK_PARSER_ERR(readCandidByte(&ctx, &val->command.configure.has_operation))
if (!val->command.configure.has_operation) {
return parser_unexpected_value;
}
candid_Operation_t *operation = &val->command.configure.operation;

CHECK_PARSER_ERR(readCandidWhichVariant(&ctx, &operation->which))
switch (val->command.configure.operation.which) {
case operation_SetDissolvedTimestamp: {
CHECK_PARSER_ERR(getHash(&ctx, check_hash_operation, operation->which, &operation->hash))

switch (operation->hash) {
case hash_operation_SetDissolvedTimestamp:{
CHECK_PARSER_ERR(readCandidNat64(&ctx,
&operation->setDissolveTimestamp.dissolve_timestamp_seconds))

Expand Down
44 changes: 25 additions & 19 deletions app/src/candid/candid_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,27 +53,31 @@ typedef enum {
} IDLTypes_e;

typedef enum {
command_Invalid = 0,

command_Spawn = 0,
command_Split = 1,
command_Follow = 2,
command_ClaimOrRefresh = 3,
command_Configure = 4,
command_RegisterVote = 5,
command_Merge = 6,
} command_variant_e;
hash_command_Spawn = 345247259,
hash_command_Split = 345791162,
hash_command_Follow = 774571409,
hash_command_ClaimOrRefresh = 1349619708,
hash_command_Configure = 1647237574,
hash_command_RegisterVote = 2455066893,
hash_command_Merge = 2566132376,
hash_command_DisburseToNeuron = 2803800337,
hash_command_MakeProposal = 3217030240,
hash_command_MergeMaturity = 3865893897,
hash_command_Disburse = 4121967011,
} command_variant_hash_e;

typedef enum {
operation_Invalid = 0,
operation_IncreaseDissolveDelay = 1,
operation_StartDissolving = 2,
operation_StopDissolving = 3,
operation_AddHotKey = 4,
operation_RemoveHotKey = 5,
operation_SetDissolvedTimestamp = 6,
operation_JoinCommunityFund = 7,
} operation_variant_e;
//Check these hashes
hash_operation_Invalid = 971299358,
hash_operation_IncreaseDissolveDelay = 628424947,
hash_operation_StartDissolving = 1954991536,
hash_operation_StopDissolving = 1977744848,
hash_operation_AddHotKey = 2143729936,
hash_operation_RemoveHotKey = 3248805476,
hash_operation_JoinCommunityFund = 45994902,

hash_operation_SetDissolvedTimestamp = 3913126211,
} operation_variant_hash_e;

typedef struct {
uint64_t len;
Expand All @@ -90,6 +94,7 @@ typedef struct {

typedef struct {
uint64_t which;
uint64_t hash;
union {
candid_SetDissolveTimestamp_t setDissolveTimestamp;
};
Expand All @@ -111,6 +116,7 @@ typedef struct {

typedef struct {
uint64_t variant;
uint64_t hash;
union {
candid_Split_t split;
candid_Merge_t merge;
Expand Down
2 changes: 2 additions & 0 deletions app/src/common/parser_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ typedef enum {
// Required fields
parser_required_nonce,
parser_required_method,
// Special codes
parser_type_not_found,
} parser_error_t;

typedef struct {
Expand Down
8 changes: 4 additions & 4 deletions app/src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,9 +605,9 @@ parser_error_t parser_getItemSetDissolveTimestamp(uint8_t displayIdx,
uint8_t pageIdx, uint8_t *pageCount) {

candid_ManageNeuron_t *fields = &parser_tx_obj.tx_fields.call.data.candid_manageNeuron;
PARSER_ASSERT_OR_ERROR(fields->command.variant == command_Configure, parser_unexpected_value)
PARSER_ASSERT_OR_ERROR(fields->command.hash == hash_command_Configure, parser_unexpected_value)
PARSER_ASSERT_OR_ERROR(fields->command.configure.has_operation, parser_unexpected_value)
PARSER_ASSERT_OR_ERROR(fields->command.configure.operation.which == operation_SetDissolvedTimestamp,
PARSER_ASSERT_OR_ERROR(fields->command.configure.operation.hash == hash_operation_SetDissolvedTimestamp,
parser_unexpected_value)

if (displayIdx == 0) {
Expand Down Expand Up @@ -713,7 +713,7 @@ parser_error_t parser_getItemSplit(uint8_t displayIdx,
uint8_t pageIdx, uint8_t *pageCount) {

candid_ManageNeuron_t *fields = &parser_tx_obj.tx_fields.call.data.candid_manageNeuron;
PARSER_ASSERT_OR_ERROR(fields->command.variant == command_Split, parser_unexpected_value)
PARSER_ASSERT_OR_ERROR(fields->command.hash == hash_command_Split, parser_unexpected_value)

if (displayIdx == 0) {
snprintf(outKey, outKeyLen, "Transaction type");
Expand Down Expand Up @@ -750,7 +750,7 @@ parser_error_t parser_getItemMerge(uint8_t displayIdx,
uint8_t pageIdx, uint8_t *pageCount) {

candid_ManageNeuron_t *fields = &parser_tx_obj.tx_fields.call.data.candid_manageNeuron;
PARSER_ASSERT_OR_ERROR(fields->command.variant == command_Merge, parser_unexpected_value)
PARSER_ASSERT_OR_ERROR(fields->command.hash == hash_command_Merge, parser_unexpected_value)

if (displayIdx == 0) {
snprintf(outKey, outKeyLen, "Transaction type");
Expand Down
12 changes: 6 additions & 6 deletions app/src/parser_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,19 +295,19 @@ parser_error_t getManageNeuronType(const parser_tx_t *v, manageNeuron_e *mn_type
}

const candid_Command_t *command = &v->tx_fields.call.data.candid_manageNeuron.command;
switch (command->variant) {
case command_Split:
switch (command->hash) {
case hash_command_Split:
*mn_type = Split;
return parser_ok;
case command_Merge:
case hash_command_Merge:
*mn_type = Merge;
return parser_ok;
case command_Configure: {
case hash_command_Configure: {
if (!command->configure.has_operation) {
return parser_unexpected_value;
}
switch (command->configure.operation.which) {
case operation_SetDissolvedTimestamp:
switch (command->configure.operation.hash) {
case hash_operation_SetDissolvedTimestamp:
*mn_type = Configure_SetDissolvedTimestamp;
break;
default:
Expand Down
16 changes: 16 additions & 0 deletions tests/phase2.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,5 +171,21 @@
],
"timestamp": 4102444799,
"valid": true
},
{
"index": 17,
"name": "Merge Neuron",
"blob": "d9d9f7a167636f6e74656e74a76361726759037d4449444c496c01dbb701786e006e796e686e786c03bc949d820302dbe2be950903ef9999fe09046c01b9ef938008786d006c02afa3bda10175c2cee0d80c076c006c029cb1fa2503ba89e5c204786b039ef5cc0f099992ccd0010adae1c99903786e0b6c01d7ab010c6c01f6b0989a08036c018eddc3a60d036c018dc3b2b303796c01c88ecad50a786b0896a7f7150ef381d4ab020fb09b9ba40709d0fb87af070990f29afe0710e4ac938d0c09f7aacfd80d09c3a2f6c90e116e126c01a78882820a136c02ea99cff20475b2b8d4960b016c01c38fbbd10b016c05f5bbe3900178d2bbf0d9017eb9ef93800878dbe2be950903ef9999fe09786c04efd6e4027198abec810119b6f798b201c500a696a48708716e716c02cbe4fdc70471fc91f4f805196e1a6c02dbb70101bac7a7fa0d1b6c01b99d9da50b796d7b6c01cedfa0a8041e6e1f6c01e0a9b302786e216c02a9ddf49b0720d8a38ca80d226b0b9b9cd0a40105bab5f1a40106918bacf10208fc9fc683050dc6b3bb9106148db2d592091598a5d0c7091691b2fab80a17e0f8fffd0b1889b8b3b30e1da3f3c0ad0f236e246b02cd8e8eb9041ecebee1d308006e266c03dbb70101cbe2b58b0825f1bb8b880d276c02e4d7bee905758effd6e90e1e6c02dbb701039df1afe707206e2a6c01f5bbe39001786c01a9ddf49b07206b02fdf59aec0b2ce3b586ff0c2d6e2e6c03ce9ca6ce012bf382ccb3072fb9ef938008786c02f9889a5778b2cc99e705786e316c01edbb85f901326e336c02cfbe93a40434c796cdbe0b036c01c2cee0d80c076c02007501366d376c0184aead33386e7e6d306c02f8b9b6c9043aa4ccf7dd0a3b6c089eb493cf0378befa8dd40479be8fe6e30478ce89be97067886f998bc0978c5cae3d40a7893a190e00c78f5e1d0e70d786d686c018594e2c50b3e6b02bf80e42b2ac6a6e4b90a2a6ec0006c01f0a2cabb0bc1006c0196bdb4e904716b0b93a7e09d021cd881c9c40328d69ce79d0a2982ffcfaa0c309dfa94a40d35e3c3c5990e39b1a5aea10e3cf5d9d7a50e3dfad5ddf40e3fdb9cebf70ec200d6f4c7ff0fc3006ec4006b0b9b9cd0a40105bab5f1a40106918bacf10208fc9fc683050dc6b3bb9106148db2d592091598a5d0c7091691b2fab80a17e0f8fffd0b1889b8b3b30e1da3f3c0ad0f236ec6006c03dbb70101cbe2b58b08c700f1bb8b880d2701c80001e2c738c140a0c107010601e787ac3d293afcf2006b63616e69737465725f69644a000000000000000101016e696e67726573735f6578706972791b170dabb81dddfa406b6d6574686f645f6e616d656d6d616e6167655f6e6575726f6e656e6f6e63655000000182c5975261ca758b1f999544eb6c726571756573745f747970656463616c6c6673656e646572581df1305df1b074e88adb99dc2f56f12d63208165f24dea7e60ae6cf6cf02",
"output": [
"0 | Transaction type : Merge Neuron",
"1 | Neuron ID : 17508933400112433127",
"2 | Into Neuron ID : 558904028750727138"
],
"output_expert": [
"0 | Transaction type : Merge Neuron",
"1 | Neuron ID : 17508933400112433127",
"2 | Into Neuron ID : 558904028750727138"
],
"valid": true
}
]
Binary file modified tests_zemu/snapshots/s-mainmenu/00004.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests_zemu/snapshots/s-mainmenu/00010.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests_zemu/snapshots/sp-mainmenu/00004.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests_zemu/snapshots/sp-mainmenu/00010.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests_zemu/snapshots/x-mainmenu/00004.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests_zemu/snapshots/x-mainmenu/00010.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit aa43058

Please sign in to comment.