diff --git a/src/apdu_handler.c b/src/apdu_handler.c index c07f97e6..fed16636 100644 --- a/src/apdu_handler.c +++ b/src/apdu_handler.c @@ -112,9 +112,11 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint view_review_show(REVIEW_TXN); *flags |= IO_ASYNCH_REPLY; break; - case PROCESS_CHUNK_FINISHED_NO_METADATA:; - zemu_log("Processing chunks finished, no metadata.\n"); - const char *error_msg = tx_parse(); + case PROCESS_CHUNK_FINISHED_NFT1: + case PROCESS_CHUNK_FINISHED_NFT2: + case PROCESS_CHUNK_FINISHED_NO_METADATA: + case PROCESS_CHUNK_FINISHED_WITH_METADATA:; + const char *error_msg = tx_parse(callType); if (error_msg != NULL) { int error_msg_length = strlen(error_msg); diff --git a/src/common/tx.c b/src/common/tx.c index 711f50b1..65018d9b 100644 --- a/src/common/tx.c +++ b/src/common/tx.c @@ -20,6 +20,7 @@ #include "parser_tx.h" #include #include "zxmacros.h" +#include "app_mode.h" #if defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX) #define RAM_BUFFER_SIZE 8192 @@ -74,16 +75,46 @@ uint8_t *tx_get_buffer() { return buffering_get_buffer()->data; } -const char *tx_parse() { - uint8_t err = parser_parse(&ctx_parsed_tx, tx_get_buffer(), tx_get_buffer_length()); +const char *tx_parse(process_chunk_response_t typeOfCall) { + script_parsed_type_t scriptType = + (typeOfCall == PROCESS_CHUNK_FINISHED_NFT1) ? SCRIPT_TYPE_NFT_SETUP_COLLECTION + : (typeOfCall == PROCESS_CHUNK_FINISHED_NFT2) ? SCRIPT_TYPE_NFT_TRANSFER + : SCRIPT_TYPE_UNKNOWN; + // parse tx + uint8_t err = parser_parse(&ctx_parsed_tx, tx_get_buffer(), tx_get_buffer_length(), scriptType); if (err != PARSER_OK) { return parser_getErrorDescription(err); } - err = parser_validate(&ctx_parsed_tx); + // parse metadata + parser_tx_obj.metadataInitialized = false; + switch (typeOfCall) { + case PROCESS_CHUNK_FINISHED_WITH_METADATA: + MEMZERO(&parser_tx_obj.metadata, sizeof(parser_tx_obj.metadata)); + err = parseTxMetadata(parser_tx_obj.hash.digest, &parser_tx_obj.metadata); + if (err != PARSER_OK) { + return parser_getErrorDescription(err); + } + parser_tx_obj.metadataInitialized = true; + break; + case PROCESS_CHUNK_FINISHED_NFT1: + case PROCESS_CHUNK_FINISHED_NFT2: + break; // we do not need metadata for these scripts + case PROCESS_CHUNK_FINISHED_NO_METADATA: + if (!app_mode_expert()) { // we do not need metadata for these scripts, but this + // workflow should work only in expert mode + return parser_getErrorDescription(PARSER_UNEXPECTED_SCRIPT); + } + break; + default: + return parser_getErrorDescription(PARSER_UNEXPECTED_ERROR); + } + CHECK_APP_CANARY() + // validate + err = parser_validate(&ctx_parsed_tx); if (err != PARSER_OK) { return parser_getErrorDescription(err); } diff --git a/src/common/tx.h b/src/common/tx.h index 4708a366..f3530bff 100644 --- a/src/common/tx.h +++ b/src/common/tx.h @@ -18,6 +18,7 @@ #include "os.h" #include "coin.h" #include "zxerror.h" +#include "app_helper.h" void tx_initialize(); @@ -50,7 +51,7 @@ uint8_t *get_signable(); /// Parse message stored in transaction buffer /// This function should be called as soon as full buffer data is loaded. /// \return It returns NULL if data is valid or error message otherwise. -const char *tx_parse(); +const char *tx_parse(process_chunk_response_t typeOfCall); /// Release zbuffer memory void tx_parse_reset(); diff --git a/src/crypto.c b/src/crypto.c index a6659378..083f6775 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -26,7 +26,7 @@ #include "cx.h" __Z_INLINE digest_type_e get_hash_type(const uint16_t options) { - const uint8_t hash_type = (uint8_t)(options & 0xFF); + const uint8_t hash_type = (uint8_t) (options & 0xFF); switch (hash_type) { case 0x01: zemu_log_stack("path: sha2_256"); @@ -41,7 +41,7 @@ __Z_INLINE digest_type_e get_hash_type(const uint16_t options) { } __Z_INLINE cx_curve_t get_cx_curve(const uint16_t options) { - const uint8_t curve_code = (uint8_t)((options >> 8) & 0xFF); + const uint8_t curve_code = (uint8_t) ((options >> 8) & 0xFF); switch (curve_code) { case 0x02: { zemu_log_stack("curve: secp256r1"); diff --git a/src/parser_impl.c b/src/parser_impl.c index c09460ae..cbd41832 100644 --- a/src/parser_impl.c +++ b/src/parser_impl.c @@ -78,6 +78,18 @@ const char *parser_getErrorDescription(parser_error_t err) { return "parser_rlp_error_buffer_too_small"; case PARSER_RLP_ERROR_INVALID_PAGE: return "parser_rlp_error_invalid_page"; + case PARSER_JSON_INVALID: + return "parser_json_invalid"; + case PARSER_JSON_INVALID_TOKEN_IDX: + return "parser_json_invalid_token_idx"; + case PARSER_JSON_TOO_MANY_TOKENS: + return "parser_json_too_many_tokens"; + case PARSER_JSON_INCOMPLETE_JSON: + return "parser_json_incomplete_json"; + case PARSER_JSON_UNEXPECTED_ERROR: + return "parser_json_unex[ected_error"; + case PARSER_JSON_ZERO_TOKENS: + return "parser_json_zero_tokens"; case PARSER_UNEXPECTED_TX_VERSION: return "tx version is not supported"; case PARSER_UNEXPECTED_TYPE: @@ -112,6 +124,12 @@ const char *parser_getErrorDescription(parser_error_t err) { return "Required field nonce"; case PARSER_REQUIRED_METHOD: return "Required field method"; + case PARSER_METADATA_TOO_MANY_HASHES: + return "Metadata too many hashes"; + case PARSER_METADATA_ERROR: + return "Metadata unknown error"; + case PARSER_TOO_MANY_ARGUMENTS: + return "Too many arguments"; default: return "Unrecognized error code"; } @@ -127,7 +145,7 @@ __Z_INLINE char hexDigit(uint8_t v) { return '?'; } -parser_error_t json_validateToken(parsed_json_t *parsedJson, uint16_t tokenIdx) { +parser_error_t json_validateToken(const parsed_json_t *parsedJson, uint16_t tokenIdx) { if (!parsedJson->isValid) { return PARSER_JSON_INVALID; } @@ -150,7 +168,7 @@ parser_error_t json_validateToken(parsed_json_t *parsedJson, uint16_t tokenIdx) parser_error_t json_extractToken(char *outVal, uint16_t outValLen, - parsed_json_t *parsedJson, + const parsed_json_t *parsedJson, uint16_t tokenIdx) { MEMZERO(outVal, outValLen); CHECK_PARSER_ERR(json_validateToken(parsedJson, tokenIdx)) @@ -164,7 +182,9 @@ parser_error_t json_extractToken(char *outVal, return PARSER_OK; } -parser_error_t json_matchToken(parsed_json_t *parsedJson, uint16_t tokenIdx, char *expectedValue) { +parser_error_t json_matchToken(const parsed_json_t *parsedJson, + uint16_t tokenIdx, + const char *expectedValue) { CHECK_PARSER_ERR(json_validateToken(parsedJson, tokenIdx)) const jsmntok_t token = parsedJson->tokens[tokenIdx]; @@ -172,7 +192,7 @@ parser_error_t json_matchToken(parsed_json_t *parsedJson, uint16_t tokenIdx, cha return PARSER_UNEXPECTED_TYPE; } - if (token.end < token.start || strlen(expectedValue) != (size_t)(token.end - token.start)) { + if (token.end < token.start || strlen(expectedValue) != (size_t) (token.end - token.start)) { return PARSER_UNEXPECTED_VALUE; } @@ -183,7 +203,7 @@ parser_error_t json_matchToken(parsed_json_t *parsedJson, uint16_t tokenIdx, cha return PARSER_OK; } -parser_error_t json_matchNull(parsed_json_t *parsedJson, uint16_t tokenIdx) { +parser_error_t json_matchNull(const parsed_json_t *parsedJson, uint16_t tokenIdx) { CHECK_PARSER_ERR(json_validateToken(parsedJson, tokenIdx)) const jsmntok_t token = parsedJson->tokens[tokenIdx]; @@ -191,7 +211,7 @@ parser_error_t json_matchNull(parsed_json_t *parsedJson, uint16_t tokenIdx) { return PARSER_UNEXPECTED_TYPE; } - if (token.end < token.start || 4 != (size_t)(token.end - token.start)) { + if (token.end < token.start || 4 != (size_t) (token.end - token.start)) { return PARSER_UNEXPECTED_VALUE; } @@ -202,9 +222,9 @@ parser_error_t json_matchNull(parsed_json_t *parsedJson, uint16_t tokenIdx) { return PARSER_OK; } -parser_error_t json_matchKeyValue(parsed_json_t *parsedJson, +parser_error_t json_matchKeyValue(const parsed_json_t *parsedJson, uint16_t tokenIdx, - char *expectedType, + const char *expectedType, jsmntype_t jsonType, uint16_t *valueTokenIdx) { CHECK_PARSER_ERR(json_validateToken(parsedJson, tokenIdx)) @@ -236,9 +256,9 @@ parser_error_t json_matchKeyValue(parsed_json_t *parsedJson, } // valueTokenIdx is JSON_MATCH_VALUE_IDX_NONE if the optional is null -parser_error_t json_matchOptionalKeyValue(parsed_json_t *parsedJson, +parser_error_t json_matchOptionalKeyValue(const parsed_json_t *parsedJson, uint16_t tokenIdx, - char *expectedType, + const char *expectedType, jsmntype_t jsonType, uint16_t *valueTokenIdx) { CHECK_PARSER_ERR(json_validateToken(parsedJson, tokenIdx)) @@ -274,7 +294,7 @@ parser_error_t json_matchOptionalKeyValue(parsed_json_t *parsedJson, } // valueTokenIdx is JSON_MATCH_VALUE_IDX_NONE if the optional is null -parser_error_t json_matchOptionalArray(parsed_json_t *parsedJson, +parser_error_t json_matchOptionalArray(const parsed_json_t *parsedJson, uint16_t tokenIdx, uint16_t *valueTokenIdx) { CHECK_PARSER_ERR(json_validateToken(parsedJson, tokenIdx)) @@ -317,6 +337,40 @@ parser_error_t json_matchOptionalArray(parsed_json_t *parsedJson, return PARSER_UNEXPECTED_VALUE; } +parser_error_t json_matchArbitraryKeyValue(const parsed_json_t *parsedJson, + uint16_t tokenIdx, + jsmntype_t *valueJsonType, + uint16_t *keyTokenIdx, + uint16_t *valueTokenIdx) { + CHECK_PARSER_ERR(json_validateToken(parsedJson, tokenIdx)) + + if (!(tokenIdx + 4 < parsedJson->numberOfTokens)) { + // we need this token and 4 more + return PARSER_JSON_INVALID_TOKEN_IDX; + } + + if (parsedJson->tokens[tokenIdx].type != JSMN_OBJECT) { + return PARSER_UNEXPECTED_TYPE; + } + + if (parsedJson->tokens[tokenIdx].size != 2) { + return PARSER_UNEXPECTED_NUMBER_ITEMS; + } + + // Type key/value + CHECK_PARSER_ERR(json_matchToken(parsedJson, tokenIdx + 1, (char *) "type")) + if (parsedJson->tokens[tokenIdx + 2].type != JSMN_STRING) { + return PARSER_UNEXPECTED_TYPE; + } + CHECK_PARSER_ERR(json_matchToken(parsedJson, tokenIdx + 3, (char *) "value")) + + *keyTokenIdx = tokenIdx + 2; + *valueJsonType = parsedJson->tokens[tokenIdx + 4].type; + *valueTokenIdx = tokenIdx + 4; + + return PARSER_OK; +} + parser_error_t formatStrUInt8AsHex(const char *decStr, char *hexStr) { uint16_t decLen = strnlen(decStr, 5); if (decLen > 3 || decLen == 0) { @@ -339,227 +393,39 @@ parser_error_t formatStrUInt8AsHex(const char *decStr, char *hexStr) { return PARSER_OK; } -parser_error_t json_extractString(char *outVal, - uint16_t outValLen, - parsed_json_t *parsedJson, - uint16_t tokenIdx) { - MEMZERO(outVal, outValLen); - - uint16_t internalTokenElemIdx; - CHECK_PARSER_ERR(json_matchKeyValue(parsedJson, - tokenIdx, - (char *) "String", - JSMN_STRING, - &internalTokenElemIdx)) - - CHECK_PARSER_ERR(json_extractToken(outVal, outValLen, parsedJson, internalTokenElemIdx)) - - return PARSER_OK; -} - -parser_error_t _matchScriptType(uint8_t scriptHash[32], script_type_e *scriptType) { - *scriptType = SCRIPT_UNKNOWN; - - char buffer[100]; - MEMZERO(buffer, sizeof(buffer)); - - // Check it is a known script digest - if (array_to_hexstr(buffer, sizeof(buffer), scriptHash, CX_SHA256_SIZE) != 64) { - return PARSER_UNEXPECTED_ERROR; - } - - struct known_script_entry { - script_type_e script_type; - const char *template; - }; - - const struct known_script_entry KNOWN_TYPES[] = { - {SCRIPT_TOKEN_TRANSFER, TEMPLATE_HASH_TOKEN_TRANSFER_EMULATOR}, - {SCRIPT_TOKEN_TRANSFER, TEMPLATE_HASH_TOKEN_TRANSFER_TESTNET}, - {SCRIPT_TOKEN_TRANSFER, TEMPLATE_HASH_TOKEN_TRANSFER_MAINNET}, - - {SCRIPT_CREATE_ACCOUNT, TEMPLATE_HASH_CREATE_ACCOUNT}, - - {SCRIPT_ADD_NEW_KEY, TEMPLATE_HASH_ADD_NEW_KEY}, - - {SCRIPT_TH01_WITHDRAW_UNLOCKED_TOKENS, TEMPLATE_HASH_TH01_WITHDRAW_UNLOCKED_TOKENS_TESTNET}, - {SCRIPT_TH01_WITHDRAW_UNLOCKED_TOKENS, TEMPLATE_HASH_TH01_WITHDRAW_UNLOCKED_TOKENS_MAINNET}, - - {SCRIPT_TH02_DEPOSIT_UNLOCKED_TOKENS, TEMPLATE_HASH_TH02_DEPOSIT_UNLOCKED_TOKENS_TESTNET}, - {SCRIPT_TH02_DEPOSIT_UNLOCKED_TOKENS, TEMPLATE_HASH_TH02_DEPOSIT_UNLOCKED_TOKENS_MAINNET}, - - {SCRIPT_TH06_REGISTER_NODE, TEMPLATE_HASH_TH06_REGISTER_NODE_TESTNET}, - {SCRIPT_TH06_REGISTER_NODE, TEMPLATE_HASH_TH06_REGISTER_NODE_MAINNET}, - - {SCRIPT_TH08_STAKE_NEW_TOKENS, TEMPLATE_HASH_TH08_STAKE_NEW_TOKENS_TESTNET}, - {SCRIPT_TH08_STAKE_NEW_TOKENS, TEMPLATE_HASH_TH08_STAKE_NEW_TOKENS_MAINNET}, - - {SCRIPT_TH09_RESTAKE_UNSTAKED_TOKENS, TEMPLATE_HASH_TH09_RESTAKE_UNSTAKED_TOKENS_TESTNET}, - {SCRIPT_TH09_RESTAKE_UNSTAKED_TOKENS, TEMPLATE_HASH_TH09_RESTAKE_UNSTAKED_TOKENS_MAINNET}, - - {SCRIPT_TH10_RESTAKE_REWARDED_TOKENS, TEMPLATE_HASH_TH10_RESTAKE_REWARDED_TOKENS_TESTNET}, - {SCRIPT_TH10_RESTAKE_REWARDED_TOKENS, TEMPLATE_HASH_TH10_RESTAKE_REWARDED_TOKENS_MAINNET}, - - {SCRIPT_TH11_UNSTAKE_TOKENS, TEMPLATE_HASH_TH11_UNSTAKE_TOKENS_TESTNET}, - {SCRIPT_TH11_UNSTAKE_TOKENS, TEMPLATE_HASH_TH11_UNSTAKE_TOKENS_MAINNET}, - - {SCRIPT_TH12_UNSTAKE_ALL_TOKENS, TEMPLATE_HASH_TH12_UNSTAKE_ALL_TOKENS_TESTNET}, - {SCRIPT_TH12_UNSTAKE_ALL_TOKENS, TEMPLATE_HASH_TH12_UNSTAKE_ALL_TOKENS_MAINNET}, - - {SCRIPT_TH13_WITHDRAW_UNSTAKED_TOKENS, TEMPLATE_HASH_TH13_WITHDRAW_UNSTAKED_TOKENS_TESTNET}, - {SCRIPT_TH13_WITHDRAW_UNSTAKED_TOKENS, TEMPLATE_HASH_TH13_WITHDRAW_UNSTAKED_TOKENS_MAINNET}, - - {SCRIPT_TH14_WITHDRAW_REWARDED_TOKENS, TEMPLATE_HASH_TH14_WITHDRAW_REWARDED_TOKENS_TESTNET}, - {SCRIPT_TH14_WITHDRAW_REWARDED_TOKENS, TEMPLATE_HASH_TH14_WITHDRAW_REWARDED_TOKENS_MAINNET}, - - {SCRIPT_TH16_REGISTER_OPERATOR_NODE, TEMPLATE_HASH_TH16_REGISTER_OPERATOR_NODE_TESTNET}, - {SCRIPT_TH16_REGISTER_OPERATOR_NODE, TEMPLATE_HASH_TH16_REGISTER_OPERATOR_NODE_MAINNET}, - - {SCRIPT_TH17_REGISTER_DELEGATOR, TEMPLATE_HASH_TH17_REGISTER_DELEGATOR_TESTNET}, - {SCRIPT_TH17_REGISTER_DELEGATOR, TEMPLATE_HASH_TH17_REGISTER_DELEGATOR_MAINNET}, - - {SCRIPT_TH19_DELEGATE_NEW_TOKENS, TEMPLATE_HASH_TH19_DELEGATE_NEW_TOKENS_TESTNET}, - {SCRIPT_TH19_DELEGATE_NEW_TOKENS, TEMPLATE_HASH_TH19_DELEGATE_NEW_TOKENS_MAINNET}, - - {SCRIPT_TH20_RESTAKE_UNSTAKED_DELEGATED_TOKENS, - TEMPLATE_HASH_TH20_RESTAKE_UNSTAKED_DELEGATED_TOKENS_TESTNET}, - {SCRIPT_TH20_RESTAKE_UNSTAKED_DELEGATED_TOKENS, - TEMPLATE_HASH_TH20_RESTAKE_UNSTAKED_DELEGATED_TOKENS_MAINNET}, - - {SCRIPT_TH21_RESTAKE_REWARDED_DELEGATED_TOKENS, - TEMPLATE_HASH_TH21_RESTAKE_REWARDED_DELEGATED_TOKENS_TESTNET}, - {SCRIPT_TH21_RESTAKE_REWARDED_DELEGATED_TOKENS, - TEMPLATE_HASH_TH21_RESTAKE_REWARDED_DELEGATED_TOKENS_MAINNET}, - - {SCRIPT_TH22_UNSTAKE_DELEGATED_TOKENS, TEMPLATE_HASH_TH22_UNSTAKE_DELEGATED_TOKENS_TESTNET}, - {SCRIPT_TH22_UNSTAKE_DELEGATED_TOKENS, TEMPLATE_HASH_TH22_UNSTAKE_DELEGATED_TOKENS_MAINNET}, - - {SCRIPT_TH23_WITHDRAW_UNSTAKED_DELEGATED_TOKENS, - TEMPLATE_HASH_TH23_WITHDRAW_UNSTAKED_DELEGATED_TOKENS_TESTNET}, - {SCRIPT_TH23_WITHDRAW_UNSTAKED_DELEGATED_TOKENS, - TEMPLATE_HASH_TH23_WITHDRAW_UNSTAKED_DELEGATED_TOKENS_MAINNET}, - - {SCRIPT_TH24_WITHDRAW_REWARDED_DELEGATED_TOKENS, - TEMPLATE_HASH_TH24_WITHDRAW_REWARDED_DELEGATED_TOKENS_TESTNET}, - {SCRIPT_TH24_WITHDRAW_REWARDED_DELEGATED_TOKENS, - TEMPLATE_HASH_TH24_WITHDRAW_REWARDED_DELEGATED_TOKENS_MAINNET}, - - {SCRIPT_TH25_UPDATE_NETWORKING_ADDRESS, - TEMPLATE_HASH_TH25_UPDATE_NETWORKING_ADDRESS_TESTNET}, - {SCRIPT_TH25_UPDATE_NETWORKING_ADDRESS, - TEMPLATE_HASH_TH25_UPDATE_NETWORKING_ADDRESS_MAINNET}, - - {SCRIPT_SCO01_SETUP_STAKING_COLLECTION, - TEMPLATE_HASH_SCO01_SETUP_STAKING_COLLECTION_TESTNET}, - {SCRIPT_SCO01_SETUP_STAKING_COLLECTION, - TEMPLATE_HASH_SCO01_SETUP_STAKING_COLLECTION_MAINNET}, - - {SCRIPT_SCO02_REGISTER_DELEGATOR, TEMPLATE_HASH_SCO02_REGISTER_DELEGATOR_TESTNET}, - {SCRIPT_SCO02_REGISTER_DELEGATOR, TEMPLATE_HASH_SCO02_REGISTER_DELEGATOR_MAINNET}, - - {SCRIPT_SCO03_REGISTER_NODE, TEMPLATE_HASH_SCO0301_REGISTER_NODE_TESTNET}, - {SCRIPT_SCO03_REGISTER_NODE, TEMPLATE_HASH_SCO0301_REGISTER_NODE_MAINNET}, - - {SCRIPT_SCO04_CREATE_MACHINE_ACCOUNT, TEMPLATE_HASH_SCO0401_CREATE_MACHINE_ACCOUNT_TESTNET}, - {SCRIPT_SCO04_CREATE_MACHINE_ACCOUNT, TEMPLATE_HASH_SCO0401_CREATE_MACHINE_ACCOUNT_MAINNET}, - - {SCRIPT_SCO05_REQUEST_UNSTAKING, TEMPLATE_HASH_SCO05_REQUEST_UNSTAKING_TESTNET}, - {SCRIPT_SCO05_REQUEST_UNSTAKING, TEMPLATE_HASH_SCO05_REQUEST_UNSTAKING_MAINNET}, - - {SCRIPT_SCO06_STAKE_NEW_TOKENS, TEMPLATE_HASH_SCO06_STAKE_NEW_TOKENS_TESTNET}, - {SCRIPT_SCO06_STAKE_NEW_TOKENS, TEMPLATE_HASH_SCO06_STAKE_NEW_TOKENS_MAINNET}, - - {SCRIPT_SCO07_STAKE_REWARD_TOKENS, TEMPLATE_HASH_SCO07_STAKE_REWARD_TOKENS_TESTNET}, - {SCRIPT_SCO07_STAKE_REWARD_TOKENS, TEMPLATE_HASH_SCO07_STAKE_REWARD_TOKENS_MAINNET}, - - {SCRIPT_SCO08_STAKE_UNSTAKED_TOKENS, TEMPLATE_HASH_SCO08_STAKE_UNSTAKED_TOKENS_TESTNET}, - {SCRIPT_SCO08_STAKE_UNSTAKED_TOKENS, TEMPLATE_HASH_SCO08_STAKE_UNSTAKED_TOKENS_MAINNET}, - - {SCRIPT_SCO09_UNSTAKE_ALL, TEMPLATE_HASH_SCO09_UNSTAKE_ALL_TESTNET}, - {SCRIPT_SCO09_UNSTAKE_ALL, TEMPLATE_HASH_SCO09_UNSTAKE_ALL_MAINNET}, - - {SCRIPT_SCO10_WITHDRAW_REWARD_TOKENS, TEMPLATE_HASH_SCO10_WITHDRAW_REWARD_TOKENS_TESTNET}, - {SCRIPT_SCO10_WITHDRAW_REWARD_TOKENS, TEMPLATE_HASH_SCO10_WITHDRAW_REWARD_TOKENS_MAINNET}, - - {SCRIPT_SCO11_WITHDRAW_UNSTAKED_TOKENS, - TEMPLATE_HASH_SCO11_WITHDRAW_UNSTAKED_TOKENS_TESTNET}, - {SCRIPT_SCO11_WITHDRAW_UNSTAKED_TOKENS, - TEMPLATE_HASH_SCO11_WITHDRAW_UNSTAKED_TOKENS_MAINNET}, - - {SCRIPT_SCO12_CLOSE_STAKE, TEMPLATE_HASH_SCO12_CLOSE_STAKE_TESTNET}, - {SCRIPT_SCO12_CLOSE_STAKE, TEMPLATE_HASH_SCO12_CLOSE_STAKE_MAINNET}, - - {SCRIPT_SCO13_TRANSFER_NODE, TEMPLATE_HASH_SCO13_TRANSFER_NODE_TESTNET}, - {SCRIPT_SCO13_TRANSFER_NODE, TEMPLATE_HASH_SCO13_TRANSFER_NODE_MAINNET}, - - {SCRIPT_SCO14_TRANSFER_DELEGATOR, TEMPLATE_HASH_SCO14_TRANSFER_DELEGATOR_TESTNET}, - {SCRIPT_SCO14_TRANSFER_DELEGATOR, TEMPLATE_HASH_SCO14_TRANSFER_DELEGATOR_MAINNET}, - - {SCRIPT_SCO15_WITHDRAW_FROM_MACHINE_ACCOUNT, - TEMPLATE_HASH_SCO15_WITHDRAW_FROM_MACHINE_ACCOUNT_TESTNET}, - {SCRIPT_SCO15_WITHDRAW_FROM_MACHINE_ACCOUNT, - TEMPLATE_HASH_SCO15_WITHDRAW_FROM_MACHINE_ACCOUNT_MAINNET}, - - {SCRIPT_SCO16_UPDATE_NETWORKING_ADDRESS, - TEMPLATE_HASH_SCO16_UPDATE_NETWORKING_ADDRESS_TESTNET}, - {SCRIPT_SCO16_UPDATE_NETWORKING_ADDRESS, - TEMPLATE_HASH_SCO16_UPDATE_NETWORKING_ADDRESS_MAINNET}, - - {SCRIPT_FUSD01_SETUP_FUSD_VAULT, TEMPLATE_HASH_FUSD01_SETUP_FUSD_VAULT_TESTNET}, - {SCRIPT_FUSD01_SETUP_FUSD_VAULT, TEMPLATE_HASH_FUSD01_SETUP_FUSD_VAULT_MAINNET}, - - {SCRIPT_FUSD02_TRANSFER_FUSD, TEMPLATE_HASH_FUSD02_TRANSFER_FUSD_TESTNET}, - {SCRIPT_FUSD02_TRANSFER_FUSD, TEMPLATE_HASH_FUSD02_TRANSFER_FUSD_MAINNET}, - - {SCRIPT_TS01_SET_UP_TOPSHOT_COLLECTION, - TEMPLATE_HASH_TS01_SET_UP_TOPSHOT_COLLECTION_TESTNET}, - {SCRIPT_TS01_SET_UP_TOPSHOT_COLLECTION, - TEMPLATE_HASH_TS01_SET_UP_TOPSHOT_COLLECTION_MAINNET}, - - {SCRIPT_TS02_TRANSFER_TOP_SHOT_MOMENT, TEMPLATE_HASH_TS02_TRANSFER_TOP_SHOT_MOMENT_TESTNET}, - {SCRIPT_TS02_TRANSFER_TOP_SHOT_MOMENT, TEMPLATE_HASH_TS02_TRANSFER_TOP_SHOT_MOMENT_MAINNET}, - - {SCRIPT_USDC01_SETUP_USDC_VAULT, TEMPLATE_HASH_USDC01_SETUP_USDC_VAULT_TESTNET}, - {SCRIPT_USDC01_SETUP_USDC_VAULT, TEMPLATE_HASH_USDC01_SETUP_USDC_VAULT_MAINNET}, - - {SCRIPT_USDC02_TRANSFER_USDC, TEMPLATE_HASH_USDC02_TRANSFER_USDC_TESTNET}, - {SCRIPT_USDC02_TRANSFER_USDC, TEMPLATE_HASH_USDC02_TRANSFER_USDC_MAINNET}, - - {SCRIPT_SCO03_REGISTER_NODE, TEMPLATE_HASH_SCO0302_REGISTER_NODE_TESTNET}, - {SCRIPT_SCO03_REGISTER_NODE, TEMPLATE_HASH_SCO0302_REGISTER_NODE_MAINNET}, - - {SCRIPT_SCO04_CREATE_MACHINE_ACCOUNT, TEMPLATE_HASH_SCO0402_CREATE_MACHINE_ACCOUNT_TESTNET}, - {SCRIPT_SCO04_CREATE_MACHINE_ACCOUNT, TEMPLATE_HASH_SCO0402_CREATE_MACHINE_ACCOUNT_MAINNET}, - - // sentinel, do not remove - {0, NULL}}; - - int i = 0; - while (KNOWN_TYPES[i].template) { - if (MEMCMP((char *) (PIC(KNOWN_TYPES[i].template)), buffer, 64) == 0) { - *scriptType = KNOWN_TYPES[i].script_type; - return PARSER_OK; - } - i++; - } - - return PARSER_UNEXPECTED_SCRIPT; -} - -parser_error_t _readScript(parser_context_t *c, flow_script_t *v) { +parser_error_t _readScript(parser_context_t *c, + flow_script_hash_t *s, + script_parsed_elements_t *e, + script_parsed_type_t scriptType) { rlp_kind_e kind; + parser_context_t script; uint32_t bytesConsumed; - MEMZERO(v, sizeof(flow_script_t)); - - CHECK_PARSER_ERR(rlp_decode(c, &v->ctx, &kind, &bytesConsumed)); + CHECK_PARSER_ERR(rlp_decode(c, &script, &kind, &bytesConsumed)); CTX_CHECK_AND_ADVANCE(c, bytesConsumed) CHECK_KIND(kind, RLP_KIND_STRING) - MEMZERO(v->digest, sizeof(v->digest)); - sha256(v->ctx.buffer, v->ctx.bufferLen, v->digest); + MEMZERO(s->digest, sizeof(s->digest)); + sha256(script.buffer, script.bufferLen, s->digest); - CHECK_PARSER_ERR(_matchScriptType(v->digest, &v->type)) + MEMZERO(e, sizeof(*e)); + e->script_type = SCRIPT_TYPE_UNKNOWN; + switch (scriptType) { + case SCRIPT_TYPE_NFT_SETUP_COLLECTION: + if (!parseNFT1(e, script.buffer, script.bufferLen)) { + return PARSER_UNEXPECTED_SCRIPT; + } + break; + case SCRIPT_TYPE_NFT_TRANSFER: + if (!parseNFT2(e, script.buffer, script.bufferLen)) { + return PARSER_UNEXPECTED_SCRIPT; + } + break; + case SCRIPT_TYPE_UNKNOWN: + break; + default: + return PARSER_UNEXPECTED_ERROR; + } return PARSER_OK; } @@ -713,7 +579,7 @@ parser_error_t _readProposalAuthorizers(parser_context_t *c, flow_proposal_autho return PARSER_OK; } -parser_error_t _read(parser_context_t *c, parser_tx_t *v) { +parser_error_t _read(parser_context_t *c, parser_tx_t *v, script_parsed_type_t scriptType) { rlp_kind_e kind; uint32_t bytesConsumed; @@ -735,7 +601,7 @@ parser_error_t _read(parser_context_t *c, parser_tx_t *v) { CHECK_KIND(kind, RLP_KIND_LIST) // Go through the inner list - CHECK_PARSER_ERR(_readScript(&ctx_rootInnerList, &v->script)) + CHECK_PARSER_ERR(_readScript(&ctx_rootInnerList, &v->hash, &v->parsedScript, scriptType)) CHECK_PARSER_ERR(_readArguments(&ctx_rootInnerList, &v->arguments)) CHECK_PARSER_ERR(_readReferenceBlockId(&ctx_rootInnerList, &v->referenceBlockId)) CHECK_PARSER_ERR(_readGasLimit(&ctx_rootInnerList, &v->gasLimit)) @@ -764,6 +630,7 @@ parser_error_t _validateTx(__Z_UNUSED const parser_context_t *c, __Z_UNUSED cons parser_error_t _countArgumentItems(const flow_argument_list_t *v, uint8_t argumentIndex, + uint8_t min_number_of_items, uint8_t max_number_of_items, uint8_t *number_of_items) { *number_of_items = 0; @@ -783,7 +650,7 @@ parser_error_t _countArgumentItems(const flow_argument_list_t *v, uint16_t arrayTokenCount; CHECK_PARSER_ERR( array_get_element_count(&parsedJson, internalTokenElementIdx, &arrayTokenCount)); - if (arrayTokenCount > max_number_of_items) { + if (arrayTokenCount < min_number_of_items || arrayTokenCount > max_number_of_items) { return PARSER_UNEXPECTED_NUMBER_ITEMS; } @@ -791,9 +658,10 @@ parser_error_t _countArgumentItems(const flow_argument_list_t *v, return PARSER_OK; } -// if Optional is null, number_of_items is set to 1 as one screen is needed to display "None" +// if Optional is null, number_of_items is set to 1 as one screen is needed to dispay "None" parser_error_t _countArgumentOptionalItems(const flow_argument_list_t *v, uint8_t argumentIndex, + uint8_t min_number_of_items, uint8_t max_number_of_items, uint8_t *number_of_items) { *number_of_items = 0; @@ -817,7 +685,7 @@ parser_error_t _countArgumentOptionalItems(const flow_argument_list_t *v, uint16_t arrayTokenCount; CHECK_PARSER_ERR( array_get_element_count(&parsedJson, internalTokenElementIdx, &arrayTokenCount)); - if (arrayTokenCount > max_number_of_items) { + if (arrayTokenCount < min_number_of_items || arrayTokenCount > max_number_of_items) { return PARSER_UNEXPECTED_NUMBER_ITEMS; } @@ -825,169 +693,10 @@ parser_error_t _countArgumentOptionalItems(const flow_argument_list_t *v, return PARSER_OK; } -parser_error_t _getNumItems(__Z_UNUSED const parser_context_t *c, - const parser_tx_t *v, - uint8_t *numItems) { - uint8_t argArrayLength = 0; - - uint8_t show_address_yes = - (show_address == SHOW_ADDRESS_YES || show_address == SHOW_ADDRESS_YES_HASH_MISMATCH); - uint8_t extraItems = v->authorizers.authorizer_count; - extraItems += (show_address_yes && !addressUsedInTx) ? 1 : 0; - extraItems += (show_address == SHOW_ADDRESS_YES_HASH_MISMATCH) ? 1 : 0; - extraItems += show_address_yes ? 0 : 1; - extraItems += app_mode_expert() ? 1 : 0; - - switch (v->script.type) { - case SCRIPT_TOKEN_TRANSFER: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_CREATE_ACCOUNT: - // array length is checked while we are parsing it - CHECK_PARSER_ERR(_countArgumentItems(&v->arguments, 0, UINT8_MAX, &argArrayLength)) - *numItems = 8 + argArrayLength + extraItems; - return PARSER_OK; - case SCRIPT_ADD_NEW_KEY: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH01_WITHDRAW_UNLOCKED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH02_DEPOSIT_UNLOCKED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH06_REGISTER_NODE: - *numItems = 14 + extraItems; - return PARSER_OK; - case SCRIPT_TH08_STAKE_NEW_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH09_RESTAKE_UNSTAKED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH10_RESTAKE_REWARDED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH11_UNSTAKE_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH12_UNSTAKE_ALL_TOKENS: - *numItems = 8 + extraItems; - return PARSER_OK; - case SCRIPT_TH13_WITHDRAW_UNSTAKED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH14_WITHDRAW_REWARDED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH16_REGISTER_OPERATOR_NODE: - *numItems = 11 + extraItems; - return PARSER_OK; - case SCRIPT_TH17_REGISTER_DELEGATOR: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_TH19_DELEGATE_NEW_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH20_RESTAKE_UNSTAKED_DELEGATED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH21_RESTAKE_REWARDED_DELEGATED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH22_UNSTAKE_DELEGATED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH23_WITHDRAW_UNSTAKED_DELEGATED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH24_WITHDRAW_REWARDED_DELEGATED_TOKENS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_TH25_UPDATE_NETWORKING_ADDRESS: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_SCO01_SETUP_STAKING_COLLECTION: - *numItems = 8 + extraItems; - return PARSER_OK; - case SCRIPT_SCO02_REGISTER_DELEGATOR: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_SCO03_REGISTER_NODE: - // array length is checked while we are parsing it - CHECK_PARSER_ERR( - _countArgumentOptionalItems(&v->arguments, 6, UINT8_MAX, &argArrayLength)); - *numItems = 14 + argArrayLength + extraItems; - return PARSER_OK; - case SCRIPT_SCO04_CREATE_MACHINE_ACCOUNT: - // array length is checked while we are parsing it - CHECK_PARSER_ERR(_countArgumentItems(&v->arguments, 1, UINT8_MAX, &argArrayLength)) - *numItems = 9 + argArrayLength + extraItems; - return PARSER_OK; - case SCRIPT_SCO05_REQUEST_UNSTAKING: - *numItems = 11 + extraItems; - return PARSER_OK; - case SCRIPT_SCO06_STAKE_NEW_TOKENS: - *numItems = 11 + extraItems; - return PARSER_OK; - case SCRIPT_SCO07_STAKE_REWARD_TOKENS: - *numItems = 11 + extraItems; - return PARSER_OK; - case SCRIPT_SCO08_STAKE_UNSTAKED_TOKENS: - *numItems = 11 + extraItems; - return PARSER_OK; - case SCRIPT_SCO09_UNSTAKE_ALL: - *numItems = 9 + extraItems; - return PARSER_OK; - case SCRIPT_SCO10_WITHDRAW_REWARD_TOKENS: - *numItems = 11 + extraItems; - return PARSER_OK; - case SCRIPT_SCO11_WITHDRAW_UNSTAKED_TOKENS: - *numItems = 11 + extraItems; - return PARSER_OK; - case SCRIPT_SCO12_CLOSE_STAKE: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_SCO13_TRANSFER_NODE: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_SCO14_TRANSFER_DELEGATOR: - *numItems = 11 + extraItems; - return PARSER_OK; - case SCRIPT_SCO15_WITHDRAW_FROM_MACHINE_ACCOUNT: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_SCO16_UPDATE_NETWORKING_ADDRESS: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_FUSD01_SETUP_FUSD_VAULT: - *numItems = 8 + extraItems; - return PARSER_OK; - case SCRIPT_FUSD02_TRANSFER_FUSD: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_TS01_SET_UP_TOPSHOT_COLLECTION: - *numItems = 8 + extraItems; - return PARSER_OK; - case SCRIPT_TS02_TRANSFER_TOP_SHOT_MOMENT: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_USDC01_SETUP_USDC_VAULT: - *numItems = 8 + extraItems; - return PARSER_OK; - case SCRIPT_USDC02_TRANSFER_USDC: - *numItems = 10 + extraItems; - return PARSER_OK; - case SCRIPT_UNKNOWN: - default: - return PARSER_UNEXPECTED_SCRIPT; - } -} - void checkAddressUsedInTx() { addressUsedInTx = 0; int authCount = parser_tx_obj.authorizers.authorizer_count; - for (int i = 0; i < authCount + 2; i++) { //+2 for proposer and payer + for (uint8_t i = 0; i < authCount + 2; i++) { //+2 for proposer and payer parser_context_t *ctx = &parser_tx_obj.payer.ctx; if (i == authCount) ctx = &parser_tx_obj.proposalKeyAddress.ctx; if (i < authCount) ctx = &parser_tx_obj.authorizers.authorizer[i].ctx; @@ -1001,3 +710,9 @@ void checkAddressUsedInTx() { } } } + +parser_error_t parseMetadata() { + MEMZERO(&parser_tx_obj.metadata, sizeof(parser_tx_obj.metadata)); + CHECK_PARSER_ERR(parseTxMetadata(parser_tx_obj.hash.digest, &parser_tx_obj.metadata)); + return PARSER_OK; +} diff --git a/src/parser_impl.h b/src/parser_impl.h index e17f3805..8887096e 100644 --- a/src/parser_impl.h +++ b/src/parser_impl.h @@ -29,64 +29,67 @@ extern parser_tx_t parser_tx_obj; parser_error_t parser_init(parser_context_t *ctx, const uint8_t *buffer, uint16_t bufferSize); -parser_error_t _matchScriptType(uint8_t scriptHash[32], script_type_e *scriptType); - -parser_error_t _read(parser_context_t *c, parser_tx_t *v); +parser_error_t _read(parser_context_t *c, parser_tx_t *v, script_parsed_type_t scriptType); parser_error_t _validateTx(const parser_context_t *c, const parser_tx_t *v); -parser_error_t _getNumItems(const parser_context_t *c, const parser_tx_t *v, uint8_t *numItems); - // Called when argumentIndex-th argument is an array. If the array length is more than // max_number_of_items returns parser error, otherwise it sets number_of_items as the array length. parser_error_t _countArgumentItems(const flow_argument_list_t *v, uint8_t argumentIndex, + uint8_t min_number_of_items, uint8_t max_number_of_items, uint8_t *number_of_items); // Same as _countArgumentItems, but the array is optional. parser_error_t _countArgumentOptionalItems(const flow_argument_list_t *v, uint8_t argumentIndex, + uint8_t min_number_of_items, uint8_t max_number_of_items, uint8_t *number_of_items); -parser_error_t json_validateToken(parsed_json_t *parsedJson, uint16_t tokenIdx); +parser_error_t json_validateToken(const parsed_json_t *parsedJson, uint16_t tokenIdx); parser_error_t json_extractToken(char *outVal, uint16_t outValLen, - parsed_json_t *parsedJson, + const parsed_json_t *parsedJson, uint16_t tokenIdx); -parser_error_t json_matchToken(parsed_json_t *parsedJson, uint16_t tokenIdx, char *expectedValue); +parser_error_t json_matchToken(const parsed_json_t *parsedJson, + uint16_t tokenIdx, + const char *expectedValue); -parser_error_t json_matchNull(parsed_json_t *parsedJson, uint16_t tokenIdx); +parser_error_t json_matchNull(const parsed_json_t *parsedJson, uint16_t tokenIdx); -parser_error_t json_matchKeyValue(parsed_json_t *parsedJson, +parser_error_t json_matchKeyValue(const parsed_json_t *parsedJson, uint16_t tokenIdx, - char *expectedType, + const char *expectedType, jsmntype_t jsonType, uint16_t *valueTokenIdx); #define JSON_MATCH_VALUE_IDX_NONE 65535 -parser_error_t json_matchOptionalKeyValue(parsed_json_t *parsedJson, +parser_error_t json_matchOptionalKeyValue(const parsed_json_t *parsedJson, uint16_t tokenIdx, - char *expectedType, + const char *expectedType, jsmntype_t jsonType, uint16_t *valueTokenIdx); -parser_error_t json_matchOptionalArray(parsed_json_t *parsedJson, +parser_error_t json_matchOptionalArray(const parsed_json_t *parsedJson, uint16_t tokenIdx, uint16_t *valueTokenIdx); -parser_error_t formatStrUInt8AsHex(const char *decStr, char *hexStr); +parser_error_t json_matchArbitraryKeyValue(const parsed_json_t *parsedJson, + uint16_t tokenIdx, + jsmntype_t *valueJsonType, + uint16_t *keyTokenIdx, + uint16_t *valueTokenIdx); -parser_error_t json_extractString(char *outVal, - uint16_t outValLen, - parsed_json_t *parsedJson, - uint16_t tokenIdx); +parser_error_t formatStrUInt8AsHex(const char *decStr, char *hexStr); void checkAddressUsedInTx(); +parser_error_t parseMetadata(); + #ifdef __cplusplus } #endif diff --git a/src/parser_tx.c b/src/parser_tx.c index 69e6604a..0d9a60e7 100644 --- a/src/parser_tx.c +++ b/src/parser_tx.c @@ -41,9 +41,12 @@ #define MAX_JSON_ARRAY_TOKEN_COUNT 64 -parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen) { +parser_error_t parser_parse(parser_context_t *ctx, + const uint8_t *data, + size_t dataLen, + script_parsed_type_t scriptType) { CHECK_PARSER_ERR(parser_init(ctx, data, dataLen)) - return _read(ctx, &parser_tx_obj); + return _read(ctx, &parser_tx_obj, scriptType); } parser_error_t parser_validate(const parser_context_t *ctx) { @@ -65,11 +68,6 @@ parser_error_t parser_validate(const parser_context_t *ctx) { return PARSER_OK; } -parser_error_t parser_getNumItems(const parser_context_t *ctx, uint8_t *num_items) { - CHECK_PARSER_ERR(_getNumItems(ctx, &parser_tx_obj, num_items)) - return PARSER_OK; -} - // based on Dapper provided code at // https://github.com/onflow/flow-go-sdk/blob/96796f0cabc1847d7879a5230ab55fd3cdd41ae8/address.go#L286 @@ -169,7 +167,7 @@ parser_error_t parser_printArgument(const flow_argument_list_t *v, jsmntype_t jsonType, char *outVal, uint16_t outValLen, - __Z_UNUSED uint8_t pageIdx, + uint8_t pageIdx, uint8_t *pageCount) { MEMZERO(outVal, outValLen); @@ -177,28 +175,34 @@ parser_error_t parser_printArgument(const flow_argument_list_t *v, return PARSER_UNEXPECTED_NUMBER_ITEMS; } - *pageCount = 1; - parsed_json_t parsedJson = {false}; CHECK_PARSER_ERR(json_parse(&parsedJson, (char *) v->argCtx[argIndex].buffer, v->argCtx[argIndex].bufferLen)); + + char bufferUI[ARGUMENT_BUFFER_SIZE_STRING]; uint16_t valueTokenIndex; - CHECK_PARSER_ERR( - json_matchKeyValue(&parsedJson, 0, (char *) expectedType, jsonType, &valueTokenIndex)) - CHECK_PARSER_ERR(json_extractToken(outVal, outValLen, &parsedJson, valueTokenIndex)) + + CHECK_PARSER_ERR(json_matchKeyValue(&parsedJson, 0, expectedType, jsonType, &valueTokenIndex)) + CHECK_PARSER_ERR(json_extractToken(bufferUI, sizeof(bufferUI), &parsedJson, valueTokenIndex)) + pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); + + // Check requested page is in range + if (pageIdx > *pageCount) { + return PARSER_DISPLAY_PAGE_OUT_OF_RANGE; + } return PARSER_OK; } -parser_error_t parser_printArgumentOptionalDelegatorID(const flow_argument_list_t *v, - uint8_t argIndex, - const char *expectedType, - jsmntype_t jsonType, - char *outVal, - uint16_t outValLen, - __Z_UNUSED uint8_t pageIdx, - uint8_t *pageCount) { +parser_error_t parser_printOptionalArgument(const flow_argument_list_t *v, + uint8_t argIndex, + const char *expectedType, + jsmntype_t jsonType, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount) { MEMZERO(outVal, outValLen); if (argIndex >= v->argCount) { @@ -212,77 +216,39 @@ parser_error_t parser_printArgumentOptionalDelegatorID(const flow_argument_list_ (char *) v->argCtx[argIndex].buffer, v->argCtx[argIndex].bufferLen)); uint16_t valueTokenIndex; - CHECK_PARSER_ERR(json_matchOptionalKeyValue(&parsedJson, - 0, - (char *) expectedType, - jsonType, - &valueTokenIndex)) + CHECK_PARSER_ERR( + json_matchOptionalKeyValue(&parsedJson, 0, expectedType, jsonType, &valueTokenIndex)) if (valueTokenIndex == JSON_MATCH_VALUE_IDX_NONE) { - if (outValLen < 5) { - return PARSER_UNEXPECTED_BUFFER_END; - } - strncpy_s(outVal, "None", 5); + snprintf(outVal, outValLen, "None"); } else { - CHECK_PARSER_ERR(json_extractToken(outVal, outValLen, &parsedJson, valueTokenIndex)) - } - - return PARSER_OK; -} - -parser_error_t parser_printArgumentString(const parser_context_t *argumentCtx, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - MEMZERO(outVal, outValLen); - - parsed_json_t parsedJson = {false}; - CHECK_PARSER_ERR(json_parse(&parsedJson, (char *) argumentCtx->buffer, argumentCtx->bufferLen)); - - char bufferUI[ARGUMENT_BUFFER_SIZE_STRING]; - CHECK_PARSER_ERR(json_extractString(bufferUI, sizeof(bufferUI), &parsedJson, 0)) - pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); - - // Check requested page is in range - if (pageIdx > *pageCount) { - return PARSER_DISPLAY_PAGE_OUT_OF_RANGE; + char bufferUI[ARGUMENT_BUFFER_SIZE_STRING]; + CHECK_PARSER_ERR( + json_extractToken(bufferUI, sizeof(bufferUI), &parsedJson, valueTokenIndex)) + pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); } return PARSER_OK; } -parser_error_t parser_printArgumentPublicKey(const parser_context_t *argumentCtx, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { +parser_error_t parser_printArgumentArray(const flow_argument_list_t *v, + uint8_t argIndex, + uint8_t arrayIndex, + const char *expectedType, + jsmntype_t jsonType, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount) { MEMZERO(outVal, outValLen); - parsed_json_t parsedJson = {false}; - CHECK_PARSER_ERR(json_parse(&parsedJson, (char *) argumentCtx->buffer, argumentCtx->bufferLen)); - - char bufferUI[ARGUMENT_BUFFER_SIZE_ACCOUNT_KEY]; - CHECK_PARSER_ERR(json_extractString(bufferUI, sizeof(bufferUI), &parsedJson, 0)) - pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); - - // Check requested page is in range - if (pageIdx > *pageCount) { - return PARSER_DISPLAY_PAGE_OUT_OF_RANGE; + if (argIndex >= v->argCount) { + return PARSER_UNEXPECTED_NUMBER_ITEMS; } - return PARSER_OK; -} - -parser_error_t parser_printArgumentPublicKeys(const parser_context_t *argumentCtx, - uint8_t argumentIndex, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - MEMZERO(outVal, outValLen); - parsed_json_t parsedJson = {false}; - CHECK_PARSER_ERR(json_parse(&parsedJson, (char *) argumentCtx->buffer, argumentCtx->bufferLen)); + CHECK_PARSER_ERR(json_parse(&parsedJson, + (char *) v->argCtx[argIndex].buffer, + v->argCtx[argIndex].bufferLen)); // Estimate number of pages uint16_t internalTokenElementIdx; @@ -291,20 +257,22 @@ parser_error_t parser_printArgumentPublicKeys(const parser_context_t *argumentCt uint16_t arrayTokenCount; CHECK_PARSER_ERR( array_get_element_count(&parsedJson, internalTokenElementIdx, &arrayTokenCount)); - if (arrayTokenCount > - MAX_JSON_ARRAY_TOKEN_COUNT) { // indirectly limits the maximum number of public keys + if (arrayTokenCount >= MAX_JSON_ARRAY_TOKEN_COUNT || arrayIndex >= arrayTokenCount) { return PARSER_UNEXPECTED_NUMBER_ITEMS; } - zemu_log_stack("PublicKeys"); - uint16_t arrayElementToken; - char bufferUI[ARGUMENT_BUFFER_SIZE_ACCOUNT_KEY]; - CHECK_PARSER_ERR(array_get_nth_element(&parsedJson, - internalTokenElementIdx, - argumentIndex, - &arrayElementToken)) - CHECK_PARSER_ERR(json_extractString(bufferUI, sizeof(bufferUI), &parsedJson, arrayElementToken)) + char bufferUI[ARGUMENT_BUFFER_SIZE_STRING]; + CHECK_PARSER_ERR( + array_get_nth_element(&parsedJson, internalTokenElementIdx, arrayIndex, &arrayElementToken)) + uint16_t internalTokenElemIdx; + CHECK_PARSER_ERR(json_matchKeyValue(&parsedJson, + arrayElementToken, + expectedType, + jsonType, + &internalTokenElemIdx)) + CHECK_PARSER_ERR( + json_extractToken(bufferUI, sizeof(bufferUI), &parsedJson, internalTokenElemIdx)) pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); // Check requested page is in range @@ -315,16 +283,25 @@ parser_error_t parser_printArgumentPublicKeys(const parser_context_t *argumentCt return PARSER_OK; } -parser_error_t parser_printArgumentOptionalPublicKeys(const parser_context_t *argumentCtx, - uint8_t argumentIndex, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { +parser_error_t parser_printArgumentOptionalArray(const flow_argument_list_t *v, + uint8_t argIndex, + uint8_t arrayIndex, + const char *expectedType, + jsmntype_t jsonType, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount) { MEMZERO(outVal, outValLen); + if (argIndex >= v->argCount) { + return PARSER_UNEXPECTED_NUMBER_ITEMS; + } + parsed_json_t parsedJson = {false}; - CHECK_PARSER_ERR(json_parse(&parsedJson, (char *) argumentCtx->buffer, argumentCtx->bufferLen)); + CHECK_PARSER_ERR(json_parse(&parsedJson, + (char *) v->argCtx[argIndex].buffer, + v->argCtx[argIndex].bufferLen)); // Estimate number of pages uint16_t internalTokenElementIdx; @@ -339,21 +316,24 @@ parser_error_t parser_printArgumentOptionalPublicKeys(const parser_context_t *ar uint16_t arrayTokenCount; CHECK_PARSER_ERR( array_get_element_count(&parsedJson, internalTokenElementIdx, &arrayTokenCount)); - if (arrayTokenCount > - MAX_JSON_ARRAY_TOKEN_COUNT) { // indirectly limits the maximum number of public keys + if (arrayTokenCount >= MAX_JSON_ARRAY_TOKEN_COUNT || arrayIndex >= arrayTokenCount) { return PARSER_UNEXPECTED_NUMBER_ITEMS; } - zemu_log_stack("PublicKeys"); - uint16_t arrayElementToken; - char bufferUI[ARGUMENT_BUFFER_SIZE_ACCOUNT_KEY]; + char bufferUI[ARGUMENT_BUFFER_SIZE_STRING]; CHECK_PARSER_ERR(array_get_nth_element(&parsedJson, internalTokenElementIdx, - argumentIndex, + arrayIndex, &arrayElementToken)) + uint16_t internalTokenElemIdx; + CHECK_PARSER_ERR(json_matchKeyValue(&parsedJson, + arrayElementToken, + expectedType, + jsonType, + &internalTokenElemIdx)) CHECK_PARSER_ERR( - json_extractString(bufferUI, sizeof(bufferUI), &parsedJson, arrayElementToken)) + json_extractToken(bufferUI, sizeof(bufferUI), &parsedJson, internalTokenElemIdx)) pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); // Check requested page is in range @@ -365,6 +345,229 @@ parser_error_t parser_printArgumentOptionalPublicKeys(const parser_context_t *ar return PARSER_OK; } +#define FLAG_IS_NONE 0x1000 +#define FLAG_IS_OPTIONAL_NOT_NONE 0x2000 +#define FLAG_IS_ARRAY 0x4000 +#define FLAGS_FURTHER_SCREENS 0x0FFF +// jsonToken points to thing that is going to be displayed: +// JSMN_ARRAY that contains actual array if it is an array or optional array, +// root JSMN_OBJECT it is optional none or non-optional scalar argument +// nested JSMN_OBJECT for optional scalar arguments +// The function validates json till jsonToken (excluded) but guarantees jsonToken type +parser_error_t parser_printArbitraryPrepareToDisplay(const flow_argument_list_t *v, + uint8_t argIndex, + uint16_t *flags, + uint16_t *jsonToken) { + if (argIndex >= v->argCount) { + return PARSER_UNEXPECTED_NUMBER_ITEMS; + } + + parsed_json_t parsedJson = {false}; + CHECK_PARSER_ERR(json_parse(&parsedJson, + (char *) v->argCtx[argIndex].buffer, + v->argCtx[argIndex].bufferLen)); + + jsmntype_t valueJsonType = JSMN_UNDEFINED; + uint16_t keyTokenElementIdx = 0; + uint16_t valueTokenElementIdx = 0; + CHECK_PARSER_ERR(json_matchArbitraryKeyValue(&parsedJson, + 0, + &valueJsonType, + &keyTokenElementIdx, + &valueTokenElementIdx)); + + const uint16_t baseValueTokenIndex = valueTokenElementIdx; + + switch (valueJsonType) { + case JSMN_ARRAY: // array + CHECK_PARSER_ERR(json_matchToken(&parsedJson, keyTokenElementIdx, "Array")); + CHECK_PARSER_ERR(array_get_element_count(&parsedJson, valueTokenElementIdx, flags)); + _Static_assert(FLAGS_FURTHER_SCREENS > MAX_JSON_ARRAY_TOKEN_COUNT, + "Flags for further screens too small"); + if (*flags > MAX_JSON_ARRAY_TOKEN_COUNT) { + return PARSER_TOO_MANY_ARGUMENTS; + } + *flags = (*flags & FLAGS_FURTHER_SCREENS) | FLAG_IS_ARRAY; + *jsonToken = valueTokenElementIdx; + return PARSER_OK; + case JSMN_STRING: // value + *flags = 0; + *jsonToken = 0; + return PARSER_OK; + case JSMN_PRIMITIVE: // optional null + *flags = FLAG_IS_NONE; + *jsonToken = 0; + return PARSER_OK; + case JSMN_OBJECT: // optional not null + CHECK_PARSER_ERR(json_matchToken(&parsedJson, keyTokenElementIdx, "Optional")); + CHECK_PARSER_ERR(json_matchArbitraryKeyValue(&parsedJson, + baseValueTokenIndex, + &valueJsonType, + &keyTokenElementIdx, + &valueTokenElementIdx)); + switch (valueJsonType) { + case JSMN_ARRAY: // array + CHECK_PARSER_ERR(json_matchToken(&parsedJson, keyTokenElementIdx, "Array")); + CHECK_PARSER_ERR( + array_get_element_count(&parsedJson, valueTokenElementIdx, flags)); + _Static_assert(FLAGS_FURTHER_SCREENS > MAX_METADATA_MAX_ARRAY_ITEMS, + "Flags for further screens too small"); + if (*flags > MAX_METADATA_MAX_ARRAY_ITEMS) { + return PARSER_TOO_MANY_ARGUMENTS; + } + *flags = (*flags & FLAGS_FURTHER_SCREENS) | FLAG_IS_ARRAY | + FLAG_IS_OPTIONAL_NOT_NONE; + *jsonToken = valueTokenElementIdx; + return PARSER_OK; + case JSMN_STRING: // value + *flags = FLAG_IS_OPTIONAL_NOT_NONE; + *jsonToken = baseValueTokenIndex; + return PARSER_OK; + default: + return PARSER_JSON_INVALID; + } + default: + return PARSER_JSON_INVALID; + } +} + +parser_error_t parser_printArbitraryArgumentFirstScreen(const flow_argument_list_t *v, + uint8_t argIndex, + uint16_t flags, + uint16_t jsonToken, + char *outKey, + uint16_t outKeyLen, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount) { + if (argIndex >= v->argCount) { + return PARSER_UNEXPECTED_NUMBER_ITEMS; + } + + parsed_json_t parsedJson = {false}; + CHECK_PARSER_ERR(json_parse(&parsedJson, + (char *) v->argCtx[argIndex].buffer, + v->argCtx[argIndex].bufferLen)); + + if (jsonToken >= parsedJson.numberOfTokens) { + return PARSER_JSON_INVALID_TOKEN_IDX; + } + + char bufferUI[ARGUMENT_BUFFER_SIZE_STRING]; + *pageCount = 1; // default value + + if (flags & FLAG_IS_ARRAY) { + const uint16_t arrayElements = flags & FLAGS_FURTHER_SCREENS; + snprintf(outKey, + outKeyLen, + "%d: %s", + (int) (argIndex + 1), + (flags & FLAG_IS_OPTIONAL_NOT_NONE) ? "Opt. Array" : "Array"); + snprintf(outVal, outValLen, "Length: %d", (int) arrayElements); + return PARSER_OK; + } else { // Not an array + jsmntype_t valueJsonType = JSMN_UNDEFINED; + uint16_t keyTokenIdx = 0; + uint16_t valueTokenIdx = 0; + if (flags & FLAG_IS_NONE) { + CHECK_PARSER_ERR(json_matchOptionalKeyValue(&parsedJson, + jsonToken, + "", + JSMN_STRING, + &valueTokenIdx)); + if (valueTokenIdx != JSON_MATCH_VALUE_IDX_NONE) { + return PARSER_JSON_INVALID; + } + snprintf(outKey, outKeyLen, "%d: Optional", (int) (argIndex + 1)); + snprintf(outVal, outValLen, "None"); + return PARSER_OK; + } else { + CHECK_PARSER_ERR(json_matchArbitraryKeyValue(&parsedJson, + jsonToken, + &valueJsonType, + &keyTokenIdx, + &valueTokenIdx)); + if (valueJsonType != JSMN_STRING) { + return PARSER_JSON_INVALID; + } + CHECK_PARSER_ERR( + json_extractToken(bufferUI, sizeof(bufferUI), &parsedJson, keyTokenIdx)) + snprintf(outKey, + outKeyLen, + "%d: %s%s", + (int) (argIndex + 1), + bufferUI, + (flags & FLAG_IS_OPTIONAL_NOT_NONE) ? "?" : ""); + CHECK_PARSER_ERR( + json_extractToken(bufferUI, sizeof(bufferUI), &parsedJson, valueTokenIdx)) + pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); + return PARSER_OK; + } + } + return PARSER_JSON_UNEXPECTED_ERROR; +} + +parser_error_t parser_printArbitraryArrayElements(const flow_argument_list_t *v, + uint8_t argIndex, + uint16_t arrayIndex, + uint16_t arrayJsonToken, + char *outKey, + uint16_t outKeyLen, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount) { + if (argIndex >= v->argCount) { + return PARSER_UNEXPECTED_NUMBER_ITEMS; + } + + parsed_json_t parsedJson = {false}; + CHECK_PARSER_ERR(json_parse(&parsedJson, + (char *) v->argCtx[argIndex].buffer, + v->argCtx[argIndex].bufferLen)); + if (arrayJsonToken >= parsedJson.numberOfTokens) { + return PARSER_JSON_INVALID_TOKEN_IDX; + } + + uint16_t arrayLen = 0; + CHECK_PARSER_ERR(array_get_element_count(&parsedJson, arrayJsonToken, &arrayLen)); + if (arrayIndex >= arrayLen) { + return PARSER_JSON_INVALID_TOKEN_IDX; + } + + uint16_t arrayElementToken = 0; + CHECK_PARSER_ERR( + array_get_nth_element(&parsedJson, arrayJsonToken, arrayIndex, &arrayElementToken)) + + jsmntype_t valueJsonType = JSMN_UNDEFINED; + uint16_t keyTokenElementIdx = 0; + uint16_t valueTokenElementIdx = 0; + CHECK_PARSER_ERR(json_matchArbitraryKeyValue(&parsedJson, + arrayElementToken, + &valueJsonType, + &keyTokenElementIdx, + &valueTokenElementIdx)); + + if (valueJsonType != JSMN_STRING) { + return PARSER_JSON_INVALID; + } + + char bufferUI[ARGUMENT_BUFFER_SIZE_STRING]; + + CHECK_PARSER_ERR(json_extractToken(bufferUI, sizeof(bufferUI), &parsedJson, keyTokenElementIdx)) + snprintf(outKey, + outKeyLen, + "%d: %s %d", + (int) (argIndex + 1), + bufferUI, + (int) (arrayIndex + 1)); + CHECK_PARSER_ERR( + json_extractToken(bufferUI, sizeof(bufferUI), &parsedJson, valueTokenElementIdx)) + pageString(outVal, outValLen, bufferUI, pageIdx, pageCount); + return PARSER_OK; +} + parser_error_t parser_printBlockId(const flow_reference_block_id_t *v, char *outVal, uint16_t outValLen, @@ -493,69 +696,578 @@ parser_error_t parser_printAuthorizer(const flow_proposal_authorizer_t *v, return PARSER_OK; } -parser_error_t parser_getItemAfterArguments(__Z_UNUSED const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Ref Block"); - return parser_printBlockId(&parser_tx_obj.referenceBlockId, - outVal, - outValLen, - pageIdx, - pageCount); - case 1: - snprintf(outKey, outKeyLen, "Gas Limit"); - return parser_printGasLimit(&parser_tx_obj.gasLimit, - outVal, - outValLen, - pageIdx, - pageCount); - case 2: - snprintf(outKey, outKeyLen, "Prop Key Addr"); - return parser_printPropKeyAddr(&parser_tx_obj.proposalKeyAddress, - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Prop Key Id"); - return parser_printPropKeyId(&parser_tx_obj.proposalKeyId, +// Small trick to avoid duplicated code here which was quite error prone: +// displayIdx is either the index of page to display, or GET_NUM_ITEMS_DISPLAY_IDX_STARTING_VALUE +// In the second case this is used to count the number of pages +// If displayIdx is GET_NUM_ITEMS_DISPLAY_IDX_STARTING_VALUE, all other values are NULL/0 +// Their use should be hiden behind SCREEN macro +#define GET_NUM_ITEMS_DISPLAY_IDX_STARTING_VALUE (-1) + +parser_error_t parser_getItem_internal(int8_t *displayIdx, + char *outKey, + uint16_t outKeyLen, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount) { + zemu_log_stack("parser_getItem_internal"); + + // validate contract + if ((*displayIdx) >= 0) { + if (outKey == NULL || outVal == NULL || pageCount == NULL) { + return PARSER_UNEXPECTED_ERROR; + } + } else if ((*displayIdx) == GET_NUM_ITEMS_DISPLAY_IDX_STARTING_VALUE) { + if (outKey != NULL || outVal != NULL || pageCount != NULL || outKeyLen != 0 || + outValLen != 0 || pageIdx != 0) { + return PARSER_UNEXPECTED_ERROR; + } + } else { + return PARSER_UNEXPECTED_ERROR; + } + +//(*displayIdx!=INT8_MIN) : this prevents displayIdx to loop around from negative valiues to +//positive ones +//(*displayIdx)--==0 : If displayIdx is positive (and not INT8_MAX), this finds the right screen in +//the end pageCount && (*pageCount = 1) : We need to set *pageCount (in case it is not set in the +// screen) but only if it is not NULL Do not forget to break after switch/case even if you return +// from within SCREEN(true) block +#define SCREEN(condition) \ + if ((condition) && (*displayIdx != INT8_MIN) && ((*displayIdx)-- == 0) && pageCount && \ + (*pageCount = 1)) + + if (parser_tx_obj.metadataInitialized) { + SCREEN(true) { + snprintf(outKey, outKeyLen, "Type"); + snprintf(outVal, outValLen, "%s", parser_tx_obj.metadata.txName); + return PARSER_OK; + } + } else { + const char storageString[] = "/storage/"; + const char publicString[] = "/public/"; + const size_t storageStringLength = sizeof(storageString) - 1; + const size_t publicStringLength = sizeof(publicString) - 1; + switch (parser_tx_obj.parsedScript.script_type) { + case SCRIPT_TYPE_NFT_SETUP_COLLECTION: { + // validate basic assumptions on the script + if (parser_tx_obj.parsedScript.elements_count != PARSED_ELEMENTS_NFT1_COUNT) { + return PARSER_UNEXPECTED_ERROR; + } + // storagePath should be preceeded with "/storage/" - double checking before + // displaying it + _Static_assert(PARSED_ELEMENTS_NFT1_STORAGE_PATH >= 1, "Script index error"); + bool enoughSpaceForStorageString = + (parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_STORAGE_PATH].data >= + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_STORAGE_PATH - 1] + .data + + storageStringLength); + if (!enoughSpaceForStorageString) { + return PARSER_UNEXPECTED_ERROR; + } + if (memcmp(parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_STORAGE_PATH] + .data - + storageStringLength, + storageString, + storageStringLength)) { + return PARSER_UNEXPECTED_ERROR; + } + // publicCollectionContractName and publicCollectionName should be separated by a + // single '.' - double checking before displaying it + _Static_assert(PARSED_ELEMENTS_NFT1_PUBLIC_COLLECTION_CONTRACT_NAME + 1 == + PARSED_ELEMENTS_NFT1_PUBLIC_COLLECTION_NAME, + "Script index error"); + if (parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_PUBLIC_COLLECTION_CONTRACT_NAME] + .data + + parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_PUBLIC_COLLECTION_CONTRACT_NAME] + .length + + 1 != + parser_tx_obj.parsedScript.elements[8].data) { + return PARSER_UNEXPECTED_ERROR; + } + size_t expectedDotIndex = + parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_PUBLIC_COLLECTION_CONTRACT_NAME] + .length; + if (parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_PUBLIC_COLLECTION_CONTRACT_NAME] + .data[expectedDotIndex] != '.') { + return PARSER_UNEXPECTED_ERROR; + } + + // publicPath should be preceeded with "/public/" - double checking before + // displaying it + _Static_assert(PARSED_ELEMENTS_NFT1_PUBLIC_PATH >= 1, "Script index error"); + bool enoughSpaceForPublicString = + (parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_PUBLIC_PATH].data >= + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_PUBLIC_PATH - 1] + .data + + publicStringLength); + if (!enoughSpaceForPublicString) { + return PARSER_UNEXPECTED_ERROR; + } + if (memcmp( + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_PUBLIC_PATH].data - + publicStringLength, + publicString, + publicStringLength)) { + return PARSER_UNEXPECTED_ERROR; + } + + SCREEN(true) { + snprintf(outKey, outKeyLen, "Set Up NFT"); + snprintf(outVal, outValLen, "Collection"); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Contract Name"); + pageStringExt( + outVal, + outValLen, + (const char *) parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_CONTRACT_NAME] + .data, + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_CONTRACT_NAME] + .length, + pageIdx, + pageCount); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Contract Address"); + pageStringExt( + outVal, + outValLen, + (const char *) parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_CONTRACT_ADDRESS] + .data, + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_CONTRACT_ADDRESS] + .length, + pageIdx, + pageCount); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Storage Path"); + pageStringExt( + outVal, + outValLen, + (const char *) parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_STORAGE_PATH] + .data - + storageStringLength, + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_STORAGE_PATH] + .length + + storageStringLength, + pageIdx, + pageCount); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Public Coll. Name"); + pageStringExt( + outVal, + outValLen, + (const char *) parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_PUBLIC_COLLECTION_CONTRACT_NAME] + .data, + parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_PUBLIC_COLLECTION_CONTRACT_NAME] + .length + + parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_PUBLIC_COLLECTION_NAME] + .length + + 1, + pageIdx, + pageCount); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Public Path"); + pageStringExt( + outVal, + outValLen, + (const char *) parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT1_PUBLIC_PATH] + .data - + publicStringLength, + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT1_PUBLIC_PATH] + .length + + publicStringLength, + pageIdx, + pageCount); + return PARSER_OK; + } + break; + } + case SCRIPT_TYPE_NFT_TRANSFER: { + // validate basic assumptions on the script + if (parser_tx_obj.parsedScript.elements_count != PARSED_ELEMENTS_NFT2_COUNT) { + return PARSER_UNEXPECTED_ERROR; + } + // storagePath should be preceeded with "/storage/" - double checking before + // displaying it + _Static_assert(PARSED_ELEMENTS_NFT2_STORAGE_PATH >= 1, "Script index error"); + bool enoughSpaceForStorageString = + (parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_STORAGE_PATH].data >= + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_STORAGE_PATH - 1] + .data + + storageStringLength); + if (!enoughSpaceForStorageString) { + return PARSER_UNEXPECTED_ERROR; + } + if (memcmp(parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_STORAGE_PATH] + .data - + storageStringLength, + storageString, + storageStringLength)) { + return PARSER_UNEXPECTED_ERROR; + } + // publicPath should be preceeded with "/public/" - double checking before + // displaying it + _Static_assert(PARSED_ELEMENTS_NFT2_PUBLIC_PATH >= 1, "Script index error"); + bool enoughSpaceForPublicString = + (parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_PUBLIC_PATH].data >= + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_PUBLIC_PATH - 1] + .data + + publicStringLength); + if (!enoughSpaceForPublicString) { + return PARSER_UNEXPECTED_ERROR; + } + if (memcmp( + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_PUBLIC_PATH].data - + publicStringLength, + publicString, + publicStringLength)) { + return PARSER_UNEXPECTED_ERROR; + } + + SCREEN(true) { + snprintf(outKey, outKeyLen, "Transfer NFT"); + snprintf(outVal, outValLen, ""); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Contract Name"); + pageStringExt( + outVal, + outValLen, + (const char *) parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT2_CONTRACT_NAME] + .data, + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_CONTRACT_NAME] + .length, + pageIdx, + pageCount); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Contract Address"); + pageStringExt( + outVal, + outValLen, + (const char *) parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT2_CONTRACT_ADDRESS] + .data, + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_CONTRACT_ADDRESS] + .length, + pageIdx, + pageCount); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Storage Path"); + pageStringExt( + outVal, + outValLen, + (const char *) parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT2_STORAGE_PATH] + .data - + storageStringLength, + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_STORAGE_PATH] + .length + + storageStringLength, + pageIdx, + pageCount); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Public Path"); + pageStringExt( + outVal, + outValLen, + (const char *) parser_tx_obj.parsedScript + .elements[PARSED_ELEMENTS_NFT2_PUBLIC_PATH] + .data - + publicStringLength, + parser_tx_obj.parsedScript.elements[PARSED_ELEMENTS_NFT2_PUBLIC_PATH] + .length + + publicStringLength, + pageIdx, + pageCount); + return PARSER_OK; + } + break; + } + case SCRIPT_TYPE_UNKNOWN: { + SCREEN(true) { + snprintf(outKey, outKeyLen, "Script hash"); + pageStringHex(outVal, + outValLen, + (const char *) parser_tx_obj.hash.digest, + sizeof(parser_tx_obj.hash.digest), + pageIdx, + pageCount); + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Verify script hash"); + snprintf(outVal, outValLen, "on a secure device."); + return PARSER_OK; + } + break; + } + default: + return PARSER_UNEXPECTED_ERROR; + } + } + + SCREEN(true) { + snprintf(outKey, outKeyLen, "ChainID"); + return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); + } + + // Arguments + if (parser_tx_obj.metadataInitialized) { + uint8_t screenCount = 0; + + if (parser_tx_obj.metadata.argCount != parser_tx_obj.arguments.argCount) { + return PARSER_UNEXPECTED_NUMBER_ITEMS; + } + + for (size_t i = 0; i < parser_tx_obj.metadata.argCount; i++) { + parsed_tx_metadata_argument_t *marg = &parser_tx_obj.metadata.arguments[i]; + switch (marg->argumentType) { + case ARGUMENT_TYPE_NORMAL: + SCREEN(true) { + snprintf(outKey, outKeyLen, "%s", marg->displayKey); + return parser_printArgument(&parser_tx_obj.arguments, + marg->argumentIndex, + marg->jsonExpectedType, + marg->jsonExpectedKind, + outVal, + outValLen, + pageIdx, + pageCount); + } + break; + case ARGUMENT_TYPE_OPTIONAL: + SCREEN(true) { + snprintf(outKey, outKeyLen, "%s", marg->displayKey); + return parser_printOptionalArgument(&parser_tx_obj.arguments, + marg->argumentIndex, + marg->jsonExpectedType, + marg->jsonExpectedKind, + outVal, + outValLen, + pageIdx, + pageCount); + } + break; + case ARGUMENT_TYPE_ARRAY: + CHECK_PARSER_ERR(_countArgumentItems(&parser_tx_obj.arguments, + marg->argumentIndex, + marg->arrayMinElements, + marg->arrayMaxElements, + &screenCount)); + for (size_t j = 0; j < screenCount; j++) { + SCREEN(true) { + snprintf(outKey, outKeyLen, "%s %d", marg->displayKey, (int) (j + 1)); + return parser_printArgumentArray(&parser_tx_obj.arguments, + marg->argumentIndex, + j, + marg->jsonExpectedType, + marg->jsonExpectedKind, + outVal, + outValLen, + pageIdx, + pageCount); + } + } + break; + case ARGUMENT_TYPE_OPTIONALARRAY: + CHECK_PARSER_ERR(_countArgumentOptionalItems(&parser_tx_obj.arguments, + marg->argumentIndex, + marg->arrayMinElements, + marg->arrayMaxElements, + &screenCount)); + for (size_t j = 0; j < screenCount; j++) { + SCREEN(true) { + snprintf(outKey, outKeyLen, "%s %d", marg->displayKey, (int) (j + 1)); + return parser_printArgumentOptionalArray(&parser_tx_obj.arguments, + marg->argumentIndex, + j, + marg->jsonExpectedType, + marg->jsonExpectedKind, + outVal, + outValLen, + pageIdx, + pageCount); + } + } + break; + default: + return PARSER_METADATA_ERROR; + } + } + } else { // No metadata + switch (parser_tx_obj.parsedScript.script_type) { + case SCRIPT_TYPE_NFT_SETUP_COLLECTION: + if (parser_tx_obj.arguments.argCount != 0) { + return PARSER_UNEXPECTED_NUMBER_ITEMS; + } + break; + + case SCRIPT_TYPE_NFT_TRANSFER: + if (parser_tx_obj.arguments.argCount != 2) { + return PARSER_UNEXPECTED_NUMBER_ITEMS; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Recipient"); + parser_printArgument(&parser_tx_obj.arguments, + 0, + "Address", + JSMN_STRING, outVal, outValLen, pageIdx, pageCount); - case 4: - snprintf(outKey, outKeyLen, "Prop Key Seq Num"); - return parser_printPropSeqNum(&parser_tx_obj.proposalKeySequenceNumber, - outVal, - outValLen, - pageIdx, - pageCount); - case 5: - snprintf(outKey, outKeyLen, "Payer"); - return parser_printPayer(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - default: - break; + return PARSER_OK; + } + SCREEN(true) { + snprintf(outKey, outKeyLen, "Token Id"); + parser_printArgument(&parser_tx_obj.arguments, + 1, + "UInt64", + JSMN_STRING, + outVal, + outValLen, + pageIdx, + pageCount); + return PARSER_OK; + } + break; + + case SCRIPT_TYPE_UNKNOWN: + SCREEN(true) { + snprintf(outKey, outKeyLen, "Script arguments"); + snprintf(outVal, + outValLen, + "Number of arguments: %d", + parser_tx_obj.arguments.argCount); + return PARSER_OK; + } + for (size_t i = 0; i < parser_tx_obj.arguments.argCount; i++) { + uint16_t flags = 0; + uint16_t jsonToken = 0; + CHECK_PARSER_ERR(parser_printArbitraryPrepareToDisplay(&parser_tx_obj.arguments, + i, + &flags, + &jsonToken)); + SCREEN(true) { + return parser_printArbitraryArgumentFirstScreen(&parser_tx_obj.arguments, + i, + flags, + jsonToken, + outKey, + outKeyLen, + outVal, + outValLen, + pageIdx, + pageCount); + } + if (flags & FLAG_IS_ARRAY) { + for (size_t j = 0; j < (flags & FLAGS_FURTHER_SCREENS); j++) { + SCREEN(true) { + return parser_printArbitraryArrayElements(&parser_tx_obj.arguments, + i, + j, + jsonToken, + outKey, + outKeyLen, + outVal, + outValLen, + pageIdx, + pageCount); + } + } + } + } + break; + default: + return PARSER_UNEXPECTED_ERROR; + } } - displayIdx -= 6; - if (displayIdx < parser_tx_obj.authorizers.authorizer_count) { - snprintf(outKey, outKeyLen, "Authorizer %d", displayIdx + 1); - return parser_printAuthorizer(&parser_tx_obj.authorizers.authorizer[displayIdx], + SCREEN(true) { + snprintf(outKey, outKeyLen, "Ref Block"); + return parser_printBlockId(&parser_tx_obj.referenceBlockId, + outVal, + outValLen, + pageIdx, + pageCount); + } + + SCREEN(true) { + snprintf(outKey, outKeyLen, "Gas Limit"); + return parser_printGasLimit(&parser_tx_obj.gasLimit, outVal, outValLen, pageIdx, pageCount); + } + + SCREEN(true) { + snprintf(outKey, outKeyLen, "Prop Key Addr"); + return parser_printPropKeyAddr(&parser_tx_obj.proposalKeyAddress, + outVal, + outValLen, + pageIdx, + pageCount); + } + + SCREEN(true) { + snprintf(outKey, outKeyLen, "Prop Key Id"); + return parser_printPropKeyId(&parser_tx_obj.proposalKeyId, + outVal, + outValLen, + pageIdx, + pageCount); + } + + SCREEN(true) { + snprintf(outKey, outKeyLen, "Prop Key Seq Num"); + return parser_printPropSeqNum(&parser_tx_obj.proposalKeySequenceNumber, outVal, outValLen, pageIdx, pageCount); } - displayIdx -= parser_tx_obj.authorizers.authorizer_count; - if (app_mode_expert() && displayIdx-- == 0) { + SCREEN(true) { + snprintf(outKey, outKeyLen, "Payer"); + return parser_printPayer(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); + } + + for (size_t i = 0; i < parser_tx_obj.authorizers.authorizer_count; i++) { + SCREEN(true) { + snprintf(outKey, outKeyLen, "Authorizer %d", (int) (i + 1)); + return parser_printAuthorizer(&parser_tx_obj.authorizers.authorizer[i], + outVal, + outValLen, + pageIdx, + pageCount); + } + } + + SCREEN(app_mode_expert()) { snprintf(outKey, outKeyLen, "Your Path"); char buffer[100]; path_options_to_string(buffer, @@ -570,12 +1282,12 @@ parser_error_t parser_getItemAfterArguments(__Z_UNUSED const parser_context_t *c switch (show_address) { case SHOW_ADDRESS_YES: case SHOW_ADDRESS_YES_HASH_MISMATCH: - if (!addressUsedInTx && displayIdx-- == 0) { + SCREEN(!addressUsedInTx) { snprintf(outKey, outKeyLen, "Warning:"); snprintf(outVal, outValLen, "Incorrect address in transaction."); return PARSER_OK; } - if (show_address == SHOW_ADDRESS_YES_HASH_MISMATCH && displayIdx-- == 0) { + SCREEN(show_address == SHOW_ADDRESS_YES_HASH_MISMATCH) { snprintf(outKey, outKeyLen, "Warning:"); #if defined(TARGET_NANOX) || defined(TARGET_NANOS2) pageString(outVal, @@ -594,2561 +1306,74 @@ parser_error_t parser_getItemAfterArguments(__Z_UNUSED const parser_context_t *c } break; case SHOW_ADDRESS_EMPTY_SLOT: - if (displayIdx-- == 0) { + SCREEN(true) { snprintf(outKey, outKeyLen, "Warning:"); snprintf(outVal, outValLen, "No address stored on the device."); return PARSER_OK; } break; case SHOW_ADDRESS_HDPATHS_NOT_EQUAL: - if (displayIdx-- == 0) { + SCREEN(true) { snprintf(outKey, outKeyLen, "Warning:"); snprintf(outVal, outValLen, "Different address stored on device."); return PARSER_OK; } break; default: - if (displayIdx-- == 0) { + SCREEN(true) { snprintf(outKey, outKeyLen, "Warning:"); snprintf(outVal, outValLen, "Slot error."); return PARSER_OK; } } + return PARSER_DISPLAY_IDX_OUT_OF_RANGE; + +#undef SCREEN } -parser_error_t parser_getItemTokenTransfer(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; +parser_error_t parser_getNumItems(__Z_UNUSED const parser_context_t *ctx, uint8_t *num_items) { + int8_t displays = GET_NUM_ITEMS_DISPLAY_IDX_STARTING_VALUE; + parser_error_t err = parser_getItem_internal(&displays, NULL, 0, NULL, 0, 0, NULL); - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Token Transfer"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Destination"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "Address", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; + if (displays == INT8_MIN) { + return PARSER_UNEXPECTED_ERROR; } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} -#define CREATE_ACCOUNT_MAX_PUB_KEYS 5 -parser_error_t parser_getItemCreateAccount(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - zemu_log_stack("parser_getItemCreateAccount"); - *pageCount = 1; + int8_t pages = GET_NUM_ITEMS_DISPLAY_IDX_STARTING_VALUE - displays; - if (displayIdx == 0) { - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Create Account"); - return PARSER_OK; - } - displayIdx--; - if (displayIdx == 0) { - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); + if (pages < 0) { + *num_items = 0; + return PARSER_UNEXPECTED_ERROR; } - displayIdx--; - uint8_t pkCount = 0; - CHECK_PARSER_ERR( - _countArgumentItems(&parser_tx_obj.arguments, 0, CREATE_ACCOUNT_MAX_PUB_KEYS, &pkCount)); - if (displayIdx < pkCount) { - snprintf(outKey, outKeyLen, "Pub key %d", displayIdx + 1); - CHECK_PARSER_ERR(parser_printArgumentPublicKeys(&parser_tx_obj.arguments.argCtx[0], - displayIdx, - outVal, - outValLen, - pageIdx, - pageCount)) + *num_items = (uint8_t) pages; + + if (err == PARSER_DISPLAY_IDX_OUT_OF_RANGE) { return PARSER_OK; } - displayIdx -= pkCount; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); + if (err == PARSER_OK) { + return PARSER_UNEXPECTED_ERROR; + } + return err; } -parser_error_t parser_getItemAddNewKey(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Add New Key"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: { - CHECK_PARSER_ERR(parser_printArgumentPublicKey(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount)) - snprintf(outKey, outKeyLen, "Pub key"); - return PARSER_OK; - } - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemWithdrawUnlockedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Withdraw FLOW from Lockbox"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemDepositUnlockedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Deposit FLOW to Lockbox"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemRegisterNode(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Register Staked Node"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - CHECK_PARSER_ERR(parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount)); - snprintf(outKey, outKeyLen, "Node ID"); - return PARSER_OK; - case 3: - snprintf(outKey, outKeyLen, "Node Role"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "UInt8", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - CHECK_PARSER_ERR(parser_printArgumentString(&parser_tx_obj.arguments.argCtx[2], - outVal, - outValLen, - pageIdx, - pageCount)); - snprintf(outKey, outKeyLen, "Networking Address"); - return PARSER_OK; - case 5: - CHECK_PARSER_ERR(parser_printArgumentString(&parser_tx_obj.arguments.argCtx[3], - outVal, - outValLen, - pageIdx, - pageCount)); - snprintf(outKey, outKeyLen, "Networking Key"); - return PARSER_OK; - case 6: - CHECK_PARSER_ERR(parser_printArgumentString(&parser_tx_obj.arguments.argCtx[4], - outVal, - outValLen, - pageIdx, - pageCount)); - snprintf(outKey, outKeyLen, "Staking Key"); - return PARSER_OK; - case 7: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 5, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 8; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemStakeNewTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Stake FLOW from Lockbox"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemRestakeUnstakedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Restake Unstaked FLOW"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemRestakeRewardedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Restake Rewarded FLOW"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemUnstakeTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Unstake FLOW"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemUnstakeAllTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Unstake All FLOW"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - default: - break; - } - displayIdx -= 2; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemWithdrawUnstakedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Withdraw Unstaked FLOW to Lockbox"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemWithdrawRewardedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Withdraw Rewarded FLOW to Lockbox"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemRegisterOperatorNode(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Register Operator Node"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Operator Address"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "Address", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[1], - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 2, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 5; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemRegisterDelegator(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Register Delegator"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemDelegateNewTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Delegate FLOW from Lockbox"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemRestakeUnstakedDelegatedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Re-delegate Unstaked FLOW"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemRestakeRewardedDelegatedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Re-delegate Rewarded FLOW"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemUnstakeDelegatedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Unstake Delegated FLOW"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemWithdrawUnstakedDelegatedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Withdraw Undelegated FLOW to Lockbox"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemWithdrawRewardedDelegatedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Withdraw Delegate Rewards to Lockbox"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItemUpdateNetworkingAddress(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Update Networking Address"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Address"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.01 -parser_error_t parser_getItemSetupStaingCollection(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Setup Staking Collection"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - default: - break; - } - displayIdx -= 2; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.02 -parser_error_t parser_getItemRegisterDelegatorSCO(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Register Delegator"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.03 -#define SCO03_REGISTER_NODE_MAX_PUB_KEYS 3 -parser_error_t parser_getItemRegisterNodeSCO(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - zemu_log_stack("parser_getItemRegisterNodeSCO"); - *pageCount = 1; - - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Register Node"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Node Role"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "UInt8", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - snprintf(outKey, outKeyLen, "Netw. Addr."); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[2], - outVal, - outValLen, - pageIdx, - pageCount); - case 5: - snprintf(outKey, outKeyLen, "Netw. Key"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[3], - outVal, - outValLen, - pageIdx, - pageCount); - case 6: - snprintf(outKey, outKeyLen, "Staking Key"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[4], - outVal, - outValLen, - pageIdx, - pageCount); - case 7: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 5, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 8; - - uint8_t pkCount = 0; - CHECK_PARSER_ERR(_countArgumentOptionalItems(&parser_tx_obj.arguments, - 6, - SCO03_REGISTER_NODE_MAX_PUB_KEYS, - &pkCount)) - if (displayIdx < pkCount) { - snprintf(outKey, outKeyLen, "Pub key %d", displayIdx + 1); - CHECK_PARSER_ERR(parser_printArgumentOptionalPublicKeys(&parser_tx_obj.arguments.argCtx[6], - displayIdx, - outVal, - outValLen, - pageIdx, - pageCount)) - return PARSER_OK; - } - displayIdx -= pkCount; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.04 -#define SCO04_CREATE_MACHINE_ACCOUNT_MAX_PUB_KEYS 3 -parser_error_t parser_getItemCreateMachineAccount(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - zemu_log_stack("parser_getItemCreateAccount"); - *pageCount = 1; - - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Create Machine Account"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - - uint8_t pkCount = 0; - CHECK_PARSER_ERR(_countArgumentItems(&parser_tx_obj.arguments, - 1, - SCO04_CREATE_MACHINE_ACCOUNT_MAX_PUB_KEYS, - &pkCount)); - if (displayIdx < pkCount) { - snprintf(outKey, outKeyLen, "Pub key %d", displayIdx + 1); - CHECK_PARSER_ERR(parser_printArgumentPublicKeys(&parser_tx_obj.arguments.argCtx[1], - displayIdx, - outVal, - outValLen, - pageIdx, - pageCount)) - return PARSER_OK; - } - displayIdx -= pkCount; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.05 -parser_error_t parser_getItemRequestUnstaking(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Request Unstaking"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Delegator ID"); - return parser_printArgumentOptionalDelegatorID(&parser_tx_obj.arguments, - 1, - "UInt32", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 2, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 5; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.06 -parser_error_t parser_getItemStakeNewTokensSCO(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Stake New Tokens"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Delegator ID"); - return parser_printArgumentOptionalDelegatorID(&parser_tx_obj.arguments, - 1, - "UInt32", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 2, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 5; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.07 -parser_error_t parser_getItemStakeRewardTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Stake Reward Tokens"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Delegator ID"); - return parser_printArgumentOptionalDelegatorID(&parser_tx_obj.arguments, - 1, - "UInt32", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 2, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 5; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.08 -parser_error_t parser_getItemStakeUnstakedTokens(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Stake Unstaked Tokens"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Delegator ID"); - return parser_printArgumentOptionalDelegatorID(&parser_tx_obj.arguments, - 1, - "UInt32", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 2, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 5; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.09 -parser_error_t parser_getItemUnstakeAll(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Unstake All"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 3; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.10 -parser_error_t parser_getItemWithdrawRewardTokensSCO(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Withdraw Reward Tokens"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Delegator ID"); - return parser_printArgumentOptionalDelegatorID(&parser_tx_obj.arguments, - 1, - "UInt32", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 2, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 5; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.11 -parser_error_t parser_getItemWithdrawUnstakedTokensSCO(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Withdraw Unstaked Tokens"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Delegator ID"); - return parser_printArgumentOptionalDelegatorID(&parser_tx_obj.arguments, - 1, - "UInt32", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 2, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 5; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.12 -parser_error_t parser_getItemCloseStake(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Close Stake"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Delegator ID"); - return parser_printArgumentOptionalDelegatorID(&parser_tx_obj.arguments, - 1, - "UInt32", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.13 -parser_error_t parser_getItemTransferNode(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Transfer Node"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Address"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "Address", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.14 -parser_error_t parser_getItemTransferDelegator(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Transfer Delegator"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Delegator ID"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "UInt32", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 4: - snprintf(outKey, outKeyLen, "Address"); - return parser_printArgument(&parser_tx_obj.arguments, - 2, - "Address", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 5; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.15 -parser_error_t parser_getItemWithdrawFromMachineAccount(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Withdraw From Machine Account"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// SCO.16 -parser_error_t parser_getItemUpdateNetworkingAddressSCO(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Update Networking Address"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Node ID"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[0], - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Address"); - return parser_printArgumentString(&parser_tx_obj.arguments.argCtx[1], - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// FUSD.01 -parser_error_t parser_getItemSetupFUSDVault(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Setup FUSD Vault"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - default: - break; - } - displayIdx -= 2; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// FUSD.02 -parser_error_t parser_getItemTransferFUSD(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Transfer FUSD"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Recipient"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "Address", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// TS.01 -parser_error_t parser_getItemSetUpTopShotCollection(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Set Up Top Shot Collection"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - default: - break; - } - displayIdx -= 2; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// TS.02 -parser_error_t parser_getItemTransferTopShotMoment(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Transfer Top Shot Moment"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Moment ID"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "UInt64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Address"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "Address", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// USDC.01 -parser_error_t parser_getItemSetupUSDCVault(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Setup USDC Vault"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - default: - break; - } - displayIdx -= 2; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -// USDC.02 -parser_error_t parser_getItemTransferUSDC(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, - uint16_t outKeyLen, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount) { - *pageCount = 1; - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Type"); - snprintf(outVal, outValLen, "Transfer USDC"); - return PARSER_OK; - case 1: - snprintf(outKey, outKeyLen, "ChainID"); - return parser_printChainID(&parser_tx_obj.payer, outVal, outValLen, pageIdx, pageCount); - case 2: - snprintf(outKey, outKeyLen, "Amount"); - return parser_printArgument(&parser_tx_obj.arguments, - 0, - "UFix64", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - case 3: - snprintf(outKey, outKeyLen, "Recipient"); - return parser_printArgument(&parser_tx_obj.arguments, - 1, - "Address", - JSMN_STRING, - outVal, - outValLen, - pageIdx, - pageCount); - default: - break; - } - displayIdx -= 4; - return parser_getItemAfterArguments(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); -} - -parser_error_t parser_getItem(const parser_context_t *ctx, - uint16_t displayIdx, +parser_error_t parser_getItem(__Z_UNUSED const parser_context_t *ctx, + uint8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) { - MEMZERO(outKey, outKeyLen); - MEMZERO(outVal, outValLen); - snprintf(outKey, outKeyLen, "? %d", displayIdx); - snprintf(outVal, outValLen, "?"); - *pageCount = 0; - - uint8_t numItems; - CHECK_PARSER_ERR(parser_getNumItems(ctx, &numItems)) - CHECK_APP_CANARY() - - if (displayIdx < 0 || displayIdx >= numItems) { - return PARSER_NO_DATA; - } - *pageCount = 1; - - switch (parser_tx_obj.script.type) { - case SCRIPT_UNKNOWN: - return PARSER_UNEXPECTED_SCRIPT; - case SCRIPT_TOKEN_TRANSFER: - return parser_getItemTokenTransfer(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_CREATE_ACCOUNT: - return parser_getItemCreateAccount(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_ADD_NEW_KEY: - return parser_getItemAddNewKey(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH01_WITHDRAW_UNLOCKED_TOKENS: - return parser_getItemWithdrawUnlockedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH02_DEPOSIT_UNLOCKED_TOKENS: - return parser_getItemDepositUnlockedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH06_REGISTER_NODE: - return parser_getItemRegisterNode(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH08_STAKE_NEW_TOKENS: - return parser_getItemStakeNewTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH09_RESTAKE_UNSTAKED_TOKENS: - return parser_getItemRestakeUnstakedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH10_RESTAKE_REWARDED_TOKENS: - return parser_getItemRestakeRewardedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH11_UNSTAKE_TOKENS: - return parser_getItemUnstakeTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH12_UNSTAKE_ALL_TOKENS: - return parser_getItemUnstakeAllTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH13_WITHDRAW_UNSTAKED_TOKENS: - return parser_getItemWithdrawUnstakedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH14_WITHDRAW_REWARDED_TOKENS: - return parser_getItemWithdrawRewardedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH16_REGISTER_OPERATOR_NODE: - return parser_getItemRegisterOperatorNode(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH17_REGISTER_DELEGATOR: - return parser_getItemRegisterDelegator(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH19_DELEGATE_NEW_TOKENS: - return parser_getItemDelegateNewTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH20_RESTAKE_UNSTAKED_DELEGATED_TOKENS: - return parser_getItemRestakeUnstakedDelegatedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH21_RESTAKE_REWARDED_DELEGATED_TOKENS: - return parser_getItemRestakeRewardedDelegatedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH22_UNSTAKE_DELEGATED_TOKENS: - return parser_getItemUnstakeDelegatedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH23_WITHDRAW_UNSTAKED_DELEGATED_TOKENS: - return parser_getItemWithdrawUnstakedDelegatedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH24_WITHDRAW_REWARDED_DELEGATED_TOKENS: - return parser_getItemWithdrawRewardedDelegatedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TH25_UPDATE_NETWORKING_ADDRESS: - return parser_getItemUpdateNetworkingAddress(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO01_SETUP_STAKING_COLLECTION: - return parser_getItemSetupStaingCollection(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO02_REGISTER_DELEGATOR: - return parser_getItemRegisterDelegatorSCO(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO03_REGISTER_NODE: - return parser_getItemRegisterNodeSCO(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO04_CREATE_MACHINE_ACCOUNT: - return parser_getItemCreateMachineAccount(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO05_REQUEST_UNSTAKING: - return parser_getItemRequestUnstaking(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO06_STAKE_NEW_TOKENS: - return parser_getItemStakeNewTokensSCO(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO07_STAKE_REWARD_TOKENS: - return parser_getItemStakeRewardTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO08_STAKE_UNSTAKED_TOKENS: - return parser_getItemStakeUnstakedTokens(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO09_UNSTAKE_ALL: - return parser_getItemUnstakeAll(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO10_WITHDRAW_REWARD_TOKENS: - return parser_getItemWithdrawRewardTokensSCO(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO11_WITHDRAW_UNSTAKED_TOKENS: - return parser_getItemWithdrawUnstakedTokensSCO(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO12_CLOSE_STAKE: - return parser_getItemCloseStake(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO13_TRANSFER_NODE: - return parser_getItemTransferNode(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO14_TRANSFER_DELEGATOR: - return parser_getItemTransferDelegator(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO15_WITHDRAW_FROM_MACHINE_ACCOUNT: - return parser_getItemWithdrawFromMachineAccount(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_SCO16_UPDATE_NETWORKING_ADDRESS: - return parser_getItemUpdateNetworkingAddressSCO(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_FUSD01_SETUP_FUSD_VAULT: - return parser_getItemSetupFUSDVault(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_FUSD02_TRANSFER_FUSD: - return parser_getItemTransferFUSD(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TS01_SET_UP_TOPSHOT_COLLECTION: - return parser_getItemSetUpTopShotCollection(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_TS02_TRANSFER_TOP_SHOT_MOMENT: - return parser_getItemTransferTopShotMoment(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_USDC01_SETUP_USDC_VAULT: - return parser_getItemSetupUSDCVault(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - case SCRIPT_USDC02_TRANSFER_USDC: - return parser_getItemTransferUSDC(ctx, - displayIdx, - outKey, - outKeyLen, - outVal, - outValLen, - pageIdx, - pageCount); - } - - return PARSER_UNEXPECTED_SCRIPT; + if (displayIdx > INT8_MAX) { + return PARSER_DISPLAY_IDX_OUT_OF_RANGE; + } + return parser_getItem_internal((int8_t *) &displayIdx, + outKey, + outKeyLen, + outVal, + outValLen, + pageIdx, + pageCount); } diff --git a/src/parser_tx.h b/src/parser_tx.h index 6254ddc2..c618dcf1 100644 --- a/src/parser_tx.h +++ b/src/parser_tx.h @@ -27,17 +27,20 @@ extern "C" { const char *parser_getErrorDescription(parser_error_t err); //// parses a tx buffer -parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen); +parser_error_t parser_parse(parser_context_t *ctx, + const uint8_t *data, + size_t dataLen, + script_parsed_type_t scriptType); //// verifies tx fields parser_error_t parser_validate(const parser_context_t *ctx); //// returns the number of items in the current parsing context -parser_error_t parser_getNumItems(const parser_context_t *ctx, uint8_t *num_items); +parser_error_t parser_getNumItems(__Z_UNUSED const parser_context_t *ctx, uint8_t *num_items); // retrieves a readable output for each field / page -parser_error_t parser_getItem(const parser_context_t *ctx, - uint16_t displayIdx, +parser_error_t parser_getItem(__Z_UNUSED const parser_context_t *ctx, + uint8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, @@ -45,23 +48,71 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t pageIdx, uint8_t *pageCount); +#ifdef __cplusplus ////for testing purposes -parser_error_t parser_printArgumentOptionalDelegatorID(const flow_argument_list_t *v, - uint8_t argIndex, - const char *expectedType, - jsmntype_t jsonType, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount); +parser_error_t parser_printArgument(const flow_argument_list_t *v, + uint8_t argIndex, + const char *expectedType, + jsmntype_t jsonType, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount); -parser_error_t parser_printArgumentOptionalPublicKeys(const parser_context_t *argumentCtx, - uint8_t argumentIndex, - char *outVal, - uint16_t outValLen, - uint8_t pageIdx, - uint8_t *pageCount); +parser_error_t parser_printOptionalArgument(const flow_argument_list_t *v, + uint8_t argIndex, + const char *expectedType, + jsmntype_t jsonType, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount); -#ifdef __cplusplus -} +parser_error_t parser_printArgumentArray(const flow_argument_list_t *v, + uint8_t argIndex, + uint8_t arrayIndex, + const char *expectedType, + jsmntype_t jsonType, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount); + +parser_error_t parser_printArgumentOptionalArray(const flow_argument_list_t *v, + uint8_t argIndex, + uint8_t arrayIndex, + const char *expectedType, + jsmntype_t jsonType, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount); + +parser_error_t parser_printArbitraryPrepareToDisplay(const flow_argument_list_t *v, + uint8_t argIndex, + uint16_t *flags, + uint16_t *jsonToken); + +parser_error_t parser_printArbitraryArgumentFirstScreen(const flow_argument_list_t *v, + uint8_t argIndex, + uint16_t flags, + uint16_t jsonToken, + char *outKey, + uint16_t outKeyLen, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount); + +parser_error_t parser_printArbitraryArrayElements(const flow_argument_list_t *v, + uint8_t argIndex, + uint16_t arrayIndex, + uint16_t arrayJsonToken, + char *outKey, + uint16_t outKeyLen, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, + uint8_t *pageCount); +} // end extern C #endif diff --git a/src/parser_txdef.h b/src/parser_txdef.h index 02a1123a..ab3845ff 100644 --- a/src/parser_txdef.h +++ b/src/parser_txdef.h @@ -24,60 +24,11 @@ extern "C" { #endif +#include #include #include #include "crypto.h" -#include "template_hashes.h" - -#define PARSER_MAX_ARGCOUNT 10 - -typedef enum { - SCRIPT_UNKNOWN, - SCRIPT_TOKEN_TRANSFER, - SCRIPT_CREATE_ACCOUNT, - SCRIPT_ADD_NEW_KEY, - SCRIPT_TH01_WITHDRAW_UNLOCKED_TOKENS, - SCRIPT_TH02_DEPOSIT_UNLOCKED_TOKENS, - SCRIPT_TH06_REGISTER_NODE, - SCRIPT_TH08_STAKE_NEW_TOKENS, - SCRIPT_TH09_RESTAKE_UNSTAKED_TOKENS, - SCRIPT_TH10_RESTAKE_REWARDED_TOKENS, - SCRIPT_TH11_UNSTAKE_TOKENS, - SCRIPT_TH12_UNSTAKE_ALL_TOKENS, - SCRIPT_TH13_WITHDRAW_UNSTAKED_TOKENS, - SCRIPT_TH14_WITHDRAW_REWARDED_TOKENS, - SCRIPT_TH16_REGISTER_OPERATOR_NODE, - SCRIPT_TH17_REGISTER_DELEGATOR, - SCRIPT_TH19_DELEGATE_NEW_TOKENS, - SCRIPT_TH20_RESTAKE_UNSTAKED_DELEGATED_TOKENS, - SCRIPT_TH21_RESTAKE_REWARDED_DELEGATED_TOKENS, - SCRIPT_TH22_UNSTAKE_DELEGATED_TOKENS, - SCRIPT_TH23_WITHDRAW_UNSTAKED_DELEGATED_TOKENS, - SCRIPT_TH24_WITHDRAW_REWARDED_DELEGATED_TOKENS, - SCRIPT_TH25_UPDATE_NETWORKING_ADDRESS, - SCRIPT_SCO01_SETUP_STAKING_COLLECTION, - SCRIPT_SCO02_REGISTER_DELEGATOR, - SCRIPT_SCO03_REGISTER_NODE, - SCRIPT_SCO04_CREATE_MACHINE_ACCOUNT, - SCRIPT_SCO05_REQUEST_UNSTAKING, - SCRIPT_SCO06_STAKE_NEW_TOKENS, - SCRIPT_SCO07_STAKE_REWARD_TOKENS, - SCRIPT_SCO08_STAKE_UNSTAKED_TOKENS, - SCRIPT_SCO09_UNSTAKE_ALL, - SCRIPT_SCO10_WITHDRAW_REWARD_TOKENS, - SCRIPT_SCO11_WITHDRAW_UNSTAKED_TOKENS, - SCRIPT_SCO12_CLOSE_STAKE, - SCRIPT_SCO13_TRANSFER_NODE, - SCRIPT_SCO14_TRANSFER_DELEGATOR, - SCRIPT_SCO15_WITHDRAW_FROM_MACHINE_ACCOUNT, - SCRIPT_SCO16_UPDATE_NETWORKING_ADDRESS, - SCRIPT_FUSD01_SETUP_FUSD_VAULT, - SCRIPT_FUSD02_TRANSFER_FUSD, - SCRIPT_TS01_SET_UP_TOPSHOT_COLLECTION, - SCRIPT_TS02_TRANSFER_TOP_SHOT_MOMENT, - SCRIPT_USDC01_SETUP_USDC_VAULT, - SCRIPT_USDC02_TRANSFER_USDC, -} script_type_e; +#include "script_parser.h" typedef enum { CHAIN_ID_UNKNOWN, @@ -87,10 +38,8 @@ typedef enum { } chain_id_e; typedef struct { - parser_context_t ctx; uint8_t digest[CX_SHA256_SIZE]; - script_type_e type; -} flow_script_t; +} flow_script_hash_t; typedef struct { parser_context_t ctx; @@ -127,7 +76,10 @@ typedef struct { } flow_proposal_authorizers_t; typedef struct { - flow_script_t script; + bool metadataInitialized; + parsed_tx_metadata_t metadata; + script_parsed_elements_t parsedScript; + flow_script_hash_t hash; flow_argument_list_t arguments; flow_reference_block_id_t referenceBlockId; flow_gaslimit_t gasLimit; diff --git a/tests/application_client/flow_command_sender.py b/tests/application_client/flow_command_sender.py index 4528e332..52b35708 100644 --- a/tests/application_client/flow_command_sender.py +++ b/tests/application_client/flow_command_sender.py @@ -7,6 +7,8 @@ from ragger.bip import CurveChoice from ragger.utils.misc import split_message +from application_client.txMerkleTree import merkleTree, merkleIndex + MAX_APDU_LEN: int = 255 MAX_SLOTS = 64 @@ -27,6 +29,9 @@ class P1(IntEnum): P1_INIT = 0x00 P1_ADD = 0x01 P1_LAST = 0x02 + P1_METADATA = 0x03 + P1_PROOF_ONGOING = 0x04 + P1_PROOF_LAST = 0x05 P1_LAST_MESSAGE = 0x10 class P2(IntEnum): @@ -249,19 +254,59 @@ def sign_tx( p1=P1.P1_ADD, data=msg) + # TODO: nft1 and nft2 if (hint == "message"): - p1 = P1.P1_LAST_MESSAGE - p2 = 0 + with self.backend.exchange_async(cla=ClaType.CLA_APP, + ins=InsType.SIGN, + p1=P1.P1_LAST_MESSAGE, + data=messages[-1]) as response: + yield response else: - p1 = P1.P1_LAST - p2 = P2.P2_NO_METADATA + scriptHash = hint + merkleI = merkleIndex.get(scriptHash[0:16], None) + if (merkleI is None): + with self.backend.exchange_async(cla=ClaType.CLA_APP, + ins=InsType.SIGN, + p1=P1.P1_LAST, + p2=P2.P2_NO_METADATA, + data=messages[-1]) as response: + yield response + else: + metadata = merkleTree["children"][merkleI[0]]["children"][merkleI[1]]["children"][merkleI[2]]["children"][merkleI[3]]["children"][0] + merkleTreeLevel1 = "".join(ch["hash"] for ch in merkleTree["children"][merkleI[0]]["children"][merkleI[1]]["children"][merkleI[2]]["children"]) + merkleTreeLevel2 = "".join(ch["hash"] for ch in merkleTree["children"][merkleI[0]]["children"][merkleI[1]]["children"]) + merkleTreeLevel3 = "".join(ch["hash"] for ch in merkleTree["children"][merkleI[0]]["children"]) + merkleTreeLevel4 = "".join(ch["hash"] for ch in merkleTree["children"]) + + #send the rest of the transaction + self.backend.exchange(cla=ClaType.CLA_APP, + ins=InsType.SIGN, + p1=P1.P1_ADD, + data=messages[-1]) + #send metadata + self.backend.exchange(cla=ClaType.CLA_APP, + ins=InsType.SIGN, + p1=P1.P1_METADATA, + data=bytes.fromhex(metadata)) + #send proof + self.backend.exchange(cla=ClaType.CLA_APP, + ins=InsType.SIGN, + p1=P1.P1_PROOF_ONGOING, + data=bytes.fromhex(merkleTreeLevel1)) + self.backend.exchange(cla=ClaType.CLA_APP, + ins=InsType.SIGN, + p1=P1.P1_PROOF_ONGOING, + data=bytes.fromhex(merkleTreeLevel2)) + self.backend.exchange(cla=ClaType.CLA_APP, + ins=InsType.SIGN, + p1=P1.P1_PROOF_ONGOING, + data=bytes.fromhex(merkleTreeLevel3)) + with self.backend.exchange_async(cla=ClaType.CLA_APP, + ins=InsType.SIGN, + p1=P1.P1_PROOF_LAST, + data=bytes.fromhex(merkleTreeLevel4)) as response: + yield response - with self.backend.exchange_async(cla=ClaType.CLA_APP, - ins=InsType.SIGN, - p1=p1, - p2=p2, - data=messages[-1]) as response: - yield response def get_async_response(self) -> Optional[RAPDU]: """ Asynchronous APDU response """ diff --git a/tests/application_client/txMerkleTree.py b/tests/application_client/txMerkleTree.py new file mode 100644 index 00000000..d95d28bb --- /dev/null +++ b/tests/application_client/txMerkleTree.py @@ -0,0 +1,2970 @@ +merkleTree = { + "hash": "fe82420959875826f6a617959b006c31fa8975e455dbf2494f5ff3740a1ece51", + "children": [ + { + "hash": "9053a0e87b7e66413b6552205fa31f3c2ed42cdb97bd3d543a130aebb29dda1e", + "children": [ + { + "hash": "07ea7f7407fda8657a35aeb24075cc654b9f06ae61d6cd1a772920ee3c6209a1", + "children": [ + { + "hash": "aa44049d7eb26d667c3714b8fcf78380878e658e22268510ff9f72e69b29decd", + "children": [ + { + "hash": "27b42f7104fa842ba664b1c199325f8339dd65db575938cef8498d082727c3ef", + "children": [ + "01eef2d0494448554177612e63026256258339230cbc6931ded78d6149443c6173437265617465204163636f756e740001030105507562206b65790000537472696e670003" + ] + }, + { + "hash": "caf67b7d0995d18f289676386108de6b4c134059b000a6f1ec0c80b857b0ec38", + "children": [ + "01595c86561441b32b2b91ee03f9e10ca6efa7b41bcc994f51317ec0aa9d8f8a42416464204e6577204b6579000101507562206b65790000537472696e670003" + ] + }, + { + "hash": "0c538359a1be1553e729aad363de4eec2dcdcc666320eb85899c2f978c5fbf94", + "children": [ + "03ca80b628d985b358ae1cb136bcd976997c942fa10dbabfeafb4e20fa66a5a5e2d56f4e1d2355cdcfacfd01e471459c6ef168bfdf84371a685ccf31cf3cdedc2d47851586d962335e3f7d9e5d11a4c527ee4b5fd1c3895e3ce1b9c2821f60b166546f6b656e205472616e73666572000201416d6f756e74000055466978363400030144657374696e6174696f6e0001416464726573730003" + ] + }, + { + "hash": "033592e53bc3280098d0043e4770cfaf7675a56b9c56d836a5e2252de61dc3a8", + "children": [ + "020ffaf77ab320ce4cc9602d39b89c85f094ebcea571ed324537e703bc07b0fdc4aa7fecdf159e71bd0b029e40b22643fb443161e67796f42bac68e9bab4630e2953657475702046555344205661756c740000" + ] + }, + { + "hash": "5f7f784ed0a40905ed96c8b96588a84b025eb04d593a7662bb66b9eb3a7e962a", + "children": [ + "02f22ca4b350a79c724f6471d5a6a7a0efa7ba9aeebb7fed2843a3ddd6e42c2e1c180cef7053a5f0ae66e19e3a96cc3b9eb7da29767fb5d6938239bf1f8e1dc2845472616e736665722046555344000201416d6f756e740000554669783634000301526563697069656e740001416464726573730003" + ] + }, + { + "hash": "12c65f0494d2165cbeaa141d705647d8071b528999782dd54a84a44ad2cf3d7b", + "children": [ + "02a524b4094fcaf1051dbf43ac33ff80bb2f553670c58eeeb719757972a25d6b500e5c2445c0b1016eed4f60c429f233aa0bb223a0d9ff2aedffce00a58037a2bf5365747570205374616b696e6720436f6c6c656374696f6e0000" + ] + }, + { + "hash": "6730cd08974b8ccd1102dd2f5159a8181cc1ede512f6d537d8eea46556e16944", + "children": [ + "02c26f69a33ead535e7d597cec4567c6c70170e86fd85ec708f5381e50d43871e2c5636d510872a16eb06996dacb43d6a28f8f72ff1b05b2eb03416cc711d9bb1f52656769737465722044656c656761746f720002014e6f64652049440000537472696e67000301416d6f756e7400015546697836340003" + ] + } + ] + }, + { + "hash": "a0affd7f78688c482a5a5bc416fa49f5844288fc61b0ee1b40cd38e3c2fbeb36", + "children": [ + { + "hash": "099d7e6cfa53ac9150cc79588f5282d3f7bb21a7fb0596ccfcf47bcb380b0fe1", + "children": [ + "02f47efa834bc0559afae9a660b2efefddd0c6dc6e1bbcf9c3994e45ea9e5135ec99997236b6d76caa298331d5cef77cbdf83c1af64584ece537a780ba4ac468835265676973746572204e6f64650007014e6f64652049440000537472696e670003014e6f646520526f6c65000155496e74380003014e6574772e20416464726573730002537472696e670003014e6574772e204b65790003537472696e670003015374616b696e67204b65790004537472696e67000301416d6f756e74000555466978363400030400035075622e204b65790006537472696e670003" + ] + }, + { + "hash": "2b5f06235697099c02556240d18fcad69e9a48594d75036edff5d0d875ec746e", + "children": [ + "029246ec9b7a5c81151156e7c2f6d356f68b1b884f88728daca46b968d9a46cd5a79de7119aea61bdafb39cc3d1f4fa17ca802c2732726a86d2c636dbc19808b685265676973746572204e6f64650007014e6f64652049440000537472696e670003014e6f646520526f6c65000155496e74380003014e6574772e20416464726573730002537472696e670003014e6574772e204b65790003537472696e670003015374616b696e67204b65790004537472696e67000301416d6f756e74000555466978363400030400035075622e204b65790006537472696e670003" + ] + }, + { + "hash": "ae90b6bab2a077c5d5e3d052fc78908e251e97cfd9407c35bf49a8d284acd3c6", + "children": [ + "02e79df145af42488e3da1d1b2e50a38a2084229896d670884f278a2119dc3bf9ec2442b498eea025099815ea613d6407407192dc12ad70e1a4f47936db804a841437265617465204d616368696e65204163636f756e740002014e6f64652049440000537472696e6700030300035075622e204b65790001537472696e670003" + ] + }, + { + "hash": "60232ddb87d93f0a82735425ae06661d752b45345ab36a2805147f02d86ab779", + "children": [ + "0286c69d731560f3bff549c5f180eb4219bfe650ae4efec8e0c5b5ad3ebed54a92dd3b327b09087ea7f8e92a22a6b04a3c6ca33b868b430c4f15f251658c38c1b7437265617465204d616368696e65204163636f756e740002014e6f64652049440000537472696e6700030300035075622e204b65790001537472696e670003" + ] + }, + { + "hash": "8350e6bc5d5a7c5c70ba73c8190e2d166ca21377b3e4204ec7103e34604c9a2b", + "children": [ + "02b00f6b3b9d8d7d4a9a8ad14fce11ee0edb23c39c56a8c1351e6b597f53f2fb71a552951c5e6300a118610fbf2d36b3073ee266e1d26787d04717c141976ef78c5265717565737420556e7374616b696e670003014e6f64652049440000537472696e6700030244656c656761746f72204944000155496e743332000301416d6f756e7400025546697836340003" + ] + }, + { + "hash": "fa8432e39483a5950c41183aff923fc39f12905eea447f0d708e204f2f751692", + "children": [ + "021307928440cee4289235793d6ff860a24315f7b6a5d5907a145dcc5f83702a2c8e10ac56db8ec5d5e0051d3c9608fabc8edd6abed983f6d3a254e7668a54b32b5374616b65204e657720546f6b656e730003014e6f64652049440000537472696e6700030244656c656761746f72204944000155496e743332000301416d6f756e7400025546697836340003" + ] + }, + { + "hash": "0c3a64b8381947ae38d4d01f057f2083fdf8cbe3b9ec780a345fecbc26eb98d0", + "children": [ + "02d7aca7113a7aa03e0afd20ee36f4873779708a02ac4c6985017740c2ecea3d62907c4cfd67a98a8003393c64dc74eb7a957b229352a266139a542bb105ac4c405374616b6520526577617264656420546f6b656e730003014e6f64652049440000537472696e6700030244656c656761746f72204944000155496e743332000301416d6f756e7400025546697836340003" + ] + } + ] + }, + { + "hash": "a1b4c2165e1fceba7324712485844e04e5e955706ae328f6cfd64c49686a8104", + "children": [ + { + "hash": "c32ced8567df06cf7b803b4462d3dce5594274870833b505b39c23c620d9565d", + "children": [ + "023595fcd68cff445c65ad99f8d4d726b5e28807b061800769c41cbe3adb98aeec082e690b9647182cf6969db1a0fa8e0f1728da6db01fe0d462e9f0841c268cbb5374616b6520556e7374616b656420546f6b656e730003014e6f64652049440000537472696e6700030244656c656761746f72204944000155496e743332000301416d6f756e7400025546697836340003" + ] + }, + { + "hash": "72919051bfc4b6791305a53562ab62bab2ab12fa78040fefebb9677d9c6d3e6d", + "children": [ + "020bde358f3965ba2f4c18fb45b6536857c3f53d7d3b740fe66fe93a4ebf7524c1df9c6486baa6f8f685368ea216659239cb81fa8ebd9062a9723edb54ca0d7525556e7374616b6520416c6c0001014e6f64652049440000537472696e670003" + ] + }, + { + "hash": "4e1470252de85beeaf3547dbb3597bbbce4023c9b3a8fe559736bd69b05a9659", + "children": [ + "023af182f568b37a8067d3fb524afcfe96991c85a928bf7651e730be0e15fdb72d27a2b60d538b8bb883b602ea83d1697986a29dd69a44a9209dc75affb9e63299576974686472617720526577617264656420546f6b656e730003014e6f64652049440000537472696e6700030244656c656761746f72204944000155496e743332000301416d6f756e7400025546697836340003" + ] + }, + { + "hash": "16541b176b0721f3029fd8bd0763ba20338b93fdb7fca214427ce0855847d71a", + "children": [ + "0268879197d961bb104a56e1e7d35660436fe4c52ed78f79d97fa50aa9e96fabf06d50ab1ef3d74203081c38306da74f5ad8fdd489e49fba732f8ba194d0c781c8576974686472617720556e7374616b656420546f6b656e730003014e6f64652049440000537472696e6700030244656c656761746f72204944000155496e743332000301416d6f756e7400025546697836340003" + ] + }, + { + "hash": "7d29c41e4fd4f0029db68b83b0e4cca4ad90be98aa1375900b4d0a7ec8700727", + "children": [ + "02079aaa9cfb22138415056b43d5d91e8d73bd8bd5f37ebff4f4023d33ea6d2f25ecdffc1ae67479bc20c06eba6c776ff37b9523660ff1cd3129a3924d92484884436c6f7365205374616b650002014e6f64652049440000537472696e6700030244656c656761746f72204944000155496e7433320003" + ] + }, + { + "hash": "15cb00985ecc29ff4a790c109d18ba52f99e0d94f42d569cc476ffa42e66e3bd", + "children": [ + "022386d7ae1a5b936e3914729ee34e01d53a8fbd2e403512ec1beccb4062c231ebcdc3a63d0c75ea95b414becb6fbb8f5a8004236d48661cd3c3d4f540ee4d422e5472616e73666572204e6f64650002014e6f64652049440000537472696e67000301416464726573730001416464726573730003" + ] + }, + { + "hash": "587e64bc3625045d275b6a7553176b272a3487ede34a48d7d66c98e9ab56af1b", + "children": [ + "0253b096b4850a30894e7b272ec5c39e2b2f4a23f8c40e76a3c64cfc63dc2999b6b34d6fafcc5a4d0ed9cf92e168a08d0674c93341e2393ee72dde6664918ec2405472616e736665722044656c656761746f720003014e6f64652049440000537472696e6700030144656c656761746f72204944000155496e743332000301416464726573730002416464726573730003" + ] + } + ] + }, + { + "hash": "d0b4592fc4f996b16fea83ab8dede757ea8bc270f4e1fbf2301e02fd38d175e3", + "children": [ + { + "hash": "08b2978dff804b0a39bb3b382a0d0e02fa7977297aab0cafcbcca6324fb7c97f", + "children": [ + "0239a126038522c6c964d53aaf78dde55bfe80929091510792fe49678bb22cbd96f9c48e18bda7f113e82711a4c95dfd151c6600ed9fbf46ceb22566d6c5728c6f57697468647261772046726f6d204d616368696e65204163636f756e740002014e6f64652049440000537472696e67000301416d6f756e7400015546697836340003" + ] + }, + { + "hash": "2af46777eb5a0ef7598b8472bcdde5e6139f4880cfb1313c97f0e81851eaa2ac", + "children": [ + "0260f2cf219d56b19dc7fd223caed42dda9143c87b1b0d2c21a9652e12a3714133ff067b40ac67020ef864cd14842f62023254da34dd2ded56affa1364305bf1c5557064617465204e6574776f726b696e6720416464726573730002014e6f64652049440000537472696e67000301416464726573730001537472696e670003" + ] + }, + { + "hash": "906e51df4d75e43aeb3042508b2f2f991401e5817820e5801c3b8e9e8a0fe419", + "children": [ + "026e73db6edd0190f5311f6adc5f2b1f27e9e60c68574b00ee90da867da52cdbb1a2146e3e6e7718779ce59376b88760c154d82b7d132fe2c377114ec7cf434e7b576974686472617720556e6c6f636b656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "9c6ed50847ac0fea0a8d90d7cdc72cac07a0dbf9997c017749b9266c8c471ad5", + "children": [ + "020cb11c10b86d2afeae086ef511d28b14760eb854935a0b0dcfeecc85db847f4874355dc8df221bc0d170b2fe8deacd6f1f554d6beea58ad9fee7a07f740eaefe4465706f73697420556e6c6f636b656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "14b699e967e1fe928a4e3d49ceadbfad9f6a2bc84a8498cd0a643f2df8fd6ca5", + "children": [ + "02b6a3502d2205eb05ec18772c13b91cc88a056b325c2617c57948d38cab8db600b64e0e3ed9eb28789198f2b0437f55f750bfa76da99450f63be6543bde66122a5265676973746572204e6f64650006014e6f64652049440000537472696e670003014e6f646520526f6c65000155496e74380003014e6574772e20416464726573730002537472696e670003014e6574772e204b65790003537472696e670003015374616b696e67204b65790004537472696e67000301416d6f756e7400055546697836340003" + ] + }, + { + "hash": "d7bfefba9a51e8ea934e2cd6e3d808cbb8b2f16a616254067bea6b1a6a98b77e", + "children": [ + "02d5689b89f53214e7ce9ba7be2bb651961f7e3036b85f9250494290da9e9ba9891929e4f38894b8641848a3c0a3b9d35495b35083d42e8a3d4c928b9db4174ee85374616b65204e6577204c6f636b656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "8efd2e3d644d5e342a79ccf0b6a7a9fb89bbf4de74692cbce9bb1c18c75ece45", + "children": [ + "0223e5bfd594bb3245090e3e0bafb9cb9246fc84d30e4a35a7fde1b51085624d86677cc0ac3962ec136ca26dbec0aa942d926640ecf8418433f0db4b7925f5d0fe52652d7374616b6520556e7374616b656420464c4f57000101416d6f756e7400005546697836340003" + ] + } + ] + }, + { + "hash": "c9967fd752058341822bc98880abb34e04d3afef58de0e256f2264991e548123", + "children": [ + { + "hash": "4b050ad3dc73d4f5fb071e7c2b2bcb03b6e16eb056786a20da2db4d7c38e1be0", + "children": [ + "02239319825ad68178e76465b5ea18cb43f06c4ee11341f8fe9424809163a027a528d1719c5b21c88c62665db5ba04886809f3234c27057b057c36d5f265ee9de452652d7374616b6520526577617264656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "c45fd23265a1c89dbc044686a3a3f4e2dd2a02bfc778e41c4d105a9b1e43be8b", + "children": [ + "0233e3977c45e7c23c1472bcf334d00b03ebf91b06b67c57b63b562c7b1ff5c59f4e2a35541453f89c55e5dc6dbc963290380d779c81df0b3bf89c29b2a8d7a9fe5265717565737420556e7374616b65206f6620464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "37868c4f30cd62f1e6fcb3f237eafdbe15400489fc2e636d17763fedc6c16541", + "children": [ + "02f92c4cd663b2e335cd821a656bb2ebcf239b222036a7825af5e512fad4d820357099904b953b062e81e2575a2c2081b3d98bfccf5c743b4bdb224b937e292dad556e7374616b6520416c6c20464c4f570000" + ] + }, + { + "hash": "08dbfc695ea6b333a55acdc60a2991f68dd408347391bc6f34f91ea1a0d543da", + "children": [ + "0290097e3aff9b67f65bbada3cdedbb73d45d093ff333aaaff38809bf9910a3e39dcae4faa6d689873f7caf7c5efef669f9fe1d4113e58b474b7aec1e07113a7ff576974686472617720556e7374616b656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "21c0ba1073bacb222bfb082d711267cb218e924c3d8f1539f946c06a886c6584", + "children": [ + "02f23406ff402f02418629432912ce732be0441b1a7e71f16c03d688a165ff7f499bb8f0562eea5e45c11f9289540f39c99a21c9a0fb060a7d3f832e98c2696f2d576974686472617720526577617264656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "16f489e59aacc8e770b1b6e3879d141cb4d7cdcad64f05e046bccf0968fbc69a", + "children": [ + "02c29d4024aaeb71ab478182542499e0ba3d5d303ec027252e3b8333515ee3de4897b3436482c5aefc1baf8b850e92c829202e468c57241dec707b6c27bd89d15c5265676973746572204f70657261746f72204e6f64650003014f70657261746f7220416464726573730000416464726573730003014e6f64652049440001537472696e67000301416d6f756e7400025546697836340003" + ] + }, + { + "hash": "c97602b25a02199c3084483d155cb1aee1182218c7897cdacc75ed797e5790e3", + "children": [ + "021378405c85e0c966344b196c0fce602f39e79f3938ec7b689e0c96a8703b018a3cb357a97a57d9abbe5c68f0df342ee96ba97ade2013753fd2ddf47695a8c08a52656769737465722044656c656761746f720002014e6f64652049440000537472696e67000301416d6f756e7400015546697836340003" + ] + } + ] + }, + { + "hash": "53b33a3b57dd772b1dff0636374eb01bc7839efd7677d32399380c37f9a2d036", + "children": [ + { + "hash": "f7b70beddf1263ba42357da3f252616fde2eeb2778ad203dd4875d5ae14648c9", + "children": [ + "0218fad68368a4394b245db91217d7dc979e1316ab757388d416eaef831f565ab3802354d8b3e7908e584bcb5217637fb9f4ef045427c32d57d81ad4a390ed1a6044656c6567617465204e6577204c6f636b656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "d67d1649a5dce91ab18dab849b0f778d9e16418f885dea1f052fbf6b3cf72dc2", + "children": [ + "028776b1521b04395754734f8f40d4a0482863274f8d832973d9e011b3cbb48c852027331b72d8710a1a05feb6ecebadb5858d134bc8c95d6f261319cd9fa1bb9552652d64656c656761746520556e7374616b656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "d987b586f0cea4efd10d34d08f022a72d15d3a1387f8d14499fbf135850ba9ed", + "children": [ + "026b40ffc9169abd75107a45da5974c7e502d38773275abb231d747e4760b7ebee864edbff384335ef21c26b3bcf17d36b2b1d894afbe2b203f58099cc457971e452652d64656c656761746520526577617264656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "bc2e00772331f81862b03c4f59599ab89e93b7e08d11768c53895e393687d107", + "children": [ + "0261cbcd1c31bbfc9ceb4a5ac726e2f8b3d845a4fdf59b0ab23cbbfa8f16d7a024262aeddd3f49fd6222d706c02696bd7d359ba962b6c30232cc93d7cf4166a23e556e7374616b652044656c65676174656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "7b5b7372017ee19ffcd4daf5bf144219907aa558a65f2ffe4ca99f8e87387af0", + "children": [ + "022ae983f78e32b989fafa58ee7910b131fb51a2a74356f7916624695cb8bf596412675a013c064b6d0ef11dbf13f92210489bf2b3d299b2f14cd09be70b37577f576974686472617720556e7374616b656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "d7d9fbd0a1e6c91685562e0e3fa922af423ce0f5b284758531f5ba55adfb7cac", + "children": [ + "02385042aa453566fcff0b2bd418b837d8f46fbc23b1b46e6651b25a395bc04be8239ffa449eae5560eec3e99633dcf9c63b1e9c99996d1c5636644dceef9ec44b576974686472617720526577617264656420464c4f57000101416d6f756e7400005546697836340003" + ] + }, + { + "hash": "b051a776ea2ddfe310cb34c965eac396818c318226539d7dc2ba1c2bd41aae31", + "children": [ + "026cbe81c71d2b04dc403ea0db89377f0abc5db14d3d2bd014397b2776aa29bc3ee79cb076f2f7da7a3039b5061916e081a823087f1560bdf3caea773992892873557064617465204e6574776f726b696e672041646472657373000101416464726573730000537472696e670003" + ] + } + ] + }, + { + "hash": "04b126988dc8f00c41d922c13e0ae5a4e7d83f18b44935103cdbbd7c2229d53f", + "children": [ + { + "hash": "2e5e81d09ba5387bc9ff4a1e691d6847ecf66f667550937ca3da595d0006a16f", + "children": [ + "020f0baeef9353ceee607c5be3b7c0f86792dadf20b9e9c89e831adb0199e758827511848f1c27a173d966f4b868fd7efead7eeb1bbf04fc3f3e60dabc6c7f759353657420757020546f702053686f7420436f6c6c656374696f6e0000" + ] + }, + { + "hash": "07ed2407699d5b48472d3d6b4b49c75f0758af64fff518c85b886dfb1ebfacd8", + "children": [ + "021ec9aea0b51409610f882f5ae4278567da675542bb378eb999f05b7c4f12f7d809d5ad21bf70dfe4f8d800db9e61a77f2f64837ae0e818c3cd67e9cea837a1cf5472616e7366657220546f702053686f74204d6f6d656e74000201526563697069656e740000416464726573730003014d6f6d656e74204944000155496e7436340003" + ] + }, + { + "hash": "bf21d978d979a90615ea5fde48c41ab7a342b0b53ced3b67718029bb13bc927f", + "children": [ + "022defee818c0c003ca519f83517f4c7bcf9dd8664a562ec80959cb6146428f971887673892a2e2c12337394570dfa30c5669e93f537ae426690f402799514a9a153657475702055534443205661756c740000" + ] + }, + { + "hash": "2a9d013b868ee0cdf8f83b5d4a80f62a78b30176a425e7a11f444af2ff1e3552", + "children": [ + "02512485ec3f8e007853b0ea2a22fb2b9f7e2fa55fd9819171c5d013282efee60a7ff4d9f53ba5eebda556d0ead0ca13911bc8996e2c91c5147f8787d10a3244835472616e736665722055534443000201416d6f756e740000554669783634000301526563697069656e740001416464726573730003" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + } + ] + }, + { + "hash": "88bd487007bf1a5be47cea944d797895181258aba33c77e8c75fe7e38ad91929", + "children": [ + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + } + ] + }, + { + "hash": "88bd487007bf1a5be47cea944d797895181258aba33c77e8c75fe7e38ad91929", + "children": [ + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + } + ] + }, + { + "hash": "88bd487007bf1a5be47cea944d797895181258aba33c77e8c75fe7e38ad91929", + "children": [ + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + } + ] + }, + { + "hash": "88bd487007bf1a5be47cea944d797895181258aba33c77e8c75fe7e38ad91929", + "children": [ + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + } + ] + }, + { + "hash": "88bd487007bf1a5be47cea944d797895181258aba33c77e8c75fe7e38ad91929", + "children": [ + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + } + ] + }, + { + "hash": "88bd487007bf1a5be47cea944d797895181258aba33c77e8c75fe7e38ad91929", + "children": [ + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + }, + { + "hash": "63981575be94aaa4f14daa9f27c6c2fd72b46de3994ed71abaec45aa4b40615a", + "children": [ + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + }, + { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "children": [ + "" + ] + } + ] + } + ] + } + ] + }, + { + "hash": "94a4bf5f458f2def50f807bf419501bfd5e77a084c30592aa3803a522a3c272e", + "children": [ + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch" + ] + }, + { + "hash": "94a4bf5f458f2def50f807bf419501bfd5e77a084c30592aa3803a522a3c272e", + "children": [ + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch" + ] + }, + { + "hash": "94a4bf5f458f2def50f807bf419501bfd5e77a084c30592aa3803a522a3c272e", + "children": [ + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch" + ] + }, + { + "hash": "94a4bf5f458f2def50f807bf419501bfd5e77a084c30592aa3803a522a3c272e", + "children": [ + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch" + ] + }, + { + "hash": "94a4bf5f458f2def50f807bf419501bfd5e77a084c30592aa3803a522a3c272e", + "children": [ + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch" + ] + }, + { + "hash": "94a4bf5f458f2def50f807bf419501bfd5e77a084c30592aa3803a522a3c272e", + "children": [ + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch", + "Empty branch" + ] + } + ] +} + +merkleIndex = { + "eef2d04944485541": [ + 0, + 0, + 0, + 0 + ], + "595c86561441b32b": [ + 0, + 0, + 0, + 1 + ], + "ca80b628d985b358": [ + 0, + 0, + 0, + 2 + ], + "d56f4e1d2355cdcf": [ + 0, + 0, + 0, + 2 + ], + "47851586d962335e": [ + 0, + 0, + 0, + 2 + ], + "0ffaf77ab320ce4c": [ + 0, + 0, + 0, + 3 + ], + "aa7fecdf159e71bd": [ + 0, + 0, + 0, + 3 + ], + "f22ca4b350a79c72": [ + 0, + 0, + 0, + 4 + ], + "180cef7053a5f0ae": [ + 0, + 0, + 0, + 4 + ], + "a524b4094fcaf105": [ + 0, + 0, + 0, + 5 + ], + "0e5c2445c0b1016e": [ + 0, + 0, + 0, + 5 + ], + "c26f69a33ead535e": [ + 0, + 0, + 0, + 6 + ], + "c5636d510872a16e": [ + 0, + 0, + 0, + 6 + ], + "f47efa834bc0559a": [ + 0, + 0, + 1, + 0 + ], + "99997236b6d76caa": [ + 0, + 0, + 1, + 0 + ], + "9246ec9b7a5c8115": [ + 0, + 0, + 1, + 1 + ], + "79de7119aea61bda": [ + 0, + 0, + 1, + 1 + ], + "e79df145af42488e": [ + 0, + 0, + 1, + 2 + ], + "c2442b498eea0250": [ + 0, + 0, + 1, + 2 + ], + "86c69d731560f3bf": [ + 0, + 0, + 1, + 3 + ], + "dd3b327b09087ea7": [ + 0, + 0, + 1, + 3 + ], + "b00f6b3b9d8d7d4a": [ + 0, + 0, + 1, + 4 + ], + "a552951c5e6300a1": [ + 0, + 0, + 1, + 4 + ], + "1307928440cee428": [ + 0, + 0, + 1, + 5 + ], + "8e10ac56db8ec5d5": [ + 0, + 0, + 1, + 5 + ], + "d7aca7113a7aa03e": [ + 0, + 0, + 1, + 6 + ], + "907c4cfd67a98a80": [ + 0, + 0, + 1, + 6 + ], + "3595fcd68cff445c": [ + 0, + 0, + 2, + 0 + ], + "082e690b9647182c": [ + 0, + 0, + 2, + 0 + ], + "0bde358f3965ba2f": [ + 0, + 0, + 2, + 1 + ], + "df9c6486baa6f8f6": [ + 0, + 0, + 2, + 1 + ], + "3af182f568b37a80": [ + 0, + 0, + 2, + 2 + ], + "27a2b60d538b8bb8": [ + 0, + 0, + 2, + 2 + ], + "68879197d961bb10": [ + 0, + 0, + 2, + 3 + ], + "6d50ab1ef3d74203": [ + 0, + 0, + 2, + 3 + ], + "079aaa9cfb221384": [ + 0, + 0, + 2, + 4 + ], + "ecdffc1ae67479bc": [ + 0, + 0, + 2, + 4 + ], + "2386d7ae1a5b936e": [ + 0, + 0, + 2, + 5 + ], + "cdc3a63d0c75ea95": [ + 0, + 0, + 2, + 5 + ], + "53b096b4850a3089": [ + 0, + 0, + 2, + 6 + ], + "b34d6fafcc5a4d0e": [ + 0, + 0, + 2, + 6 + ], + "39a126038522c6c9": [ + 0, + 0, + 3, + 0 + ], + "f9c48e18bda7f113": [ + 0, + 0, + 3, + 0 + ], + "60f2cf219d56b19d": [ + 0, + 0, + 3, + 1 + ], + "ff067b40ac67020e": [ + 0, + 0, + 3, + 1 + ], + "6e73db6edd0190f5": [ + 0, + 0, + 3, + 2 + ], + "a2146e3e6e771877": [ + 0, + 0, + 3, + 2 + ], + "0cb11c10b86d2afe": [ + 0, + 0, + 3, + 3 + ], + "74355dc8df221bc0": [ + 0, + 0, + 3, + 3 + ], + "b6a3502d2205eb05": [ + 0, + 0, + 3, + 4 + ], + "b64e0e3ed9eb2878": [ + 0, + 0, + 3, + 4 + ], + "d5689b89f53214e7": [ + 0, + 0, + 3, + 5 + ], + "1929e4f38894b864": [ + 0, + 0, + 3, + 5 + ], + "23e5bfd594bb3245": [ + 0, + 0, + 3, + 6 + ], + "677cc0ac3962ec13": [ + 0, + 0, + 3, + 6 + ], + "239319825ad68178": [ + 0, + 0, + 4, + 0 + ], + "28d1719c5b21c88c": [ + 0, + 0, + 4, + 0 + ], + "33e3977c45e7c23c": [ + 0, + 0, + 4, + 1 + ], + "4e2a35541453f89c": [ + 0, + 0, + 4, + 1 + ], + "f92c4cd663b2e335": [ + 0, + 0, + 4, + 2 + ], + "7099904b953b062e": [ + 0, + 0, + 4, + 2 + ], + "90097e3aff9b67f6": [ + 0, + 0, + 4, + 3 + ], + "dcae4faa6d689873": [ + 0, + 0, + 4, + 3 + ], + "f23406ff402f0241": [ + 0, + 0, + 4, + 4 + ], + "9bb8f0562eea5e45": [ + 0, + 0, + 4, + 4 + ], + "c29d4024aaeb71ab": [ + 0, + 0, + 4, + 5 + ], + "97b3436482c5aefc": [ + 0, + 0, + 4, + 5 + ], + "1378405c85e0c966": [ + 0, + 0, + 4, + 6 + ], + "3cb357a97a57d9ab": [ + 0, + 0, + 4, + 6 + ], + "18fad68368a4394b": [ + 0, + 0, + 5, + 0 + ], + "802354d8b3e7908e": [ + 0, + 0, + 5, + 0 + ], + "8776b1521b043957": [ + 0, + 0, + 5, + 1 + ], + "2027331b72d8710a": [ + 0, + 0, + 5, + 1 + ], + "6b40ffc9169abd75": [ + 0, + 0, + 5, + 2 + ], + "864edbff384335ef": [ + 0, + 0, + 5, + 2 + ], + "61cbcd1c31bbfc9c": [ + 0, + 0, + 5, + 3 + ], + "262aeddd3f49fd62": [ + 0, + 0, + 5, + 3 + ], + "2ae983f78e32b989": [ + 0, + 0, + 5, + 4 + ], + "12675a013c064b6d": [ + 0, + 0, + 5, + 4 + ], + "385042aa453566fc": [ + 0, + 0, + 5, + 5 + ], + "239ffa449eae5560": [ + 0, + 0, + 5, + 5 + ], + "6cbe81c71d2b04dc": [ + 0, + 0, + 5, + 6 + ], + "e79cb076f2f7da7a": [ + 0, + 0, + 5, + 6 + ], + "0f0baeef9353ceee": [ + 0, + 0, + 6, + 0 + ], + "7511848f1c27a173": [ + 0, + 0, + 6, + 0 + ], + "1ec9aea0b5140961": [ + 0, + 0, + 6, + 1 + ], + "09d5ad21bf70dfe4": [ + 0, + 0, + 6, + 1 + ], + "2defee818c0c003c": [ + 0, + 0, + 6, + 2 + ], + "887673892a2e2c12": [ + 0, + 0, + 6, + 2 + ], + "512485ec3f8e0078": [ + 0, + 0, + 6, + 3 + ], + "7ff4d9f53ba5eebd": [ + 0, + 0, + 6, + 3 + ] +} + diff --git a/tests/test_sign_cmd.py b/tests/test_sign_cmd.py index d1b63f88..04bf99fc 100644 --- a/tests/test_sign_cmd.py +++ b/tests/test_sign_cmd.py @@ -67,19 +67,29 @@ def test_transaction_params(firmware, backend, navigator, test_name): HashType.HASH_SHA2, HashType.HASH_SHA3, ] - transactions = [ - "f9023ff9023bb90195696d706f72742046756e6769626c65546f6b656e2066726f6d203078656538323835366266323065326161360a7472616e73616374696f6e28616d6f756e743a205546697836342c20746f3a204164647265737329207b0a6c6574207661756c743a204046756e6769626c65546f6b656e2e5661756c740a70726570617265287369676e65723a20417574684163636f756e7429207b0a73656c662e7661756c74203c2d207369676e65720a2e626f72726f773c267b46756e6769626c65546f6b656e2e50726f76696465727d3e2866726f6d3a202f73746f726167652f666c6f77546f6b656e5661756c7429210a2e776974686472617728616d6f756e743a20616d6f756e74290a7d0a65786563757465207b0a6765744163636f756e7428746f290a2e6765744361706162696c697479282f7075626c69632f666c6f77546f6b656e526563656976657229210a2e626f72726f773c267b46756e6769626c65546f6b656e2e52656365697665727d3e2829210a2e6465706f7369742866726f6d3a203c2d73656c662e7661756c74290a7d0a7df861b07b2274797065223a22554669783634222c2276616c7565223a223138343436373434303733372e39353531363135227daf7b2274797065223a2241646472657373222c2276616c7565223a22307866386436653035383662306132306337227da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f8d6e0586b0a20c7040a88f8d6e0586b0a20c7c988f8d6e0586b0a20c7c0", - "f90289f90261b8a97472616e73616374696f6e287075626c69634b6579733a205b537472696e675d29207b0a70726570617265287369676e65723a20417574684163636f756e7429207b0a6c65742061636374203d20417574684163636f756e742870617965723a207369676e6572290a666f72206b657920696e207075626c69634b657973207b0a616363742e6164645075626c69634b6579286b65792e6465636f64654865782829290a7d0a7d0a7df90173b901707b2274797065223a224172726179222c2276616c7565223a5b7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303934343838613739356130373730306336666238336530363663663537646664383766393263653730636263383163623362643366656132646637623637303733623730653336623434663335373862343364363464336661613265386534313565663663326235666534333930643561373865323338353831633665346263333033303330227d2c7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303934343838613739356130373730306336666238336530363663663537646664383766393263653730636263383163623362643366656132646637623637303733623730653336623434663335373862343364363464336661613265386534313565663663326235666534333930643561373865323338353831633665346263333033303331227d5d7da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f8d6e0586b0a20c7040a88f8d6e0586b0a20c7c988f8d6e0586b0a20c7e4e38004a0f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162", - "f90186f9015eb86e7472616e73616374696f6e287075626c69634b65793a20537472696e6729207b0a70726570617265287369676e65723a20417574684163636f756e7429207b0a7369676e65722e6164645075626c69634b6579287075626c69634b65792e6465636f64654865782829290a7d0a7df8acb8aa7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303934343838613739356130373730306336666238336530363663663537646664383766393263653730636263383163623362643366656132646637623637303733623730653336623434663335373862343364363464336661613265386534313565663663326235666534333930643561373865323338353831633665346263333033303330227da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f8d6e0586b0a20c7040a88f8d6e0586b0a20c7c988f8d6e0586b0a20c7e4e38004a0f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162", + + transactionsAndScriptHashes = [ + ( + "f9023ff9023bb90195696d706f72742046756e6769626c65546f6b656e2066726f6d203078656538323835366266323065326161360a7472616e73616374696f6e28616d6f756e743a205546697836342c20746f3a204164647265737329207b0a6c6574207661756c743a204046756e6769626c65546f6b656e2e5661756c740a70726570617265287369676e65723a20417574684163636f756e7429207b0a73656c662e7661756c74203c2d207369676e65720a2e626f72726f773c267b46756e6769626c65546f6b656e2e50726f76696465727d3e2866726f6d3a202f73746f726167652f666c6f77546f6b656e5661756c7429210a2e776974686472617728616d6f756e743a20616d6f756e74290a7d0a65786563757465207b0a6765744163636f756e7428746f290a2e6765744361706162696c697479282f7075626c69632f666c6f77546f6b656e526563656976657229210a2e626f72726f773c267b46756e6769626c65546f6b656e2e52656365697665727d3e2829210a2e6465706f7369742866726f6d3a203c2d73656c662e7661756c74290a7d0a7df861b07b2274797065223a22554669783634222c2276616c7565223a223138343436373434303733372e39353531363135227daf7b2274797065223a2241646472657373222c2276616c7565223a22307866386436653035383662306132306337227da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f8d6e0586b0a20c7040a88f8d6e0586b0a20c7c988f8d6e0586b0a20c7c0", + "ca80b628d985b358ae1cb136bcd976997c942fa10dbabfeafb4e20fa66a5a5e2" + ), + ( + "f90289f90261b8a97472616e73616374696f6e287075626c69634b6579733a205b537472696e675d29207b0a70726570617265287369676e65723a20417574684163636f756e7429207b0a6c65742061636374203d20417574684163636f756e742870617965723a207369676e6572290a666f72206b657920696e207075626c69634b657973207b0a616363742e6164645075626c69634b6579286b65792e6465636f64654865782829290a7d0a7d0a7df90173b901707b2274797065223a224172726179222c2276616c7565223a5b7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303934343838613739356130373730306336666238336530363663663537646664383766393263653730636263383163623362643366656132646637623637303733623730653336623434663335373862343364363464336661613265386534313565663663326235666534333930643561373865323338353831633665346263333033303330227d2c7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303934343838613739356130373730306336666238336530363663663537646664383766393263653730636263383163623362643366656132646637623637303733623730653336623434663335373862343364363464336661613265386534313565663663326235666534333930643561373865323338353831633665346263333033303331227d5d7da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f8d6e0586b0a20c7040a88f8d6e0586b0a20c7c988f8d6e0586b0a20c7e4e38004a0f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162", + "eef2d0494448554177612e63026256258339230cbc6931ded78d6149443c6173" + ), + ( + "f90186f9015eb86e7472616e73616374696f6e287075626c69634b65793a20537472696e6729207b0a70726570617265287369676e65723a20417574684163636f756e7429207b0a7369676e65722e6164645075626c69634b6579287075626c69634b65792e6465636f64654865782829290a7d0a7df8acb8aa7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303934343838613739356130373730306336666238336530363663663537646664383766393263653730636263383163623362643366656132646637623637303733623730653336623434663335373862343364363464336661613265386534313565663663326235666534333930643561373865323338353831633665346263333033303330227da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f8d6e0586b0a20c7040a88f8d6e0586b0a20c7c988f8d6e0586b0a20c7e4e38004a0f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162", + "595c86561441b32b2b91ee03f9e10ca6efa7b41bcc994f51317ec0aa9d8f8a42" + ) ] # Send the APDU and check the results part = 0 - for transaction in transactions: + for transaction in transactionsAndScriptHashes: for curve in curve_list: for hash_t in hash_list: part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, hash_t, "") + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction[0], path, curve, hash_t, transaction[1]) class Test_EXPERT(): @@ -101,6 +111,7 @@ def test_transaction_expert(self, firmware, backend, navigator, test_name): }, ] transaction = "f9023ff9023bb90195696d706f72742046756e6769626c65546f6b656e2066726f6d203078656538323835366266323065326161360a7472616e73616374696f6e28616d6f756e743a205546697836342c20746f3a204164647265737329207b0a6c6574207661756c743a204046756e6769626c65546f6b656e2e5661756c740a70726570617265287369676e65723a20417574684163636f756e7429207b0a73656c662e7661756c74203c2d207369676e65720a2e626f72726f773c267b46756e6769626c65546f6b656e2e50726f76696465727d3e2866726f6d3a202f73746f726167652f666c6f77546f6b656e5661756c7429210a2e776974686472617728616d6f756e743a20616d6f756e74290a7d0a65786563757465207b0a6765744163636f756e7428746f290a2e6765744361706162696c697479282f7075626c69632f666c6f77546f6b656e526563656976657229210a2e626f72726f773c267b46756e6769626c65546f6b656e2e52656365697665727d3e2829210a2e6465706f7369742866726f6d3a203c2d73656c662e7661756c74290a7d0a7df861b07b2274797065223a22554669783634222c2276616c7565223a223138343436373434303733372e39353531363135227daf7b2274797065223a2241646472657373222c2276616c7565223a22307866386436653035383662306132306337227da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f8d6e0586b0a20c7040a88f8d6e0586b0a20c7c988f8d6e0586b0a20c7c0" + txHash = "ca80b628d985b358ae1cb136bcd976997c942fa10dbabfeafb4e20fa66a5a5e2" part = 0 # Navigate in the main menu to change to expert mode @@ -109,7 +120,7 @@ def test_transaction_expert(self, firmware, backend, navigator, test_name): # Send the APDU and check the results for cfg in test_cfg: part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, cfg["curve"], cfg["hash"], "") + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, cfg["curve"], cfg["hash"], txHash) def test_transaction_slot(firmware, backend, navigator, test_name): @@ -125,11 +136,12 @@ def test_transaction_slot(firmware, backend, navigator, test_name): bad_hash: HashType = HashType.HASH_SHA2 slot = 0 transaction = "f9023ff9023bb90195696d706f72742046756e6769626c65546f6b656e2066726f6d203078656538323835366266323065326161360a7472616e73616374696f6e28616d6f756e743a205546697836342c20746f3a204164647265737329207b0a6c6574207661756c743a204046756e6769626c65546f6b656e2e5661756c740a70726570617265287369676e65723a20417574684163636f756e7429207b0a73656c662e7661756c74203c2d207369676e65720a2e626f72726f773c267b46756e6769626c65546f6b656e2e50726f76696465727d3e2866726f6d3a202f73746f726167652f666c6f77546f6b656e5661756c7429210a2e776974686472617728616d6f756e743a20616d6f756e74290a7d0a65786563757465207b0a6765744163636f756e7428746f290a2e6765744361706162696c697479282f7075626c69632f666c6f77546f6b656e526563656976657229210a2e626f72726f773c267b46756e6769626c65546f6b656e2e52656365697665727d3e2829210a2e6465706f7369742866726f6d3a203c2d73656c662e7661756c74290a7d0a7df861b07b2274797065223a22554669783634222c2276616c7565223a223138343436373434303733372e39353531363135227daf7b2274797065223a2241646472657373222c2276616c7565223a22307866386436653035383662306132306337227da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f8d6e0586b0a20c7040a88f8d6e0586b0a20c7c988f8d6e0586b0a20c7c0" + scriptHash = "ca80b628d985b358ae1cb136bcd976997c942fa10dbabfeafb4e20fa66a5a5e2" address = "f8d6e0586b0a20c7" # Send the APDU and check the results part = 0 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, hash_t, "") + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, hash_t, scriptHash) # Set slot to correct path correct address, part += 1 @@ -137,11 +149,11 @@ def test_transaction_slot(firmware, backend, navigator, test_name): # Sign the Tx again - incorrect hd path part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, bad_path, curve, hash_t, "") + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, bad_path, curve, hash_t, scriptHash) # Sign the Tx again - correct path part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, hash_t, "") + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, hash_t, scriptHash) # e467b9dd11fa00df - used as incorrect address; f8d6e0586b0a20c7 - correct one transactions = [ @@ -162,11 +174,11 @@ def test_transaction_slot(firmware, backend, navigator, test_name): # Send the APDU and check the results for blob in transactions: part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", blob, path, curve, hash_t, "") + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", blob, path, curve, hash_t, scriptHash) # sign the Tx again - correct path - wrong hash part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, bad_hash, "") + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, bad_hash, scriptHash) # Now delete the slot so that the next test starts in a clean state util_set_slot(client, firmware, navigator, test_name, slot) @@ -202,13 +214,14 @@ def test_transaction_refused(firmware, backend, navigator, test_name): curve: CurveChoice = CurveChoice.Nist256p1 hash_t = HashType.HASH_SHA2 transaction = "f9023ff9023bb90195696d706f72742046756e6769626c65546f6b656e2066726f6d203078656538323835366266323065326161360a7472616e73616374696f6e28616d6f756e743a205546697836342c20746f3a204164647265737329207b0a6c6574207661756c743a204046756e6769626c65546f6b656e2e5661756c740a70726570617265287369676e65723a20417574684163636f756e7429207b0a73656c662e7661756c74203c2d207369676e65720a2e626f72726f773c267b46756e6769626c65546f6b656e2e50726f76696465727d3e2866726f6d3a202f73746f726167652f666c6f77546f6b656e5661756c7429210a2e776974686472617728616d6f756e743a20616d6f756e74290a7d0a65786563757465207b0a6765744163636f756e7428746f290a2e6765744361706162696c697479282f7075626c69632f666c6f77546f6b656e526563656976657229210a2e626f72726f773c267b46756e6769626c65546f6b656e2e52656365697665727d3e2829210a2e6465706f7369742866726f6d3a203c2d73656c662e7661756c74290a7d0a7df861b07b2274797065223a22554669783634222c2276616c7565223a223138343436373434303733372e39353531363135227daf7b2274797065223a2241646472657373222c2276616c7565223a22307866386436653035383662306132306337227da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f8d6e0586b0a20c7040a88f8d6e0586b0a20c7c988f8d6e0586b0a20c7c0" + scriptHash = "ca80b628d985b358ae1cb136bcd976997c942fa10dbabfeafb4e20fa66a5a5e2" # Convert message to bytes message = bytes.fromhex(transaction) # Send the APDU (Asynchronous) with pytest.raises(ExceptionRAPDU) as err: - with client.sign_tx(path, curve, message, hash_t): + with client.sign_tx(path, curve, message, hash_t, scriptHash): util_navigate(firmware, navigator, test_name, "REJECT_SIGN") # Assert we have received a refusal @@ -216,6 +229,7 @@ def test_transaction_refused(firmware, backend, navigator, test_name): assert len(err.value.data) == 0 +@pytest.mark.skip(reason="Script hashes not easily available yet") def test_transaction_manifest(firmware, backend, navigator, test_name): """ Check transaction based on legacy manifest file """