From b6818327e705f6b2be2440c19d0fc2cbea66b5ca Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Thu, 8 Aug 2024 07:57:21 +0200 Subject: [PATCH 01/34] Parsing simple transaction --- CMakeLists.txt | 25 ++- app/Makefile | 4 +- app/src/coin.h | 5 + app/src/common/parser_common.h | 26 ++- app/src/jsmn/jsmn.c | 390 ++++++++++++++++++++++++++++++++ app/src/jsmn/jsmn.h | 105 +++++++++ app/src/json/json_parser.c | 294 ++++++++++++++++++++++++ app/src/json/json_parser.h | 114 ++++++++++ app/src/parser.c | 108 ++++++++- app/src/parser_impl.c | 65 +++++- app/src/parser_impl.h | 13 +- app/src/parser_txdef.h | 64 +++++- tests/json_parser.cpp | 398 +++++++++++++++++++++++++++++++++ tests/testcases.json | 85 ++----- tests/ui_tests.cpp | 7 +- tests/utils/common.h | 16 ++ 16 files changed, 1612 insertions(+), 107 deletions(-) create mode 100644 app/src/jsmn/jsmn.c create mode 100644 app/src/jsmn/jsmn.h create mode 100644 app/src/json/json_parser.c create mode 100644 app/src/json/json_parser.h create mode 100644 tests/json_parser.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8cbb8b2..e719faf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,9 +128,14 @@ add_definitions( ##{TODO} ############################################################## # Static Libraries -file(GLOB_RECURSE LIB_SRC + +file(GLOB_RECURSE BLAKE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/deps/BLAKE2/ref/blake2b-ref.c + ) + +file(GLOB_RECURSE LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/app_mode.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/base64.c ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/base58.c ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/bech32.c ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/bignum.c @@ -141,18 +146,28 @@ file(GLOB_RECURSE LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/crypto_helper.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/json/json_parser.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/jsmn/jsmn.c ) -add_library(app_lib STATIC ${LIB_SRC}) +add_library(app_lib STATIC + ${LIB_SRC} + ${JSMN_SRC} + ${BLAKE_SRC} + ) target_include_directories(app_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/deps/BLAKE2/ref ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/include ${CMAKE_CURRENT_SOURCE_DIR}/app/src - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/lib ${CMAKE_CURRENT_SOURCE_DIR}/app/src/common + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/json + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/jsmn + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/app/common ) +target_link_libraries(app_lib PUBLIC) + ############################################################## # Fuzz Targets if(ENABLE_FUZZING) @@ -177,6 +192,8 @@ else() ${gmock_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/app/src ${CMAKE_CURRENT_SOURCE_DIR}/app/src/lib + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/json + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/jsmn ) target_link_libraries(unittests PRIVATE @@ -188,4 +205,4 @@ else() add_compile_definitions(TESTVECTORS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/") add_test(NAME unittests COMMAND unittests) set_tests_properties(unittests PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) -endif() +endif() \ No newline at end of file diff --git a/app/Makefile b/app/Makefile index 5a8bc11..b9e6100 100755 --- a/app/Makefile +++ b/app/Makefile @@ -61,8 +61,8 @@ $(info COIN = [$(COIN)]) ifeq ($(COIN),KDA) # Main app configuration -APPNAME = "Kadena" -APPPATH = "44'/626'" +APPNAME = "Kadena-Led" +APPPATH = "44'/626'" --path "44'/1'" else define error_message diff --git a/app/src/coin.h b/app/src/coin.h index 19d2147..07ad602 100644 --- a/app/src/coin.h +++ b/app/src/coin.h @@ -52,6 +52,11 @@ extern "C" { #define APPVERSION_LINE1 "Kadena" #define APPVERSION_LINE2 "v" APPVERSION +typedef enum { + tx_json = 0, + tx_textual +} tx_type_e; + #ifdef __cplusplus } #endif diff --git a/app/src/common/parser_common.h b/app/src/common/parser_common.h index 6afacf3..8fcc3d5 100644 --- a/app/src/common/parser_common.h +++ b/app/src/common/parser_common.h @@ -22,8 +22,6 @@ extern "C" { #include #include -#include "parser_txdef.h" - #define CHECK_ERROR(__CALL) \ { \ parser_error_t __err = __CALL; \ @@ -56,15 +54,23 @@ typedef enum { parser_missing_field, paser_unknown_transaction, parser_tx_obj_empty, -} parser_error_t; -typedef struct { - const uint8_t *buffer; - uint16_t bufferLen; - uint16_t offset; - parser_tx_t *tx_obj; -} parser_context_t; + // Coin Specific + parser_json_zero_tokens, + parser_json_too_many_tokens, // "NOMEM: JSON string contains too many tokens" + parser_json_incomplete_json, // "JSON string is not complete"; + // TODO : Clean these if never used + //parser_json_contains_whitespace, + //parser_json_is_not_sorted, + //parser_json_missing_chain_id, + //parser_json_missing_sequence, + //parser_json_missing_fee, + //parser_json_missing_msgs, + //parser_json_missing_account_number, + //parser_json_missing_memo, + parser_json_unexpected_error, +} parser_error_t; #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/app/src/jsmn/jsmn.c b/app/src/jsmn/jsmn.c new file mode 100644 index 0000000..422139e --- /dev/null +++ b/app/src/jsmn/jsmn.c @@ -0,0 +1,390 @@ +/* + * MIT License + * + * Copyright (c) 2010 Serge Zaitsev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "jsmn.h" +/** + * Allocates a fresh unused token from the token pool. + */ +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; +#ifdef JSMN_PARENT_LINKS + tok->parent = -1; +#endif + return tok; +} + +/** + * Fills token type and boundaries. + */ +static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, + const int start, const int end) { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; +} + +/** + * Fills next available token with JSON primitive. + */ +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { +#ifndef JSMN_STRICT + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': +#endif + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + default: + /* to quiet a warning from gcc*/ + break; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } +#ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; +#endif + +found: + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + parser->pos--; + return 0; +} + +/** + * Fills next token with JSON string. + */ +static int jsmn_parse_string(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + + int start = parser->pos; + + /* Skip starting quote */ + parser->pos++; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; + i++) { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; +} + +/** + * Parse JSON string and fill tokens. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens) { + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) { + case '{': + case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + return JSMN_ERROR_NOMEM; + } + if (parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; +#ifdef JSMN_STRICT + /* In strict mode an object or array can't become a key */ + if (t->type == JSMN_OBJECT) { + return JSMN_ERROR_INVAL; + } +#endif + t->size++; +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == NULL) { + break; + } + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); +#ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + if (token->type != type || parser->toksuper == -1) { + return JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } +#else + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) { + return JSMN_ERROR_INVAL; + } + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } +#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { +#ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; +#else + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } +#endif + } + break; +#ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + const jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } +#else + /* In non-strict mode every unquoted value is a primitive */ + default: +#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + +#ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; +#endif + } + } + + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } + + return count; +} + +/** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ +JSMN_API void jsmn_init(jsmn_parser *parser) { + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; +} + +#ifdef __cplusplus +} +#endif diff --git a/app/src/jsmn/jsmn.h b/app/src/jsmn/jsmn.h new file mode 100644 index 0000000..44dd8a5 --- /dev/null +++ b/app/src/jsmn/jsmn.h @@ -0,0 +1,105 @@ +/* + * MIT License + * + * Copyright (c) 2010 Serge Zaitsev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef JSMN_H +#define JSMN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef JSMN_STATIC +#define JSMN_API static +#else +#define JSMN_API extern +#endif + +/** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1 << 0, + JSMN_ARRAY = 1 << 1, + JSMN_STRING = 1 << 2, + JSMN_PRIMITIVE = 1 << 3 +} jsmntype_t; + +enum jsmnerr { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 +}; + +/** + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +typedef struct jsmntok { + jsmntype_t type; + int start; + int end; + int size; +#ifdef JSMN_PARENT_LINKS + int parent; +#endif +} jsmntok_t; + +/** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string. + */ +typedef struct jsmn_parser { + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g. parent object or array */ +} jsmn_parser; + +/** + * Create JSON parser over an array of tokens + */ +JSMN_API void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing + * a single JSON object. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens); +#ifdef __cplusplus +} +#endif + +#endif /* JSMN_H */ diff --git a/app/src/json/json_parser.c b/app/src/json/json_parser.c new file mode 100644 index 0000000..3c4d890 --- /dev/null +++ b/app/src/json/json_parser.c @@ -0,0 +1,294 @@ +#include "json_parser.h" +#include +#include "../common/parser_common.h" +#include "jsmn.h" + +#define EQUALS(_P, _Q, _LEN) (MEMCMP( (const void*) PIC(_P), (const void*) PIC(_Q), (_LEN))==0) + +/** + * Create JSON parser over an array of tokens + */ +extern void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing + * a single JSON object. + */ +extern int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens); + +parser_error_t array_get_element_count(const parsed_json_t *json, + uint16_t array_token_index, + uint16_t *number_elements) { + *number_elements = 0; + if (array_token_index < 0 || array_token_index > json->numberOfTokens) { + return parser_no_data; + } + + jsmntok_t array_token = json->tokens[array_token_index]; + uint16_t token_index = array_token_index; + uint16_t prev_element_end = array_token.start; + while (true) { + token_index++; + if (token_index >= json->numberOfTokens) { + break; + } + jsmntok_t current_token = json->tokens[token_index]; + if (current_token.start > array_token.end) { + break; + } + if (current_token.start <= prev_element_end) { + continue; + } + prev_element_end = current_token.end; + (*number_elements)++; + } + + return parser_ok; +} + +parser_error_t array_get_nth_element(const parsed_json_t *json, + uint16_t array_token_index, + uint16_t element_index, + uint16_t *token_index) { + if (array_token_index < 0 || array_token_index > json->numberOfTokens) { + return parser_no_data; + } + + jsmntok_t array_token = json->tokens[array_token_index]; + *token_index = array_token_index; + + uint16_t element_count = 0; + uint16_t prev_element_end = array_token.start; + while (true) { + (*token_index)++; + if (*token_index >= json->numberOfTokens) { + break; + } + jsmntok_t current_token = json->tokens[*token_index]; + if (current_token.start > array_token.end) { + break; + } + if (current_token.start <= prev_element_end) { + continue; + } + prev_element_end = current_token.end; + if (element_count == element_index) { + return parser_ok; + } + element_count++; + } + + return parser_no_data; +} + +parser_error_t object_get_element_count(const parsed_json_t *json, + uint16_t object_token_index, + uint16_t *element_count) { + *element_count = 0; + if (object_token_index < 0 || object_token_index > json->numberOfTokens) { + return parser_no_data; + } + + jsmntok_t object_token = json->tokens[object_token_index]; + uint16_t token_index = object_token_index; + uint16_t prev_element_end = object_token.start; + token_index++; + while (true) { + if (token_index >= json->numberOfTokens) { + break; + } + jsmntok_t key_token = json->tokens[token_index++]; + jsmntok_t value_token = json->tokens[token_index]; + if (key_token.start > object_token.end) { + break; + } + if (key_token.start <= prev_element_end) { + continue; + } + prev_element_end = value_token.end; + (*element_count)++; + } + + return parser_ok; +} + +parser_error_t object_get_nth_key(const parsed_json_t *json, + uint16_t object_token_index, + uint16_t object_element_index, + uint16_t *token_index) { + *token_index = object_token_index; + if (object_token_index < 0 || object_token_index > json->numberOfTokens) { + return parser_no_data; + } + + jsmntok_t object_token = json->tokens[object_token_index]; + uint16_t element_count = 0; + uint16_t prev_element_end = object_token.start; + (*token_index)++; + while (true) { + if (*token_index >= json->numberOfTokens) { + break; + } + jsmntok_t key_token = json->tokens[(*token_index)++]; + jsmntok_t value_token = json->tokens[*token_index]; + if (key_token.start > object_token.end) { + break; + } + if (key_token.start <= prev_element_end) { + continue; + } + prev_element_end = value_token.end; + if (element_count == object_element_index) { + (*token_index)--; + return parser_ok; + } + element_count++; + } + + return parser_no_data; +} + +parser_error_t object_get_nth_value(const parsed_json_t *json, + uint16_t object_token_index, + uint16_t object_element_index, + uint16_t *key_index) { + if (object_token_index < 0 || object_token_index > json->numberOfTokens) { + return parser_no_data; + } + + CHECK_ERROR(object_get_nth_key(json, object_token_index, object_element_index, key_index)) + (*key_index)++; + + return parser_ok; +} + +parser_error_t object_get_value(const parsed_json_t *json, + uint16_t object_token_index, + const char *key_name, + uint16_t *token_index) { + if (object_token_index < 0 || object_token_index > json->numberOfTokens) { + return parser_no_data; + } + + const jsmntok_t object_token = json->tokens[object_token_index]; + + *token_index = object_token_index; + int prev_element_end = object_token.start; + (*token_index)++; + + while (*token_index < json->numberOfTokens) { + const jsmntok_t key_token = json->tokens[*token_index]; + (*token_index)++; + const jsmntok_t value_token = json->tokens[*token_index]; + + if (key_token.start > object_token.end) { + break; + } + if (key_token.start <= prev_element_end) { + continue; + } + + if (value_token.type == JSMN_OBJECT) { + // An object was found, look inside it + parsed_json_t json_obj; + uint16_t token_index_before_recursion = *token_index; + + json_parse(&json_obj, json->buffer + value_token.start, value_token.end - value_token.start); + + if (object_get_value(&json_obj, 0, key_name, token_index) == parser_ok) { + *token_index = *token_index + token_index_before_recursion; + return parser_ok; + } + } else if (value_token.type == JSMN_ARRAY) { + // An array was found, look inside it + parsed_json_t json_array; + parsed_json_t json_array_element; + uint16_t token_index_before_object_recursion = 0; + uint16_t token_index_before_array_iteration = 0; + uint16_t element_count = 0; + + json_parse(&json_array, json->buffer + value_token.start, value_token.end - value_token.start); + + CHECK_ERROR(array_get_element_count(&json_array, 0, &element_count)) + + for (int i = 0; i < element_count; i++) { + CHECK_ERROR(array_get_nth_element(&json_array, 0, i, &token_index_before_array_iteration)) + + json_parse(&json_array_element, json_array.buffer + json_array.tokens[token_index_before_array_iteration].start, json_array.tokens[token_index_before_array_iteration].end - json_array.tokens[token_index_before_array_iteration].start); + + if (object_get_value(&json_array_element, 0, key_name, &token_index_before_object_recursion) == parser_ok) { + *token_index = *token_index + token_index_before_object_recursion + token_index_before_array_iteration; + return parser_ok; + } + } + } + + prev_element_end = value_token.end; + + if (((uint16_t) strlen(key_name)) == (key_token.end - key_token.start)) { + if (EQUALS(key_name, + json->buffer + key_token.start, + key_token.end - key_token.start)) { + return parser_ok; + } + } + } + + return parser_no_data; +} + +parser_error_t json_parse(parsed_json_t *parsed_json, const char *buffer, uint16_t bufferLen) { + jsmn_parser parser; + + jsmn_init(&parser); + + MEMZERO(parsed_json, sizeof(parsed_json_t)); + parsed_json->buffer = buffer; + parsed_json->bufferLen = bufferLen; + + int32_t num_tokens = jsmn_parse( + &parser, + parsed_json->buffer, + parsed_json->bufferLen, + parsed_json->tokens, + MAX_NUMBER_OF_TOKENS); + +#ifdef APP_TESTING + char tmpBuffer[100]; + snprintf(tmpBuffer, sizeof(tmpBuffer), "tokens: %d\n", num_tokens); + zemu_log(tmpBuffer); +#endif + + if (num_tokens < 0) { + switch (num_tokens) { + case JSMN_ERROR_NOMEM: + return parser_json_too_many_tokens; + case JSMN_ERROR_INVAL: + return parser_unexpected_characters; + case JSMN_ERROR_PART: + return parser_json_incomplete_json; + default: + return parser_json_unexpected_error; + } + } + + parsed_json->numberOfTokens = 0; + parsed_json->isValid = 0; + + // Parsing error + if (num_tokens <= 0) { + return parser_json_zero_tokens; + } + + // We cannot support if number of tokens exceeds the limit + if (num_tokens > MAX_NUMBER_OF_TOKENS) { + return parser_json_too_many_tokens; + } + + parsed_json->numberOfTokens = num_tokens; + parsed_json->isValid = true; + + return parser_ok; +} \ No newline at end of file diff --git a/app/src/json/json_parser.h b/app/src/json/json_parser.h new file mode 100644 index 0000000..2b93e48 --- /dev/null +++ b/app/src/json/json_parser.h @@ -0,0 +1,114 @@ +/******************************************************************************* + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#pragma once + +#include "jsmn.h" +#include +#include +#include +#include "common/parser_common.h" + +/// Max number of accepted tokens in the JSON input +#define MAX_NUMBER_OF_TOKENS 768 + +// Limit depending on target +#if defined(TARGET_NANOS) || defined(TARGET_NANOX) +#undef MAX_NUMBER_OF_TOKENS +#define MAX_NUMBER_OF_TOKENS 10 // TODO : Check how many are actually needed, currently made to fit in memory. +#endif + +#if defined(TARGET_STAX) || defined(TARGET_FLEX) +#undef MAX_NUMBER_OF_TOKENS +#define MAX_NUMBER_OF_TOKENS 600 +#endif +// Context that keeps all the parsed data together. That includes: +// - parsed json tokens +// - re-created SendMsg struct with indices pointing to tokens in parsed json +typedef struct { + uint8_t isValid; + uint32_t numberOfTokens; + jsmntok_t tokens[MAX_NUMBER_OF_TOKENS]; + const char *buffer; + uint16_t bufferLen; +} parsed_json_t; + +/// Parse json to create a token representation +/// \param parsed_json +/// \param transaction +/// \param transaction_length +/// \return Error message +parser_error_t json_parse(parsed_json_t *parsed_json, const char *buffer, uint16_t bufferLen); + +/// Get the number of elements in the array +/// \param json +/// \param array_token_index +/// \param number of elements (out) +/// \return Error message +parser_error_t array_get_element_count(const parsed_json_t *json, + uint16_t array_token_index, + uint16_t *number_elements); + +/// Get the token index of the nth array's element +/// \param json +/// \param array_token_index +/// \param element_index +/// \param token index +/// \return Error message +parser_error_t array_get_nth_element(const parsed_json_t *json, + uint16_t array_token_index, + uint16_t element_index, + uint16_t *token_index); + +/// Get the number of dictionary elements (key/value pairs) under given object +/// \param json +/// \param object_token_index: token index of the parent object +/// \param number of elements (out) +/// \return Error message +parser_error_t object_get_element_count(const parsed_json_t *json, + uint16_t object_token_index, + uint16_t *number_elements); + +/// Get the token index for the nth dictionary key +/// \param json +/// \param object_token_index: token index of the parent object +/// \param object_element_index +/// \return token index (out) +/// \return Error message +parser_error_t object_get_nth_key(const parsed_json_t *json, + uint16_t object_token_index, + uint16_t object_element_index, + uint16_t *token_index); + +/// Get the token index for the nth dictionary value +/// \param json +/// \param object_token_index: token index of the parent object +/// \param object_element_index +/// \return token index (out)) +/// \return Error message +parser_error_t object_get_nth_value(const parsed_json_t *json, + uint16_t object_token_index, + uint16_t object_element_index, + uint16_t *token_index); + +/// Get the token index of the value that matches the given key +/// \param json +/// \param object_token_index: token index of the parent object +/// \param key_name: key name of the wanted value +/// \return Error message +parser_error_t object_get_value(const parsed_json_t *json, + uint16_t object_token_index, + const char *key_name, + uint16_t *token_index); \ No newline at end of file diff --git a/app/src/parser.c b/app/src/parser.c index b5feefd..8f48d93 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -20,20 +20,20 @@ #include #include #include +#include #include "coin.h" #include "crypto.h" #include "crypto_helper.h" -#include "parser_common.h" #include "parser_impl.h" parser_error_t parser_init_context(parser_context_t *ctx, const uint8_t *buffer, uint16_t bufferSize) { ctx->offset = 0; - ctx->buffer = NULL; - ctx->bufferLen = 0; if (bufferSize == 0 || buffer == NULL) { // Not available, use defaults + ctx->buffer = NULL; + ctx->bufferLen = 0; return parser_init_context_empty; } @@ -45,10 +45,16 @@ parser_error_t parser_init_context(parser_context_t *ctx, const uint8_t *buffer, parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen, parser_tx_t *tx_obj) { CHECK_ERROR(parser_init_context(ctx, data, dataLen)) ctx->tx_obj = tx_obj; - return _read(ctx, tx_obj); + + CHECK_ERROR(_read_json_tx(ctx, tx_obj)); + + return parser_ok; } parser_error_t parser_validate(parser_context_t *ctx) { + + // TODO: validate the tx (JSON validation) + // Iterate through all items to check that all can be shown and are valid uint8_t numItems = 0; CHECK_ERROR(parser_getNumItems(ctx, &numItems)) @@ -68,7 +74,7 @@ parser_error_t parser_getNumItems(const parser_context_t *ctx, uint8_t *num_item return parser_tx_obj_empty; } - *num_items = 3; + *num_items = 10; return parser_ok; } @@ -99,20 +105,98 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c switch (displayIdx) { case 0: - snprintf(outKey, outKeyLen, "Blind sign"); - snprintf(outVal, outValLen, "Plain text"); + snprintf(outKey, outKeyLen, "Signing"); + snprintf(outVal, outValLen, "Transaction"); return parser_ok; case 1: - snprintf(outKey, outKeyLen, "Blob"); - pageString(outVal, outValLen, (char *)ctx->buffer, pageIdx, pageCount); + snprintf(outKey, outKeyLen, "On Network"); + char net[9]; + uint16_t net_size; + CHECK_ERROR(parser_getJsonValueAsString("networkId", net, &net_size)); + snprintf(outVal, net_size + 1, "%s", net); return parser_ok; case 2: - snprintf(outKey, outKeyLen, "Hash"); - uint8_t hash[BLAKE2B_HASH_SIZE] = {0}; + snprintf(outKey, outKeyLen, "Requiring"); + snprintf(outVal, outValLen, "Capabilities"); + return parser_ok; + case 3: + snprintf(outKey, outKeyLen, "Of Key"); + char pubKey[64]; + uint16_t pubKey_size; + CHECK_ERROR(parser_getJsonValueAsString("sender", pubKey, &pubKey_size)); + snprintf(outVal, pubKey_size + 1, "%s", pubKey); + return parser_ok; + case 4: + snprintf(outKey, outKeyLen, "Paying Gas"); + snprintf(outVal, outValLen, ""); + return parser_ok; + case 5: + // TODO : Iterate over all the transfers + snprintf(outKey, outKeyLen, "Transfer 1"); + char to[65]; + char from[65]; + char amount[10]; + uint16_t to_size; + uint16_t from_size; + uint16_t amount_size; + CHECK_ERROR(parser_getTransactionParams(1, amount, &amount_size, from, &from_size, to, &to_size)); + + snprintf(outVal, amount_size + from_size + to_size + 15, "%s from \"%s\" to \"%s\"", amount, from, to); + + return parser_ok; + case 6: + snprintf(outKey, outKeyLen, "On Chain"); + char chain[2]; + uint16_t chain_size; + CHECK_ERROR(parser_getJsonValueAsString("chainId", chain, &chain_size)); + snprintf(outVal, chain_size + 1, "%s", chain); + return parser_ok; + case 7: + snprintf(outKey, outKeyLen, "Using Gas"); + char gasLimit[10]; + char gasPrice[10]; + uint16_t gasLimit_size; + uint16_t gasPrice_size; + + CHECK_ERROR(parser_getJsonValueAsString("gasLimit", gasLimit, &gasLimit_size)); + CHECK_ERROR(parser_getJsonValueAsString("gasPrice", gasPrice, &gasPrice_size)); + + snprintf(outVal, 8, "at most"); + snprintf(outVal + strlen(outVal), gasLimit_size + 2, " %s", gasLimit); + snprintf(outVal + strlen(outVal), 10, " at price"); + snprintf(outVal + strlen(outVal), gasPrice_size + 2, " %s", gasPrice); + return parser_ok; + case 8: + snprintf(outKey, outKeyLen, "Transaction hash"); + uint8_t hash[BLAKE2B_OUTPUT_LEN] = {0}; if (blake2b_hash((uint8_t *)ctx->buffer, ctx->bufferLen, hash) != zxerr_ok) { return parser_unexpected_error; } - pageStringHex(outVal, outValLen, (char *)hash, BLAKE2B_HASH_SIZE, pageIdx, pageCount); + + uint8_t base64_hash[44]; + base64_encode(base64_hash, 44, hash, sizeof(hash)); + + // Make it base64 URL safe + for (int i = 0; base64_hash[i] != '\0'; i++) { + if (base64_hash[i] == '+') { + base64_hash[i] = '-'; + } else if (base64_hash[i] == '/') { + base64_hash[i] = '_'; + } + } + + snprintf(outVal, sizeof(base64_hash), "%s", base64_hash); + return parser_ok; + case 9: + snprintf(outKey, outKeyLen, "Sign for Address"); + /* + Currently launching cpp tests, so this is not available + uint8_t address[32]; + uint16_t address_size; + CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); + snprintf(outVal, address_size + 1, "%s", address); + */ + return parser_ok; default: break; diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 8f275e6..f5b2413 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -16,14 +16,65 @@ #include "parser_impl.h" -parser_error_t _read(parser_context_t *c, parser_tx_t *v) { - if (c == NULL || v == NULL) { - return parser_unexpected_error; - } +parser_tx_t parser_tx_obj; + +parser_error_t _read_json_tx(parser_context_t *c, __Z_UNUSED parser_tx_t *v) { + CHECK_ERROR(json_parse(&parser_tx_obj.tx_json.json, (const char *) c->buffer, + c->bufferLen)); + + parser_tx_obj.tx_json.tx = (const char *) c->buffer; + parser_tx_obj.tx_json.flags.cache_valid = 0; + parser_tx_obj.tx_json.filter_msg_type_count = 0; + parser_tx_obj.tx_json.filter_msg_from_count = 0; + + return parser_ok; +} + + +parser_error_t parser_getJsonValueAsString(const char *key_name, char *outVal, uint16_t *outValLen) { + uint16_t token_index = 0; + + // Search token_index to access the parsed JSON object + object_get_value(&parser_tx_obj.tx_json.json, 0, key_name, &token_index); + + *outValLen = (parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); + strncpy(outVal, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, *outValLen); + + return parser_ok; +} + +parser_error_t parser_getTransactionParams(uint8_t tx_index, char *amount, uint16_t *amount_size, char *from, uint16_t *from_size, char *to, uint16_t *to_size) { + parsed_json_t json_clist; + parsed_json_t json_tx; + parsed_json_t json_args; + uint16_t token_index = 0; + + object_get_value(&parser_tx_obj.tx_json.json, 0, "clist", &token_index); + + json_parse(&json_clist, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); + + array_get_nth_element(&json_clist, 0, 0, &token_index); + + json_parse(&json_tx, json_clist.buffer + json_clist.tokens[token_index].start, json_clist.tokens[token_index].end - json_clist.tokens[token_index].start); + + object_get_value(&json_tx, 0, "args", &token_index); + + json_parse(&json_args, json_tx.buffer + json_tx.tokens[token_index].start, json_tx.tokens[token_index].end - json_tx.tokens[token_index].start); + + array_get_nth_element(&json_args, 0, 0, &token_index); + strncpy(from, json_args.buffer + json_args.tokens[token_index].start, json_args.tokens[token_index].end - json_args.tokens[token_index].start); + *from_size = json_args.tokens[token_index].end - json_args.tokens[token_index].start; + from[*from_size] = '\0'; + + array_get_nth_element(&json_args, 0, 1, &token_index); + strncpy(to, json_args.buffer + json_args.tokens[token_index].start, json_args.tokens[token_index].end - json_args.tokens[token_index].start); + *to_size = json_args.tokens[token_index].end - json_args.tokens[token_index].start; + to[*to_size] = '\0'; - // TODO: implement parser - v->generic_tx.len = c->bufferLen; - v->generic_tx.ptr = c->buffer; + array_get_nth_element(&json_args, 0, 2, &token_index); + strncpy(amount, json_args.buffer + json_args.tokens[token_index].start, json_args.tokens[token_index].end - json_args.tokens[token_index].start); + *amount_size = json_args.tokens[token_index].end - json_args.tokens[token_index].start; + amount[*amount_size] = '\0'; return parser_ok; } diff --git a/app/src/parser_impl.h b/app/src/parser_impl.h index 9c31332..62b7a40 100644 --- a/app/src/parser_impl.h +++ b/app/src/parser_impl.h @@ -25,8 +25,17 @@ extern "C" { #endif -// #{TODO} --> functions to parse, get, process transaction fields -parser_error_t _read(parser_context_t *c, parser_tx_t *v); + +typedef struct { + const uint8_t *buffer; + uint16_t bufferLen; + uint16_t offset; + parser_tx_t *tx_obj; +} parser_context_t; + +parser_error_t _read_json_tx(parser_context_t *c, parser_tx_t *v); +parser_error_t parser_getJsonValueAsString(const char *key_name, char *outVal, uint16_t *outValLen); +parser_error_t parser_getTransactionParams(uint8_t index, char *amount, uint16_t *amount_size, char *from, uint16_t *from_size, char *to, uint16_t *to_size); #ifdef __cplusplus } diff --git a/app/src/parser_txdef.h b/app/src/parser_txdef.h index 94128e4..0bebeb7 100644 --- a/app/src/parser_txdef.h +++ b/app/src/parser_txdef.h @@ -19,16 +19,76 @@ extern "C" { #endif -#include #include +#include +#include +#include "coin.h" typedef struct { uint16_t len; const uint8_t *ptr; } Bytes_t; +typedef struct tx_textual_t{ + size_t n_containers; + uint8_t n_expert; + uint8_t tmpBuffer[625]; +} tx_textual_t; + +typedef struct { + // These are internal values used for tracking the state of the query/search + uint16_t _item_index_current; + + // maximum json tree level. Beyond this tree depth, key/values are flattened + uint8_t max_level; + + // maximum tree traversal depth. This limits possible stack overflow issues + uint8_t max_depth; + + // Index of the item to retrieve + int16_t item_index; + // Chunk of the item to retrieve (assuming partitioning based on out_val_len chunks) + int16_t page_index; + + // These fields (out_*) are where query results are placed + char *out_key; + uint16_t out_key_len; + char *out_val; + int16_t out_val_len; +} tx_query_t; + +typedef struct +{ + // Buffer to the original tx blob + const char *tx; + + // parsed data (tokens, etc.) + parsed_json_t json; + + // internal flags + struct { + bool cache_valid:1; + bool msg_type_grouping:1; // indicates if msg type grouping is enabled + bool msg_from_grouping:1; // indicates if msg from grouping is enabled + bool msg_from_grouping_hide_all:1; // indicates if msg from grouping should hide all + } flags; + + // indicates that N identical msg_type fields have been detected + uint8_t filter_msg_type_count; + int32_t filter_msg_type_valid_idx; + + // indicates that N identical msg_from fields have been detected + uint8_t filter_msg_from_count; + int32_t filter_msg_from_valid_idx; + const char *own_addr; + + // current tx query + tx_query_t query; +}tx_json_t; + typedef struct { - Bytes_t generic_tx; + // TODO : Remove this abstraction if no more fields are needed + tx_json_t tx_json; } parser_tx_t; #ifdef __cplusplus diff --git a/tests/json_parser.cpp b/tests/json_parser.cpp new file mode 100644 index 0000000..49bf87b --- /dev/null +++ b/tests/json_parser.cpp @@ -0,0 +1,398 @@ +/******************************************************************************* +* (c) 2024 Zondax GmbH +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +********************************************************************************/ + +#include "parser_impl.h" + +#include + +#include +#include + +#include "gmock/gmock.h" +#include "parser.h" +#include "parser_txdef.h" +#include "utils/common.h" + +namespace { + TEST(JsonParserTest, Empty) { + parsed_json_t parserData = {false}; + JSON_PARSE(&parserData, ""); + + EXPECT_FALSE(parserData.isValid); + EXPECT_EQ(0, parserData.numberOfTokens); + } + + TEST(JsonParserTest, SinglePrimitive) { + parsed_json_t parserData = {false}; + JSON_PARSE(&parserData, "EMPTY"); + + EXPECT_TRUE(parserData.isValid); + EXPECT_EQ(1, parserData.numberOfTokens); + EXPECT_TRUE(parserData.tokens[0].type == jsmntype_t::JSMN_PRIMITIVE); + } + + TEST(JsonParserTest, KeyValuePrimitives) { + parsed_json_t parserData = {false}; + JSON_PARSE(&parserData, "KEY : VALUE"); + + EXPECT_TRUE(parserData.isValid); + EXPECT_EQ(2, parserData.numberOfTokens); + EXPECT_TRUE(parserData.tokens[0].type == jsmntype_t::JSMN_PRIMITIVE); + EXPECT_TRUE(parserData.tokens[1].type == jsmntype_t::JSMN_PRIMITIVE); + } + + TEST(JsonParserTest, SingleString) { + parsed_json_t parserData = {false}; + JSON_PARSE(&parserData, "\"EMPTY\""); + + EXPECT_TRUE(parserData.isValid); + EXPECT_EQ(1, parserData.numberOfTokens); + EXPECT_TRUE(parserData.tokens[0].type == jsmntype_t::JSMN_STRING); + } + + TEST(JsonParserTest, KeyValueStrings) { + parsed_json_t parserData = {false}; + JSON_PARSE(&parserData, R"("KEY" : "VALUE")"); + + EXPECT_TRUE(parserData.isValid); + EXPECT_EQ(2, parserData.numberOfTokens); + EXPECT_TRUE(parserData.tokens[0].type == jsmntype_t::JSMN_STRING); + EXPECT_TRUE(parserData.tokens[1].type == jsmntype_t::JSMN_STRING); + } + + TEST(JsonParserTest, SimpleArray) { + parsed_json_t parserData = {false}; + JSON_PARSE(&parserData, "LIST : [1, 2, 3, 4]"); + + EXPECT_TRUE(parserData.isValid); + EXPECT_EQ(6, parserData.numberOfTokens); + EXPECT_TRUE(parserData.tokens[0].type == jsmntype_t::JSMN_PRIMITIVE); + EXPECT_TRUE(parserData.tokens[1].type == jsmntype_t::JSMN_ARRAY); + EXPECT_TRUE(parserData.tokens[2].type == jsmntype_t::JSMN_PRIMITIVE); + EXPECT_TRUE(parserData.tokens[3].type == jsmntype_t::JSMN_PRIMITIVE); + EXPECT_TRUE(parserData.tokens[4].type == jsmntype_t::JSMN_PRIMITIVE); + EXPECT_TRUE(parserData.tokens[5].type == jsmntype_t::JSMN_PRIMITIVE); + } + + TEST(JsonParserTest, MixedArray) { + parsed_json_t parserData = {false}; + JSON_PARSE(&parserData, R"(LIST : [1, "Text", 3, "Another text"])"); + + EXPECT_TRUE(parserData.isValid); + EXPECT_EQ(6, parserData.numberOfTokens); + EXPECT_TRUE(parserData.tokens[0].type == jsmntype_t::JSMN_PRIMITIVE); + EXPECT_TRUE(parserData.tokens[1].type == jsmntype_t::JSMN_ARRAY); + EXPECT_TRUE(parserData.tokens[2].type == jsmntype_t::JSMN_PRIMITIVE); + EXPECT_TRUE(parserData.tokens[3].type == jsmntype_t::JSMN_STRING); + EXPECT_TRUE(parserData.tokens[4].type == jsmntype_t::JSMN_PRIMITIVE); + EXPECT_TRUE(parserData.tokens[5].type == jsmntype_t::JSMN_STRING); + } + + TEST(JsonParserTest, SimpleObject) { + parsed_json_t parserData = {false}; + JSON_PARSE(&parserData, "vote : " + "{ " + "\"key\" : \"value\", " + "\"another key\" : { " + "\"inner key\" : \"inner value\", " + "\"total\":123 }" + "}"); + + EXPECT_TRUE(parserData.isValid); + EXPECT_EQ(10, parserData.numberOfTokens); + EXPECT_TRUE(parserData.tokens[0].type == jsmntype_t::JSMN_PRIMITIVE); + EXPECT_TRUE(parserData.tokens[1].type == jsmntype_t::JSMN_OBJECT); + EXPECT_TRUE(parserData.tokens[2].type == jsmntype_t::JSMN_STRING); + EXPECT_TRUE(parserData.tokens[3].type == jsmntype_t::JSMN_STRING); + EXPECT_TRUE(parserData.tokens[4].type == jsmntype_t::JSMN_STRING); + EXPECT_TRUE(parserData.tokens[5].type == jsmntype_t::JSMN_OBJECT); + EXPECT_TRUE(parserData.tokens[6].type == jsmntype_t::JSMN_STRING); + EXPECT_TRUE(parserData.tokens[7].type == jsmntype_t::JSMN_STRING); + EXPECT_TRUE(parserData.tokens[8].type == jsmntype_t::JSMN_STRING); + EXPECT_TRUE(parserData.tokens[9].type == jsmntype_t::JSMN_PRIMITIVE); + } + + TEST(JsonParserTest, ArrayElementCount_objects) { + auto transaction = + R"({"array":[{"amount":5,"denom":"photon"}, {"amount":5,"denom":"photon"}, {"amount":5,"denom":"photon"}]})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token; + EXPECT_EQ(array_get_element_count(&parsed_json, 2, &token), parser_ok); + EXPECT_EQ(token, 3) << "Wrong number of array elements"; + } + + TEST(JsonParserTest, ArrayElementCount_primitives) { + auto transaction = R"({"array":[1, 2, 3, 4, 5, 6, 7]})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token; + EXPECT_EQ(array_get_element_count(&parsed_json, 2, &token), parser_ok); + EXPECT_EQ(token, 7) << "Wrong number of array elements"; + } + + TEST(JsonParserTest, ArrayElementCount_strings) { + auto transaction = R"({"array":["hello", "there"]})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token; + EXPECT_EQ(array_get_element_count(&parsed_json, 2, &token), parser_ok); + EXPECT_EQ(token, 2) << "Wrong number of array elements"; + } + + TEST(JsonParserTest, ArrayElementCount_empty) { + auto transaction = R"({"array":[])"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token; + EXPECT_EQ(array_get_element_count(&parsed_json, 2, &token), parser_no_data); + } + + TEST(JsonParserTest, ArrayElementGet_objects) { + auto transaction = + R"({"array":[{"amount":5,"denom":"photon"}, {"amount":5,"denom":"photon"}, {"amount":5,"denom":"photon"}]})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(array_get_nth_element(&parsed_json, 2, 1, &token_index), parser_ok); + EXPECT_EQ(token_index, 8) << "Wrong token index returned"; + EXPECT_EQ(parsed_json.tokens[token_index].type, JSMN_OBJECT) << "Wrong token type returned"; + } + + TEST(JsonParserTest, ArrayElementGet_primitives) { + auto transaction = R"({"array":[1, 2, 3, 4, 5, 6, 7]})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(array_get_nth_element(&parsed_json, 2, 5, &token_index), parser_ok); + EXPECT_EQ(token_index, 8) << "Wrong token index returned"; + EXPECT_EQ(parsed_json.tokens[token_index].type, JSMN_PRIMITIVE) << "Wrong token type returned"; + } + + TEST(TxValidationTest, ArrayElementGet_strings) { + auto transaction = R"({"array":["hello", "there"]})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(array_get_nth_element(&parsed_json, 2, 0, &token_index), parser_ok); + EXPECT_EQ(token_index, 3) << "Wrong token index returned"; + EXPECT_EQ(parsed_json.tokens[token_index].type, JSMN_STRING) << "Wrong token type returned"; + } + + TEST(TxValidationTest, ArrayElementGet_empty) { + auto transaction = R"({"array":[])"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(array_get_nth_element(&parsed_json, 2, 0, &token_index), parser_no_data) + << "Token index should be invalid (not found)."; + } + + TEST(TxValidationTest, ArrayElementGet_out_of_bounds_negative) { + auto transaction = R"({"array":["hello", "there"])"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(array_get_nth_element(&parsed_json, 2, -1, &token_index), parser_no_data) + << "Token index should be invalid (not found)."; + } + + TEST(TxValidationTest, ArrayElementGet_out_of_bounds) { + auto transaction = R"({"array":["hello", "there"])"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(array_get_nth_element(&parsed_json, 2, 3, &token_index), parser_no_data) + << "Token index should be invalid (not found)."; + } + + TEST(TxValidationTest, ObjectElementCount_primitives) { + auto transaction = R"({"age":36, "height":185, "year":1981})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t count; + EXPECT_EQ(object_get_element_count(&parsed_json, 0, &count), parser_ok); + EXPECT_EQ(count, 3) << "Wrong number of object elements"; + } + + TEST(TxValidationTest, ObjectElementCount_string) { + auto transaction = R"({"age":"36", "height":"185", "year":"1981", "month":"july"})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t count; + EXPECT_EQ(object_get_element_count(&parsed_json, 0, &count), parser_ok); + EXPECT_EQ(count, 4) << "Wrong number of object elements"; + } + + TEST(TxValidationTest, ObjectElementCount_array) { + auto transaction = R"({ "ages":[36, 31, 10, 2], + "heights":[185, 164, 154, 132], + "years":[1981, 1985, 2008, 2016], + "months":["july", "august", "february", "july"]})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t count; + EXPECT_EQ(object_get_element_count(&parsed_json, 0, &count), parser_ok); + EXPECT_EQ(count, 4) << "Wrong number of object elements"; + } + + TEST(TxValidationTest, ObjectElementCount_object) { + auto transaction = R"({"person1":{"age":36, "height":185, "year":1981}, + "person2":{"age":36, "height":185, "year":1981}, + "person3":{"age":36, "height":185, "year":1981}})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t count; + EXPECT_EQ(object_get_element_count(&parsed_json, 0, &count), parser_ok); + EXPECT_EQ(count, 3) << "Wrong number of object elements"; + } + + TEST(TxValidationTest, ObjectElementCount_deep) { + auto transaction = R"({"person1":{"age":{"age":36, "height":185, "year":1981}, "height":{"age":36, "height":185, "year":1981}, "year":1981}, + "person2":{"age":{"age":36, "height":185, "year":1981}, "height":{"age":36, "height":185, "year":1981}, "year":1981}, + "person3":{"age":{"age":36, "height":185, "year":1981}, "height":{"age":36, "height":185, "year":1981}, "year":1981}})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t count; + EXPECT_EQ(object_get_element_count(&parsed_json, 0, &count), parser_ok); + EXPECT_EQ(count, 3) << "Wrong number of object elements"; + } + + TEST(TxValidationTest, ObjectElementGet_primitives) { + auto transaction = R"({"age":36, "height":185, "year":1981})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(object_get_nth_key(&parsed_json, 0, 0, &token_index), parser_ok); + EXPECT_EQ(token_index, 1) << "Wrong token index"; + EXPECT_EQ(parsed_json.tokens[token_index].type, JSMN_STRING) << "Wrong token type returned"; + EXPECT_EQ(memcmp(transaction + parsed_json.tokens[token_index].start, "age", strlen("age")), 0) + << "Wrong key returned"; + } + + TEST(TxValidationTest, ObjectElementGet_string) { + auto transaction = R"({"age":"36", "height":"185", "year":"1981", "month":"july"})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(object_get_nth_value(&parsed_json, 0, 3, &token_index), parser_ok); + EXPECT_EQ(token_index, 8) << "Wrong token index"; + EXPECT_EQ(parsed_json.tokens[token_index].type, JSMN_STRING) << "Wrong token type returned"; + EXPECT_EQ(memcmp(transaction + parsed_json.tokens[token_index].start, "july", strlen("july")), 0) + << "Wrong key returned"; + } + + TEST(TxValidationTest, ObjectElementGet_out_of_bounds_negative) { + auto transaction = R"({"age":36, "height":185, "year":1981})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(object_get_nth_key(&parsed_json, 0, -1, &token_index), parser_no_data) + << "Wrong token index, should be invalid"; + } + + TEST(TxValidationTest, ObjectElementGet_out_of_bounds) { + auto transaction = R"({"age":36, "height":185, "year":1981})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(object_get_nth_key(&parsed_json, 0, 5, &token_index), parser_no_data) + << "Wrong token index, should be invalid"; + } + + TEST(TxValidationTest, ObjectElementGet_array) { + auto transaction = R"({ "ages":[36, 31, 10, 2], + "heights":[185, 164, 154, 132], + "years":[1981, 1985, 2008, 2016, 2022], + "months":["july", "august", "february", "july"]})"; + + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(object_get_value(&parsed_json, 0, "years", &token_index), parser_ok); + + EXPECT_EQ(token_index, 14) << "Wrong token index"; + EXPECT_EQ(parsed_json.tokens[token_index].type, JSMN_ARRAY) << "Wrong token type returned"; + uint16_t number_elements; + EXPECT_EQ(array_get_element_count(&parsed_json, token_index, &number_elements), parser_ok); + EXPECT_EQ(number_elements, 5) << "Wrong number of array elements"; + } + + TEST(TxValidationTest, ObjectGetValueCorrectFormat) { + auto transaction = + R"({"account_number":"0","chain_id":"test-chain-1","fee":{"amount":[{"amount":"5","denom":"photon"}],"gas":"10000"},"memo":"testmemo","msgs":[{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"amount":"10","denom":"atom"}]}]}],"sequence":"1"})"; + parsed_json_t parsed_json; + JSON_PARSE(&parsed_json, transaction); + + uint16_t token_index; + EXPECT_EQ(object_get_value(&parsed_json, 0, "alt_bytes", &token_index), parser_no_data) + << "Wrong token index"; // alt_bytes should not be found + + EXPECT_EQ(object_get_value(&parsed_json, 0, "account_number", &token_index), parser_ok); + EXPECT_EQ(token_index, 2) << "Wrong token index"; // alt_bytes should not be found + + EXPECT_EQ(object_get_value(&parsed_json, 0, "chain_id", &token_index), parser_ok); + EXPECT_EQ(token_index, 4) << "Wrong token index"; + + EXPECT_EQ(object_get_value(&parsed_json, 0, "fee", &token_index), parser_ok); + EXPECT_EQ(token_index, 6) << "Wrong token index"; + + EXPECT_EQ(object_get_value(&parsed_json, 0, "msgs", &token_index), parser_ok); + EXPECT_EQ(token_index, 19) << "Wrong token index"; + + EXPECT_EQ(object_get_value(&parsed_json, 0, "sequence", &token_index), parser_ok); + EXPECT_EQ(token_index, 46) << "Wrong token index"; + } +} \ No newline at end of file diff --git a/tests/testcases.json b/tests/testcases.json index bc16c98..dfea211 100644 --- a/tests/testcases.json +++ b/tests/testcases.json @@ -2,73 +2,30 @@ { "index": 0, "name": "Asset_Freeze", - "blob": "8ba466616464c4204b2a4ad9d4d900ea16f9dcee534b9c0189daa1acbccace73d794bf168b8a73e3a466616964ce000b6717a3666565ce001e163fa26676ce000153c8a367656eac6d61696e6e65742d76312e30a26768c420c061c4d8fc1dbdded2d7604be4568e3f6d041987ac37bde4b620b5ab39248adfa26c76ce00018b66a46e6f7465c41c48656c6c6f2074686572652c20746869732069732061206e6f746521a572656b6579c4206a08f935de3bb9eb65b9d206598f5d34419257491c4024ca5f88ea73749de231a3736e64c4209fa4543b7caf05ad7334a5a74033acdc130137d7afa1f6733509f6d4377c30d7a474797065a46166727a", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", "output": [ - "0 | Txn type : Asset Freeze", - "1 | Sender [1/2] : T6SFIO34V4C224ZUUWTUAM5M3QJQCN6XV6Q7M4", - "1 | Sender [2/2] : ZVBH3NIN34GDLSK2ETKM", - "2 | Rekey to [1/2] : WARNING: NIEPSNO6HO46WZNZ2IDFTD25GRAZE", - "2 | Rekey to [2/2] : V2JDRACJSS7RDVHG5E54IYZOIA3MI", - "3 | Fee : ALGO 1.971775", - "4 | Genesis ID : mainnet-v1.0", - "5 | Genesis hash [1/2] : wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qz", - "5 | Genesis hash [2/2] : kkit8=", - "6 | Note : 28 bytes", - "7 | Asset ID : 747287", - "8 | Asset account [1/2] : JMVEVWOU3EAOUFXZ3TXFGS44AGE5VINMXTFM44", - "8 | Asset account [2/2] : 6XSS7RNC4KOPR5HR537U", - "9 | Freeze flag : Unfrozen" + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ - "0 | Txn type : Asset Freeze", - "1 | Sender [1/2] : T6SFIO34V4C224ZUUWTUAM5M3QJQCN6XV6Q7M4", - "1 | Sender [2/2] : ZVBH3NIN34GDLSK2ETKM", - "2 | Rekey to [1/2] : WARNING: NIEPSNO6HO46WZNZ2IDFTD25GRAZE", - "2 | Rekey to [2/2] : V2JDRACJSS7RDVHG5E54IYZOIA3MI", - "3 | Fee : ALGO 1.971775", - "4 | Genesis ID : mainnet-v1.0", - "5 | Genesis hash [1/2] : wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qz", - "5 | Genesis hash [2/2] : kkit8=", - "6 | Note : 28 bytes", - "7 | Asset ID : 747287", - "8 | Asset account [1/2] : JMVEVWOU3EAOUFXZ3TXFGS44AGE5VINMXTFM44", - "8 | Asset account [2/2] : 6XSS7RNC4KOPR5HR537U", - "9 | Freeze flag : Unfrozen" - ] - }, - { - "index": 1, - "name": "Asset_Freeze", - "blob": "8aa466616464c4204b2a4ad9d4d900ea16f9dcee534b9c0189daa1acbccace73d794bf168b8a73e3a466616964ce00038ce6a3666565ce00272460a26676cd6584a367656eac6d61696e6e65742d76312e30a26768c420c061c4d8fc1dbdded2d7604be4568e3f6d041987ac37bde4b620b5ab39248adfa26c76ce0001cd3ca572656b6579c42075895bccedfa0c747cea13601babff1de5cecf4dd7a3fe86eaeccb74b60124dea3736e64c420aba83eaca22287f68cad3906661fc72b1c3537dbbae4ba2c6e35a51c03c87f80a474797065a46166727a", - "output": [ - "0 | Txn type : Asset Freeze", - "1 | Sender [1/2] : VOUD5LFCEKD7NDFNHEDGMH6HFMODKN63XLSLUL", - "1 | Sender [2/2] : DOGWSRYA6IP6ADQBWT6Y", - "2 | Rekey to [1/2] : WARNING: OWEVXTHN7IGHI7HKCNQBXK77DXS45", - "2 | Rekey to [2/2] : T2N26R75BXK5TFXJNQBETPAS7VK74", - "3 | Fee : ALGO 2.565216", - "4 | Genesis ID : mainnet-v1.0", - "5 | Genesis hash [1/2] : wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qz", - "5 | Genesis hash [2/2] : kkit8=", - "6 | Asset ID : 232678", - "7 | Asset account [1/2] : JMVEVWOU3EAOUFXZ3TXFGS44AGE5VINMXTFM44", - "7 | Asset account [2/2] : 6XSS7RNC4KOPR5HR537U", - "8 | Freeze flag : Unfrozen" - ], - "output_expert": [ - "0 | Txn type : Asset Freeze", - "1 | Sender [1/2] : VOUD5LFCEKD7NDFNHEDGMH6HFMODKN63XLSLUL", - "1 | Sender [2/2] : DOGWSRYA6IP6ADQBWT6Y", - "2 | Rekey to [1/2] : WARNING: OWEVXTHN7IGHI7HKCNQBXK77DXS45", - "2 | Rekey to [2/2] : T2N26R75BXK5TFXJNQBETPAS7VK74", - "3 | Fee : ALGO 2.565216", - "4 | Genesis ID : mainnet-v1.0", - "5 | Genesis hash [1/2] : wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qz", - "5 | Genesis hash [2/2] : kkit8=", - "6 | Asset ID : 232678", - "7 | Asset account [1/2] : JMVEVWOU3EAOUFXZ3TXFGS44AGE5VINMXTFM44", - "7 | Asset account [2/2] : 6XSS7RNC4KOPR5HR537U", - "8 | Freeze flag : Unfrozen" + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] } ] \ No newline at end of file diff --git a/tests/ui_tests.cpp b/tests/ui_tests.cpp index 1c76533..b2066b5 100644 --- a/tests/ui_tests.cpp +++ b/tests/ui_tests.cpp @@ -111,19 +111,18 @@ void check_testcase(const testcase_t &tc, bool expert_mode) { std::vector expected = app_mode_expert() ? tc.expected_expert : tc.expected; -// #{TODO} --> After updating testvector, enable this part -#if 0 EXPECT_EQ(output.size(), expected.size()); for (size_t i = 0; i < expected.size(); i++) { if (i < output.size()) { EXPECT_THAT(output[i], testing::Eq(expected[i])); } } -#endif } INSTANTIATE_TEST_SUITE_P (JsonTestCasesCurrentTxVer, JsonTestsA, ::testing::ValuesIn(GetJsonTestCases("testcases.json")), JsonTestsA::PrintToStringParamName()); -TEST_P(JsonTestsA, CheckUIOutput_CurrentTX_Expert) { check_testcase(GetParam(), true); } + +//TEST_P(JsonTestsA, CheckUIOutput_CurrentTX_Expert) { check_testcase(GetParam(), true); } +TEST_P(JsonTestsA, CheckUIOutput_CurrentTX) { check_testcase(GetParam(), false); } \ No newline at end of file diff --git a/tests/utils/common.h b/tests/utils/common.h index 7bfc863..78ae772 100644 --- a/tests/utils/common.h +++ b/tests/utils/common.h @@ -13,9 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************/ +#pragma once + #include #include +#include "parser_impl.h" #include "parser_common.h" +#include +#include + +#define EXPECT_EQ_STR(_STR1, _STR2, _ERROR_MESSAGE) { if ((_STR1) != nullptr & (_STR2) != nullptr) \ +EXPECT_TRUE(!strcmp(_STR1, _STR2)) << (_ERROR_MESSAGE) << ", expected: " << (_STR2) << ", received: " << (_STR1); \ +else FAIL() << "One of the strings is null"; } + std::vector dumpUI(parser_context_t *ctx, uint16_t maxKeyLen, uint16_t maxValueLen); + +parser_error_t parse_tx(parsed_json_t *parsed_json, const char *tx); + +std::vector dumpUI(parser_context_t *ctx, uint16_t maxKeyLen, uint16_t maxValueLen); + +#define JSON_PARSE(parsed_json, buffer) json_parse(parsed_json, buffer, strlen(buffer)) \ No newline at end of file From 4e8e1178e7f4529b0f32856d5e58d2949ee1e1d4 Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Fri, 9 Aug 2024 11:37:50 +0200 Subject: [PATCH 02/34] Refactor parserGetItem --- app/src/common/parser_common.h | 10 +- app/src/parser.c | 110 +-------- app/src/parser_impl.c | 399 ++++++++++++++++++++++++++++++--- app/src/parser_impl.h | 30 ++- tests/testcases.json | 66 +++++- 5 files changed, 475 insertions(+), 140 deletions(-) diff --git a/app/src/common/parser_common.h b/app/src/common/parser_common.h index 8fcc3d5..78b1822 100644 --- a/app/src/common/parser_common.h +++ b/app/src/common/parser_common.h @@ -59,15 +59,7 @@ typedef enum { parser_json_zero_tokens, parser_json_too_many_tokens, // "NOMEM: JSON string contains too many tokens" parser_json_incomplete_json, // "JSON string is not complete"; - // TODO : Clean these if never used - //parser_json_contains_whitespace, - //parser_json_is_not_sorted, - //parser_json_missing_chain_id, - //parser_json_missing_sequence, - //parser_json_missing_fee, - //parser_json_missing_msgs, - //parser_json_missing_account_number, - //parser_json_missing_memo, + parser_json_not_a_transfer, parser_json_unexpected_error, } parser_error_t; diff --git a/app/src/parser.c b/app/src/parser.c index 8f48d93..6f70f42 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -20,7 +20,6 @@ #include #include #include -#include #include "coin.h" #include "crypto.h" @@ -48,6 +47,9 @@ parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t d CHECK_ERROR(_read_json_tx(ctx, tx_obj)); + CHECK_ERROR(parser_initItems()); + CHECK_ERROR(parser_storeItems(ctx)); + return parser_ok; } @@ -74,7 +76,8 @@ parser_error_t parser_getNumItems(const parser_context_t *ctx, uint8_t *num_item return parser_tx_obj_empty; } - *num_items = 10; + *num_items = 0; + parser_getTotalItems(num_items); return parser_ok; } @@ -97,110 +100,15 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) { *pageCount = 1; uint8_t numItems = 0; + item_array_t *item_array = parser_getItemArray(); CHECK_ERROR(parser_getNumItems(ctx, &numItems)) CHECK_APP_CANARY() CHECK_ERROR(checkSanity(numItems, displayIdx)) cleanOutput(outKey, outKeyLen, outVal, outValLen); - switch (displayIdx) { - case 0: - snprintf(outKey, outKeyLen, "Signing"); - snprintf(outVal, outValLen, "Transaction"); - return parser_ok; - case 1: - snprintf(outKey, outKeyLen, "On Network"); - char net[9]; - uint16_t net_size; - CHECK_ERROR(parser_getJsonValueAsString("networkId", net, &net_size)); - snprintf(outVal, net_size + 1, "%s", net); - return parser_ok; - case 2: - snprintf(outKey, outKeyLen, "Requiring"); - snprintf(outVal, outValLen, "Capabilities"); - return parser_ok; - case 3: - snprintf(outKey, outKeyLen, "Of Key"); - char pubKey[64]; - uint16_t pubKey_size; - CHECK_ERROR(parser_getJsonValueAsString("sender", pubKey, &pubKey_size)); - snprintf(outVal, pubKey_size + 1, "%s", pubKey); - return parser_ok; - case 4: - snprintf(outKey, outKeyLen, "Paying Gas"); - snprintf(outVal, outValLen, ""); - return parser_ok; - case 5: - // TODO : Iterate over all the transfers - snprintf(outKey, outKeyLen, "Transfer 1"); - char to[65]; - char from[65]; - char amount[10]; - uint16_t to_size; - uint16_t from_size; - uint16_t amount_size; - CHECK_ERROR(parser_getTransactionParams(1, amount, &amount_size, from, &from_size, to, &to_size)); - - snprintf(outVal, amount_size + from_size + to_size + 15, "%s from \"%s\" to \"%s\"", amount, from, to); - - return parser_ok; - case 6: - snprintf(outKey, outKeyLen, "On Chain"); - char chain[2]; - uint16_t chain_size; - CHECK_ERROR(parser_getJsonValueAsString("chainId", chain, &chain_size)); - snprintf(outVal, chain_size + 1, "%s", chain); - return parser_ok; - case 7: - snprintf(outKey, outKeyLen, "Using Gas"); - char gasLimit[10]; - char gasPrice[10]; - uint16_t gasLimit_size; - uint16_t gasPrice_size; - - CHECK_ERROR(parser_getJsonValueAsString("gasLimit", gasLimit, &gasLimit_size)); - CHECK_ERROR(parser_getJsonValueAsString("gasPrice", gasPrice, &gasPrice_size)); - - snprintf(outVal, 8, "at most"); - snprintf(outVal + strlen(outVal), gasLimit_size + 2, " %s", gasLimit); - snprintf(outVal + strlen(outVal), 10, " at price"); - snprintf(outVal + strlen(outVal), gasPrice_size + 2, " %s", gasPrice); - return parser_ok; - case 8: - snprintf(outKey, outKeyLen, "Transaction hash"); - uint8_t hash[BLAKE2B_OUTPUT_LEN] = {0}; - if (blake2b_hash((uint8_t *)ctx->buffer, ctx->bufferLen, hash) != zxerr_ok) { - return parser_unexpected_error; - } - - uint8_t base64_hash[44]; - base64_encode(base64_hash, 44, hash, sizeof(hash)); - - // Make it base64 URL safe - for (int i = 0; base64_hash[i] != '\0'; i++) { - if (base64_hash[i] == '+') { - base64_hash[i] = '-'; - } else if (base64_hash[i] == '/') { - base64_hash[i] = '_'; - } - } - - snprintf(outVal, sizeof(base64_hash), "%s", base64_hash); - return parser_ok; - case 9: - snprintf(outKey, outKeyLen, "Sign for Address"); - /* - Currently launching cpp tests, so this is not available - uint8_t address[32]; - uint16_t address_size; - CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); - snprintf(outVal, address_size + 1, "%s", address); - */ - - return parser_ok; - default: - break; - } + snprintf(outKey, outKeyLen, item_array->items[displayIdx].key); + item_array->items[displayIdx].toString(item_array->items[displayIdx].buf, item_array->items[displayIdx].len, outVal, &outValLen); - return parser_display_idx_out_of_range; + return parser_ok; } diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index f5b2413..3b40caa 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -15,8 +15,25 @@ ********************************************************************************/ #include "parser_impl.h" +#include "crypto_helper.h" +#include + +static parser_error_t parser_getTransferValue(uint16_t* clist_array_idx, char **value, uint16_t *value_len); +static parser_error_t parser_getGasArgsFromClist(parsed_json_t *json_gas_args); +static parser_error_t parser_stdToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); +static parser_error_t parser_transferToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); +static parser_error_t parser_gasToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); +static parser_error_t parser_unknownCapabilityToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); parser_tx_t parser_tx_obj; +parsed_json_t json_clist; +item_array_t item_array; + +char signing_buf[] = "Transaction"; +char capabilities_buf[] = "Capabilities"; + +uint8_t hash[BLAKE2B_HASH_SIZE] = {0}; +uint8_t base64_hash[44]; parser_error_t _read_json_tx(parser_context_t *c, __Z_UNUSED parser_tx_t *v) { CHECK_ERROR(json_parse(&parser_tx_obj.tx_json.json, (const char *) c->buffer, @@ -27,58 +44,388 @@ parser_error_t _read_json_tx(parser_context_t *c, __Z_UNUSED parser_tx_t *v) { parser_tx_obj.tx_json.filter_msg_type_count = 0; parser_tx_obj.tx_json.filter_msg_from_count = 0; + parser_initClistObject(); + return parser_ok; } +parser_error_t parser_initItems() { + MEMZERO(&item_array, sizeof(item_array_t)); + return parser_ok; +} + +parser_error_t parser_storeItems(parser_context_t *ctx) { + parsed_json_t json_gas_args; + uint8_t items_idx = 0; + uint8_t unknown_capabitilies = 1; + + strcpy(item_array.items[items_idx].key, "Signing"); + item_array.items[items_idx].buf = signing_buf; + item_array.items[items_idx].len = sizeof(signing_buf); + item_array.items[items_idx].toString = parser_stdToDisplayString; + items_idx++; + + strcpy(item_array.items[items_idx].key, "On Network"); + parser_getJsonValueBuffer(parser_tx_obj.tx_json.json, "networkId", &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); + item_array.items[items_idx].toString = parser_stdToDisplayString; + items_idx++; + + strcpy(item_array.items[items_idx].key, "Requiring"); + item_array.items[items_idx].buf = capabilities_buf; + item_array.items[items_idx].len = sizeof(capabilities_buf); + item_array.items[items_idx].toString = parser_stdToDisplayString; + items_idx++; + + strcpy(item_array.items[items_idx].key, "Of Key"); + parser_getJsonValueBuffer(parser_tx_obj.tx_json.json, "sender", &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); + item_array.items[items_idx].toString = parser_stdToDisplayString; + items_idx++; + + parser_getGasArgsFromClist(&json_gas_args); + uint16_t args_count = 0; + array_get_element_count(&json_gas_args, 0, &args_count); + if (args_count == 0) { + strcpy(item_array.items[items_idx].key, "Paying Gas"); + item_array.items[items_idx].buf = ""; + item_array.items[items_idx].len = 0; + item_array.items[items_idx].toString = parser_stdToDisplayString; + } else { + snprintf(item_array.items[items_idx].key, strlen("Unknown Capability X") + 1, "Unknown Capability %d", unknown_capabitilies++); + item_array.items[items_idx].buf = json_gas_args.buffer; + item_array.items[items_idx].len = json_gas_args.bufferLen; + item_array.items[items_idx].toString = parser_unknownCapabilityToDisplayString; + } + items_idx++; + + uint16_t obj_token_idx = 0; + for (uint8_t i = 0; i < parser_getNumberOfTransfers(); i++, items_idx++) { + snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Transfer %d", i + 1); + parser_getTransferValue(&obj_token_idx, &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); + item_array.items[items_idx].toString = parser_transferToDisplayString; + } -parser_error_t parser_getJsonValueAsString(const char *key_name, char *outVal, uint16_t *outValLen) { + strcpy(item_array.items[items_idx].key, "On Chain"); + parser_getJsonValueBuffer(parser_tx_obj.tx_json.json, "chainId", &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); + item_array.items[items_idx].toString = parser_stdToDisplayString; + items_idx++; + + strcpy(item_array.items[items_idx].key, "Using Gas"); + parser_getJsonValueBuffer(parser_tx_obj.tx_json.json, "gasLimit", &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); + item_array.items[items_idx].toString = parser_gasToDisplayString; + items_idx++; + + strcpy(item_array.items[items_idx].key, "Transaction Hash"); + if (blake2b_hash((uint8_t *)ctx->buffer, ctx->bufferLen, hash) != zxerr_ok) { + return parser_unexpected_error; + } + + base64_encode(base64_hash, 44, hash, sizeof(hash)); + + // Make it base64 URL safe + for (int i = 0; base64_hash[i] != '\0'; i++) { + if (base64_hash[i] == '+') { + base64_hash[i] = '-'; + } else if (base64_hash[i] == '/') { + base64_hash[i] = '_'; + } + } + + item_array.items[items_idx].buf = base64_hash; + item_array.items[items_idx].buf[sizeof(base64_hash) - 1] = '\0'; + item_array.items[items_idx].len = sizeof(base64_hash); + item_array.items[items_idx].toString = parser_stdToDisplayString; + items_idx++; + + strcpy(item_array.items[items_idx].key, "Sign for Address"); + /* + Currently launching cpp tests, so this is not available + uint8_t address[32]; + uint16_t address_size; + CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); + snprintf(outVal, address_size + 1, "%s", address); + */ + item_array.items[items_idx].buf = "?"; + item_array.items[items_idx].len = 1; + item_array.items[items_idx].toString = parser_stdToDisplayString; + + item_array.numOfItems = items_idx + 1; + + return parser_ok; +} + +parser_error_t parser_getTotalItems(uint8_t *num_items) { + *num_items = item_array.numOfItems; + return parser_ok; +} + +parser_error_t parser_getJsonValueBuffer(parsed_json_t json_obj, const char *key_name, char **outVal, uint16_t *outValLen) { uint16_t token_index = 0; // Search token_index to access the parsed JSON object - object_get_value(&parser_tx_obj.tx_json.json, 0, key_name, &token_index); + object_get_value(&json_obj, 0, key_name, &token_index); + + *outValLen = (json_obj.tokens[token_index].end - json_obj.tokens[token_index].start); + *outVal = json_obj.buffer + json_obj.tokens[token_index].start; + + return parser_ok; +} + +parser_error_t parser_initClistObject() { + uint16_t token_index = 0; + + CHECK_ERROR(object_get_value(&parser_tx_obj.tx_json.json, 0, "clist", &token_index)); + + CHECK_ERROR(json_parse(&json_clist, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start)); + + return parser_ok; +} + +parser_error_t parser_getNthClistObject(parsed_json_t *json_obj, uint8_t clist_array_idx) { + uint16_t token_index = 0; + + CHECK_ERROR(array_get_nth_element(&json_clist, 0, clist_array_idx, &token_index)); - *outValLen = (parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); - strncpy(outVal, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, *outValLen); + // Parse corresponding object in clist + CHECK_ERROR(json_parse(json_obj, json_clist.buffer + json_clist.tokens[token_index].start, json_clist.tokens[token_index].end - json_clist.tokens[token_index].start)); return parser_ok; } -parser_error_t parser_getTransactionParams(uint8_t tx_index, char *amount, uint16_t *amount_size, char *from, uint16_t *from_size, char *to, uint16_t *to_size) { - parsed_json_t json_clist; - parsed_json_t json_tx; - parsed_json_t json_args; +parser_error_t parser_isTransfer(parsed_json_t *json_obj) { + uint16_t name_token_idx = 0; + parser_error_t ret = parser_json_not_a_transfer; + + object_get_value(json_obj, 0, "name", &name_token_idx); + + if (((uint16_t) strlen("coin.TRANSFER")) == (json_obj->tokens[name_token_idx].end - json_obj->tokens[name_token_idx].start)) { + if (MEMCMP("coin.TRANSFER", + json_obj->buffer + json_obj->tokens[name_token_idx].start, + json_obj->tokens[name_token_idx].end - json_obj->tokens[name_token_idx].start) == 0) { + ret = parser_ok; + } + } + + return ret; +} + +uint16_t parser_getNumberOfPossibleTransfers() { + uint16_t number_of_transfers = 0; + CHECK_ERROR(array_get_element_count(&json_clist, 0, &number_of_transfers)); + return number_of_transfers; +} + +uint16_t parser_getNumberOfTransfers() { + uint16_t number_of_transfers = 0; + parsed_json_t json_obj; + + for (uint16_t i = 0; i < parser_getNumberOfPossibleTransfers(); i++) { + parser_getNthClistObject(&json_obj, i); + if (parser_isTransfer(&json_obj) == parser_ok) { + number_of_transfers++; + } + } + return number_of_transfers; +} + +item_array_t *parser_getItemArray() { + return &item_array; +} + +static parser_error_t parser_getGasArgsFromClist(parsed_json_t *json_gas_args) { + uint16_t name_token_idx = 0; + parsed_json_t json_gas; + parsed_json_t json_obj; + uint16_t args_token_idx = 0; + + for (uint16_t i = 0; i < parser_getNumberOfPossibleTransfers(); i++) { + parser_getNthClistObject(&json_obj, i); + + object_get_value(&json_obj, 0, "name", &name_token_idx); + + json_parse(&json_gas, json_obj.buffer, json_obj.tokens[name_token_idx].end - json_obj.tokens[name_token_idx].start); + + if (((uint16_t) strlen("coin.GAS")) == (json_obj.tokens[name_token_idx].end - json_obj.tokens[name_token_idx].start)) { + if (MEMCMP("coin.GAS", + json_obj.buffer + json_obj.tokens[name_token_idx].start, + json_obj.tokens[name_token_idx].end - json_obj.tokens[name_token_idx].start) == 0) { + + object_get_value(&json_obj, 0, "args", &args_token_idx); + json_parse(json_gas_args, json_obj.buffer + json_obj.tokens[args_token_idx].start, json_obj.tokens[args_token_idx].end - json_obj.tokens[args_token_idx].start); + + return parser_ok; + } + } + } + + return parser_json_unexpected_error; +} + +static parser_error_t parser_getTransferValue(uint16_t* clist_array_idx, char **value, uint16_t *value_len) { + parsed_json_t json_obj; uint16_t token_index = 0; - object_get_value(&parser_tx_obj.tx_json.json, 0, "clist", &token_index); + if (*clist_array_idx > parser_getNumberOfPossibleTransfers()) { + return parser_value_out_of_range; + } + + CHECK_ERROR(parser_getNthClistObject(&json_obj, *clist_array_idx)); - json_parse(&json_clist, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); + while (parser_isTransfer(&json_obj) == parser_json_not_a_transfer) { + (*clist_array_idx)++; + CHECK_ERROR(parser_getNthClistObject(&json_obj, *clist_array_idx)); + } + + (*clist_array_idx)++; + + object_get_value(&json_obj, 0, "args", &token_index); + *value = json_obj.buffer + json_obj.tokens[token_index].start; + *value_len = json_obj.tokens[token_index].end - json_obj.tokens[token_index].start; + + return parser_ok; +} + +static parser_error_t parser_stdToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen) { + snprintf(outVal, inBufLen + 1, "%s", inBuf); + return parser_ok; +} + +static parser_error_t parser_transferToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen) { + char from[65]; + char to[65]; + char amount[10]; + uint8_t from_len = 0; + uint8_t to_len = 0; + uint8_t amount_len = 0; + uint16_t buf_index = 0; + uint16_t i = 0; + + // Reach first address in buffer + while (inBuf[++buf_index] != '"') { + ; + } + + // From + while (inBuf[++buf_index] != '"') { + from[i++] = inBuf[buf_index]; + } + from_len = i; + from[from_len] = '\0'; - array_get_nth_element(&json_clist, 0, 0, &token_index); + // Reach second address in buffer + while (inBuf[++buf_index] != '"') { + ; + } - json_parse(&json_tx, json_clist.buffer + json_clist.tokens[token_index].start, json_clist.tokens[token_index].end - json_clist.tokens[token_index].start); + i = 0; - object_get_value(&json_tx, 0, "args", &token_index); + // To + while (inBuf[++buf_index] != '"') { + to[i++] = inBuf[buf_index]; + } + to_len = i; + to[to_len] = '\0'; + + // Skip "," + buf_index++; + + i = 0; + + while (inBuf[++buf_index] != ']') { + amount[i++] = inBuf[buf_index]; + } + amount_len = i; + amount[amount_len] = '\0'; + + *outValLen = amount_len + from_len + to_len + 15; + snprintf(outVal, *outValLen, "%s from \"%s\" to \"%s\"", amount, from, to); + + return parser_ok; +} + +static parser_error_t parser_gasToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen) { + char gasLimit[10]; + char gasPrice[10]; + uint8_t gasLimit_len = 0; + uint8_t gasPrice_len = 0; + uint16_t buf_index = 0; + uint16_t i = 0; + + // From + while (inBuf[buf_index] != ',') { + gasLimit[i++] = inBuf[buf_index]; + buf_index++; + } + gasLimit_len = i; + gasLimit[gasLimit_len] = '\0'; + + while (inBuf[++buf_index] != ':') { + ; + } - json_parse(&json_args, json_tx.buffer + json_tx.tokens[token_index].start, json_tx.tokens[token_index].end - json_tx.tokens[token_index].start); + while (inBuf[++buf_index] != ':') { + ; + } + + i = 0; + + while (inBuf[++buf_index] != ',') { + gasPrice[i++] = inBuf[buf_index]; + } + gasPrice_len = i; + gasPrice[gasPrice_len] = '\0'; + + *outValLen = gasPrice_len + gasLimit_len + 19; + snprintf(outVal, *outValLen, "at most %s at price %s", gasLimit, gasPrice); + + return parser_ok; +} + +static parser_error_t parser_unknownCapabilityToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen) { + char name[20] = {0}; + char *arg; + uint16_t name_len = 0; + uint16_t buf_index = 1; + uint16_t arg_len = 0; + uint8_t arg_index = 1; + uint16_t out_index = 0; - array_get_nth_element(&json_args, 0, 0, &token_index); - strncpy(from, json_args.buffer + json_args.tokens[token_index].start, json_args.tokens[token_index].end - json_args.tokens[token_index].start); - *from_size = json_args.tokens[token_index].end - json_args.tokens[token_index].start; - from[*from_size] = '\0'; + while (!name_len) { + while (inBuf[++buf_index] != 'n') {} + if (MEMCMP("name", inBuf + buf_index, 4) == 0) { + while (inBuf[++buf_index] != ':') {} + // Skip "\"" + buf_index++; + while (inBuf[++buf_index] != '"') { + name[name_len++] = inBuf[buf_index]; + } + } + } - array_get_nth_element(&json_args, 0, 1, &token_index); - strncpy(to, json_args.buffer + json_args.tokens[token_index].start, json_args.tokens[token_index].end - json_args.tokens[token_index].start); - *to_size = json_args.tokens[token_index].end - json_args.tokens[token_index].start; - to[*to_size] = '\0'; + snprintf(outVal, strlen("name: ,") + name_len + 1, "name: %s,", name); + out_index += strlen("name: ,") + name_len; - array_get_nth_element(&json_args, 0, 2, &token_index); - strncpy(amount, json_args.buffer + json_args.tokens[token_index].start, json_args.tokens[token_index].end - json_args.tokens[token_index].start); - *amount_size = json_args.tokens[token_index].end - json_args.tokens[token_index].start; - amount[*amount_size] = '\0'; + buf_index = 1; + while (inBuf[buf_index - 1] != ']') { + arg = inBuf + buf_index; + arg_len = 0; + while (inBuf[buf_index] != ',' && inBuf[buf_index] != ']') { + buf_index++; + arg_len++; + } + buf_index++; + snprintf(outVal + out_index, strlen(" arg X: ,") + arg_len + 1, " arg %d: %s,", arg_index++, arg); + out_index += strlen(" arg X: ,") + arg_len; + } + + // Remove the last comma + outVal[out_index - 1] = '\0'; + + *outValLen = out_index; return parser_ok; } + const char *parser_getErrorDescription(parser_error_t err) { switch (err) { case parser_ok: diff --git a/app/src/parser_impl.h b/app/src/parser_impl.h index 62b7a40..3773852 100644 --- a/app/src/parser_impl.h +++ b/app/src/parser_impl.h @@ -33,10 +33,34 @@ typedef struct { parser_tx_t *tx_obj; } parser_context_t; +typedef struct { + char key[20]; + char *buf; + uint16_t len; + parser_error_t (*toString)(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); +} item_t; + +typedef struct { + item_t items[20]; + uint8_t numOfItems; +} item_array_t; + parser_error_t _read_json_tx(parser_context_t *c, parser_tx_t *v); -parser_error_t parser_getJsonValueAsString(const char *key_name, char *outVal, uint16_t *outValLen); -parser_error_t parser_getTransactionParams(uint8_t index, char *amount, uint16_t *amount_size, char *from, uint16_t *from_size, char *to, uint16_t *to_size); +parser_error_t parser_initItems(); +parser_error_t parser_storeItems(parser_context_t *ctx); +parser_error_t parser_getTotalItems(uint8_t *num_items); +parser_error_t parser_getJsonValueBuffer(parsed_json_t json_obj, const char *key_name, char **outVal, uint16_t *outValLen); +parser_error_t parser_initClistObject(); +parser_error_t parser_initTransfer(); +parser_error_t parser_getNthClistObject(parsed_json_t *json_obj, uint8_t clist_array_idx); +parser_error_t parser_isTransfer(parsed_json_t *json_obj); +parser_error_t parser_getTransferFrom(char **from, uint16_t *from_len); +parser_error_t parser_getTransferTo(char **to, uint16_t *to_len); +parser_error_t parser_getTransferAmount(char **amount, uint16_t *amount_len); +uint16_t parser_getNumberOfPossibleTransfers(); +uint16_t parser_getNumberOfTransfers(); +item_array_t *parser_getItemArray(); #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/tests/testcases.json b/tests/testcases.json index dfea211..758a443 100644 --- a/tests/testcases.json +++ b/tests/testcases.json @@ -1,7 +1,7 @@ [ { "index": 0, - "name": "Asset_Freeze", + "name": "Simple_Transaction", "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", "output": [ "0 | Signing : Transaction", @@ -27,5 +27,69 @@ "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] + }, + { + "index": 1, + "name": "coin_GAS_with_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B312C747275652C6E756C6C5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Unknown Capability 1 : name: coin.GAS, arg 1: 1, arg 2: true, arg 3: null", + "5 | Transfer 1 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Unknown Capability 1 : name: coin.GAS, arg 1: 1, arg 2: true, arg 3: null", + "5 | Transfer 1 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 2, + "name": "Multiple_transfers", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646661222C315D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646662222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646663222C335D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 : 1 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfa\"", + "6 | Transfer 2 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfb\"", + "7 | Transfer 3 : 3 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfc\"", + "8 | Transfer 4 : 4 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "9 | On Chain : 0", + "10 | Using Gas : at most 600 at price 1.0e-6", + "11 | Transaction hash : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOREfZhk", + "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 : 1 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfa\"", + "6 | Transfer 2 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfb\"", + "7 | Transfer 3 : 3 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfc\"", + "8 | Transfer 4 : 4 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "9 | On Chain : 0", + "10 | Using Gas : at most 600 at price 1.0e-6", + "11 | Transaction hash : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOREfZhk", + "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] } ] \ No newline at end of file From 7d81624d0a412e344b5fb1d566dc9ce67cc4ca72 Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Mon, 12 Aug 2024 20:44:10 +0200 Subject: [PATCH 03/34] Create items files --- CMakeLists.txt | 1 + app/src/items.c | 339 ++++++++++++++++++++++++++++++++++++ app/src/items.h | 37 ++++ app/src/parser.c | 15 +- app/src/parser_impl.c | 389 +++++------------------------------------- app/src/parser_impl.h | 33 ++-- tests/testcases.json | 161 ++++++++++++----- 7 files changed, 559 insertions(+), 416 deletions(-) create mode 100644 app/src/items.c create mode 100644 app/src/items.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e719faf..a337b1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,6 +144,7 @@ file(GLOB_RECURSE LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/zxformat.c #### ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/items.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/crypto_helper.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/json/json_parser.c diff --git a/app/src/items.c b/app/src/items.c new file mode 100644 index 0000000..c62afc8 --- /dev/null +++ b/app/src/items.c @@ -0,0 +1,339 @@ + +/******************************************************************************* + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#include "crypto_helper.h" +#include "items.h" +#include "parser_impl.h" +#include + +static parser_error_t items_stdToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); +static parser_error_t items_signingToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); +static parser_error_t items_requiringToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); +static parser_error_t items_transferToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); +static parser_error_t items_gasToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); +static parser_error_t items_unknownCapabilityToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); +static void items_storeGasItem(parsed_json_t *json_gas_obj, uint8_t items_idx, uint8_t *unknown_capabitilies); +static void items_storeTransferItem(parsed_json_t *json_possible_transfer, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); + +#define CURR_ITEM_JSON item_array.items[items_idx].json + +item_array_t item_array; + +parsed_json_t signing_json; +parsed_json_t requiring_json; + +uint8_t hash[BLAKE2B_HASH_SIZE] = {0}; +uint8_t base64_hash[44]; + +void items_initItems() { + MEMZERO(&item_array, sizeof(item_array_t)); + MEMZERO(&signing_json, sizeof(parsed_json_t)); + MEMZERO(&requiring_json, sizeof(parsed_json_t)); +} + +item_array_t *items_getItemArray() { + return &item_array; +} + +void items_storeItems() { + parsed_json_t json_clist; + parsed_json_t json_possible_transfer; + parsed_json_t parsed_json_all = parser_getParserTxObj()->tx_json.json; + uint8_t items_idx = 0; + uint8_t unknown_capabitilies = 1; + uint8_t num_of_transfers = 1; + uint16_t token_index = 0; + + strcpy(item_array.items[items_idx].key, "Signing"); + item_array.items[items_idx].toString = items_signingToDisplayString; + items_idx++; + + // Skip item if network id is not available + if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_NETWORK_ID) == parser_ok) { + strcpy(item_array.items[items_idx].key, "On Network"); + item_array.items[items_idx].toString = items_stdToDisplayString; + items_idx++; + } + + strcpy(item_array.items[items_idx].key, "Requiring"); + item_array.items[items_idx].toString = items_requiringToDisplayString; + items_idx++; + + if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_META) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_SENDER) == parser_ok) { + strcpy(item_array.items[items_idx].key, "Of Key"); + item_array.items[items_idx].toString = items_stdToDisplayString; + items_idx++; + } + } + + if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_SIGNERS) == parser_ok) { + if (parser_getJsonValue(&json_clist, JSON_CLIST) == parser_ok) { + parser_getGasObject(&json_clist); + items_storeGasItem(&json_clist, items_idx, &unknown_capabitilies); + items_idx++; + } + } + + if (parser_getJsonValue(&json_clist, JSON_SIGNERS) == parser_ok) { + if (parser_getJsonValue(&json_clist, JSON_CLIST) == parser_ok) { + for (uint8_t i = 0; i < parser_getNumberOfClistElements(); i++) { + if (array_get_nth_element(&json_clist, 0, i, &token_index) == parser_ok) { + json_parse(&json_possible_transfer, json_clist.buffer + json_clist.tokens[token_index].start, + json_clist.tokens[token_index].end - json_clist.tokens[token_index].start); + + if (object_get_value(&json_possible_transfer, 0, "name", &token_index) == parser_ok) { + if (MEMCMP("coin.TRANSFER", json_possible_transfer.buffer + json_possible_transfer.tokens[token_index].start, + json_possible_transfer.tokens[token_index].end - json_possible_transfer.tokens[token_index].start) == 0) { + items_storeTransferItem(&json_possible_transfer, items_idx, &num_of_transfers, &unknown_capabitilies); + items_idx++; + } + } + } + } + } + } + + if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_META) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_CHAIN_ID) == parser_ok) { + strcpy(item_array.items[items_idx].key, "On Chain"); + item_array.items[items_idx].toString = items_stdToDisplayString; + items_idx++; + } + } + + if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_META) == parser_ok) { + strcpy(item_array.items[items_idx].key, "Using Gas"); + item_array.items[items_idx].toString = items_gasToDisplayString; + items_idx++; + } + + strcpy(item_array.items[items_idx].key, "Transaction hash"); + if (blake2b_hash((uint8_t *)parser_getParserTxObj()->tx_json.json.buffer, parser_getParserTxObj()->tx_json.json.bufferLen, hash) != zxerr_ok) { + return ; + } + + base64_encode(base64_hash, 44, hash, sizeof(hash)); + + // Make it base64 URL safe + for (int i = 0; base64_hash[i] != '\0'; i++) { + if (base64_hash[i] == '+') { + base64_hash[i] = '-'; + } else if (base64_hash[i] == '/') { + base64_hash[i] = '_'; + } + } + + CURR_ITEM_JSON.buffer = base64_hash; + CURR_ITEM_JSON.bufferLen = sizeof(base64_hash) - 1; + item_array.items[items_idx].toString = items_stdToDisplayString; + items_idx++; + + strcpy(item_array.items[items_idx].key, "Sign for Address"); + /* + Currently launching cpp tests, so this is not available + uint8_t address[32]; + uint16_t address_size; + CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); + snprintf(outVal, address_size + 1, "%s", address); + */ + item_array.items[items_idx].toString = items_stdToDisplayString; + items_idx++; + + item_array.numOfItems = items_idx; +} + +uint16_t items_getTotalItems() { + return item_array.numOfItems; +} + +static void items_storeGasItem(parsed_json_t *json_gas_obj, uint8_t items_idx, uint8_t *unknown_capabitilies) { + uint16_t token_index = 0; + uint16_t args_count = 0; + parsed_json_t args_json; + + CURR_ITEM_JSON = *json_gas_obj; + object_get_value(json_gas_obj, 0, "args", &token_index); + json_parse(&args_json, json_gas_obj->buffer + json_gas_obj->tokens[token_index].start, + json_gas_obj->tokens[token_index].end - json_gas_obj->tokens[token_index].start); + array_get_element_count(&args_json, 0, &args_count); + + if (args_count > 0) { + snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); + (*unknown_capabitilies)++; + item_array.items[items_idx].toString = items_unknownCapabilityToDisplayString; + } else { + strcpy(item_array.items[items_idx].key, "Paying Gas"); + item_array.items[items_idx].json.bufferLen = 0; + item_array.items[items_idx].toString = items_stdToDisplayString; + } +} + +static void items_storeTransferItem(parsed_json_t *json_possible_transfer, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies) { + uint16_t token_index = 0; + uint16_t num_of_args = 0; + parsed_json_t args_json; + + CURR_ITEM_JSON = *json_possible_transfer; + + object_get_value(json_possible_transfer, 0, "args", &token_index); + json_parse(&args_json, json_possible_transfer->buffer + json_possible_transfer->tokens[token_index].start, + json_possible_transfer->tokens[token_index].end - json_possible_transfer->tokens[token_index].start); + + array_get_element_count(&args_json, 0, &num_of_args); + + if (num_of_args == 3) { + snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Transfer %d", *num_of_transfers); + (*num_of_transfers)++; + item_array.items[items_idx].toString = items_transferToDisplayString; + } else { + snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); + (*unknown_capabitilies)++; + item_array.items[items_idx].toString = items_unknownCapabilityToDisplayString; + } +} + +static parser_error_t items_stdToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { + *outValLen = json_obj.bufferLen + 1; + snprintf(outVal, *outValLen, "%s", json_obj.buffer); + return parser_ok; +} + +static parser_error_t items_signingToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof("Transaction"); + snprintf(outVal, *outValLen, "Transaction"); + return parser_ok; +} + +static parser_error_t items_requiringToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof("Capabilities"); + snprintf(outVal, *outValLen, "Capabilities"); + return parser_ok; +} + +static parser_error_t items_transferToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { + char amount[50]; + uint8_t amount_len = 0; + char to[65]; + uint8_t to_len = 0; + char from[65]; + uint8_t from_len = 0; + uint16_t token_index = 0; + parsed_json_t args_json; + + object_get_value(&json_obj, 0, "args", &token_index); + json_parse(&args_json, json_obj.buffer + json_obj.tokens[token_index].start, + json_obj.tokens[token_index].end - json_obj.tokens[token_index].start); + array_get_nth_element(&args_json, 0, 0, &token_index); + strncpy(from, args_json.buffer + args_json.tokens[token_index].start, args_json.tokens[token_index].end - args_json.tokens[token_index].start); + from_len = args_json.tokens[token_index].end - args_json.tokens[token_index].start; + from[from_len] = '\0'; + + array_get_nth_element(&args_json, 0, 1, &token_index); + strncpy(to, args_json.buffer + args_json.tokens[token_index].start, args_json.tokens[token_index].end - args_json.tokens[token_index].start); + to_len = args_json.tokens[token_index].end - args_json.tokens[token_index].start; + to[to_len] = '\0'; + + array_get_nth_element(&args_json, 0, 2, &token_index); + strncpy(amount, args_json.buffer + args_json.tokens[token_index].start, args_json.tokens[token_index].end - args_json.tokens[token_index].start); + amount_len = args_json.tokens[token_index].end - args_json.tokens[token_index].start; + amount[amount_len] = '\0'; + + *outValLen = amount_len + from_len + to_len + sizeof(" from ") + sizeof(" to ") + 4 * sizeof("\""); + snprintf(outVal, *outValLen, "%s from \"%s\" to \"%s\"", amount, from, to); + + return parser_ok; +} + +static parser_error_t items_gasToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { + char gasLimit[10]; + uint8_t gasLimit_len = 0; + char gasPrice[64]; + uint8_t gasPrice_len = 0; + uint16_t token_index = 0; + parsed_json_t gas_json_obj; + + parser_getJsonValue(&gas_json_obj, JSON_GAS_LIMIT); + gasLimit_len = gas_json_obj.bufferLen + 1; + snprintf(gasLimit, gasLimit_len, "%s", gas_json_obj.buffer); + + parser_getJsonValue(&gas_json_obj, JSON_GAS_PRICE); + gasPrice_len = gas_json_obj.bufferLen + 1; + snprintf(gasPrice, gasPrice_len, "%s", gas_json_obj.buffer); + + *outValLen = gasLimit_len + gasPrice_len + sizeof("at most ") + sizeof(" at price "); + snprintf(outVal, *outValLen, "at most %s at price %s", gasLimit, gasPrice); + + return parser_ok; +} + +static parser_error_t items_unknownCapabilityToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { + uint16_t token_index = 0; + uint16_t args_count = 0; + uint8_t len = 0; + uint8_t outVal_idx= 0; + parsed_json_t args_json; + parsed_json_t nth_arg_json; + + object_get_value(&json_obj, 0, "name", &token_index); + len = json_obj.tokens[token_index].end - json_obj.tokens[token_index].start + sizeof("name: "); + snprintf(outVal, len, "name: %s", json_obj.buffer + json_obj.tokens[token_index].start); + outVal_idx += len; + + // Remove null terminator + outVal[outVal_idx - 1] = ','; + + // Add space + outVal[outVal_idx] = ' '; + outVal_idx++; + + object_get_value(&json_obj, 0, "args", &token_index); + json_parse(&args_json, json_obj.buffer + json_obj.tokens[token_index].start, + json_obj.tokens[token_index].end - json_obj.tokens[token_index].start); + array_get_element_count(&args_json, 0, &args_count); + + for (uint8_t i = 0; i < args_count - 1; i++) { + array_get_nth_element(&args_json, 0, i, &token_index); + if (args_json.tokens[token_index].type == JSMN_STRING) { + // Strings go in between double quotes + len = args_json.tokens[token_index].end - args_json.tokens[token_index].start + sizeof("arg X: \"\","); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\",", i + 1, args_json.buffer + args_json.tokens[token_index].start); + } else { + len = args_json.tokens[token_index].end - args_json.tokens[token_index].start + sizeof("arg X: ,"); + snprintf(outVal + outVal_idx, len, "arg %d: %s,", i + 1, args_json.buffer + args_json.tokens[token_index].start); + } + outVal_idx += len; + + // Remove null terminator + outVal[outVal_idx - 1] = ' '; + } + + // Last arg (without comma) + array_get_nth_element(&args_json, 0, args_count - 1, &token_index); + if (args_json.tokens[token_index].type == JSMN_STRING) { + len = args_json.tokens[token_index].end - args_json.tokens[token_index].start + sizeof("arg X: \"\""); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\"", args_count, args_json.buffer + args_json.tokens[token_index].start); + } else { + len = args_json.tokens[token_index].end - args_json.tokens[token_index].start + sizeof("arg X: "); + snprintf(outVal + outVal_idx, len, "arg %d: %s", args_count, args_json.buffer + args_json.tokens[token_index].start); + } + + outVal_idx += len; + + *outValLen = outVal_idx; + + return parser_ok; +} \ No newline at end of file diff --git a/app/src/items.h b/app/src/items.h new file mode 100644 index 0000000..c3be9ef --- /dev/null +++ b/app/src/items.h @@ -0,0 +1,37 @@ +/******************************************************************************* + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#pragma once + +#include +#include "zxtypes.h" +#include "parser_common.h" +#include "json_parser.h" + +typedef struct { + char key[25]; + parsed_json_t json; + parser_error_t (*toString)(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); +} item_t; + +typedef struct { + item_t items[20]; + uint8_t numOfItems; +} item_array_t; + +void items_initItems(); +void items_storeItems(); +uint16_t items_getTotalItems(); +item_array_t *items_getItemArray(); \ No newline at end of file diff --git a/app/src/parser.c b/app/src/parser.c index 6f70f42..65b5012 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -14,17 +14,17 @@ * limitations under the License. ********************************************************************************/ -#include "parser.h" - #include #include #include #include +#include "items.h" #include "coin.h" #include "crypto.h" #include "crypto_helper.h" #include "parser_impl.h" +#include "parser.h" parser_error_t parser_init_context(parser_context_t *ctx, const uint8_t *buffer, uint16_t bufferSize) { ctx->offset = 0; @@ -47,8 +47,8 @@ parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t d CHECK_ERROR(_read_json_tx(ctx, tx_obj)); - CHECK_ERROR(parser_initItems()); - CHECK_ERROR(parser_storeItems(ctx)); + items_initItems(); + items_storeItems(ctx); return parser_ok; } @@ -76,8 +76,7 @@ parser_error_t parser_getNumItems(const parser_context_t *ctx, uint8_t *num_item return parser_tx_obj_empty; } - *num_items = 0; - parser_getTotalItems(num_items); + *num_items = items_getTotalItems(); return parser_ok; } @@ -100,7 +99,7 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) { *pageCount = 1; uint8_t numItems = 0; - item_array_t *item_array = parser_getItemArray(); + item_array_t *item_array = items_getItemArray(); CHECK_ERROR(parser_getNumItems(ctx, &numItems)) CHECK_APP_CANARY() @@ -108,7 +107,7 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c cleanOutput(outKey, outKeyLen, outVal, outValLen); snprintf(outKey, outKeyLen, item_array->items[displayIdx].key); - item_array->items[displayIdx].toString(item_array->items[displayIdx].buf, item_array->items[displayIdx].len, outVal, &outValLen); + item_array->items[displayIdx].toString(item_array->items[displayIdx].json, outVal, &outValLen); return parser_ok; } diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 3b40caa..135c4f0 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -18,22 +18,8 @@ #include "crypto_helper.h" #include -static parser_error_t parser_getTransferValue(uint16_t* clist_array_idx, char **value, uint16_t *value_len); -static parser_error_t parser_getGasArgsFromClist(parsed_json_t *json_gas_args); -static parser_error_t parser_stdToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); -static parser_error_t parser_transferToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); -static parser_error_t parser_gasToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); -static parser_error_t parser_unknownCapabilityToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); parser_tx_t parser_tx_obj; -parsed_json_t json_clist; -item_array_t item_array; - -char signing_buf[] = "Transaction"; -char capabilities_buf[] = "Capabilities"; - -uint8_t hash[BLAKE2B_HASH_SIZE] = {0}; -uint8_t base64_hash[44]; parser_error_t _read_json_tx(parser_context_t *c, __Z_UNUSED parser_tx_t *v) { CHECK_ERROR(json_parse(&parser_tx_obj.tx_json.json, (const char *) c->buffer, @@ -44,151 +30,11 @@ parser_error_t _read_json_tx(parser_context_t *c, __Z_UNUSED parser_tx_t *v) { parser_tx_obj.tx_json.filter_msg_type_count = 0; parser_tx_obj.tx_json.filter_msg_from_count = 0; - parser_initClistObject(); - - return parser_ok; -} - -parser_error_t parser_initItems() { - MEMZERO(&item_array, sizeof(item_array_t)); - return parser_ok; -} - -parser_error_t parser_storeItems(parser_context_t *ctx) { - parsed_json_t json_gas_args; - uint8_t items_idx = 0; - uint8_t unknown_capabitilies = 1; - - strcpy(item_array.items[items_idx].key, "Signing"); - item_array.items[items_idx].buf = signing_buf; - item_array.items[items_idx].len = sizeof(signing_buf); - item_array.items[items_idx].toString = parser_stdToDisplayString; - items_idx++; - - strcpy(item_array.items[items_idx].key, "On Network"); - parser_getJsonValueBuffer(parser_tx_obj.tx_json.json, "networkId", &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); - item_array.items[items_idx].toString = parser_stdToDisplayString; - items_idx++; - - strcpy(item_array.items[items_idx].key, "Requiring"); - item_array.items[items_idx].buf = capabilities_buf; - item_array.items[items_idx].len = sizeof(capabilities_buf); - item_array.items[items_idx].toString = parser_stdToDisplayString; - items_idx++; - - strcpy(item_array.items[items_idx].key, "Of Key"); - parser_getJsonValueBuffer(parser_tx_obj.tx_json.json, "sender", &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); - item_array.items[items_idx].toString = parser_stdToDisplayString; - items_idx++; - - parser_getGasArgsFromClist(&json_gas_args); - uint16_t args_count = 0; - array_get_element_count(&json_gas_args, 0, &args_count); - if (args_count == 0) { - strcpy(item_array.items[items_idx].key, "Paying Gas"); - item_array.items[items_idx].buf = ""; - item_array.items[items_idx].len = 0; - item_array.items[items_idx].toString = parser_stdToDisplayString; - } else { - snprintf(item_array.items[items_idx].key, strlen("Unknown Capability X") + 1, "Unknown Capability %d", unknown_capabitilies++); - item_array.items[items_idx].buf = json_gas_args.buffer; - item_array.items[items_idx].len = json_gas_args.bufferLen; - item_array.items[items_idx].toString = parser_unknownCapabilityToDisplayString; - } - items_idx++; - - uint16_t obj_token_idx = 0; - for (uint8_t i = 0; i < parser_getNumberOfTransfers(); i++, items_idx++) { - snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Transfer %d", i + 1); - parser_getTransferValue(&obj_token_idx, &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); - item_array.items[items_idx].toString = parser_transferToDisplayString; - } - - strcpy(item_array.items[items_idx].key, "On Chain"); - parser_getJsonValueBuffer(parser_tx_obj.tx_json.json, "chainId", &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); - item_array.items[items_idx].toString = parser_stdToDisplayString; - items_idx++; - - strcpy(item_array.items[items_idx].key, "Using Gas"); - parser_getJsonValueBuffer(parser_tx_obj.tx_json.json, "gasLimit", &(item_array.items[items_idx].buf), &(item_array.items[items_idx].len)); - item_array.items[items_idx].toString = parser_gasToDisplayString; - items_idx++; - - strcpy(item_array.items[items_idx].key, "Transaction Hash"); - if (blake2b_hash((uint8_t *)ctx->buffer, ctx->bufferLen, hash) != zxerr_ok) { - return parser_unexpected_error; - } - - base64_encode(base64_hash, 44, hash, sizeof(hash)); - - // Make it base64 URL safe - for (int i = 0; base64_hash[i] != '\0'; i++) { - if (base64_hash[i] == '+') { - base64_hash[i] = '-'; - } else if (base64_hash[i] == '/') { - base64_hash[i] = '_'; - } - } - - item_array.items[items_idx].buf = base64_hash; - item_array.items[items_idx].buf[sizeof(base64_hash) - 1] = '\0'; - item_array.items[items_idx].len = sizeof(base64_hash); - item_array.items[items_idx].toString = parser_stdToDisplayString; - items_idx++; - - strcpy(item_array.items[items_idx].key, "Sign for Address"); - /* - Currently launching cpp tests, so this is not available - uint8_t address[32]; - uint16_t address_size; - CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); - snprintf(outVal, address_size + 1, "%s", address); - */ - item_array.items[items_idx].buf = "?"; - item_array.items[items_idx].len = 1; - item_array.items[items_idx].toString = parser_stdToDisplayString; - - item_array.numOfItems = items_idx + 1; - return parser_ok; } -parser_error_t parser_getTotalItems(uint8_t *num_items) { - *num_items = item_array.numOfItems; - return parser_ok; -} - -parser_error_t parser_getJsonValueBuffer(parsed_json_t json_obj, const char *key_name, char **outVal, uint16_t *outValLen) { - uint16_t token_index = 0; - - // Search token_index to access the parsed JSON object - object_get_value(&json_obj, 0, key_name, &token_index); - - *outValLen = (json_obj.tokens[token_index].end - json_obj.tokens[token_index].start); - *outVal = json_obj.buffer + json_obj.tokens[token_index].start; - - return parser_ok; -} - -parser_error_t parser_initClistObject() { - uint16_t token_index = 0; - - CHECK_ERROR(object_get_value(&parser_tx_obj.tx_json.json, 0, "clist", &token_index)); - - CHECK_ERROR(json_parse(&json_clist, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start)); - - return parser_ok; -} - -parser_error_t parser_getNthClistObject(parsed_json_t *json_obj, uint8_t clist_array_idx) { - uint16_t token_index = 0; - - CHECK_ERROR(array_get_nth_element(&json_clist, 0, clist_array_idx, &token_index)); - - // Parse corresponding object in clist - CHECK_ERROR(json_parse(json_obj, json_clist.buffer + json_clist.tokens[token_index].start, json_clist.tokens[token_index].end - json_clist.tokens[token_index].start)); - - return parser_ok; +parser_tx_t *parser_getParserTxObj() { + return &parser_tx_obj; } parser_error_t parser_isTransfer(parsed_json_t *json_obj) { @@ -208,224 +54,65 @@ parser_error_t parser_isTransfer(parsed_json_t *json_obj) { return ret; } -uint16_t parser_getNumberOfPossibleTransfers() { - uint16_t number_of_transfers = 0; - CHECK_ERROR(array_get_element_count(&json_clist, 0, &number_of_transfers)); - return number_of_transfers; -} - -uint16_t parser_getNumberOfTransfers() { - uint16_t number_of_transfers = 0; - parsed_json_t json_obj; - - for (uint16_t i = 0; i < parser_getNumberOfPossibleTransfers(); i++) { - parser_getNthClistObject(&json_obj, i); - if (parser_isTransfer(&json_obj) == parser_ok) { - number_of_transfers++; - } - } - return number_of_transfers; -} - -item_array_t *parser_getItemArray() { - return &item_array; -} - -static parser_error_t parser_getGasArgsFromClist(parsed_json_t *json_gas_args) { - uint16_t name_token_idx = 0; - parsed_json_t json_gas; +uint16_t parser_getNumberOfClistElements() { + uint16_t number_of_elements = 0; parsed_json_t json_obj; - uint16_t args_token_idx = 0; - - for (uint16_t i = 0; i < parser_getNumberOfPossibleTransfers(); i++) { - parser_getNthClistObject(&json_obj, i); - - object_get_value(&json_obj, 0, "name", &name_token_idx); - - json_parse(&json_gas, json_obj.buffer, json_obj.tokens[name_token_idx].end - json_obj.tokens[name_token_idx].start); - - if (((uint16_t) strlen("coin.GAS")) == (json_obj.tokens[name_token_idx].end - json_obj.tokens[name_token_idx].start)) { - if (MEMCMP("coin.GAS", - json_obj.buffer + json_obj.tokens[name_token_idx].start, - json_obj.tokens[name_token_idx].end - json_obj.tokens[name_token_idx].start) == 0) { - - object_get_value(&json_obj, 0, "args", &args_token_idx); - json_parse(json_gas_args, json_obj.buffer + json_obj.tokens[args_token_idx].start, json_obj.tokens[args_token_idx].end - json_obj.tokens[args_token_idx].start); - return parser_ok; - } - } - } - - return parser_json_unexpected_error; + parser_getJsonValue(&json_obj, JSON_META); + parser_getJsonValue(&json_obj, JSON_CLIST); + CHECK_ERROR(array_get_element_count(&json_obj, 0, &number_of_elements)); + return number_of_elements; } -static parser_error_t parser_getTransferValue(uint16_t* clist_array_idx, char **value, uint16_t *value_len) { - parsed_json_t json_obj; +// TODO: join all these functions into a parametrized one +parser_error_t parser_getJsonValue(parsed_json_t *json_obj, const char *key) { uint16_t token_index = 0; + object_get_value(&parser_tx_obj.tx_json.json, 0, key, &token_index); + json_parse(json_obj, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); - if (*clist_array_idx > parser_getNumberOfPossibleTransfers()) { - return parser_value_out_of_range; - } - - CHECK_ERROR(parser_getNthClistObject(&json_obj, *clist_array_idx)); - - while (parser_isTransfer(&json_obj) == parser_json_not_a_transfer) { - (*clist_array_idx)++; - CHECK_ERROR(parser_getNthClistObject(&json_obj, *clist_array_idx)); + if (MEMCMP("null", json_obj->buffer, json_obj->bufferLen) == 0) { + return parser_no_data; } - (*clist_array_idx)++; - - object_get_value(&json_obj, 0, "args", &token_index); - *value = json_obj.buffer + json_obj.tokens[token_index].start; - *value_len = json_obj.tokens[token_index].end - json_obj.tokens[token_index].start; - - return parser_ok; -} - -static parser_error_t parser_stdToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen) { - snprintf(outVal, inBufLen + 1, "%s", inBuf); return parser_ok; } -static parser_error_t parser_transferToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen) { - char from[65]; - char to[65]; - char amount[10]; - uint8_t from_len = 0; - uint8_t to_len = 0; - uint8_t amount_len = 0; - uint16_t buf_index = 0; - uint16_t i = 0; - - // Reach first address in buffer - while (inBuf[++buf_index] != '"') { - ; - } - - // From - while (inBuf[++buf_index] != '"') { - from[i++] = inBuf[buf_index]; - } - from_len = i; - from[from_len] = '\0'; - - // Reach second address in buffer - while (inBuf[++buf_index] != '"') { - ; - } - - i = 0; - - // To - while (inBuf[++buf_index] != '"') { - to[i++] = inBuf[buf_index]; - } - to_len = i; - to[to_len] = '\0'; - - // Skip "," - buf_index++; - - i = 0; - - while (inBuf[++buf_index] != ']') { - amount[i++] = inBuf[buf_index]; - } - amount_len = i; - amount[amount_len] = '\0'; - - *outValLen = amount_len + from_len + to_len + 15; - snprintf(outVal, *outValLen, "%s from \"%s\" to \"%s\"", amount, from, to); - - return parser_ok; -} - -static parser_error_t parser_gasToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen) { - char gasLimit[10]; - char gasPrice[10]; - uint8_t gasLimit_len = 0; - uint8_t gasPrice_len = 0; - uint16_t buf_index = 0; - uint16_t i = 0; - - // From - while (inBuf[buf_index] != ',') { - gasLimit[i++] = inBuf[buf_index]; - buf_index++; - } - gasLimit_len = i; - gasLimit[gasLimit_len] = '\0'; - - while (inBuf[++buf_index] != ':') { - ; - } - - while (inBuf[++buf_index] != ':') { - ; - } - - i = 0; - - while (inBuf[++buf_index] != ',') { - gasPrice[i++] = inBuf[buf_index]; - } - gasPrice_len = i; - gasPrice[gasPrice_len] = '\0'; - - *outValLen = gasPrice_len + gasLimit_len + 19; - snprintf(outVal, *outValLen, "at most %s at price %s", gasLimit, gasPrice); +parser_error_t parser_getNthClistElement(parsed_json_t *json_obj, uint8_t clist_array_idx) { + uint16_t token_index = 0; + array_get_nth_element(json_obj, 0, clist_array_idx, &token_index); + json_parse(json_obj, json_obj->buffer + json_obj->tokens[token_index].start, json_obj->tokens[token_index].end - json_obj->tokens[token_index].start); return parser_ok; } -static parser_error_t parser_unknownCapabilityToDisplayString(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen) { - char name[20] = {0}; - char *arg; - uint16_t name_len = 0; - uint16_t buf_index = 1; - uint16_t arg_len = 0; - uint8_t arg_index = 1; - uint16_t out_index = 0; - - while (!name_len) { - while (inBuf[++buf_index] != 'n') {} - if (MEMCMP("name", inBuf + buf_index, 4) == 0) { - while (inBuf[++buf_index] != ':') {} - // Skip "\"" - buf_index++; - while (inBuf[++buf_index] != '"') { - name[name_len++] = inBuf[buf_index]; - } +parser_error_t parser_getGasObject(parsed_json_t *json_obj) { + uint16_t token_index = 0; + parsed_json_t *json_clist = json_obj; + parsed_json_t temp_json_obj; + + for (uint16_t i = 0; i < parser_getNumberOfClistElements(); i++) { + array_get_nth_element(json_clist, 0, i, &token_index); + json_parse(&temp_json_obj, json_clist->buffer + json_clist->tokens[token_index].start, json_clist->tokens[token_index].end - json_clist->tokens[token_index].start); + + object_get_value(&temp_json_obj, 0, "name", &token_index); + if (MEMCMP("coin.GAS", temp_json_obj.buffer + temp_json_obj.tokens[token_index].start, + temp_json_obj.tokens[token_index].end - temp_json_obj.tokens[token_index].start) == 0) { + *json_obj = temp_json_obj; + return parser_ok; } } - snprintf(outVal, strlen("name: ,") + name_len + 1, "name: %s,", name); - out_index += strlen("name: ,") + name_len; - - buf_index = 1; - - while (inBuf[buf_index - 1] != ']') { - arg = inBuf + buf_index; - arg_len = 0; - while (inBuf[buf_index] != ',' && inBuf[buf_index] != ']') { - buf_index++; - arg_len++; - } - buf_index++; - snprintf(outVal + out_index, strlen(" arg X: ,") + arg_len + 1, " arg %d: %s,", arg_index++, arg); - out_index += strlen(" arg X: ,") + arg_len; - } + return parser_no_data; +} - // Remove the last comma - outVal[out_index - 1] = '\0'; +parser_error_t parser_getChainId(parsed_json_t *json_obj) { + uint16_t token_index = 0; + object_get_value(&parser_tx_obj.tx_json.json, 0, "chainId", &token_index); + json_parse(json_obj, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); - *outValLen = out_index; return parser_ok; } - const char *parser_getErrorDescription(parser_error_t err) { switch (err) { case parser_ok: diff --git a/app/src/parser_impl.h b/app/src/parser_impl.h index 3773852..39b8f44 100644 --- a/app/src/parser_impl.h +++ b/app/src/parser_impl.h @@ -25,6 +25,14 @@ extern "C" { #endif +#define JSON_NETWORK_ID "networkId" +#define JSON_META "meta" +#define JSON_SENDER "sender" +#define JSON_CHAIN_ID "chainId" +#define JSON_GAS_LIMIT "gasLimit" +#define JSON_GAS_PRICE "gasPrice" +#define JSON_SIGNERS "signers" +#define JSON_CLIST "clist" typedef struct { const uint8_t *buffer; @@ -33,33 +41,20 @@ typedef struct { parser_tx_t *tx_obj; } parser_context_t; -typedef struct { - char key[20]; - char *buf; - uint16_t len; - parser_error_t (*toString)(char *inBuf, uint16_t inBufLen, char *outVal, uint16_t *outValLen); -} item_t; - -typedef struct { - item_t items[20]; - uint8_t numOfItems; -} item_array_t; - parser_error_t _read_json_tx(parser_context_t *c, parser_tx_t *v); -parser_error_t parser_initItems(); -parser_error_t parser_storeItems(parser_context_t *ctx); -parser_error_t parser_getTotalItems(uint8_t *num_items); -parser_error_t parser_getJsonValueBuffer(parsed_json_t json_obj, const char *key_name, char **outVal, uint16_t *outValLen); +parser_tx_t *parser_getParserTxObj(); parser_error_t parser_initClistObject(); parser_error_t parser_initTransfer(); -parser_error_t parser_getNthClistObject(parsed_json_t *json_obj, uint8_t clist_array_idx); parser_error_t parser_isTransfer(parsed_json_t *json_obj); parser_error_t parser_getTransferFrom(char **from, uint16_t *from_len); parser_error_t parser_getTransferTo(char **to, uint16_t *to_len); parser_error_t parser_getTransferAmount(char **amount, uint16_t *amount_len); -uint16_t parser_getNumberOfPossibleTransfers(); +uint16_t parser_getNumberOfClistElements(); uint16_t parser_getNumberOfTransfers(); -item_array_t *parser_getItemArray(); +parser_error_t parser_getJsonValue(parsed_json_t *json_obj, const char *key); +parser_error_t parser_getNthClistElement(parsed_json_t *json_obj, uint8_t clist_array_idx); +parser_error_t parser_getGasObject(parsed_json_t *json_obj); +parser_error_t parser_getChainId(parsed_json_t *json_obj); #ifdef __cplusplus } diff --git a/tests/testcases.json b/tests/testcases.json index 758a443..e814171 100644 --- a/tests/testcases.json +++ b/tests/testcases.json @@ -1,64 +1,149 @@ [ { - "index": 0, - "name": "Simple_Transaction", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "index": 0, + "name": "Simple_transfer", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 1, + "name": "Gas_with_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B312C747275652C6E756C6C5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Unknown Capability 1 : name: coin.GAS, arg 1: 1, arg 2: true, arg 3: null", + "5 | Transfer 1 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Unknown Capability 1 : name: coin.GAS, arg 1: 1, arg 2: true, arg 3: null", + "5 | Transfer 1 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 2, + "name": "Network_null", + "blob": "7B226E6574776F726B4964223A6E756C6C2C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + "0 | Signing : Transaction", + "1 | Requiring : Capabilities", + "2 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "3 | Paying Gas : ", + "4 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", + "5 | On Chain : 0", + "6 | Using Gas : at most 600 at price 1.0e-5", + "7 | Transaction hash : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb-Cn8w", + "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + "0 | Signing : Transaction", + "1 | Requiring : Capabilities", + "2 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "3 | Paying Gas : ", + "4 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", + "5 | On Chain : 0", + "6 | Using Gas : at most 600 at price 1.0e-5", + "7 | Transaction hash : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb-Cn8w", + "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 3, + "name": "Transfer_with_decimal_amount", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C7B22646563696D616C223A223132333435363738392E30313233343536373839227D5D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 : {\"decimal\":\"123456789.0123456789\"} from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4bAvk4", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 : {\"decimal\":\"123456789.0123456789\"} from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4bAvk4", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { - "index": 1, - "name": "coin_GAS_with_args", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B312C747275652C6E756C6C5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "index": 4, + "name": "Transfer_with_2_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432225D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", "output": [ "0 | Signing : Transaction", "1 | On Network : mainnet01", "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Unknown Capability 1 : name: coin.GAS, arg 1: 1, arg 2: true, arg 3: null", - "5 | Transfer 1 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: coin.TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-6", - "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew7VnMY", "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", "1 | On Network : mainnet01", "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Unknown Capability 1 : name: coin.GAS, arg 1: 1, arg 2: true, arg 3: null", - "5 | Transfer 1 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: coin.TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-6", - "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew7VnMY", "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { - "index": 2, + "index": 5, "name": "Multiple_transfers", "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646661222C315D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646662222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646663222C335D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", "output": [ @@ -92,4 +177,4 @@ "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] } -] \ No newline at end of file +] From aaf4e42493eca295d7e526541f63def494a987a6 Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Mon, 12 Aug 2024 20:57:18 +0200 Subject: [PATCH 04/34] Clean compilation warnings --- app/src/items.c | 17 +++++++---------- app/src/parser.c | 2 +- tests/testcases.json | 12 ------------ 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/app/src/items.c b/app/src/items.c index c62afc8..fc329c3 100644 --- a/app/src/items.c +++ b/app/src/items.c @@ -36,7 +36,7 @@ parsed_json_t signing_json; parsed_json_t requiring_json; uint8_t hash[BLAKE2B_HASH_SIZE] = {0}; -uint8_t base64_hash[44]; +char base64_hash[44]; void items_initItems() { MEMZERO(&item_array, sizeof(item_array_t)); @@ -51,7 +51,6 @@ item_array_t *items_getItemArray() { void items_storeItems() { parsed_json_t json_clist; parsed_json_t json_possible_transfer; - parsed_json_t parsed_json_all = parser_getParserTxObj()->tx_json.json; uint8_t items_idx = 0; uint8_t unknown_capabitilies = 1; uint8_t num_of_transfers = 1; @@ -142,16 +141,16 @@ void items_storeItems() { item_array.items[items_idx].toString = items_stdToDisplayString; items_idx++; - strcpy(item_array.items[items_idx].key, "Sign for Address"); /* + strcpy(item_array.items[items_idx].key, "Sign for Address"); Currently launching cpp tests, so this is not available uint8_t address[32]; uint16_t address_size; CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); snprintf(outVal, address_size + 1, "%s", address); - */ item_array.items[items_idx].toString = items_stdToDisplayString; items_idx++; + */ item_array.numOfItems = items_idx; } @@ -206,19 +205,19 @@ static void items_storeTransferItem(parsed_json_t *json_possible_transfer, uint8 } } -static parser_error_t items_stdToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { +static parser_error_t items_stdToDisplayString(__Z_UNUSED parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { *outValLen = json_obj.bufferLen + 1; snprintf(outVal, *outValLen, "%s", json_obj.buffer); return parser_ok; } -static parser_error_t items_signingToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { +static parser_error_t items_signingToDisplayString(__Z_UNUSED parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("Transaction"); snprintf(outVal, *outValLen, "Transaction"); return parser_ok; } -static parser_error_t items_requiringToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { +static parser_error_t items_requiringToDisplayString(__Z_UNUSED parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("Capabilities"); snprintf(outVal, *outValLen, "Capabilities"); return parser_ok; @@ -258,12 +257,11 @@ static parser_error_t items_transferToDisplayString(parsed_json_t json_obj, char return parser_ok; } -static parser_error_t items_gasToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { +static parser_error_t items_gasToDisplayString(__Z_UNUSED parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { char gasLimit[10]; uint8_t gasLimit_len = 0; char gasPrice[64]; uint8_t gasPrice_len = 0; - uint16_t token_index = 0; parsed_json_t gas_json_obj; parser_getJsonValue(&gas_json_obj, JSON_GAS_LIMIT); @@ -286,7 +284,6 @@ static parser_error_t items_unknownCapabilityToDisplayString(parsed_json_t json_ uint8_t len = 0; uint8_t outVal_idx= 0; parsed_json_t args_json; - parsed_json_t nth_arg_json; object_get_value(&json_obj, 0, "name", &token_index); len = json_obj.tokens[token_index].end - json_obj.tokens[token_index].start + sizeof("name: "); diff --git a/app/src/parser.c b/app/src/parser.c index 65b5012..bdd9ef4 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -106,7 +106,7 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c CHECK_ERROR(checkSanity(numItems, displayIdx)) cleanOutput(outKey, outKeyLen, outVal, outValLen); - snprintf(outKey, outKeyLen, item_array->items[displayIdx].key); + snprintf(outKey, outKeyLen, "%s", item_array->items[displayIdx].key); item_array->items[displayIdx].toString(item_array->items[displayIdx].json, outVal, &outValLen); return parser_ok; diff --git a/tests/testcases.json b/tests/testcases.json index e814171..32efe02 100644 --- a/tests/testcases.json +++ b/tests/testcases.json @@ -13,7 +13,6 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-5", "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -25,7 +24,6 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-5", "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -42,7 +40,6 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-6", "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -54,7 +51,6 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-6", "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -70,7 +66,6 @@ "5 | On Chain : 0", "6 | Using Gas : at most 600 at price 1.0e-5", "7 | Transaction hash : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb-Cn8w", - "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -81,7 +76,6 @@ "5 | On Chain : 0", "6 | Using Gas : at most 600 at price 1.0e-5", "7 | Transaction hash : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb-Cn8w", - "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -98,7 +92,6 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-6", "8 | Transaction hash : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4bAvk4", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -110,7 +103,6 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-6", "8 | Transaction hash : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4bAvk4", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -127,7 +119,6 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-5", "8 | Transaction hash : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew7VnMY", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -139,7 +130,6 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-5", "8 | Transaction hash : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew7VnMY", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -159,7 +149,6 @@ "9 | On Chain : 0", "10 | Using Gas : at most 600 at price 1.0e-6", "11 | Transaction hash : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOREfZhk", - "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -174,7 +163,6 @@ "9 | On Chain : 0", "10 | Using Gas : at most 600 at price 1.0e-6", "11 | Transaction hash : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOREfZhk", - "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] } ] From e033635c6eff7bc05f0535e039c44fe9cb761312 Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Tue, 13 Aug 2024 10:06:59 +0200 Subject: [PATCH 05/34] Stop storing duplicate data for items --- app/src/items.c | 216 +++++++++++++++++++------------------ app/src/items.h | 4 +- app/src/json/json_parser.c | 36 ------- app/src/parser.c | 2 +- app/src/parser_impl.c | 43 ++++---- app/src/parser_impl.h | 4 +- tests/testcases.json | 13 +++ 7 files changed, 155 insertions(+), 163 deletions(-) diff --git a/app/src/items.c b/app/src/items.c index fc329c3..e7ccf59 100644 --- a/app/src/items.c +++ b/app/src/items.c @@ -19,16 +19,18 @@ #include "parser_impl.h" #include -static parser_error_t items_stdToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); -static parser_error_t items_signingToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); -static parser_error_t items_requiringToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); -static parser_error_t items_transferToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); -static parser_error_t items_gasToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); -static parser_error_t items_unknownCapabilityToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); -static void items_storeGasItem(parsed_json_t *json_gas_obj, uint8_t items_idx, uint8_t *unknown_capabitilies); -static void items_storeTransferItem(parsed_json_t *json_possible_transfer, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); - -#define CURR_ITEM_JSON item_array.items[items_idx].json +static parser_error_t items_stdToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); +static parser_error_t items_nothingToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen); +static parser_error_t items_signingToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); +static parser_error_t items_requiringToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); +static parser_error_t items_transferToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); +static parser_error_t items_gasToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); +static parser_error_t items_hashToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); +static parser_error_t items_unknownCapabilityToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); +static void items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); +static void items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); + +#define CURR_ITEM_TOKEN item_array.items[items_idx].json_token_index item_array_t item_array; @@ -49,8 +51,7 @@ item_array_t *items_getItemArray() { } void items_storeItems() { - parsed_json_t json_clist; - parsed_json_t json_possible_transfer; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; uint8_t items_idx = 0; uint8_t unknown_capabitilies = 1; uint8_t num_of_transfers = 1; @@ -61,7 +62,7 @@ void items_storeItems() { items_idx++; // Skip item if network id is not available - if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_NETWORK_ID) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_NETWORK_ID) == parser_ok) { strcpy(item_array.items[items_idx].key, "On Network"); item_array.items[items_idx].toString = items_stdToDisplayString; items_idx++; @@ -71,33 +72,36 @@ void items_storeItems() { item_array.items[items_idx].toString = items_requiringToDisplayString; items_idx++; - if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_META) == parser_ok) { - if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_SENDER) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SENDER) == parser_ok) { strcpy(item_array.items[items_idx].key, "Of Key"); item_array.items[items_idx].toString = items_stdToDisplayString; items_idx++; } } - if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_SIGNERS) == parser_ok) { - if (parser_getJsonValue(&json_clist, JSON_CLIST) == parser_ok) { - parser_getGasObject(&json_clist); - items_storeGasItem(&json_clist, items_idx, &unknown_capabitilies); + + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { + array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CLIST) == parser_ok) { + parser_getGasObject(&CURR_ITEM_TOKEN); + items_storeGasItem(CURR_ITEM_TOKEN, items_idx, &unknown_capabitilies); items_idx++; } } - if (parser_getJsonValue(&json_clist, JSON_SIGNERS) == parser_ok) { - if (parser_getJsonValue(&json_clist, JSON_CLIST) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { + array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CLIST) == parser_ok) { + uint16_t clist_token_index = CURR_ITEM_TOKEN; for (uint8_t i = 0; i < parser_getNumberOfClistElements(); i++) { - if (array_get_nth_element(&json_clist, 0, i, &token_index) == parser_ok) { - json_parse(&json_possible_transfer, json_clist.buffer + json_clist.tokens[token_index].start, - json_clist.tokens[token_index].end - json_clist.tokens[token_index].start); - - if (object_get_value(&json_possible_transfer, 0, "name", &token_index) == parser_ok) { - if (MEMCMP("coin.TRANSFER", json_possible_transfer.buffer + json_possible_transfer.tokens[token_index].start, - json_possible_transfer.tokens[token_index].end - json_possible_transfer.tokens[token_index].start) == 0) { - items_storeTransferItem(&json_possible_transfer, items_idx, &num_of_transfers, &unknown_capabitilies); + if (array_get_nth_element(&json_all, clist_token_index, i, &token_index) == parser_ok) { + uint16_t name_token_index = 0; + if (object_get_value(&json_all, token_index, "name", &name_token_index) == parser_ok) { + if (MEMCMP("coin.TRANSFER", json_all.buffer + json_all.tokens[name_token_index].start, + json_all.tokens[name_token_index].end - json_all.tokens[name_token_index].start) == 0) { + CURR_ITEM_TOKEN = token_index; + items_storeTransferItem(&json_all, token_index, items_idx, &num_of_transfers, &unknown_capabitilies); items_idx++; } } @@ -106,15 +110,15 @@ void items_storeItems() { } } - if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_META) == parser_ok) { - if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_CHAIN_ID) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CHAIN_ID) == parser_ok) { strcpy(item_array.items[items_idx].key, "On Chain"); item_array.items[items_idx].toString = items_stdToDisplayString; items_idx++; } } - if (parser_getJsonValue(&CURR_ITEM_JSON, JSON_META) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { strcpy(item_array.items[items_idx].key, "Using Gas"); item_array.items[items_idx].toString = items_gasToDisplayString; items_idx++; @@ -136,21 +140,19 @@ void items_storeItems() { } } - CURR_ITEM_JSON.buffer = base64_hash; - CURR_ITEM_JSON.bufferLen = sizeof(base64_hash) - 1; - item_array.items[items_idx].toString = items_stdToDisplayString; + item_array.items[items_idx].toString = items_hashToDisplayString; items_idx++; - /* strcpy(item_array.items[items_idx].key, "Sign for Address"); + /* Currently launching cpp tests, so this is not available uint8_t address[32]; uint16_t address_size; CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); snprintf(outVal, address_size + 1, "%s", address); - item_array.items[items_idx].toString = items_stdToDisplayString; - items_idx++; */ + item_array.items[items_idx].toString = items_hashToDisplayString; + items_idx++; item_array.numOfItems = items_idx; } @@ -159,16 +161,13 @@ uint16_t items_getTotalItems() { return item_array.numOfItems; } -static void items_storeGasItem(parsed_json_t *json_gas_obj, uint8_t items_idx, uint8_t *unknown_capabitilies) { +static void items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies) { uint16_t token_index = 0; uint16_t args_count = 0; - parsed_json_t args_json; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - CURR_ITEM_JSON = *json_gas_obj; - object_get_value(json_gas_obj, 0, "args", &token_index); - json_parse(&args_json, json_gas_obj->buffer + json_gas_obj->tokens[token_index].start, - json_gas_obj->tokens[token_index].end - json_gas_obj->tokens[token_index].start); - array_get_element_count(&args_json, 0, &args_count); + object_get_value(&json_all, json_token_index, "args", &token_index); + array_get_element_count(&json_all, token_index, &args_count); if (args_count > 0) { snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); @@ -176,23 +175,17 @@ static void items_storeGasItem(parsed_json_t *json_gas_obj, uint8_t items_idx, u item_array.items[items_idx].toString = items_unknownCapabilityToDisplayString; } else { strcpy(item_array.items[items_idx].key, "Paying Gas"); - item_array.items[items_idx].json.bufferLen = 0; - item_array.items[items_idx].toString = items_stdToDisplayString; + item_array.items[items_idx].toString = items_nothingToDisplayString; } } -static void items_storeTransferItem(parsed_json_t *json_possible_transfer, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies) { +static void items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies) { uint16_t token_index = 0; uint16_t num_of_args = 0; - parsed_json_t args_json; - CURR_ITEM_JSON = *json_possible_transfer; + object_get_value(json_all, transfer_token_index, "args", &token_index); - object_get_value(json_possible_transfer, 0, "args", &token_index); - json_parse(&args_json, json_possible_transfer->buffer + json_possible_transfer->tokens[token_index].start, - json_possible_transfer->tokens[token_index].end - json_possible_transfer->tokens[token_index].start); - - array_get_element_count(&args_json, 0, &num_of_args); + array_get_element_count(json_all, token_index, &num_of_args); if (num_of_args == 3) { snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Transfer %d", *num_of_transfers); @@ -205,25 +198,34 @@ static void items_storeTransferItem(parsed_json_t *json_possible_transfer, uint8 } } -static parser_error_t items_stdToDisplayString(__Z_UNUSED parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { - *outValLen = json_obj.bufferLen + 1; - snprintf(outVal, *outValLen, "%s", json_obj.buffer); +static parser_error_t items_stdToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen) { + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + + *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start + 1; + snprintf(outVal, *outValLen, "%s", json_all.buffer + json_all.tokens[token_index].start); + + return parser_ok; +} + +static parser_error_t items_nothingToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen) { + *outValLen = 1; + snprintf(outVal, *outValLen, " "); return parser_ok; } -static parser_error_t items_signingToDisplayString(__Z_UNUSED parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { +static parser_error_t items_signingToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("Transaction"); snprintf(outVal, *outValLen, "Transaction"); return parser_ok; } -static parser_error_t items_requiringToDisplayString(__Z_UNUSED parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { +static parser_error_t items_requiringToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("Capabilities"); snprintf(outVal, *outValLen, "Capabilities"); return parser_ok; } -static parser_error_t items_transferToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { +static parser_error_t items_transferToDisplayString(__Z_UNUSED uint16_t token_index_json, char *outVal, uint16_t *outValLen) { char amount[50]; uint8_t amount_len = 0; char to[65]; @@ -231,24 +233,23 @@ static parser_error_t items_transferToDisplayString(parsed_json_t json_obj, char char from[65]; uint8_t from_len = 0; uint16_t token_index = 0; - parsed_json_t args_json; - - object_get_value(&json_obj, 0, "args", &token_index); - json_parse(&args_json, json_obj.buffer + json_obj.tokens[token_index].start, - json_obj.tokens[token_index].end - json_obj.tokens[token_index].start); - array_get_nth_element(&args_json, 0, 0, &token_index); - strncpy(from, args_json.buffer + args_json.tokens[token_index].start, args_json.tokens[token_index].end - args_json.tokens[token_index].start); - from_len = args_json.tokens[token_index].end - args_json.tokens[token_index].start; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + + object_get_value(&json_all, token_index_json, "args", &token_index); + + array_get_nth_element(&json_all, token_index, 0, &token_index); + strncpy(from, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); + from_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; from[from_len] = '\0'; - array_get_nth_element(&args_json, 0, 1, &token_index); - strncpy(to, args_json.buffer + args_json.tokens[token_index].start, args_json.tokens[token_index].end - args_json.tokens[token_index].start); - to_len = args_json.tokens[token_index].end - args_json.tokens[token_index].start; + array_get_nth_element(&json_all, token_index, 1, &token_index); + strncpy(to, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); + to_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; to[to_len] = '\0'; - array_get_nth_element(&args_json, 0, 2, &token_index); - strncpy(amount, args_json.buffer + args_json.tokens[token_index].start, args_json.tokens[token_index].end - args_json.tokens[token_index].start); - amount_len = args_json.tokens[token_index].end - args_json.tokens[token_index].start; + array_get_nth_element(&json_all, token_index, 2, &token_index); + strncpy(amount, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); + amount_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; amount[amount_len] = '\0'; *outValLen = amount_len + from_len + to_len + sizeof(" from ") + sizeof(" to ") + 4 * sizeof("\""); @@ -257,20 +258,22 @@ static parser_error_t items_transferToDisplayString(parsed_json_t json_obj, char return parser_ok; } -static parser_error_t items_gasToDisplayString(__Z_UNUSED parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { +static parser_error_t items_gasToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen) { char gasLimit[10]; uint8_t gasLimit_len = 0; char gasPrice[64]; uint8_t gasPrice_len = 0; - parsed_json_t gas_json_obj; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t meta_token_index = token_index; - parser_getJsonValue(&gas_json_obj, JSON_GAS_LIMIT); - gasLimit_len = gas_json_obj.bufferLen + 1; - snprintf(gasLimit, gasLimit_len, "%s", gas_json_obj.buffer); + parser_getJsonValue(&token_index, JSON_GAS_LIMIT); + gasLimit_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start + 1; + snprintf(gasLimit, gasLimit_len, "%s", json_all.buffer + json_all.tokens[token_index].start); - parser_getJsonValue(&gas_json_obj, JSON_GAS_PRICE); - gasPrice_len = gas_json_obj.bufferLen + 1; - snprintf(gasPrice, gasPrice_len, "%s", gas_json_obj.buffer); + token_index = meta_token_index; + parser_getJsonValue(&token_index, JSON_GAS_PRICE); + gasPrice_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start + 1; + snprintf(gasPrice, gasPrice_len, "%s", json_all.buffer + json_all.tokens[token_index].start); *outValLen = gasLimit_len + gasPrice_len + sizeof("at most ") + sizeof(" at price "); snprintf(outVal, *outValLen, "at most %s at price %s", gasLimit, gasPrice); @@ -278,16 +281,22 @@ static parser_error_t items_gasToDisplayString(__Z_UNUSED parsed_json_t json_obj return parser_ok; } -static parser_error_t items_unknownCapabilityToDisplayString(parsed_json_t json_obj, char *outVal, uint16_t *outValLen) { +static parser_error_t items_hashToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof(base64_hash); + snprintf(outVal, *outValLen, "%s", base64_hash); + return parser_ok; +} + +static parser_error_t items_unknownCapabilityToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen) { uint16_t token_index = 0; uint16_t args_count = 0; uint8_t len = 0; uint8_t outVal_idx= 0; - parsed_json_t args_json; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - object_get_value(&json_obj, 0, "name", &token_index); - len = json_obj.tokens[token_index].end - json_obj.tokens[token_index].start + sizeof("name: "); - snprintf(outVal, len, "name: %s", json_obj.buffer + json_obj.tokens[token_index].start); + object_get_value(&json_all, token_index_json, "name", &token_index); + len = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("name: "); + snprintf(outVal, len, "name: %s", json_all.buffer + json_all.tokens[token_index].start); outVal_idx += len; // Remove null terminator @@ -297,20 +306,19 @@ static parser_error_t items_unknownCapabilityToDisplayString(parsed_json_t json_ outVal[outVal_idx] = ' '; outVal_idx++; - object_get_value(&json_obj, 0, "args", &token_index); - json_parse(&args_json, json_obj.buffer + json_obj.tokens[token_index].start, - json_obj.tokens[token_index].end - json_obj.tokens[token_index].start); - array_get_element_count(&args_json, 0, &args_count); + object_get_value(&json_all, token_index_json, "args", &token_index); + array_get_element_count(&json_all, token_index, &args_count); + uint16_t args_token_index = 0; for (uint8_t i = 0; i < args_count - 1; i++) { - array_get_nth_element(&args_json, 0, i, &token_index); - if (args_json.tokens[token_index].type == JSMN_STRING) { + array_get_nth_element(&json_all, token_index, i, &args_token_index); + if (json_all.tokens[args_token_index].type == JSMN_STRING) { // Strings go in between double quotes - len = args_json.tokens[token_index].end - args_json.tokens[token_index].start + sizeof("arg X: \"\","); - snprintf(outVal + outVal_idx, len, "arg %d: \"%s\",", i + 1, args_json.buffer + args_json.tokens[token_index].start); + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\","); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\",", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); } else { - len = args_json.tokens[token_index].end - args_json.tokens[token_index].start + sizeof("arg X: ,"); - snprintf(outVal + outVal_idx, len, "arg %d: %s,", i + 1, args_json.buffer + args_json.tokens[token_index].start); + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: ,"); + snprintf(outVal + outVal_idx, len, "arg %d: %s,", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); } outVal_idx += len; @@ -319,13 +327,13 @@ static parser_error_t items_unknownCapabilityToDisplayString(parsed_json_t json_ } // Last arg (without comma) - array_get_nth_element(&args_json, 0, args_count - 1, &token_index); - if (args_json.tokens[token_index].type == JSMN_STRING) { - len = args_json.tokens[token_index].end - args_json.tokens[token_index].start + sizeof("arg X: \"\""); - snprintf(outVal + outVal_idx, len, "arg %d: \"%s\"", args_count, args_json.buffer + args_json.tokens[token_index].start); + array_get_nth_element(&json_all, token_index, args_count - 1, &args_token_index); + if (json_all.tokens[args_token_index].type == JSMN_STRING) { + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\""); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\"", args_count, json_all.buffer + json_all.tokens[args_token_index].start); } else { - len = args_json.tokens[token_index].end - args_json.tokens[token_index].start + sizeof("arg X: "); - snprintf(outVal + outVal_idx, len, "arg %d: %s", args_count, args_json.buffer + args_json.tokens[token_index].start); + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: "); + snprintf(outVal + outVal_idx, len, "arg %d: %s", args_count, json_all.buffer + json_all.tokens[args_token_index].start); } outVal_idx += len; diff --git a/app/src/items.h b/app/src/items.h index c3be9ef..b43c5b5 100644 --- a/app/src/items.h +++ b/app/src/items.h @@ -22,8 +22,8 @@ typedef struct { char key[25]; - parsed_json_t json; - parser_error_t (*toString)(parsed_json_t json_obj, char *outVal, uint16_t *outValLen); + uint16_t json_token_index; + parser_error_t (*toString)(uint16_t token_index, char *outVal, uint16_t *outValLen); } item_t; typedef struct { diff --git a/app/src/json/json_parser.c b/app/src/json/json_parser.c index 3c4d890..bffe0f8 100644 --- a/app/src/json/json_parser.c +++ b/app/src/json/json_parser.c @@ -189,42 +189,6 @@ parser_error_t object_get_value(const parsed_json_t *json, if (key_token.start <= prev_element_end) { continue; } - - if (value_token.type == JSMN_OBJECT) { - // An object was found, look inside it - parsed_json_t json_obj; - uint16_t token_index_before_recursion = *token_index; - - json_parse(&json_obj, json->buffer + value_token.start, value_token.end - value_token.start); - - if (object_get_value(&json_obj, 0, key_name, token_index) == parser_ok) { - *token_index = *token_index + token_index_before_recursion; - return parser_ok; - } - } else if (value_token.type == JSMN_ARRAY) { - // An array was found, look inside it - parsed_json_t json_array; - parsed_json_t json_array_element; - uint16_t token_index_before_object_recursion = 0; - uint16_t token_index_before_array_iteration = 0; - uint16_t element_count = 0; - - json_parse(&json_array, json->buffer + value_token.start, value_token.end - value_token.start); - - CHECK_ERROR(array_get_element_count(&json_array, 0, &element_count)) - - for (int i = 0; i < element_count; i++) { - CHECK_ERROR(array_get_nth_element(&json_array, 0, i, &token_index_before_array_iteration)) - - json_parse(&json_array_element, json_array.buffer + json_array.tokens[token_index_before_array_iteration].start, json_array.tokens[token_index_before_array_iteration].end - json_array.tokens[token_index_before_array_iteration].start); - - if (object_get_value(&json_array_element, 0, key_name, &token_index_before_object_recursion) == parser_ok) { - *token_index = *token_index + token_index_before_object_recursion + token_index_before_array_iteration; - return parser_ok; - } - } - } - prev_element_end = value_token.end; if (((uint16_t) strlen(key_name)) == (key_token.end - key_token.start)) { diff --git a/app/src/parser.c b/app/src/parser.c index bdd9ef4..98de973 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -107,7 +107,7 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c cleanOutput(outKey, outKeyLen, outVal, outValLen); snprintf(outKey, outKeyLen, "%s", item_array->items[displayIdx].key); - item_array->items[displayIdx].toString(item_array->items[displayIdx].json, outVal, &outValLen); + item_array->items[displayIdx].toString(item_array->items[displayIdx].json_token_index, outVal, &outValLen); return parser_ok; } diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 135c4f0..1852b81 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -56,24 +56,32 @@ parser_error_t parser_isTransfer(parsed_json_t *json_obj) { uint16_t parser_getNumberOfClistElements() { uint16_t number_of_elements = 0; - parsed_json_t json_obj; + parsed_json_t *json_all = &parser_tx_obj.tx_json.json; + uint16_t token_index = 0; + + parser_getJsonValue(&token_index, JSON_SIGNERS); + array_get_nth_element(&json_all, token_index, 0, &token_index); + parser_getJsonValue(&token_index, JSON_CLIST); + + CHECK_ERROR(array_get_element_count(json_all, token_index, &number_of_elements)); - parser_getJsonValue(&json_obj, JSON_META); - parser_getJsonValue(&json_obj, JSON_CLIST); - CHECK_ERROR(array_get_element_count(&json_obj, 0, &number_of_elements)); return number_of_elements; } -// TODO: join all these functions into a parametrized one -parser_error_t parser_getJsonValue(parsed_json_t *json_obj, const char *key) { +parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key) { + parsed_json_t json_obj; uint16_t token_index = 0; - object_get_value(&parser_tx_obj.tx_json.json, 0, key, &token_index); - json_parse(json_obj, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); - if (MEMCMP("null", json_obj->buffer, json_obj->bufferLen) == 0) { + object_get_value(&parser_tx_obj.tx_json.json, *json_token_index, key, &token_index); + + json_parse(&json_obj, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); + + if (MEMCMP("null", json_obj.buffer, json_obj.bufferLen) == 0) { return parser_no_data; } + *json_token_index = token_index; + return parser_ok; } @@ -85,19 +93,18 @@ parser_error_t parser_getNthClistElement(parsed_json_t *json_obj, uint8_t clist_ return parser_ok; } -parser_error_t parser_getGasObject(parsed_json_t *json_obj) { +parser_error_t parser_getGasObject(uint16_t *json_token_index) { uint16_t token_index = 0; - parsed_json_t *json_clist = json_obj; - parsed_json_t temp_json_obj; + parsed_json_t *json_all = &parser_tx_obj.tx_json.json; + uint16_t name_token_index = 0; for (uint16_t i = 0; i < parser_getNumberOfClistElements(); i++) { - array_get_nth_element(json_clist, 0, i, &token_index); - json_parse(&temp_json_obj, json_clist->buffer + json_clist->tokens[token_index].start, json_clist->tokens[token_index].end - json_clist->tokens[token_index].start); + array_get_nth_element(json_all, *json_token_index, i, &token_index); - object_get_value(&temp_json_obj, 0, "name", &token_index); - if (MEMCMP("coin.GAS", temp_json_obj.buffer + temp_json_obj.tokens[token_index].start, - temp_json_obj.tokens[token_index].end - temp_json_obj.tokens[token_index].start) == 0) { - *json_obj = temp_json_obj; + object_get_value(json_all, token_index, "name", &name_token_index); + if (MEMCMP("coin.GAS", json_all->buffer + json_all->tokens[name_token_index].start, + json_all->tokens[name_token_index].end - json_all->tokens[name_token_index].start) == 0) { + *json_token_index = token_index; return parser_ok; } } diff --git a/app/src/parser_impl.h b/app/src/parser_impl.h index 39b8f44..1aa2e72 100644 --- a/app/src/parser_impl.h +++ b/app/src/parser_impl.h @@ -51,9 +51,9 @@ parser_error_t parser_getTransferTo(char **to, uint16_t *to_len); parser_error_t parser_getTransferAmount(char **amount, uint16_t *amount_len); uint16_t parser_getNumberOfClistElements(); uint16_t parser_getNumberOfTransfers(); -parser_error_t parser_getJsonValue(parsed_json_t *json_obj, const char *key); +parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key); parser_error_t parser_getNthClistElement(parsed_json_t *json_obj, uint8_t clist_array_idx); -parser_error_t parser_getGasObject(parsed_json_t *json_obj); +parser_error_t parser_getGasObject(uint16_t *json_token_index); parser_error_t parser_getChainId(parsed_json_t *json_obj); #ifdef __cplusplus diff --git a/tests/testcases.json b/tests/testcases.json index 32efe02..e76d7c5 100644 --- a/tests/testcases.json +++ b/tests/testcases.json @@ -13,6 +13,7 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-5", "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -24,6 +25,7 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-5", "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -40,6 +42,7 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-6", "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -51,6 +54,7 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-6", "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -66,6 +70,7 @@ "5 | On Chain : 0", "6 | Using Gas : at most 600 at price 1.0e-5", "7 | Transaction hash : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb-Cn8w", + "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -76,6 +81,7 @@ "5 | On Chain : 0", "6 | Using Gas : at most 600 at price 1.0e-5", "7 | Transaction hash : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb-Cn8w", + "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -92,6 +98,7 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-6", "8 | Transaction hash : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4bAvk4", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -103,6 +110,7 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-6", "8 | Transaction hash : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4bAvk4", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -119,6 +127,7 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-5", "8 | Transaction hash : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew7VnMY", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -130,6 +139,7 @@ "6 | On Chain : 0", "7 | Using Gas : at most 600 at price 1.0e-5", "8 | Transaction hash : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew7VnMY", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] }, { @@ -149,6 +159,7 @@ "9 | On Chain : 0", "10 | Using Gas : at most 600 at price 1.0e-6", "11 | Transaction hash : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOREfZhk", + "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ], "output_expert": [ "0 | Signing : Transaction", @@ -163,6 +174,8 @@ "9 | On Chain : 0", "10 | Using Gas : at most 600 at price 1.0e-6", "11 | Transaction hash : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOREfZhk", + "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] } ] + From 1650152995463d74278da21404a78b20757e25db Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Tue, 13 Aug 2024 15:07:45 +0200 Subject: [PATCH 06/34] transfer.rotate + raise warnings when no clist --- app/src/items.c | 90 ++++++++++++++++++++++++++++++++++++++++++- app/src/parser_impl.c | 58 +++++++++++++++------------- app/src/parser_impl.h | 7 ++-- 3 files changed, 122 insertions(+), 33 deletions(-) diff --git a/app/src/items.c b/app/src/items.c index e7ccf59..85fdd37 100644 --- a/app/src/items.c +++ b/app/src/items.c @@ -21,14 +21,17 @@ static parser_error_t items_stdToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); static parser_error_t items_nothingToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen); +static parser_error_t items_warningToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen); static parser_error_t items_signingToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); static parser_error_t items_requiringToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); static parser_error_t items_transferToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); +static parser_error_t items_rotateToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen); static parser_error_t items_gasToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); static parser_error_t items_hashToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); static parser_error_t items_unknownCapabilityToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); static void items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); static void items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); +static void items_storeRotateItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); #define CURR_ITEM_TOKEN item_array.items[items_idx].json_token_index @@ -56,6 +59,7 @@ void items_storeItems() { uint8_t unknown_capabitilies = 1; uint8_t num_of_transfers = 1; uint16_t token_index = 0; + bool unscoped_signer = false; strcpy(item_array.items[items_idx].key, "Signing"); item_array.items[items_idx].toString = items_signingToDisplayString; @@ -80,7 +84,39 @@ void items_storeItems() { } } + // TODO : Cleanup + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { + array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CLIST) == parser_ok) { + uint16_t clist_token_index = CURR_ITEM_TOKEN; + for (uint8_t i = 0; i < parser_getNumberOfClistElements(); i++) { + if (array_get_nth_element(&json_all, clist_token_index, i, &token_index) == parser_ok) { + uint16_t name_token_index = 0; + if (object_get_value(&json_all, token_index, JSON_NAME, &name_token_index) == parser_ok) { + if (MEMCMP("coin.TRANSFER", json_all.buffer + json_all.tokens[name_token_index].start, + json_all.tokens[name_token_index].end - json_all.tokens[name_token_index].start) == 0) { + if (parser_findKeyInClist(item_array.items[items_idx - 1].json_token_index) == parser_no_data) { + unscoped_signer = true; + break; + } + } + } + } + } + } else { + // No Clist given + unscoped_signer = true; + } + } + if (unscoped_signer) { + strcpy(item_array.items[items_idx].key, "Unscoped Signer"); + CURR_ITEM_TOKEN = item_array.items[items_idx - 1].json_token_index; + item_array.items[items_idx].toString = items_stdToDisplayString; + items_idx++; + } + + CURR_ITEM_TOKEN = 0; if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CLIST) == parser_ok) { @@ -90,6 +126,7 @@ void items_storeItems() { } } + CURR_ITEM_TOKEN = 0; if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CLIST) == parser_ok) { @@ -97,19 +134,30 @@ void items_storeItems() { for (uint8_t i = 0; i < parser_getNumberOfClistElements(); i++) { if (array_get_nth_element(&json_all, clist_token_index, i, &token_index) == parser_ok) { uint16_t name_token_index = 0; - if (object_get_value(&json_all, token_index, "name", &name_token_index) == parser_ok) { + if (object_get_value(&json_all, token_index, JSON_NAME, &name_token_index) == parser_ok) { if (MEMCMP("coin.TRANSFER", json_all.buffer + json_all.tokens[name_token_index].start, json_all.tokens[name_token_index].end - json_all.tokens[name_token_index].start) == 0) { CURR_ITEM_TOKEN = token_index; items_storeTransferItem(&json_all, token_index, items_idx, &num_of_transfers, &unknown_capabitilies); items_idx++; + } else if (MEMCMP("coin.ROTATE", json_all.buffer + json_all.tokens[name_token_index].start, + json_all.tokens[name_token_index].end - json_all.tokens[name_token_index].start) == 0) { + CURR_ITEM_TOKEN = token_index; + items_storeRotateItem(&json_all, token_index, items_idx, &unknown_capabitilies); + items_idx++; } } } } + } else { + // No Clist given, Raise warning + strcpy(item_array.items[items_idx].key, "WARNING"); + item_array.items[items_idx].toString = items_warningToDisplayString; + items_idx++; } } + CURR_ITEM_TOKEN = 0; if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CHAIN_ID) == parser_ok) { strcpy(item_array.items[items_idx].key, "On Chain"); @@ -118,6 +166,7 @@ void items_storeItems() { } } + CURR_ITEM_TOKEN = 0; if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { strcpy(item_array.items[items_idx].key, "Using Gas"); item_array.items[items_idx].toString = items_gasToDisplayString; @@ -198,6 +247,24 @@ static void items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_t } } +static void items_storeRotateItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies) { + uint16_t token_index = 0; + uint16_t num_of_args = 0; + + object_get_value(json_all, transfer_token_index, "args", &token_index); + + array_get_element_count(json_all, token_index, &num_of_args); + + if (num_of_args == 1) { + snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Rotate for account"); + item_array.items[items_idx].toString = items_rotateToDisplayString; + } else { + snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); + (*unknown_capabitilies)++; + item_array.items[items_idx].toString = items_unknownCapabilityToDisplayString; + } +} + static parser_error_t items_stdToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen) { parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; @@ -213,6 +280,12 @@ static parser_error_t items_nothingToDisplayString(__Z_UNUSED uint16_t token_ind return parser_ok; } +static parser_error_t items_warningToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof("UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds."); + snprintf(outVal, *outValLen, "UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds."); + return parser_ok; +} + static parser_error_t items_signingToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("Transaction"); snprintf(outVal, *outValLen, "Transaction"); @@ -225,7 +298,7 @@ static parser_error_t items_requiringToDisplayString(__Z_UNUSED uint16_t token_i return parser_ok; } -static parser_error_t items_transferToDisplayString(__Z_UNUSED uint16_t token_index_json, char *outVal, uint16_t *outValLen) { +static parser_error_t items_transferToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen) { char amount[50]; uint8_t amount_len = 0; char to[65]; @@ -258,6 +331,19 @@ static parser_error_t items_transferToDisplayString(__Z_UNUSED uint16_t token_in return parser_ok; } +static parser_error_t items_rotateToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen) { + uint16_t token_index = 0; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + + object_get_value(&json_all, token_index_json, "args", &token_index); + array_get_nth_element(&json_all, token_index, 0, &token_index); + + *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("\"\""); + snprintf(outVal, *outValLen, "\"%s\"", json_all.buffer + json_all.tokens[token_index].start); + + return parser_ok; +} + static parser_error_t items_gasToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen) { char gasLimit[10]; uint8_t gasLimit_len = 0; diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 1852b81..334ac1b 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -37,23 +37,6 @@ parser_tx_t *parser_getParserTxObj() { return &parser_tx_obj; } -parser_error_t parser_isTransfer(parsed_json_t *json_obj) { - uint16_t name_token_idx = 0; - parser_error_t ret = parser_json_not_a_transfer; - - object_get_value(json_obj, 0, "name", &name_token_idx); - - if (((uint16_t) strlen("coin.TRANSFER")) == (json_obj->tokens[name_token_idx].end - json_obj->tokens[name_token_idx].start)) { - if (MEMCMP("coin.TRANSFER", - json_obj->buffer + json_obj->tokens[name_token_idx].start, - json_obj->tokens[name_token_idx].end - json_obj->tokens[name_token_idx].start) == 0) { - ret = parser_ok; - } - } - - return ret; -} - uint16_t parser_getNumberOfClistElements() { uint16_t number_of_elements = 0; parsed_json_t *json_all = &parser_tx_obj.tx_json.json; @@ -68,11 +51,40 @@ uint16_t parser_getNumberOfClistElements() { return number_of_elements; } +parser_error_t parser_findKeyInClist(uint16_t key_token_index) { + parsed_json_t *json_all = &parser_tx_obj.tx_json.json; + uint16_t token_index = 0; + uint16_t clist_token_index = 0; + uint16_t args_token_index = 0; + uint16_t number_of_args = 0; + + parser_getJsonValue(&clist_token_index, JSON_SIGNERS); + array_get_nth_element(&json_all, clist_token_index, 0, &clist_token_index); + parser_getJsonValue(&clist_token_index, JSON_CLIST); + + for (uint16_t i = 0; i < parser_getNumberOfClistElements(); i++) { + CHECK_ERROR(array_get_nth_element(json_all, clist_token_index, i, &args_token_index)); + CHECK_ERROR(parser_getJsonValue(&args_token_index, JSON_ARGS)); + CHECK_ERROR(array_get_element_count(json_all, args_token_index, &number_of_args)); + for (uint16_t j = 0; j < number_of_args; j++) { + array_get_nth_element(json_all, args_token_index, j, &token_index); + if (MEMCMP(json_all->buffer + json_all->tokens[key_token_index].start, + json_all->buffer + json_all->tokens[token_index].start, + json_all->tokens[key_token_index].end - json_all->tokens[key_token_index].start) == 0) { + return parser_ok; + } + } + } + + return parser_no_data; +} + + parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key) { parsed_json_t json_obj; uint16_t token_index = 0; - object_get_value(&parser_tx_obj.tx_json.json, *json_token_index, key, &token_index); + CHECK_ERROR(object_get_value(&parser_tx_obj.tx_json.json, *json_token_index, key, &token_index)); json_parse(&json_obj, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); @@ -85,14 +97,6 @@ parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key) return parser_ok; } -parser_error_t parser_getNthClistElement(parsed_json_t *json_obj, uint8_t clist_array_idx) { - uint16_t token_index = 0; - array_get_nth_element(json_obj, 0, clist_array_idx, &token_index); - json_parse(json_obj, json_obj->buffer + json_obj->tokens[token_index].start, json_obj->tokens[token_index].end - json_obj->tokens[token_index].start); - - return parser_ok; -} - parser_error_t parser_getGasObject(uint16_t *json_token_index) { uint16_t token_index = 0; parsed_json_t *json_all = &parser_tx_obj.tx_json.json; @@ -101,7 +105,7 @@ parser_error_t parser_getGasObject(uint16_t *json_token_index) { for (uint16_t i = 0; i < parser_getNumberOfClistElements(); i++) { array_get_nth_element(json_all, *json_token_index, i, &token_index); - object_get_value(json_all, token_index, "name", &name_token_index); + object_get_value(json_all, token_index, JSON_NAME, &name_token_index); if (MEMCMP("coin.GAS", json_all->buffer + json_all->tokens[name_token_index].start, json_all->tokens[name_token_index].end - json_all->tokens[name_token_index].start) == 0) { *json_token_index = token_index; diff --git a/app/src/parser_impl.h b/app/src/parser_impl.h index 1aa2e72..30f74b0 100644 --- a/app/src/parser_impl.h +++ b/app/src/parser_impl.h @@ -33,7 +33,8 @@ extern "C" { #define JSON_GAS_PRICE "gasPrice" #define JSON_SIGNERS "signers" #define JSON_CLIST "clist" - +#define JSON_ARGS "args" +#define JSON_NAME "name" typedef struct { const uint8_t *buffer; uint16_t bufferLen; @@ -44,15 +45,13 @@ typedef struct { parser_error_t _read_json_tx(parser_context_t *c, parser_tx_t *v); parser_tx_t *parser_getParserTxObj(); parser_error_t parser_initClistObject(); -parser_error_t parser_initTransfer(); -parser_error_t parser_isTransfer(parsed_json_t *json_obj); parser_error_t parser_getTransferFrom(char **from, uint16_t *from_len); parser_error_t parser_getTransferTo(char **to, uint16_t *to_len); parser_error_t parser_getTransferAmount(char **amount, uint16_t *amount_len); uint16_t parser_getNumberOfClistElements(); +parser_error_t parser_findKeyInClist(uint16_t key_token_index); uint16_t parser_getNumberOfTransfers(); parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key); -parser_error_t parser_getNthClistElement(parsed_json_t *json_obj, uint8_t clist_array_idx); parser_error_t parser_getGasObject(uint16_t *json_token_index); parser_error_t parser_getChainId(parsed_json_t *json_obj); From 6ef14c7f938bc41ff4d051d64de07d017b73bd37 Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Wed, 14 Aug 2024 10:34:19 +0200 Subject: [PATCH 07/34] Crosschain transfers and some corner case handling --- app/src/common/parser_common.h | 1 + app/src/items.c | 353 +++++++++++++----- app/src/items.h | 8 +- app/src/parser.c | 2 +- app/src/parser_impl.c | 44 ++- app/src/parser_impl.h | 13 +- tests/testcases.json | 638 ++++++++++++++++++++++++++++++++- 7 files changed, 946 insertions(+), 113 deletions(-) diff --git a/app/src/common/parser_common.h b/app/src/common/parser_common.h index 78b1822..e7913f5 100644 --- a/app/src/common/parser_common.h +++ b/app/src/common/parser_common.h @@ -60,6 +60,7 @@ typedef enum { parser_json_too_many_tokens, // "NOMEM: JSON string contains too many tokens" parser_json_incomplete_json, // "JSON string is not complete"; parser_json_not_a_transfer, + parser_invalid_meta_field, parser_json_unexpected_error, } parser_error_t; diff --git a/app/src/items.c b/app/src/items.c index 85fdd37..22711ec 100644 --- a/app/src/items.c +++ b/app/src/items.c @@ -19,34 +19,38 @@ #include "parser_impl.h" #include -static parser_error_t items_stdToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); -static parser_error_t items_nothingToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen); -static parser_error_t items_warningToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen); -static parser_error_t items_signingToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); -static parser_error_t items_requiringToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); -static parser_error_t items_transferToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); -static parser_error_t items_rotateToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen); -static parser_error_t items_gasToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); -static parser_error_t items_hashToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); -static parser_error_t items_unknownCapabilityToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen); -static void items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); -static void items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); -static void items_storeRotateItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); +static parser_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_signingToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_requiringToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_gasToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static parser_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); +static items_error_t items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); +static items_error_t items_storeCrossTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); +static items_error_t items_storeRotateItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); +static items_error_t items_storeUnknownItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); #define CURR_ITEM_TOKEN item_array.items[items_idx].json_token_index item_array_t item_array; -parsed_json_t signing_json; -parsed_json_t requiring_json; - uint8_t hash[BLAKE2B_HASH_SIZE] = {0}; char base64_hash[44]; void items_initItems() { MEMZERO(&item_array, sizeof(item_array_t)); - MEMZERO(&signing_json, sizeof(parsed_json_t)); - MEMZERO(&requiring_json, sizeof(parsed_json_t)); + + for (uint8_t i = 0; i < sizeof(item_array.items) / sizeof(item_array.items[0]); i++) { + item_array.items[i].can_display = true; + } } item_array_t *items_getItemArray() { @@ -62,24 +66,25 @@ void items_storeItems() { bool unscoped_signer = false; strcpy(item_array.items[items_idx].key, "Signing"); - item_array.items[items_idx].toString = items_signingToDisplayString; + item_array.toString[items_idx] = items_signingToDisplayString; items_idx++; // Skip item if network id is not available if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_NETWORK_ID) == parser_ok) { strcpy(item_array.items[items_idx].key, "On Network"); - item_array.items[items_idx].toString = items_stdToDisplayString; + item_array.toString[items_idx] = items_stdToDisplayString; items_idx++; } strcpy(item_array.items[items_idx].key, "Requiring"); - item_array.items[items_idx].toString = items_requiringToDisplayString; + item_array.toString[items_idx] = items_requiringToDisplayString; items_idx++; - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SENDER) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { + array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_PUBKEY) == parser_ok) { strcpy(item_array.items[items_idx].key, "Of Key"); - item_array.items[items_idx].toString = items_stdToDisplayString; + item_array.toString[items_idx] = items_stdToDisplayString; items_idx++; } } @@ -112,7 +117,7 @@ void items_storeItems() { if (unscoped_signer) { strcpy(item_array.items[items_idx].key, "Unscoped Signer"); CURR_ITEM_TOKEN = item_array.items[items_idx - 1].json_token_index; - item_array.items[items_idx].toString = items_stdToDisplayString; + item_array.toString[items_idx] = items_stdToDisplayString; items_idx++; } @@ -135,16 +140,28 @@ void items_storeItems() { if (array_get_nth_element(&json_all, clist_token_index, i, &token_index) == parser_ok) { uint16_t name_token_index = 0; if (object_get_value(&json_all, token_index, JSON_NAME, &name_token_index) == parser_ok) { - if (MEMCMP("coin.TRANSFER", json_all.buffer + json_all.tokens[name_token_index].start, - json_all.tokens[name_token_index].end - json_all.tokens[name_token_index].start) == 0) { + if (MEMCMP("coin.TRANSFER_XCHAIN", json_all.buffer + json_all.tokens[name_token_index].start, + sizeof("coin.TRANSFER_XCHAIN") - 1) == 0) { + CURR_ITEM_TOKEN = token_index; + items_storeCrossTransferItem(&json_all, token_index, items_idx, &num_of_transfers, &unknown_capabitilies); + items_idx++; + } else if (MEMCMP("coin.TRANSFER", json_all.buffer + json_all.tokens[name_token_index].start, + sizeof("coin.TRANSFER") - 1) == 0) { CURR_ITEM_TOKEN = token_index; items_storeTransferItem(&json_all, token_index, items_idx, &num_of_transfers, &unknown_capabitilies); items_idx++; } else if (MEMCMP("coin.ROTATE", json_all.buffer + json_all.tokens[name_token_index].start, - json_all.tokens[name_token_index].end - json_all.tokens[name_token_index].start) == 0) { + sizeof("coin.ROTATE") - 1) == 0) { CURR_ITEM_TOKEN = token_index; items_storeRotateItem(&json_all, token_index, items_idx, &unknown_capabitilies); items_idx++; + } else if (MEMCMP("coin.GAS", json_all.buffer + json_all.tokens[name_token_index].start, + sizeof("coin.GAS") - 1) != 0) { + // Any other case that's not coin.GAS + CURR_ITEM_TOKEN = token_index; + items_storeUnknownItem(&json_all, token_index, items_idx, &unknown_capabitilies); + items_idx++; + item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; } } } @@ -152,25 +169,40 @@ void items_storeItems() { } else { // No Clist given, Raise warning strcpy(item_array.items[items_idx].key, "WARNING"); - item_array.items[items_idx].toString = items_warningToDisplayString; + item_array.toString[items_idx] = items_warningToDisplayString; items_idx++; } } - CURR_ITEM_TOKEN = 0; - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CHAIN_ID) == parser_ok) { - strcpy(item_array.items[items_idx].key, "On Chain"); - item_array.items[items_idx].toString = items_stdToDisplayString; + if (parser_validateMetaField() != parser_ok) { + strcpy(item_array.items[items_idx].key, "CAUTION"); + item_array.toString[items_idx] = items_cautionToDisplayString; + items_idx++; + } else { + CURR_ITEM_TOKEN = 0; + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CHAIN_ID) == parser_ok) { + strcpy(item_array.items[items_idx].key, "On Chain"); + item_array.toString[items_idx] = items_stdToDisplayString; + items_idx++; + } + } + + CURR_ITEM_TOKEN = 0; + if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { + strcpy(item_array.items[items_idx].key, "Using Gas"); + item_array.toString[items_idx] = items_gasToDisplayString; items_idx++; } } - CURR_ITEM_TOKEN = 0; - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { - strcpy(item_array.items[items_idx].key, "Using Gas"); - item_array.items[items_idx].toString = items_gasToDisplayString; - items_idx++; + for (uint8_t i = 0; i < items_idx; i++) { + if (!item_array.items[i].can_display) { + strcpy(item_array.items[items_idx].key, "WARNING"); + item_array.toString[items_idx] = items_txTooLargeToDisplayString; + items_idx++; + break; + } } strcpy(item_array.items[items_idx].key, "Transaction hash"); @@ -189,7 +221,7 @@ void items_storeItems() { } } - item_array.items[items_idx].toString = items_hashToDisplayString; + item_array.toString[items_idx] = items_hashToDisplayString; items_idx++; strcpy(item_array.items[items_idx].key, "Sign for Address"); @@ -200,7 +232,7 @@ void items_storeItems() { CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); snprintf(outVal, address_size + 1, "%s", address); */ - item_array.items[items_idx].toString = items_hashToDisplayString; + item_array.toString[items_idx] = items_hashToDisplayString; items_idx++; item_array.numOfItems = items_idx; @@ -210,7 +242,7 @@ uint16_t items_getTotalItems() { return item_array.numOfItems; } -static void items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies) { +static items_error_t items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies) { uint16_t token_index = 0; uint16_t args_count = 0; parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; @@ -221,14 +253,16 @@ static void items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uin if (args_count > 0) { snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); (*unknown_capabitilies)++; - item_array.items[items_idx].toString = items_unknownCapabilityToDisplayString; + item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; } else { strcpy(item_array.items[items_idx].key, "Paying Gas"); - item_array.items[items_idx].toString = items_nothingToDisplayString; + item_array.toString[items_idx] = items_nothingToDisplayString; } + + return items_ok; } -static void items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies) { +static items_error_t items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies) { uint16_t token_index = 0; uint16_t num_of_args = 0; @@ -239,15 +273,46 @@ static void items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_t if (num_of_args == 3) { snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Transfer %d", *num_of_transfers); (*num_of_transfers)++; - item_array.items[items_idx].toString = items_transferToDisplayString; + item_array.toString[items_idx] = items_transferToDisplayString; } else { snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); (*unknown_capabitilies)++; - item_array.items[items_idx].toString = items_unknownCapabilityToDisplayString; + item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; + + if (num_of_args > 5) { + item_array.items[items_idx].can_display = false; + } } + + return items_ok; } -static void items_storeRotateItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies) { +static items_error_t items_storeCrossTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies) { + uint16_t token_index = 0; + uint16_t num_of_args = 0; + + object_get_value(json_all, transfer_token_index, "args", &token_index); + + array_get_element_count(json_all, token_index, &num_of_args); + + if (num_of_args == 4) { + snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Transfer %d", *num_of_transfers); + (*num_of_transfers)++; + item_array.toString[items_idx] = items_crossTransferToDisplayString; + } else { + snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); + (*unknown_capabitilies)++; + item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; + + if (num_of_args > 5) { + item_array.items[items_idx].can_display = false; + } + } + + return items_ok; +} + +static items_error_t items_storeRotateItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies) { uint16_t token_index = 0; uint16_t num_of_args = 0; @@ -257,48 +322,86 @@ static void items_storeRotateItem(parsed_json_t *json_all, uint16_t transfer_tok if (num_of_args == 1) { snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Rotate for account"); - item_array.items[items_idx].toString = items_rotateToDisplayString; + item_array.toString[items_idx] = items_rotateToDisplayString; } else { snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); (*unknown_capabitilies)++; - item_array.items[items_idx].toString = items_unknownCapabilityToDisplayString; + item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; + + if (num_of_args > 5) { + item_array.items[items_idx].can_display = false; + } } + + return items_ok; } -static parser_error_t items_stdToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen) { +static items_error_t items_storeUnknownItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies) { + uint16_t token_index = 0; + uint16_t num_of_args = 0; + + object_get_value(json_all, transfer_token_index, "args", &token_index); + + array_get_element_count(json_all, token_index, &num_of_args); + + snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); + (*unknown_capabitilies)++; + item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; + + if (num_of_args > 5) { + item_array.items[items_idx].can_display = false; + } + + return items_ok; +} + +static parser_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t item_token_index = item.json_token_index; - *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start + 1; - snprintf(outVal, *outValLen, "%s", json_all.buffer + json_all.tokens[token_index].start); + *outValLen = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; + snprintf(outVal, *outValLen, "%s", json_all.buffer + json_all.tokens[item_token_index].start); return parser_ok; } -static parser_error_t items_nothingToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen) { +static parser_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { *outValLen = 1; snprintf(outVal, *outValLen, " "); return parser_ok; } -static parser_error_t items_warningToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen) { +static parser_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds."); snprintf(outVal, *outValLen, "UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds."); return parser_ok; } -static parser_error_t items_signingToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen) { +static parser_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof("'meta' field of transaction not recognized"); + snprintf(outVal, *outValLen, "'meta' field of transaction not recognized"); + return parser_ok; +} + +static parser_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof("Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?"); + snprintf(outVal, *outValLen, "Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?"); + return parser_ok; +} + +static parser_error_t items_signingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("Transaction"); snprintf(outVal, *outValLen, "Transaction"); return parser_ok; } -static parser_error_t items_requiringToDisplayString(__Z_UNUSED uint16_t token_index, char *outVal, uint16_t *outValLen) { +static parser_error_t items_requiringToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("Capabilities"); snprintf(outVal, *outValLen, "Capabilities"); return parser_ok; } -static parser_error_t items_transferToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen) { +static parser_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { char amount[50]; uint8_t amount_len = 0; char to[65]; @@ -307,8 +410,9 @@ static parser_error_t items_transferToDisplayString(uint16_t token_index_json, c uint8_t from_len = 0; uint16_t token_index = 0; parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t item_token_index = item.json_token_index; - object_get_value(&json_all, token_index_json, "args", &token_index); + object_get_value(&json_all, item_token_index, "args", &token_index); array_get_nth_element(&json_all, token_index, 0, &token_index); strncpy(from, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); @@ -331,11 +435,53 @@ static parser_error_t items_transferToDisplayString(uint16_t token_index_json, c return parser_ok; } -static parser_error_t items_rotateToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen) { +static parser_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { + char amount[50]; + uint8_t amount_len = 0; + char to[65]; + uint8_t to_len = 0; + char from[65]; + uint8_t from_len = 0; + char chain[3]; + uint8_t chain_len = 0; + uint16_t token_index = 0; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t item_token_index = item.json_token_index; + + object_get_value(&json_all, item_token_index, "args", &token_index); + + array_get_nth_element(&json_all, token_index, 0, &token_index); + strncpy(from, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); + from_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; + from[from_len] = '\0'; + + array_get_nth_element(&json_all, token_index, 1, &token_index); + strncpy(to, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); + to_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; + to[to_len] = '\0'; + + array_get_nth_element(&json_all, token_index, 2, &token_index); + strncpy(amount, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); + amount_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; + amount[amount_len] = '\0'; + + array_get_nth_element(&json_all, token_index, 3, &token_index); + strncpy(chain, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); + chain_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; + chain[chain_len] = '\0'; + + *outValLen = amount_len + from_len + to_len + chain_len + sizeof("Cross-chain ") + sizeof(" from ") + sizeof(" to ") + 6 * sizeof("\"") + sizeof(" to chain "); + snprintf(outVal, *outValLen, "Cross-chain %s from \"%s\" to \"%s\" to chain \"%s\"", amount, from, to, chain); + + return parser_ok; +} + +static parser_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { uint16_t token_index = 0; + uint16_t item_token_index = item.json_token_index; parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - object_get_value(&json_all, token_index_json, "args", &token_index); + object_get_value(&json_all, item_token_index, "args", &token_index); array_get_nth_element(&json_all, token_index, 0, &token_index); *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("\"\""); @@ -344,22 +490,23 @@ static parser_error_t items_rotateToDisplayString(uint16_t token_index_json, cha return parser_ok; } -static parser_error_t items_gasToDisplayString(uint16_t token_index, char *outVal, uint16_t *outValLen) { +static parser_error_t items_gasToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { char gasLimit[10]; uint8_t gasLimit_len = 0; char gasPrice[64]; uint8_t gasPrice_len = 0; parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - uint16_t meta_token_index = token_index; + uint16_t item_token_index = item.json_token_index; + uint16_t meta_token_index = item_token_index; - parser_getJsonValue(&token_index, JSON_GAS_LIMIT); - gasLimit_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start + 1; - snprintf(gasLimit, gasLimit_len, "%s", json_all.buffer + json_all.tokens[token_index].start); + parser_getJsonValue(&item_token_index, JSON_GAS_LIMIT); + gasLimit_len = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; + snprintf(gasLimit, gasLimit_len, "%s", json_all.buffer + json_all.tokens[item_token_index].start); - token_index = meta_token_index; - parser_getJsonValue(&token_index, JSON_GAS_PRICE); - gasPrice_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start + 1; - snprintf(gasPrice, gasPrice_len, "%s", json_all.buffer + json_all.tokens[token_index].start); + item_token_index = meta_token_index; + parser_getJsonValue(&item_token_index, JSON_GAS_PRICE); + gasPrice_len = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; + snprintf(gasPrice, gasPrice_len, "%s", json_all.buffer + json_all.tokens[item_token_index].start); *outValLen = gasLimit_len + gasPrice_len + sizeof("at most ") + sizeof(" at price "); snprintf(outVal, *outValLen, "at most %s at price %s", gasLimit, gasPrice); @@ -367,20 +514,21 @@ static parser_error_t items_gasToDisplayString(uint16_t token_index, char *outVa return parser_ok; } -static parser_error_t items_hashToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen) { +static parser_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { *outValLen = sizeof(base64_hash); snprintf(outVal, *outValLen, "%s", base64_hash); return parser_ok; } -static parser_error_t items_unknownCapabilityToDisplayString(uint16_t token_index_json, char *outVal, uint16_t *outValLen) { +static parser_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { uint16_t token_index = 0; uint16_t args_count = 0; uint8_t len = 0; uint8_t outVal_idx= 0; parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t item_token_index = item.json_token_index; - object_get_value(&json_all, token_index_json, "name", &token_index); + object_get_value(&json_all, item_token_index, "name", &token_index); len = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("name: "); snprintf(outVal, len, "name: %s", json_all.buffer + json_all.tokens[token_index].start); outVal_idx += len; @@ -392,38 +540,51 @@ static parser_error_t items_unknownCapabilityToDisplayString(uint16_t token_inde outVal[outVal_idx] = ' '; outVal_idx++; - object_get_value(&json_all, token_index_json, "args", &token_index); + if (!item.can_display) { + len = sizeof("args cannot be displayed on Ledger"); + snprintf(outVal + outVal_idx, len, "args cannot be displayed on Ledger"); + outVal_idx += len; + return parser_ok; + } + + object_get_value(&json_all, item_token_index, "args", &token_index); array_get_element_count(&json_all, token_index, &args_count); - uint16_t args_token_index = 0; - for (uint8_t i = 0; i < args_count - 1; i++) { - array_get_nth_element(&json_all, token_index, i, &args_token_index); + + if (args_count) { + uint16_t args_token_index = 0; + for (uint8_t i = 0; i < args_count - 1; i++) { + array_get_nth_element(&json_all, token_index, i, &args_token_index); + if (json_all.tokens[args_token_index].type == JSMN_STRING) { + // Strings go in between double quotes + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\","); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\",", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); + } else { + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: ,"); + snprintf(outVal + outVal_idx, len, "arg %d: %s,", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); + } + outVal_idx += len; + + // Remove null terminator + outVal[outVal_idx - 1] = ' '; + } + + // Last arg (without comma) + array_get_nth_element(&json_all, token_index, args_count - 1, &args_token_index); if (json_all.tokens[args_token_index].type == JSMN_STRING) { - // Strings go in between double quotes - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\","); - snprintf(outVal + outVal_idx, len, "arg %d: \"%s\",", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\""); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\"", args_count, json_all.buffer + json_all.tokens[args_token_index].start); } else { - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: ,"); - snprintf(outVal + outVal_idx, len, "arg %d: %s,", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: "); + snprintf(outVal + outVal_idx, len, "arg %d: %s", args_count, json_all.buffer + json_all.tokens[args_token_index].start); } outVal_idx += len; - - // Remove null terminator - outVal[outVal_idx - 1] = ' '; - } - - // Last arg (without comma) - array_get_nth_element(&json_all, token_index, args_count - 1, &args_token_index); - if (json_all.tokens[args_token_index].type == JSMN_STRING) { - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\""); - snprintf(outVal + outVal_idx, len, "arg %d: \"%s\"", args_count, json_all.buffer + json_all.tokens[args_token_index].start); } else { - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: "); - snprintf(outVal + outVal_idx, len, "arg %d: %s", args_count, json_all.buffer + json_all.tokens[args_token_index].start); + len = sizeof("no args"); + snprintf(outVal + outVal_idx, len, "no args"); + outVal_idx += len; } - outVal_idx += len; - *outValLen = outVal_idx; return parser_ok; diff --git a/app/src/items.h b/app/src/items.h index b43c5b5..96aa2eb 100644 --- a/app/src/items.h +++ b/app/src/items.h @@ -23,14 +23,20 @@ typedef struct { char key[25]; uint16_t json_token_index; - parser_error_t (*toString)(uint16_t token_index, char *outVal, uint16_t *outValLen); + bool can_display; } item_t; typedef struct { item_t items[20]; uint8_t numOfItems; + parser_error_t (*toString[20])(item_t item, char *outVal, uint16_t *outValLen); } item_array_t; +typedef enum { + items_ok, + items_error, +} items_error_t; + void items_initItems(); void items_storeItems(); uint16_t items_getTotalItems(); diff --git a/app/src/parser.c b/app/src/parser.c index 98de973..2415c9b 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -107,7 +107,7 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c cleanOutput(outKey, outKeyLen, outVal, outValLen); snprintf(outKey, outKeyLen, "%s", item_array->items[displayIdx].key); - item_array->items[displayIdx].toString(item_array->items[displayIdx].json_token_index, outVal, &outValLen); + item_array->toString[displayIdx](item_array->items[displayIdx], outVal, &outValLen); return parser_ok; } diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 334ac1b..e79eb87 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -68,8 +68,13 @@ parser_error_t parser_findKeyInClist(uint16_t key_token_index) { CHECK_ERROR(array_get_element_count(json_all, args_token_index, &number_of_args)); for (uint16_t j = 0; j < number_of_args; j++) { array_get_nth_element(json_all, args_token_index, j, &token_index); + uint8_t offset = 0; + // Take into account the "k:" notation for the key + if (MEMCMP("k:", json_all->buffer + json_all->tokens[token_index].start, 2) == 0) { + offset = 2; + } if (MEMCMP(json_all->buffer + json_all->tokens[key_token_index].start, - json_all->buffer + json_all->tokens[token_index].start, + json_all->buffer + json_all->tokens[token_index].start + offset, json_all->tokens[key_token_index].end - json_all->tokens[key_token_index].start) == 0) { return parser_ok; } @@ -79,14 +84,13 @@ parser_error_t parser_findKeyInClist(uint16_t key_token_index) { return parser_no_data; } - parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key) { parsed_json_t json_obj; uint16_t token_index = 0; CHECK_ERROR(object_get_value(&parser_tx_obj.tx_json.json, *json_token_index, key, &token_index)); - json_parse(&json_obj, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); + CHECK_ERROR(json_parse(&json_obj, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start)); if (MEMCMP("null", json_obj.buffer, json_obj.bufferLen) == 0) { return parser_no_data; @@ -116,10 +120,36 @@ parser_error_t parser_getGasObject(uint16_t *json_token_index) { return parser_no_data; } -parser_error_t parser_getChainId(parsed_json_t *json_obj) { - uint16_t token_index = 0; - object_get_value(&parser_tx_obj.tx_json.json, 0, "chainId", &token_index); - json_parse(json_obj, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start); +parser_error_t parser_validateMetaField() { + char *keywords[20] = { + JSON_CREATION_TIME, + JSON_TTL, + JSON_GAS_LIMIT, + JSON_CHAIN_ID, + JSON_GAS_PRICE, + JSON_SENDER + }; + char meta_curr_key[20]; + uint16_t meta_token_index = 0; + uint16_t meta_num_elements = 0; + uint16_t key_token_idx = 0; + + if (parser_getJsonValue(&meta_token_index, JSON_META) == parser_ok) { + object_get_element_count(&parser_tx_obj.tx_json.json, meta_token_index, &meta_num_elements); + for (uint16_t i = 0; i < meta_num_elements; i++) { + object_get_nth_key(&parser_tx_obj.tx_json.json, meta_token_index, i, &key_token_idx); + + MEMCPY(meta_curr_key, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[key_token_idx].start, + parser_tx_obj.tx_json.json.tokens[key_token_idx].end - parser_tx_obj.tx_json.json.tokens[key_token_idx].start); + meta_curr_key[parser_tx_obj.tx_json.json.tokens[key_token_idx].end - parser_tx_obj.tx_json.json.tokens[key_token_idx].start] = '\0'; + + if (strcmp(keywords[i], meta_curr_key) != 0) { + return parser_invalid_meta_field; + } + + MEMZERO(meta_curr_key, sizeof(meta_curr_key)); + } + } return parser_ok; } diff --git a/app/src/parser_impl.h b/app/src/parser_impl.h index 30f74b0..bb7a5d4 100644 --- a/app/src/parser_impl.h +++ b/app/src/parser_impl.h @@ -27,14 +27,17 @@ extern "C" { #define JSON_NETWORK_ID "networkId" #define JSON_META "meta" -#define JSON_SENDER "sender" -#define JSON_CHAIN_ID "chainId" -#define JSON_GAS_LIMIT "gasLimit" -#define JSON_GAS_PRICE "gasPrice" #define JSON_SIGNERS "signers" +#define JSON_PUBKEY "pubKey" #define JSON_CLIST "clist" #define JSON_ARGS "args" #define JSON_NAME "name" +#define JSON_CREATION_TIME "creationTime" +#define JSON_TTL "ttl" +#define JSON_CHAIN_ID "chainId" +#define JSON_GAS_LIMIT "gasLimit" +#define JSON_GAS_PRICE "gasPrice" +#define JSON_SENDER "sender" typedef struct { const uint8_t *buffer; uint16_t bufferLen; @@ -53,7 +56,7 @@ parser_error_t parser_findKeyInClist(uint16_t key_token_index); uint16_t parser_getNumberOfTransfers(); parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key); parser_error_t parser_getGasObject(uint16_t *json_token_index); -parser_error_t parser_getChainId(parsed_json_t *json_obj); +parser_error_t parser_validateMetaField(); #ifdef __cplusplus } diff --git a/tests/testcases.json b/tests/testcases.json index e76d7c5..9ed090b 100644 --- a/tests/testcases.json +++ b/tests/testcases.json @@ -115,6 +115,64 @@ }, { "index": 4, + "name": "Simple_transfer_create", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B22726563702D6B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637225D7D7D2C22636F6465223A2228636F696E2E7472616E736665722D637265617465205C22653461316232393830633038366334353531616237643231343863663536653937373463363465623836663739356435666438336533396363666432656336365C22205C22383735653434393365313963383732313538336266623436663037363866313032363665626363613333633461306530346263303939613730343461393066375C222028726561642D6B6579736574205C22726563702D6B735C222920342E393833343034383829227D7D2C227369676E657273223A5B7B227075624B6579223A2265346131623239383063303836633435353161623764323134386366353665393737346336346562383666373935643566643833653339636366643265633636222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2265346131623239383063303836633435353161623764323134386366353665393737346336346562383666373935643566643833653339636366643265633636222C2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637222C342E39383334303438385D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393134322C2274746C223A32383830302C226761734C696D6974223A36303030302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2265346131623239383063303836633435353161623764323134386366353665393737346336346562383666373935643566643833653339636366643265633636227D2C226E6F6E6365223A225C22313633343030393135363934335C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : e4a1b2980c086c4551ab7d2148cf56e9774c64eb86f795d5fd83e39ccfd2ec66", + "4 | Paying Gas : ", + "5 | Transfer 1 : 4.98340488 from \"e4a1b2980c086c4551ab7d2148cf56e9774c64eb86f795d5fd83e39ccfd2ec66\" to \"875e4493e19c8721583bfb46f0768f10266ebcca33c4a0e04bc099a7044a90f7\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 60000 at price 1.0e-6", + "8 | Transaction hash : SrjHkjfzLHLiOS-5_lcZvLOhiU42NynfAfezMzbeXsw", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : e4a1b2980c086c4551ab7d2148cf56e9774c64eb86f795d5fd83e39ccfd2ec66", + "4 | Paying Gas : ", + "5 | Transfer 1 : 4.98340488 from \"e4a1b2980c086c4551ab7d2148cf56e9774c64eb86f795d5fd83e39ccfd2ec66\" to \"875e4493e19c8721583bfb46f0768f10266ebcca33c4a0e04bc099a7044a90f7\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 60000 at price 1.0e-6", + "8 | Transaction hash : SrjHkjfzLHLiOS-5_lcZvLOhiU42NynfAfezMzbeXsw", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 5, + "name": "Second_transfer_create", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B22726563702D6B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637225D7D7D2C22636F6465223A2228636F696E2E7472616E736665722D637265617465205C22373335383066666233653563613938353934343233393564346331636230626633616134653732343635363463653934336237616535303862336565376330335C22205C22383735653434393365313963383732313538336266623436663037363866313032363665626363613333633461306530346263303939613730343461393066375C222028726561642D6B6579736574205C22726563702D6B735C222920342E383930393334353529227D7D2C227369676E657273223A5B7B227075624B6579223A2237333538306666623365356361393835393434323339356434633163623062663361613465373234363536346365393433623761653530386233656537633033222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2237333538306666623365356361393835393434323339356434633163623062663361613465373234363536346365393433623761653530386233656537633033222C2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637222C342E38393039333435355D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393039382C2274746C223A32383830302C226761734C696D6974223A36303030302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2237333538306666623365356361393835393434323339356434633163623062663361613465373234363536346365393433623761653530386233656537633033227D2C226E6F6E6365223A225C22313633343030393131333037335C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 73580ffb3e5ca9859442395d4c1cb0bf3aa4e7246564ce943b7ae508b3ee7c03", + "4 | Paying Gas : ", + "5 | Transfer 1 : 4.89093455 from \"73580ffb3e5ca9859442395d4c1cb0bf3aa4e7246564ce943b7ae508b3ee7c03\" to \"875e4493e19c8721583bfb46f0768f10266ebcca33c4a0e04bc099a7044a90f7\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 60000 at price 1.0e-6", + "8 | Transaction hash : pJsk0-vgbqfzOBFc4zHtFMSMa0aCZpXBZ_QQFxox1-k", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 73580ffb3e5ca9859442395d4c1cb0bf3aa4e7246564ce943b7ae508b3ee7c03", + "4 | Paying Gas : ", + "5 | Transfer 1 : 4.89093455 from \"73580ffb3e5ca9859442395d4c1cb0bf3aa4e7246564ce943b7ae508b3ee7c03\" to \"875e4493e19c8721583bfb46f0768f10266ebcca33c4a0e04bc099a7044a90f7\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 60000 at price 1.0e-6", + "8 | Transaction hash : pJsk0-vgbqfzOBFc4zHtFMSMa0aCZpXBZ_QQFxox1-k", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 6, "name": "Transfer_with_2_args", "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432225D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", "output": [ @@ -143,7 +201,239 @@ ] }, { - "index": 5, + "index": 7, + "name": "Rotate_transaction", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933225D7D7D2C22636F6465223A2228636F696E2E726F74617465205C22643333303064323834663462636662633931353535313834656630323661333536653537666630666139376235653663393833303735303839326364333039335C222028726561642D6B6579736574205C226B735C222929227D7D2C227369676E657273223A5B7B227075624B6579223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933225D2C226E616D65223A22636F696E2E524F54415445227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633333436363736342C2274746C223A32383830302C226761734C696D6974223A313530302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663227D2C226E6F6E6365223A225C22313633333436363736345C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 81b4511b257fb975dace13e823c257c17ac6a695da65f91b6036d6e1429268fc", + "4 | Paying Gas : ", + "5 | Rotate for account : \"d3300d284f4bcfbc91555184ef026a356e57ff0fa97b5e6c9830750892cd3093\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 1500 at price 1.0e-5", + "8 | Transaction hash : WQImvdxCaI7U5Qy2U_3Mxoa3i-Lp-PyNu9aZNtXclHo", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 81b4511b257fb975dace13e823c257c17ac6a695da65f91b6036d6e1429268fc", + "4 | Paying Gas : ", + "5 | Rotate for account : \"d3300d284f4bcfbc91555184ef026a356e57ff0fa97b5e6c9830750892cd3093\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 1500 at price 1.0e-5", + "8 | Transaction hash : WQImvdxCaI7U5Qy2U_3Mxoa3i-Lp-PyNu9aZNtXclHo", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 8, + "name": "Rotate_with_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933225D7D7D2C22636F6465223A2228636F696E2E726F74617465205C22643333303064323834663462636662633931353535313834656630323661333536653537666630666139376235653663393833303735303839326364333039335C222028726561642D6B6579736574205C226B735C222929227D7D2C227369676E657273223A5B7B227075624B6579223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933222C6E756C6C5D2C226E616D65223A22636F696E2E524F54415445227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633333436363736342C2274746C223A32383830302C226761734C696D6974223A313530302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663227D2C226E6F6E6365223A225C22313633333436363736345C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 81b4511b257fb975dace13e823c257c17ac6a695da65f91b6036d6e1429268fc", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: coin.ROTATE, arg 1: \"d3300d284f4bcfbc91555184ef026a356e57ff0fa97b5e6c9830750892cd3093\", arg 2: null", + "6 | On Chain : 0", + "7 | Using Gas : at most 1500 at price 1.0e-5", + "8 | Transaction hash : Rr78KvlVRiX59dDOqZFaK9vgW6GzgMss13p67yGOkN4", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 81b4511b257fb975dace13e823c257c17ac6a695da65f91b6036d6e1429268fc", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: coin.ROTATE, arg 1: \"d3300d284f4bcfbc91555184ef026a356e57ff0fa97b5e6c9830750892cd3093\", arg 2: null", + "6 | On Chain : 0", + "7 | Using Gas : at most 1500 at price 1.0e-5", + "8 | Transaction hash : Rr78KvlVRiX59dDOqZFaK9vgW6GzgMss13p67yGOkN4", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 9, + "name": "Transaction_with_no_capabilities", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A22286E6F742D636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Unscoped Signer : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "5 | WARNING : UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds.", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : EsF-vcYfXYn8-NpYIvBcOMYCfUxiV6wxECU5FWNFz5g", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Unscoped Signer : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "5 | WARNING : UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds.", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : EsF-vcYfXYn8-NpYIvBcOMYCfUxiV6wxECU5FWNFz5g", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 10, + "name": "Transaction_with_clist_null", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A22286E6F742D636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A6E756C6C7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Unscoped Signer : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "5 | WARNING : UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds.", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : 0j8JyVmew5_ibulW2WO-OXb9j5woNPX1T9Y1BQQvmFM", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Unscoped Signer : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "5 | WARNING : UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds.", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : 0j8JyVmew5_ibulW2WO-OXb9j5woNPX1T9Y1BQQvmFM", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 11, + "name": "k_account_names", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2264666462333839363931393534343439303633376330666432663334663862663434363364343136666264393135393930633861313336623161393730636135225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D637265617465205C226B3A623961633363613535353963633666333934656130653331633131626531366566643663366666363830346239386365376365653439366263636139363136345C22205C226B3A646664623338393639313935343434393036333763306664326633346638626634343633643431366662643931353939306338613133366231613937306361355C222028726561642D6B6579736574205C226B735C222920322E3029227D7D2C227369676E657273223A5B7B22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E53464552222C2261726773223A5B226B3A62396163336361353535396363366633393465613065333163313162653136656664366336666636383034623938636537636565343936626363613936313634222C226B3A64666462333839363931393534343439303633376330666432663334663862663434363364343136666264393135393930633861313336623161393730636135222C325D7D5D2C227075624B6579223A2262396163336361353535396363366633393465613065333163313162653136656664366336666636383034623938636537636565343936626363613936313634227D5D2C226D657461223A7B226372656174696F6E54696D65223A313634313333313232302C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A226B3A62396163336361353535396363366633393465613065333163313162653136656664366336666636383034623938636537636565343936626363613936313634227D2C226E6F6E6365223A225C225C5C5C22323032322D30312D30345432313A32313A32302E3434305A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : b9ac3ca5559cc6f394ea0e31c11be16efd6c6ff6804b98ce7cee496bcca96164", + "4 | Paying Gas : ", + "5 | Transfer 1 : 2 from \"k:b9ac3ca5559cc6f394ea0e31c11be16efd6c6ff6804b98ce7cee496bcca96164\" to \"k:dfdb3896919544490637c0fd2f34f8bf4463d416fbd915990c8a136b1a970ca5\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : 9VlNQ6wmY5UpfOcazQNGpBZDt9Cd_sl_DO0POpiBDvU", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : b9ac3ca5559cc6f394ea0e31c11be16efd6c6ff6804b98ce7cee496bcca96164", + "4 | Paying Gas : ", + "5 | Transfer 1 : 2 from \"k:b9ac3ca5559cc6f394ea0e31c11be16efd6c6ff6804b98ce7cee496bcca96164\" to \"k:dfdb3896919544490637c0fd2f34f8bf4463d416fbd915990c8a136b1a970ca5\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : 9VlNQ6wmY5UpfOcazQNGpBZDt9Cd_sl_DO0POpiBDvU", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 12, + "name": "basic_cross_chain", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E534645525F58434841494E222C2261726773223A5B226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C312E302C2230225D7D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Transfer 1 : Cross-chain 1.0 from \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to chain \"0\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : nw3YtHZ5EgogG2oQ9JbOOEqyhy7IN4cevGjdEKuWgQM", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Transfer 1 : Cross-chain 1.0 from \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to chain \"0\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : nw3YtHZ5EgogG2oQ9JbOOEqyhy7IN4cevGjdEKuWgQM", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 13, + "name": "decimal_cross_chain", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E534645525F58434841494E222C2261726773223A5B226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C7B22646563696D616C223A223132333435363738392E30313233343536373839227D2C2230225D7D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Transfer 1 : Cross-chain {\"decimal\":\"123456789.0123456789\"} from \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to chain \"0\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : gaYu1-LR6N9V0bUt1u_N9p4cbm_dwy7IeHC52rD92gs", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Transfer 1 : Cross-chain {\"decimal\":\"123456789.0123456789\"} from \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to chain \"0\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : gaYu1-LR6N9V0bUt1u_N9p4cbm_dwy7IeHC52rD92gs", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 14, + "name": "cross_chain_not_4_args", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E534645525F58434841494E222C2261726773223A5B226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C7B22646563696D616C223A223132333435363738392E30313233343536373839227D2C2230222C747275655D7D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: coin.TRANSFER_XCHAIN, arg 1: \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\", arg 2: \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\", arg 3: {\"decimal\":\"123456789.0123456789\"}, arg 4: \"0\", arg 5: true", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : LY8HM_kQ2nRO7Wl0PD9flhbibi0K1CXxv27KmlDBQmo", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: coin.TRANSFER_XCHAIN, arg 1: \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\", arg 2: \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\", arg 3: {\"decimal\":\"123456789.0123456789\"}, arg 4: \"0\", arg 5: true", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash : LY8HM_kQ2nRO7Wl0PD9flhbibi0K1CXxv27KmlDBQmo", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 15, "name": "Multiple_transfers", "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646661222C315D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646662222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646663222C335D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", "output": [ @@ -176,6 +466,348 @@ "11 | Transaction hash : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOREfZhk", "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] + }, + { + "index": 16, + "name": "Multiple_cross_chain_transfers", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646661222C315D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646662222C322C2233225D2C226E616D65223A22636F696E2E5452414E534645525F58434841494E227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646663222C332C2232225D2C226E616D65223A22636F696E2E5452414E534645525F58434841494E227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 : 1 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfa\"", + "6 | Transfer 2 : Cross-chain 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfb\" to chain \"3\"", + "7 | Transfer 3 : Cross-chain 3 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfc\" to chain \"2\"", + "8 | Transfer 4 : 4 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "9 | On Chain : 0", + "10 | Using Gas : at most 600 at price 1.0e-6", + "11 | Transaction hash : AoXqSSMScM_u4glsmLV3C8Eawexbm2YEFgFMHYFzm4o", + "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 : 1 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfa\"", + "6 | Transfer 2 : Cross-chain 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfb\" to chain \"3\"", + "7 | Transfer 3 : Cross-chain 3 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfc\" to chain \"2\"", + "8 | Transfer 4 : 4 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", + "9 | On Chain : 0", + "10 | Using Gas : at most 600 at price 1.0e-6", + "11 | Transaction hash : AoXqSSMScM_u4glsmLV3C8Eawexbm2YEFgFMHYFzm4o", + "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 17, + "name": "meta_field_missing", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B22756E6B6E6F776E2D6669656C64223A747275652C226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", + "6 | CAUTION : 'meta' field of transaction not recognized", + "7 | Transaction hash : fysHQicr1iPz-sbSntIM3Rx_Iw_agBhRxt-XL9X7ENk", + "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", + "6 | CAUTION : 'meta' field of transaction not recognized", + "7 | Transaction hash : fysHQicr1iPz-sbSntIM3Rx_Iw_agBhRxt-XL9X7ENk", + "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 18, + "name": "arbitrary_cap_with_no_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B5D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, no args", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : hnaoFEVgtSMrwKbm2Ui4wnARtUwMo6rtB3fnvZGb8oE", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, no args", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : hnaoFEVgtSMrwKbm2Ui4wnARtUwMo6rtB3fnvZGb8oE", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 19, + "name": "arbitrary_cap_with_one_arg", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930225D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : kQqVYwYzDNSKqcRwJ3Yd4xgG2UW9j2sdcupQx-T6XEY", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : kQqVYwYzDNSKqcRwJ3Yd4xgG2UW9j2sdcupQx-T6XEY", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 20, + "name": "arbitrary_cap_with_two_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267225D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : ONXn9kz2V9InGB-RddO3kUCy-GHQOEs8jRYqO2vzxuY", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : ONXn9kz2V9InGB-RddO3kUCy-GHQOEs8jRYqO2vzxuY", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 21, + "name": "arbitrary_cap_with_two_args_one_num", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267222C32322E325D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 22.2", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : OEV1W2Adz7vvU3qYzV9V48pDhxRdFDi2KG4JXx73WTA", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 22.2", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : OEV1W2Adz7vvU3qYzV9V48pDhxRdFDi2KG4JXx73WTA", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 22, + "name": "arbitrary_cap_with_various_json_types", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B7B226B657931223A7B226B657932223A2276616C32227D2C226B657933223A2D322E34362C226B657934223A7B226B657935223A747275652C226B657936223A7B226B657937223A302E30317D2C226B657938223A5B2261222C66616C73652C6E756C6C2C392C31302E32332C2D35382E32345D7D7D2C7B7D2C5B5D2C66616C73652C6E756C6C5D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: {\"key1\":{\"key2\":\"val2\"},\"key3\":-2.46,\"key4\":{\"key5\":true,\"key6\":{\"key7\":0.01},\"key8\":[\"a\",false,null,9,10.23,-58.24]}}, arg 2: {}, arg 3: [], arg 4: false, arg 5: null", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : 5RygRqoczKtecEebMtaPLrulHa5aprNcjkRhMAAogNc", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: {\"key1\":{\"key2\":\"val2\"},\"key3\":-2.46,\"key4\":{\"key5\":true,\"key6\":{\"key7\":0.01},\"key8\":[\"a\",false,null,9,10.23,-58.24]}}, arg 2: {}, arg 3: [], arg 4: false, arg 5: null", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash : 5RygRqoczKtecEebMtaPLrulHa5aprNcjkRhMAAogNc", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 23, + "name": "multiple_arbitrary_caps", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B5D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455230227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455231227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455232227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267222C32322E325D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455233227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267222C353030302C32322E325D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455234227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", + "6 | Unknown Capability 2 : name: mycoin.MY_TRANSFER1, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", + "7 | Unknown Capability 3 : name: mycoin.MY_TRANSFER2, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\"", + "8 | Unknown Capability 4 : name: mycoin.MY_TRANSFER3, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 22.2", + "9 | Unknown Capability 5 : name: mycoin.MY_TRANSFER4, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 5000, arg 4: 22.2", + "10 | On Chain : 0", + "11 | Using Gas : at most 600 at price 1.0e-5", + "12 | Transaction hash : QJDO0ks635Xpnq2GC85cqoQUxLgESujMgun7NUgrf5E", + "13 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", + "6 | Unknown Capability 2 : name: mycoin.MY_TRANSFER1, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", + "7 | Unknown Capability 3 : name: mycoin.MY_TRANSFER2, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\"", + "8 | Unknown Capability 4 : name: mycoin.MY_TRANSFER3, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 22.2", + "9 | Unknown Capability 5 : name: mycoin.MY_TRANSFER4, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 5000, arg 4: 22.2", + "10 | On Chain : 0", + "11 | Using Gas : at most 600 at price 1.0e-5", + "12 | Transaction hash : QJDO0ks635Xpnq2GC85cqoQUxLgESujMgun7NUgrf5E", + "13 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 24, + "name": "multiple_arbitrary_caps_multiple_transfers", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B5D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455230227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455231227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373931222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373931222C32322E322C2234225D2C226E616D65223A22636F696E2E5452414E534645525F58434841494E227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373932222C353030302C2230225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455234227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", + "6 | Unknown Capability 2 : name: mycoin.MY_TRANSFER1, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", + "7 | Transfer 1 : 4 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471791\"", + "8 | Transfer 2 : Cross-chain 22.2 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471791\" to chain \"4\"", + "9 | Unknown Capability 3 : name: mycoin.MY_TRANSFER4, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471792\", arg 3: 5000, arg 4: \"0\"", + "10 | On Chain : 0", + "11 | Using Gas : at most 600 at price 1.0e-5", + "12 | Transaction hash : yMXcVG1vcnLrbtdiKHI1MAYgrBgoDqr15YSRID70DyU", + "13 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", + "6 | Unknown Capability 2 : name: mycoin.MY_TRANSFER1, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", + "7 | Transfer 1 : 4 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471791\"", + "8 | Transfer 2 : Cross-chain 22.2 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471791\" to chain \"4\"", + "9 | Unknown Capability 3 : name: mycoin.MY_TRANSFER4, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471792\", arg 3: 5000, arg 4: \"0\"", + "10 | On Chain : 0", + "11 | Using Gas : at most 600 at price 1.0e-5", + "12 | Transaction hash : yMXcVG1vcnLrbtdiKHI1MAYgrBgoDqr15YSRID70DyU", + "13 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 25, + "name": "arbitrary_caps_large_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C226164666173222C342C352C362C372C385D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, args cannot be displayed on Ledger", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | WARNING : Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?", + "9 | Transaction hash : Y2q38WX4sd5fWzw2knr7mfAltsaYxhWnDGtFaZ7NV40", + "10 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, args cannot be displayed on Ledger", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | WARNING : Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?", + "9 | Transaction hash : Y2q38WX4sd5fWzw2knr7mfAltsaYxhWnDGtFaZ7NV40", + "10 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 26, + "name": "large_json", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B7B2268617368223A224453395F587857495239416D38584333584541374A39396B546431354F614259486C6834506A5849707A38222C2264617461223A5B7B22646174756D223A7B22746F6B656E5F74797065223A224365727469666963617465206F662041757468656E746963697479222C226E616D65223A22544E20434F41222C226372656174696F6E5F64617465223A22323032322D30312D3031222C226465736372697074696F6E223A224420434F41222C2270726F70657274696573223A7B22417574686F725F746F5F43657274696669636174655F6F665F41757468656E746963697479223A226174636F61227D2C2261737365745F75726C223A2268747470733A2F2F646E612D746F6B656E732D746573742E73332E75732D656173742D322E616D617A6F6E6177732E636F6D2F7075626C69632F336538633865363833633339626463396632643337353535383365303562333366626436623234646465393564613061393564323065653239643338376632612F36613132303038662D353738362D343961372D616337312D3833633863336335363939322F6D61696E5F61737365742E6A706567227D2C2268617368223A22556E6847325848462D336947624B7944333062484B44506F5F4A6D547A5865484C645F50774432747A4E59222C22757269223A7B22736368656D65223A22636F6E74726163742E736368656D61222C2264617461223A22706163743A736368656D61227D2C22757269223A7B22736368656D65223A22696D6167652F6A7065673B626173653634222C2264617461223A222F396A2F34414151536B5A4A5267414241514141415141424141442F3467496F53554E445831425354305A4A544555414151454141414959414141414141517741414274626E5279556B64434946685A576941414141414141414141414141414141426859334E77414141414141414141414141414141414141414141414141414141414141414141414141415141413974594141514141414144544C5141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141416C6B5A584E6A41414141384141414148527957466C61414141425A4141414142526E57466C6141414142654141414142526957466C61414141426A4141414142527956464A44414141426F4141414143686E56464A44414141426F4141414143686956464A44414141426F414141414368336448423041414142794141414142526A63484A304141414233414141414478746248566A4141414141414141414145414141414D5A57355655774141414667414141416341484D41556742484145494141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414146685A5769414141414141414142766F6741414F50554141414F5157466C61494141414141414141474B5A4141433368514141474E705957566F6741414141414141414A4B414141412B45414143327A334268636D45414141414141415141414141435A6D594141504B6E4141414E57514141453941414141706241414141414141414141425957566F6741414141414141413974594141514141414144544C57317364574D414141414141414141415141414141786C626C565441414141494141414142774152774276414738415A774273414755414941424A4147344159774175414341414D674177414445414E762F6241454D4141514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241662F6241454D4241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241662F4141424549414A344179414D4245514143455145444551482F78414165414141434177454241514542415141414141414141414147427755494351514441676F4241502F4541436F51414149444151454141674D4141674943417745424141514641674D4741516354464167534652455741434D4A4A4263684969556D2F3851414851454141674D424151454241514141414141414141414142515944424163434341454A41502F4541446B5241414D4241414943415151424241454342514D4342774543417751464552495442674155495349784278556A4D6B456B555167574D304A684A554E53596F4654564846796B6248772F396F4144414D4241414952417845415077443877617866626B613948324A335645627878712B304D7147346B5856386D7748506A4E5968366939554C43564854627850754678582F574750756C583934566358483038666A4F484D4D327A6B36586D3962352F744C38686842592B55577247625378364C78684852476250314E3656554C354C4B364A57735542392B7651436B6C57614B74467373744B795A4F774234714B6D486C33346B66674F52312B66456B41364766682F6A42505339315476476A4F746D362F6E303354712F74417A617141377A7877394330456A557452525869716737755857684E4654662B716B4B4E564266585A794530464A7A6C5938644C6A4D6F6C684E413179324C7877336A783164475448753379483771677977794C6C70734E4E73386459766C55496D344837625342625271693946466971644657633064616548585A57564730336531572F432B6B654963466943417652327051656655797A756556454F317469656B34624B5A3451616770584F316B4C6D37446557716A4D6763506D776253424C3765384F34706E6D4C702F73514B72702F59557133387750366F663841695A356A345038414D666B66413856774762417A5830303565396559315A366368616B5938324E526165534C514F534C536A3662366B306161543034476A7850486A506258715878332B6E37383578546367327679584F6C6254696B51567A746E765447464170755479566E4B7252356A7A6433567657656A3955472F4D663864764B4E48354C734F72466D507A7030515038413546714950796F437A55616E512F57586659596A3649654668414F6761434B727864455451497945315139775549683373496A4E464874332B6B6536667A7A6A3839647A55307455583053706D4E41636D64355A392B46394456664A66544E754E726855353936593957567256766F7A6F6D6B6E466E3939476A69392F5A4A5A51476B4F325A5659546F59754A7A64696F424339723266314250586C304F38506D334E614A634E4A6872776D537345664F4C6B444A615475556F5151614B7561505041475246515A425A49384D476F51615443326C6B524B2B76356675322F594B6C627358462F4865514D744F6A6B4D57434F485079523436476E4C4C782B39536D38596B4D3749725A725A37316F48563332337A316F33724E41484D6C766E524E764C375A726C6D5132716E6C4E4855703253796B6C6C634B69427569422B76354838666A5A5478447A5250702F4A30326630564F55395946626F422B754559724A726F6131594A792B444B757464714A4D3632556A6F7343375158737236547245514177744B673561534F6B734477622B73337A543550384C3450487950776E2B6E664E664C7276384149353844795043344768786C6F354C7457543837396E506A64644B38626D655764633530553466446F4C3664756E564C484871584878666A754735766E75546838692B56532B4D7A6878577266782F4A636E35585458727A306A464D4156745766484A4C516131586C6C4E74395A79595A634F725456433142667972387731506A6E70726B524F7153414B5848474A55782B3062636568656E4A747546574D61564B336C63653350684A384F5A5668694D7567367752735749654C5266554B44726678336B6E33596C70776152305A4D546D572F536468317A527A6F75306F764C696A65365661496B4A70335654374A5675454676754B69634E66646E6D646B644757722B44712B69555A6B71305A5565623330754775633958706E56716C624E4B4B7136794938456D76786E614C644D646C3834337A757174655230744D3161664A6B7636484A514862444765694F5472576D6359703656314E4E43706B564E7A71316C4B2B39516339376142477467446F744B336136772B4738687A656933783768744846523261487A66493957376973313661593538304E6272593177335437675A56724D58626B4E73306E6C77563472653265756D6E584D48354431647657466D6A5037684A38645A315658636959384E3874456C5A7148792B3155315038412B5665316B753157637953764A5A79656643726843796B326C2F5A6145445364336B37714B47417179347472493868736166415773436C613159736F6C565742567A737170725773592B42666B50384155787A38703476463868484C372B653576527A47763435386A307358343369317763436D57327A35586D79614F4D4878374850567630657966454C784245386464323348505A4D32354A69783852717678664A374D6A516C6C343663786F77314C666461546F6F7935353578424C2B35724251664A3362774C65514C775A4E464B6D2B3365595A5973737348454C77424E5A767A5837524A6831764F53465949732F645A4D6A586C5646703637365857516A774E792F376B4732324A54715979573851374F6752746C306672663464387530592F6A7462664B7562572B2B4F585267546D655234666A3461396C37584A6878504A61754C6C7866783766316F704362386E796E48384454546A5452574563334943764C6653774F5073614C504A4F727A6B5775325A4C5830474A6D7432397561415339764C2F4630544B62685356382B2B674772367338653950556B4D5164646C6D71674A4369306B787953374164644A50704641796936696878633033574E49467A4241354A3832494C4D497734583535782F644F4C496E71692F7750395475492B585877355069584B634E6F47756132504166494872385A30614E47744B737263546F35586A2B6235506C4D324A595258313168384D354B33336E48362F37766D3037754D2B2F6A32594C345A5530626C33544A30685A36345A3375726F44347369434C53795438663841536C30725759667365725249436A54436E6371514D2F6C4B646977646D6B317431757A6477754330574C4E304F636A71484E612F45695243325272586A39717049574D4C4A71466E704B7063762F6E3277394D42316D7071795931586277764A77356A6B736E49706F792B2F44727A5A2B576D634C63636C324E5768796375503558693771795A4B5A426C5364644D314F736D2B6E42697877727072657A617339566D6D617371305367634A625657704351626F5130307754534B32594E5630635A5A55514670676F6F4B744D616E3061706A357049434B564467627242726173737477316E6F363070797952545062443846566143787471744569323868444C43744A76562B754253696F7138375167584F5169714C325868666966473857495679386A54355475303657333530732B4A306C753163666C74397A74315963795A4F4376687A6136564845634E6C305A66647235476B392F4B2F646270374B2B726C4E463954534758524C464B58707453527565347237566E4E5A583065796A4B375A2F583750585230704F7A684161424B397448377477742B67637758366551553351544A6E6B7445787064756975543555464C2F58545674347346676F2F42314548656A32724B74307862417553327158515A6E55556D76334834506B4779766A586A35386C683433466A305A65576244484D747447657255306A4F642B572B58573058675963667733485A70344A35644D4E334A4C69305A495261764F554942625456386461316F72356156632B764B2F5A495757634E526E4E5041765853556B56526B6C576A6C5239434E586A54317A693352376C615A592B4A724A4C5455507445305A4D5858467663384853483045582B4F4E593848715A336C485A716E515979584C5A676D484A6E533739476E42653648466362786C654B586B783939796F676457684E484A38764C4C654B30767374716645726263343155666A5A367348483474467033336553743750556C724B37772B746171674F65552F4479564441416A39474B2B35622F6C66797A64722B78552B4A516C575764472F477076656B6D45324C62523343486C425A6967415453416851514D30356B3677527A4C4D595A6D52725A63476C59664A6F39736A584D676D6C6E6F7871687A5A7238777838373862707A4D4D642F6A65733239644B6164546362385830513471385A6B2B4F7A50723030356573744774384F6157737470475775735574736E5A4A517354473757456F36326D63374B33714E4B366D6478312F414B3245507A2B51415A6C51503967514F696534484C71494A6E464B4955756E516A6B4E413352323349594D54382F7741416643566E704B637962554F434977574C7539714D4B694D304A49306777776B4C6C77524256713578336E646F764854445057756A5642707275553257306374526F462F736C6850526E565550635A47584B61703433573276513031395765677757667A555870366F546F72797A54554756616B677A585255756F56584D3355683056724E34536774543754494574387A6F43796264694F2F2F6D4E4E415456596B2F74504344435745795639495649794C505756755A643458644C7451756963747968614B727872436B6F4E3959394453505A6A315A59424D64305461456254626B5871786E6B62323534786D3176747130705366334450363569654F5A36584C6E393373496C6C712B347150624B6A7A6E51675A306D776E2B6F56757977627859487936494B4E2B4F77535177415A424530474551347441666578724849574456506D746F6B35754E4F5A77496175796B632B4A51685A534D77383962544336446F61746945577043725932424833564D4F545A707A79386275305672504E6F7A4E4E4C696A576136415736304272367374744D355A526A462F612F7742766F6D374E782B656C4A5572545756713231363541493946704F61746279476453524E696F385653616A324B56524A71534638664D394B524C7646514256347A742F705A4C56397A5A446E51716756633257625539704C75756F7576456F376656765846444155674A666977314A3941355455686D34534738343344512F643269667257397061566534654D567A74374B67565A54424B55646C664B61774476596F7A425A476B2B676A7A3958396C576B7738596D48656562566F3268326D7458566B48636945703332574A6E2B5237542B4641385366707A69302B694C4534323479705252655346667949465576476B6D6A5A757147414B3044433869734A376E51696161786D526E38775A2F6F5632566F6F6847344742644E59684C634A6F6C506B745839765345347A3872322B356D49766F6156367047326650525A31553031657571695372792B7A4D38355661655671346C74463930594D396E4C5566776E4D5A32657338797365777232486B7A79507355744C777047746C526A4B73365430546830346F50327661735749624448764E425152304F59316D36395050684D79446C6B41526130623541634B79355532496E52776E2B654B69775A61704B474C6D304C7A57313063505A664C5A2B43346F486B4C5A634F7049776158472F634A6E6E4F65724D7A5A38556365336C67526D5856536B38724932664F32625A62506B78356B536F6839526164744669596E64544F77713164644A446F326E594B7851724A7336306373504A4F323156756F616C576E5257523249442B4D33734F50524D46563744464358394C67367969372F414F52582B57774F6B44624D71656B724C384472736B7537646C724658436273357A535836756E35716178547A62362F2B2B6854332F314E2B4A444C4B6357356D752F53697670624677764B36493462357948734C3379726C30466F736C4A375879794E5256435A5A3678506D656368473359544B4E467A53444961364D7169724D66785070613164314C45666E705556663841384142304F483062386366517377456873556D4D6D5936397143547965623852784F473071696C6D5661754D706D2F56614C557078514B4C7A725A4C6A42324E356A527143324668414563594D32737238562B6666472F6C6E47625532387A697A664973314B36386E7837647531636F764963646B363155315A467A786C7A764A3763306C6E576E45357542315869615A70713462334A6D76616374386575544A6A76584C64525056704771616A4D3764717156674F357A53732F44787070706B517651416558613065522F43507A4E6C6A667958382B61485A6E59455079644C73304C6E52734E4F4D7852504973636873706D4679377947647559436A6B67304D4B756B42374653334A2F58525159564D716337515A6D332F6943706C35502B6D75375A6B355450644D7649635A5A505A6D72476A39624B52434C445845746B736832786B495A6254304C3974795571706C797930513036462F5461314A664B4D735769555775665A457A445470362B6F7432704D4E46554A553550456E7756475A2B314C4141766A67323872655A7072303850526565444B574964786451663977652F7744726766537259667A78314335577331424A5264504153616F38414358664C5241776977634B2B6A73396E5A4C34615A726D5354386C6C4B6D42613859716474364D3936506F354E385748526D4969706B7336624B54364C694B2B78425A58585450514B524D3959756A743557536435757172312B6F3770725669522F7430553641485A62384262306669555A6F2F4C64504C7139666352557A42454562326B4C596F732B4C56317A565663614539434A666168384776424E4D663670566E7330325A5859784670544F4A775138385A70465250354877694C783738687333635279455634336B317A34654A32357552354444783973656A46796C4E7644592B427A7A7A706C6D63692F65323251774C64307A4C794170726A4C534774346162546C4D75617133744E4E45554C72584D65387A6578697634414C72565041456B6A2B65752F7255764F666B46677738786C474D333747496D717461684C654F55786F57376331676D32695774544D63717661756E525176424373312F73435755515137777156777854494B51427666482F7A722F77702F452F6C587947752F526C3477547952524E433562364D6D5363377A61613274756F2F42744E546D70455A55744452796D754F595553664534615631497859506D334F63564375504B6451576C486D5436552F436A7067382F77412B48355A7954306569573869584944696C58354F2F6C45704A386962676735424F61667164546F38754A5851794B46615A6F7A47716C414A4C49367368434259644777646D4664534B762F78634D4F305875754D5672416B5A636D39472F7742492F77436D6E2F6C746B4F5262374D4F444E677754354C4678577A4667354446624971797A684F4866614D34783434724661636C713431363673576E6A38632F586D6E79664B6874567162486D4E547A5164745256616E334454642F324D7A4F776D30694366796B3173696E7365776A396A6B35366770376A385038413749394461666559444139584432456155537A72476372724B7067574E77466B6961523442324D6546425271586374344E574D6556542F2B502B4F503957766C76473854384A356B34646373334A386A7A5338666C79386679756262494136583546655931797863767532357445345A4B31684C6C4868757A3634786E704769684C564C2F48636A37755A654C534C5A63325639467265734943705431724A656A34455670525A4E2B3358697A663841752F48313735585A366B484D69644233445A4851794257324E526864646D6871467046677863436F44776C4E33314B77694F364F2F7741644D4347495857466B4553684138595572707A6A666A3254357638627866494E4F32383755346A4261375453322B4B33654564466B70504877736A6B6D4B554D61526656704D4B4B3033494B66714D30526E6B32326A396F725047314A74316E31555069724870566F75716379416E366A755869414348527A356552737163725666446B78724C31726236643876737458514F554C66635159426B57314F625749794857674A534262326375633777746149366F5047746D58595A58773271714E6C4F456A77325262446A2B5371645256547434336A376334734B4B366961777873534A71377547724A594A5838483157446E396174484E5439784B6E48353838484B654C56504756586F416D5833556F305675682F774462574D4A6A767678374C4D575A2B4F694C64346E6351304A4757625457726F4E5075556B4B55695A714C54454B75686372767A424F75546B3567797132415A6D5734366C315455376D6F4E67476374725752726A7277504862654A315A5262377A6D48717564724C68666A382F48795736766279687949547A7A38686E6575486B636D476157334A58546966546D6B77716B75766B3574346675697A2F4141543432315642506946383130537A4F6A644251664E32414858624144386D34726E38764665664A496F39447A627644443170583971596C50663132626F4E494F65746F457157636E6D32712F714B4130794769786B373078524E4A4D72686E6B6E66624673684D7935622B672F4C62453348447134725877796F6A374D462B4A2B51374F536B6153555A6475656D6534655239307854547177533265764D755747564B5178504858336D3177306B56554B39774158314C5A524D656661364A76566577656C502F546D714B2F6B614676782B666F4C7833355A656538334F44636B4E6E4F61525A514C52417032543870684634516A3338533732613356464C4B6D514A4177424447565A77626879594A32336C624D4E54417859422F6B6C386F2F70507A322F2B6D2F4F386278755965345A744C53715A51347565486644504C413135614E484B55305A7A797244556D4A4C78532F47365679617556464A7149302B514E4D764A523176346147383358546D674A3266524A2F6234647942587631415239674241594E52657972416D7A32362F4B6678484E426C4C7A745736664D563634594B51794170514E3973753853786D76766F61324A486C4C6D687A323664715A6D70434B7A2F4146567967317552582F6342437438692F77424D6636456631482B502F4B7637357A657471526A793276646B356A6536636A74694E57483278782B76424C6A65587A38577576633265462B65355746755434726A38723449543470754D303533626E6566346E6B384351793553486E6E793572704936383074617874493272662B3578324E376174426D716B4D7553596F687A6F73725330374E4F626D62625A712B7658754C494535374C686A30467136307A696F466B6531354379367A6A676F4E766B78336875667261687748556B672F7A364C6144547831414A31374131702B692B6E4A6C3065726B4B2B6D6D6D454459303435593774734B5238564D556A6B6577684971714E667A4632684B4C464C353541794F5771747945684B53366A356456577147307768506854313166776F41366B6B426B38565967422F486F2F5378594B426E6F69397064706E6479675A4B32564949374C587168306775584A504C4D4E5A5A374B4A694F6C62566163795767574D62316F5639314A36792B6D7069796B6874364253342F67732B6941313850485679306444636862667A6D712B78636D445A6F4A396C5A352B5354684F4A3262375647596239584A61545430354D385346726A69624747303152764371434C685A536E444A6C393755385254317A6579392B72504A6E71796F6F364C6161466A2B464C44494174726D616C6176656A31566E6D726C514C596D6B5561324D62544C59784E6B3268424547745839764D5A5171417368587973526178592F455A525945344E74486C2B4E33507233616236755A7068665A374953692B794D35347055756A307738626832345A644C3630504A4743745058597A483373586C4235586A6143394A6C6E4531583245716E525066384173664F683756694F77663142503558766F6A363373384B38342F30727A5448494734674E7A6379534A654A4363653272776732636847476F674C5A2B7930347375466A535A4270634C4A73727638674B6932734A674A4C7266422F2F41496A666D48796A457A364F41656E336B4D47376C3234714F333063323779342B6D6A69703854585276647261353077595533634A696F6332764F6330396B4D584537743153552B503473577654474F6F5461643948716A656946344A4A2B3130316F6577717A485143316F516B763270526B565366706D3666425A6E5144584B43314B79655A73704572716F48737354306A6C44584363714A57513658487135364155774A6D6B4B4244725944394443734B726C7A355664506D542B6D763957666B6D766C636E48387662646C686E332B7235487235484C737258546D352B617254354E727A7A32506B78384C4C527A7646773439743934572B55536C4E4E766A6D546C5075487A6E766A6D4B434E54497A5772574E446D45434B4C50506D4F6D333279546354633661665A364B55556F45556C476B37653251624D7232594842433775323748737574556A2F542F414D5762566C4871797068524E2B6E494D4C7471697157437869396345617063757653446D4B52424D7970477A4E7558433674574B2F30382F706E7A472F3548384F6933794757626A2F6B4F4854796558354278484472794E786A336364546B4F4D467074724F6A5A664E4E754C347938374A37485A3971636E706657326F386C794754386F424334564574554E3458794738676A6A75526378372F414E56704D6969654C4D437275796B39487636724244525A656E305A686F387451744B487A4B38666F5862716762417A6D427742795A51717558584541554570726D647A49316E6564332B663855726F3056387A36344354467174363377364468385767567A6E704353786544765844494B574655706C564458446E6678464B2B5457362F56767153464E434A49615359567432397641412B434E306150332F414B71417A6678333564466567423139634F5774312F732B687843506C46594D596E69614579426C42386C6377614F7743716448313030642F5353494370784E554150774332777936336C52394A7A465056476D3839764A553471346B305074564E625171464F6956643374527462554D314F6965305A36305773794D7A58795A68434A726F545765624E6C775133466E386C6F77694B4C2B54526B5A4B4F7171656D3868354B50775035505A373650316162594B6A572B6264436F4668413670645A6E564B366B4F73455A7555446F6C4E4C6869476D4743716A4E4D796171486563342F614D3646415342622F52486F727370517743714938727838645571365948546F30344D7956615A6F326242475769516361615034654664364A4E733265516233547A7A74564930735168455971444D6B6C71516A4F657735506B794762764B49494834394B544C64412F735730544A582B5374302F78552F4775686B745631376878496255714155636B4143515170316B6B412B776C2F7445677A5A6C6D66796F776976594C4F4C78626151534C72416A447236584C536B75516E6D37354E2F556E6B50696E4A5A4E75506A736C655031354E2B57563274687A4233747031596B544A484E49366A46354A706650374C39374A62495A2F66435A324C63705446486B4D395A7A2F4150555778506B6F4A634B68565865374146566D4379466E4A4858536F417A6D614E714C68636C5666515567525A4B58414570304A476D2F454F796B786330517349735064335747444D394D376B4A5647774A534A5A6E314B364A4646466C464D714B6157486B722B70333959576850544A6551355358496246306574736D6C4F45305A635370555A72515A6375367642636664483166597A56644849366D6A71466C6F32684E4A62666A6E7861396172563832616D4F5A487666564536553644713173346B4B7969394659544F7330616D65467836534864653163516E6D43343452704B6E6C414443674D6F46655973564B466C43473076675A526F705242436B593565563273635932644669327A6B544B617162724C4C78756831594D333953755658586D706C72796434546E6D4779764C61642F49366A355156612F625A71636854546E616B325A6158595A6D63435863774A465765352F4575505850584F347A4A656839795334355A5A596866456543335753565370444438303952512F7A365344307162622B4D676A467063724D5655574A574B3134706A334F32374B746A497731494262585775457642366B465655584130466D416A6B41467774674F33575772467352774E512B4B664E655230527A633177764A32305537642B52342F496D4C6A2F7439383776523161575365722B35616442667648493538476D5A305473334972717070584D4735486849427447545A45516F714C574F7A3257325A6849716F37517A704F3076556578616371316C354A516A436E35525539347A34497378767353746C4B72536F5178644A6F656F367253375775564C657345423439746150546A4468743649324B6C357050554F714735566F78714A7645626836695071457233502B70487A486B75642F70787836386462343974347A6B632B585A386767352F74507954696E7A624D41785774386435584A36393736744E714A506E4F463072386A785279633377334A35636E41356E7835655036657979792B5543656B4F4E6B4A324F5371306A624E63506B704E6658726B732F5762357446644538645A71746B44566C617A536F422B665038767644715553454A384F54627131626C7A615176304457326B72524C795A325772726B5474355A576259554D47514454476F6973355748466C45774F394F4A654547342F3536362B4C3868797679663772376A695A7932594936704469556C695448792F48594B6C6C624E696C6F7A30342F5569576B397036387A504C78677963346D666B6B74544E736E4A496571686E5636325931556570446E64756C56573845375A47536174352F6C326F62466C2F686D51766C754B6368416E6A7671376C7A6370634161706F4B6F4C6F4950424D3459766B73664B726852654E6761686531734B37434F6B644971504841695849717A3767326F2F474533636F61577A71357A594B4F5A6966326D666B49624F4F4C35304A58496375336B5867367668664C74554E782F49767250756A7950465A2F5A4879476D45626959506B614145734435414D7A4141796F667A34676B467135775648526D7A677631394E4D73455050586C535854614A4A7848496753596E307053366D4D794C4C6844437865774E5733776F4B574646687352722B3247786F6E5A5130684B51355862587A4E7864484B566A7458666A6F395579356466474671343839564F686F614E47666A4F51686B545264625672355A557A57315370727A52573276546A634F312F6376666D766B4372426E436F354A36444D71304B2F6E2B50466B2F58782F68674F67517652484C7A3268377875385A766D527058776B616257466C61457373384D586E367A697A74444D706E5A32644931564A6E48744850716A5668786C4F6D2B7273415578666A79634B4E2F6236586A5743386277752F6B4D633535622B79766A396C783050546C6B62315A7A6E74777331612F3630576A46766F6D504E47486B4261617376386D5374526D36424939726F4B42542B517973773650594A42422B71352B7A334C474B525463427A3445634E574547514A3864635271544F6B79695456562F4D754F5845575844326B45546F58736D742F614466334C4F6D564C6C68586E542F414D51394E69635838597A63672F6C79454E484955302B7864454E506E4C694D3634565A64744A364B6F633757394E6E7935423553595A733063787A7158623464347071354D3036565450444A584A5667462B36397267504D73414435795677442B5654706766465239573538682F446C317373516F5A486A614244595A6E73345253785A4A487A684B5763554F75734E746F4A756B4B70576956634B67354A2B446870636171596957424253675151537163702F586234682F5448682F6976457478477A6D4778386268687A69347559347555654E302F3247644448624866733236484E75546157484376433864446A70787246655A3177306C354C46626964584B62646C35317A7846644F6973425658386A4E72315653676B305A736F436E7637697257382B6C684A356C443963587148342B36767878424A30335A597A71386B345A654A3243656D78766545534554664234485A566B4F2F354758474279574E3759522F614E6A5A5059744C6531574E703576572F36572F31302B4A2F50696E413563484B486679574854736C6770796575764559633251306854427647626E4D6D546A36766F39697967687A373757687679307878767864546B466368784737454670536A30514F6B47385961306F77645379465673486372305756624A4F73765A2F69543255563566536F797059347271646F697564497474786368544668594F6659326B6B417773684C6875714665577844354551716D32536636384236344553674F445564544B7A5A394848356B6775574D724E6D61733246447944387077753977792B314554513735415674374A654230764B4646724E3531302B4E3834472B6859654E6130436D53654C686D6D4C5338575A2F462F745537566770567731455777386747494868394D41675566527A506C736C745A626D6D6B6D73617355412F5A484543304557454572656C6D74494F46315951743978554F4B72726A37795A397548344C79565A38612B6E6E487A346A6C33327938626C7A2B327A7443764163655663756B3761684358444756372B7368376D6671692B654C554D4A4E507972556E376258576E472B7A51395848534C536B30596B4574354D6A7165695432786451436568332B5439664A344F3730747464614E44414149536B69674666726E2B6579676B4A442F42483536463173346352387576675155766F64636F357753754B2B68686156544F457763506D6C6342773854787473327957694770355135567475765A707973774D724C587748716D564A386270566F612F636E3279714A56376C45733356394654526151704F6476736B566C6A5A2F4D5751305257705A683472374A6F725569517674524336643845634436465265484C5535425A78575A336E66375376514A646C62586464495767546C4E5766726733717071747335476D76373836413665336D3345784745742F7A58354C3535584A6B4F47756550456256593261504757476939565439372B7A4E783347623756643136375A4B574A50384473665575515A645069324853375338764165344E697A4C3245542F66566F7A78413855566679515046564852436A366B63583537704654576378733165784D5858534D34783045684671494E6C52796F73456C63462F74496A4237634A3264647768676E396F61726B72343264444D6952585175312F71723864767843636E702B5155796B33755979354464506A41396372556C5543504F7938616662487A566732425450537330654D79744A71546269747676624B324F326C436B2F50374450713544744B4B744A6C623456305A7A4E68346B736D6C5146494966384159426F72315250736E35785654756576346B6A384A38704668624E39352B43624F32775A3637626B73697A4E414F5A5439336C6C354B2F4F4D4B436134544837647867444B776D37772F7958682B547278395130666C51327377342B57766C634739626172542F36444468344E4E75546A425679724E4257356173316C6D335562504E566973356F5954466D6C364A594B7949536F6E6E305A64424B416833387445687157666B76344952704F536853722F676B4A5852477736685A656537514F61475443747742415979684D4E4C34715A30784B485336714352583049736763674979386A686C2F7741426B687252372B78732F5A694E4279657654786E496D36356C696730384938707A7944585241692B5563334A6A49744D72452B7071504B3261797A53316978523531475A714E35795270306B572F77416A4C52366C515744394F5A557541362B514C534553454C452F674836314838512F4A367A53446D785930755157334B34774C31527174716852467252466F3079774C2F6B627677325A714B3233686C56515A713148624E67465575624A68334C4B6872676E7A5834496E4C5245487955354C6773744E71624F44354837446E4E493544592B6E4F64676854674D57724C484E69315643386F75377962377A54474E686D463232663036694C654572543939444D4938464A62775878366955397A314C457236562F547075673147434652426C50505A527354556A646D503833564A6A624B3350675134704175656C74576A413230363131337448333759576E386239746F304646375A2F4E684E697546735947336B5A2F77583948313551386A364D484A5A4E327A6B6F383361322F6D744A6A7332344555724D516979356D746C333347614931636667354C4C6C766B68585654586D6E46374F6E6D674756714F624B4D394564597A5374704476716857526D7A2B687044313230514E496B44706E38514F71442F6C6637472B395764465A42577A49465A7131705776515A7A345572774F384B3965712F704B68356B324161463352424349482F55596F556B426271787A74415143765A437571526466345834566D2F7039486678484537595A506B48494345742B522B4F7A3563476C7355306E794847614F46302B7666786E4556476A4E63364F4F385534693272637A6537464F394D644F4F366E492B725673672F39754C6D45765A6434756E636C6C4B6B6D69687A4C64417330584E526E7138414A65455661625058584A44624251764F71634466454D497641646E754A6C7279564E38446770506C677A61466A70614377485563624752424D722F77665263416F414671486F54574B6C6A7250686561456333487A512F6663546B35434F62545356704F73392B5335664B2B57636E61726342763361636D585662504A61527A354E4A5445637934566C747477412B586E357776584F706D7A466E2F77614D314E425568564158544748545A5A66342F46336733364F6C344F72787434783475664C374C347178753562486F37536F726635786C664844425375594D5253534F4446586B4668727068356D6D346A6945794C526B34684D4568717A69593063586E354F634C52724C4C495A2B4B79766A6B30615444506C3437626D7A37454C666270654C557A364C3539716B727131596F346365337974706777766173614E6E634B584C626444466530363832513156714B366C417273304A304962747567434843723370353475666D434C526938306A37306F696E6A46356B3252453877566F4174303370755A5A5A6334737149764E70636A4F57536D4177347076314D2F3070777643754D466749636A66314131617545786E5237364B615577354A6265504131557930303147534632796C6B6F66744B776C70342B61784C7276586A576F763259327959504A6230317A677A722B71733559442B5679684A6F68626F64436C7972575139686B5257506B77432F5770486C43785A464D5655414A304A434D74754C5963543845583132434E4C544F524D4E6C4F4D677A4B69732B70496645557365745A414E4C466C6F4B336759593950507A742F7131386C35445674304F6557726831307054496C6C3967785A71634E544F75365351704A5175654731734848346674587856783864743362456D776C3672614A386578355A796B4C514E2F4372423139684E6D42376D484C4D4F3631435572632B316748764F43305A704B366C34663475774B6D70594E59594F6166473477756F4F7273513166626875567868476E2F4D37595376756A4555416367695A70545074374B5566737265782F7743654566366E664F654C2B4D6A52386853513238787962546E78574F3154433349557935387A507965775A2B714F364F683238695A556B782B36484835486B434E4758646669587837547A4B5478566335736D414B756C35723569585A5970677A4E5257444A4B624F4D725542514F473033685571326534797479545461724C4C436A544F35796D3079674A43717444735A74757065324C536F696D6B32577145514142416B6C6632534B755845486A483141564B523167316A544F2B443454354C387A7A53332F4E506C76794963613147315A666A7646624B594F47584E6A7A6D6157474752474A6A63536D4A584765657651576252713150735A744265655133636477464B5A2B4634726A6E326A384E7430536D32696232426F366A556B6C3131636475444E334F6554396955546D4D63756371633559664A6D414A6B44707077454775336761356C6442374131725A5A58594E413078774C66564E704359465953632B5447432B7070634743594464574D67595565716636632F5952305A38584C614F59746877356C785A4E4F6E6B3937614F49764454467675346164464C6139666952742B377932707334783855416D6E50555A32787A79506E7A70306A56584B32576533525A4E46516D624A4C336563475363486C4F4F664B6944754B2B63704A6439526D357331474A2B6B6B7658764D7836646D64477A376F6A6B2B67667178376C563935626C4F424B6B316D6F4461446A4D32444C533567685959554375595167774E7A5A6430464A797453733638637A522B6E4F63336356752B4237735746382F6A7865584F387463466E69306D7035476566626732506D6839687A3064465830622B50315557484B7779496A57354371356C7762466234676C34664D735458554A54544737307A4643565161493171727A643239733771326435624642614F6C315452307063536A69662B5143326B52646F76503444746973746F6942376E46516733474647652B6345512B7A525A79456135576D556B6B56495744414F41316C6F6C4331794F724B67327442703736382B4F637A713476354C6A6A7131486A4E2B2B7470635A5837745A594E664A5A396D612F4734723869456A2F625A38356732626348446F2B6175724E79756E6A6D545478755869535A3548486A744E6B336138792B5538464958654A6F42656B4B31306F3268592F2B71304D7A5139656877684557645050704F32464C415535515577306431736F744D7742516C646A7737786A594D556C7448725943337A4B2B6D524965587755667147303732785A796B503434555663576E422B684D37533134587552654930366E72686F4C726F397A504339704E53534A66485446794F5263373231354D3963327854544E4A3544694F502B33724D7853336446386F4E2B796A312B6F796E324154332F4150615A4B45456B663741487339483838597755576E394F376D65496853766A654E53514E3974644A59314B702F53714E356B31354649592F6630724970483071744D445067316C3844414B766B726C65316370747A4E6A6254757A342B547A6436787172397272394E6254664E39335868395736504A6E6B566C65655A745848385A7A686F316853754C5273625073705A704879556D4B73366B66705364416B4755646674562B6C384A6678354B74386C41785252622F41476C586A30366852386341456A4270564F79786247342F4D774372646B323169534835426E5450746C682F3177706475704B417472467171732F6130777A6C6E65633534375279525A6D454E4F36545A612B6E4C795232373046467231374A63686262733078307533356E6E7052737441567236636230535A34446B785075584E4E704D336D686E724D664539716856576D47566A332F414F354638667754312B657137653072615437734B69746A66542B2B6A4168554E497367695630376D4B385930343063362B2B366C6877506C5A6B364159336A56386D544F464562624B4343504F333962654F354C5A38672B465235436930626C746C654F616338383833704A3034637335744D4E584E356761624A57745549435A703648444D6567362F4562537A38647A4E5A6D79744A4A5549667A615A644630364F35712F355A46436F475838427644312F78342F58364E2F4D52734374576E71566F794E685A656B4756673356694F697A5176352F39792F6931396C5A63466E5576744C733634625A316653425343362B2B69736F5846444667312F6C482F5776354C2F557250763576675069334D6649754835536679546A63554D30766C6D79664F313059632F4F62394F7A507957677732765631354434787263354F623561755044782F48366F766E7A6378586762374838506A774F6B35646E4B797937386C636C6D304B3058664B7765734A5043736D30766E4764477A62575764636F7A7456375439564E46546455312B5831496A4849613753575646476946724C69394F4E593351646D3459335476554B64462F77437A2F6C7A624E4473746943535262556461574B785932325868473157464B6A7651662F676E347A356A702B646350623567334B5735336865482B515572792F4B386D2F4A34776E4B56345A384B464938687277386A386735766962386C786D726B72307863684F4847636878393965343231507861542F55362F4743646F38544F4D734436754F5978674A5150746E6A61656E7A796D6336356F79454D766357587A7446793868475A387457554F6578314C693533484E6758642B74477A5457576C556C6B38355547445A414D2F516A49383447706231514675376578764B6442536F4773754E6C38634C6C66625031683237632B58796A6F3058546B6A6C7A48586F42317834384B59786D41772B3769326B724B4D7A4D316C7A4D5957612B5A4E50694F382B4E6F354872616844414930556D574B763449376E73616142327A5A706C6D7133614762715838456479564C6878766B724B71377035512F584E336171766D546E566931336C4C7552352B684C6D6852514945474E3334724F314372616856643967466C62462B316C412B6F464432556876726A727532367132784E3935484E4147634D6C37797043656C4576376334524939745058796B396430643374787646384C656A314D3339796E6E6B38634D35776C6F55712B6854524B57554D5379426778306850496B6C5252315034583358525A6C625A2B652B634D587A674E566E4D6651337045717134773146515937693669456F45644B6F7A69376770797743484A797570487642506B46644C6C30546D786C766136346F2F49664A2B4B2B4D787452395846634E68566C475A64584A446A7378742B5048714765713031586D56514D793474496F336A307965503751665A374F5A7250324E73317561487631544E364476727A5476522F695131364837762B4155505866524831594668344235556F37387532333565524C76723754656F45376D7373303547634C72426F744B6C64545437415A512F2F594C5A48693471507964456A5A6632377450635A356A2B75485038707638413766783332584D5943505364326D6D75654B674A557A544B2B7A5A69755A722B783961592F477850673551447636656358777A454D38646D6D584A544D794B7A486E4A714B7737386D64705A4E4D434841554878434838416C6D364831474A764A2F7877644C3249465A646A38417571394D585941334A73637373387872355177524D46696D654A4D70576B32577A366343764162707A316A426A583951786C793271707A79664C6F326D47397678664A757A72477A68716A476B4E456B58306A316A6C2B52684C5A4953524D3463783049717A395555524F6B704A782B6E49314B522F75387331364D717171544B5564324A65676F6D586A74524250624E31643545487A39626B4C524272334C774879697A46484D6B37484E36504F6B4F56414B6C4D703065674C7078634B627279644C3957462B6F69486E5762566832794C526D743569543254426451755076456A2F646D774F66482B61316A6C5257625479374E4D74466E66556D5A363674463076484E6F746C626833504E353833336575584879337935584B303733317A49766E5657683173384D354F6174626962654C546D624250476E6256387866527179785A6D56545856565932616E6A5037706156384B4A5144385A5049647431756A732F7136454D61584866415764676D573256416647496C4E746B32564A68714C52307736324770593663392B4F2F65457A7575754D4B4A6E576655667A62656534505650666B2B53636C6C533670464A5532506F34352F3762426C544A6A6E4E3436654C78704A4E58574F6566486E79694E5935796A726E673946755262564D6555704F30674850362F6261445076784272436E334D616857364B4F37563968554B367942383057686E3469453538356B77387230626D7933496879494D566C3535454C535573565731736E7148554C7131616F7047355333394530595A6D6C362F48766E5173304374343362444541726D4350795162396F34726C394E792B37546E6B786E70327457644D2B7330466744704B704451367169365A355A306E646873526D312F39536B5654524D314B746C68634B674C7436653631526941515065396F7036304A4E65364C4A466D356D4A5456565372697A5857656673337557595A476E4742682F7A2B6D497A78675231622B5638347058765246484C426B5A35626B45694B712B6B79746444376F553654674F79733070436E37656A52793763754A70354F4F533659744E49357772587A586B5938646A2B7848636B7A33443279726E6A474E3533725A3875377A777A7A5934355A6F616E6E5974397A57694D353866654B7156515034566F34476D62716F415755797358554130426D56597662475949375A36734170565364714F714E446E563167527566577742534F4D33565A2B326D43444B482B79777A6A64635772715A386B785933574236456432495575306633666C6F443544777646636479334B367553354D776E6D705062787A576A68356A6A4E45444F56394F626B50736C7931342F5A43756662786C67457A356D4B5A4D73737959353764504A6C726B595A356A4C4339414443302F4B7374634C4D616854454D5565734B397A4D4B67395462736A7770313950363338593879573352584836646A31566C346F6D51576657554F53686335656F3557704B74436C45544E7459584B344B62594739733450656D6D484C6F44577868625936454335503633714D66737734585238795339656E655A306774597733593552555A6D3063584F7543704978594B4856685736666376796B7A5238305A42772B6D4C50466A416664417053636E6F326831554C5667304C555754414D2F6D6F566646442B713946666F45632F6A33487A335867736869644176444E30566E4C476951673754493951744F6B2B59576F7A3162774344582F41474257503276716753777076706A4B6A3268674A554B533751527457346635745035784C4E794B374E45744848796B3170326870714E4B36493463614B575456746763675561386D655258486C6E64727A7A5A3872576139684731375A68614E424B6F646741394645715A544D6C78656A52414C7052316B7441652B3155666E3848366365497937485A47357667366F39356F38446B6E4D71594B4B72474D594E41456E386842764F7943746C414C6E523632675630624F4545324C5739304C62362B71614C626B7635334C54676976494732544E6B7A377331343539636E4B5335757679586848787765737730614E6A56504C52476F5958686C746E7A6B51714A2F55755769466E50734476533833426D43504C4F58647241446F476A4635534C70332F6F34592F3764665737666E344661584E542F414A42465569446379774D5767484B626F44512F6855564133334E4C7946304C3156384F7337714F634A4C45746A797A764B367272344679752F4B6A2B72643950397A347950694E474C37326F354651596B7076484B784E4D354B6B4C5244786579466A454D7764356F6569306C4B362F77444634526250617A6F466F526D7450784E474E4D3134753632434F5333726F5A4D69743467467745372F414755486B39474B614161522F4B377637485444584571767279743545684A794E6B362B42664A5832766C3162455745595532536A395969306A7046454B696F6B33666E462F57366536487A4B4F6A6139577A4C78395268314936305657476B4858437975336D6C49353753764A326D7661317936354D796F43767033344E624E54686973464332545536366C4B2B4C4276436254666F6764683163736A48736B6551483442374D736D6375306551445641575556456F4C4B2B64452F5330417A736147426871776D56463059546D4C5A53543949726C6B7538375A38737271724F46443278307A2B6D76797244796E7879334732746D6C7966485A6F3861386741762F41452B4F6569575851674446546B317957446E544E557979722F67713661454D6C57666C48466173664B6A52344D2B53315271533338675052696154446A73417A5675696A4654312B76582F41476A76564E496C47574E64424736716246434B65316F706F4F47444E2F76726B787467693232646E62755573654844446D683173424C7136623468457A6F756A396B65375575452B61352F6A366161373631582B366B4747615556536D6A54535168796E477053384B32707233354E6C7656544A43723635556E6C6C354E324B4B72385333496134516773316F715765326B7A745357584F434C3539756961556C4D51686F6C4E585A714A346D666D4F7941434335375047412B674A574A4A716969426A6B30323550597935773249526E33514579565546565A2F693842666355712F79736A52645172696B723554395436456165656D39717972385335616D6474506E505238577A4E614E5A323437516D4C67635044367A563079776E50585938506A354D643339724E794A695A503231614A48785A3248797269612B4371746676564F65716B61594C71666B392B5974374873364361376B68306145764A4663644956515A5237584C6836304E70394B73342F707831725657504B46512F77415951485A6B44327A745751714C753055573134354B67786D556D6D4F57776F492F704576312B587A3166743766784E74324F382B5765656657553452577678744E4B6E467A574C6A6A726C79664551716C5A3549343832617955484768712F59584531726A7754684E4D767937703439304E504868394535486B554762596B376663386457786E6648766F6C46725958745266536C4A364A7A734249696C4B796539612F642F4D48572F716B357976793237634E545A4A32787A63317A4F6E6164426D41477231396D5A586F6F4657777469464E646F316F706C6D677A7042566F5143346D4D6C66454C2F384141766C547A7862666A32336B493852386E77306E435656795A576A644A78454631525851622F3271764B59357A34726B6B726E544C463761382F494E68625278653263477A42504B36616F4A5452772B74455A505A52326250554548546A72634B52536B542B36436A49396C4A5A4C45717A44507A6574396635315A4A6436506E6E4975325542572F715369416D786B74695443715A775A77376368684278685038304379434C6B32506943634C78584A4D43454C43517A506B2B545635504678657932486458506E6C6250765042774F6A4E6A354A596F3064656242656D724C2F617232446A52524F573433516D6449356E2B5059786C78386A762B486A497057733832716564584A7368766F654B32586F2B416D5657444A74513968336A436371705539326F784D30367469794830566F54724B324174344D716F794372447A2B565A69536F467435536142303264707A2F414F312B316C455371536D466A652B42526636775657387671453047463879546C6A344855546974347471586A745047364D7A72374F3437456D2F47636E792B335A417359484F4C504E4A494A492B6A77565641786B716D7962533853617347445633794C4D345A67675A477A53524F6741515A736E5859382F782B556A365553644B7A43504C56316566676931306861684A634C446843756A6F42465A524652612B694E6476787242367638694E4367784B6F7A476A306564304A6377762B7544327A38723851354B7370537838507A4D3174593030734E692F6678327470716C634F4B71326250783136624D366D695A57304A6A434C4758742B6E54346B4A50506B4D2F73466A707A4B4A73765141427A506D645A394D33734D7161344F545245387A3539653155632F5768534633374B4A6D52497247776775656369703230444E3646644D35797A6F586C4342674B394B35424773694F525254474E4F5657793551304F7168457574786376587958752F4D2F4466365638775938792F7737682F6E4E38366A4935313438334D35754E717A6D6C78586A4B633571474F6548383044796A6C6E6870536D69797A4F7A5575685279624F5979307641636C7634672B527236466F754E6248384772437338394F6D656E54503272765954676F566B686E564472586554652F774471484D382B30704B656C4D74587271714C6E584C306165746148584C746F365A42526569736274613158364A7A47656D4C5551476A77475672703647726945482F4148456266696E78443778666A66784C692B4430364A5A637A3868783676546B613430304E5938667532592B582B357078434B7A764C6A4956354C42697130644C3861737655715356746F32395633636C61346C37444B626F566B7856663261667578794343674C45306E6B69533750525A657A746E592B49386841554C58675341654C61465A4A6633724C484C713065524E504B437157544E6C63796B694553567A6D59324F6B314A5A6E616674415757794E565756524D5655512F5038417979504853562B5A3548565462632B5754445A386B6559306172396F4A5350637255714751524231556B326453712B65616753384B6B385639317130575557797A4B71616B4E534D355342495854546F4A706C4B61696E71365949784C306B505A323530566E716B4E4577373538643151574C6857333242346F46516C30786179324C5969303073707762546652496D35475459483070536F6E475949536C6A46637A725374504B38676E47766F35444664326A5237767850483672526C72616C48656558527947694C6A79706E65424B65726253644A31436264437353743265614461784A64416972703632326134445138422F77447A4563674D47704B662B6B6B72655567683638572F6B4F587A5849614C4E524A7663364353564C7A2F414262537658613634415A675432456F2F58504A586A7544625630712B31566A696752526C5655772F534E667A3937565A6C5079567458796A487877773857493239355A44666A4B2B634D72443277686E35625679464E76492B74337170744469654B45572F456F3052773461754F664C7831744C485139314B2B4B4F2B73555636426748595A6F516E47434253544F644E58494F5639684E56395A4C566E39453944764239524E696E7368666C59463263712F3139626D787731485261714F3348755865317663764778444D7235436241434554763841534E334B4278612B56444577316E3458384C34392F6A6D584C796646346238776F44366447365768394D7155486B6957654849635A5A4B4D76526B6D59386252683134534C666B72484B66496552665A62526E3562566B784E306B7338724A49614A2F6B67796B7547324A523253504B77756842364148386C5A442B715A3238687464626B7359767A3541455531566E504D7373444853534B45357A73614E426D632B6D34537A4659464573612B4D61714D31433062363978682F4B682B327A637238447937587A6354766A386C304C6C44307050627A504F6E68636B44704E7A666A6546356A6D65617248797A792B785776336A4E6C7653622B69453630307A7338567A5849343536644F62586864362B44646B63653349394D565678656D546A3859744A4F78576B786C5479724F66576A706643682F6939776A6349533362465178356C736E504D78644B6334784A3839324F4C374D736C4D654B4842385A2F42577347433875356F6F4D324378657659663639464A6D4866567A2F3841714D4A7358444E69327A34444856786F31436E54636B744F545851632B6531736B2B58346E5678774F31446E6A464B614D4E746766557648626A6B4D4950677631625375684730327A4B6D64614A52426C36514D78465574624C716E71314B6C7A526834686C6E655157672F78646C545065702B6241706173356F6D5A6A37622B66324341574B584465564E6670586D7267674D6D33697436566771314E476B745A4D3155535264534D4C477877616A2F6C75694735616C645777592F6A652B757166497A305A44772F497073716D6B687870345035426C307656447958454862647371324F62434B484865715069644E564D6A6B614879786F3871444B6D54375461756E4E584F6F386E6D396235714E35443136335755744A5A712B74556F79326834462F593475794F4444772F3134474931656678523144417A52564B4B316F656D30566C474F3032675355327250394B30613230596C346965614E4A3052566864466E37375030664C56716468416C646E784457342F6E754F75744A6377364D557A353366504B47466978393464495231614A6966397777356473566E396E79574E744D3875725137364572542B333535654F5942725A583973326F775779766F6171544B487361502B556A524A6B466E7A473356492B2F504A6E656173682F796338777A4F6D7874756A544C437964506B3962616B3034773152796737684E4E50467774676C413574797759516A4A69357732685A686C5646686D744B577163364B6D554D70496C78626A746D66587A5753394461454F5479353377336C64367643734A6F5961616C6A5739625A2B51686F6E543776372F41454E54426134616D2F6A453576584A4133797A644153505739537A73473830594977575A5A574952612F67457A6F303571336E35646C704A362F2B502B675942695171666C3356465747464B6D65646C61635046657343495A7954335A364D4A685245513172586A466D56316150617A6865794D6173624F477A4476717A542B75325A754E2B4B7735445469706E34334E7A6478767A5A39584958694D6A5631666338524E4A7074464F467669454D643948323333554A57777834324F66566B674549634E6F6C6F35634B6756413675325A776B6C2F79746C67387145644967744773365441556F6171454E412F3673646F736F6D3839594374474F6A6F54482F644456734C6D2F47743635364143316C717A584D32697361765367785967306C704F4669776168306B31324D313930334443504F7550487564766B2F48383938632B4F38447864642F4663695A386C79476D4A357250544C7962362B526E72354B32576C383975503170464F4F7A4C6B313673734F4C6E6C31636377356A50486A6F783065492B4F617358493739326E50506B592B557336565742706F7A686C7031356E3246697250535331784F505031717945672B5270563664683563795A434938692F50536530304F4C366C734677594B52726E6D6B4B4B2B6A4E597A7466786177764D5769386F704F5839442F303149794273364E5446634C36392F6F357A7235393249766C577257484E5151364A556A6D2B3132706C31307A2F41472F545A786C7A484A614F4E623571577A66333572354579507356375A4E3870797A6E6F6F2B61733238446D4E5A4D56647571436A786F772F4A6F6C46636F51504A41594E35674D72665651636271343563314270576A6C6F7473745A49346961767448564C455266635347385255617671666B70716C48574154515056423369317164557131723961563967676F7342707676796250506C506A6E4D63522F5A61386E614E496D334735743142706B4D6649492B585A416C6F732B30614E484735632F6F5335316263305464426D33585231374D686C5A486E547070653167474C504E327173354D716C757976677564515370414A3662386B6B6E553379503369366F786E6A39746F346F4E5550734D6E774731714E394C4B6D55537934704A717A70767A7356582B74625731526F616A35644B5938516C46454D4B2B466D584A44672F7A2B2F71722F41456C6A7347586B6C34322F4F2F46322B4D3765513357346D6E70307A7078307475444C386D6C697A312F754539754D3179636672342F4C52323543756A4B38354E57573632563434623544397356514579354437694F664D3162734A306E3746745069727458774B7258524F565A394F694B69556E50524975715676753947576268564A58475676476179345555636775756B637050647858776E3454756C53467374574D6F5531697974434A7470734B73724546726D484171363338362F366E2F434D584F5A4E504237695A5662564563667A3634473333794A50544A76474F65577A4B3971636A6957674D6136327A614D39636D333137715A494B665166772F354A664657657042376C724D7271342B31714B586239764F61575A4F6B7044516A52374D314B556E54505154496F71563757354C634A4845514C514E434466566432344667474462455373574674383667676D612B35634C7A6C6361363547556B6E31522B4F7A6764637170333168562B59372F30372B623854794666737344617178386F76795844386F6B6A5955386E54596A652F4C73775939644F744353725045636870396D6D564168493170506B664261594C536D365353636A7A7A36354B72696E38736C49654C7A6571742B4761516F7273503064683139534E7556315474366E6A6F717A36465368384B2B364B385A554D57424A41304B7A6754575161716651314765727646425A326E316E4A696E52416F717A35566F747852764E652F70442F52333572752B58384A38702B567061655067655254646A7958356D6D31655335434C4C5357666A332B363178655A354231767A4F69433131726A6C737979342F57394D6D2F696C72355838362B505A2B41356269754C306F2B2F6D4D46754F314E6E7848476E4863586F6B38646C394A57475859394B77616B63614B426E573170616A756E534968546D6E7432314732387A7162715753377266584A464766415A7A7A58505148513062496846367077506E49445246564A67475452664E4E5259496842556D4D7458795A4C516851676A2B6B50495A70362F6948796D4F505A7732795845436374584F6344673544423856575935474E44785878747551385A587A55305A6F53466F7072325A6C342B5847364E4C3774484A3666727A31385A372F38363850734539635272656C35354E64703232656463373051367847746651717A64774134696C664C4B3261617957694C6D46724B724C64467532713056714D53446F68544649634B7937565A5377317959534D433346477437314C77684D4377704C664A46356A5941706338587141443744714C6F6530666A572F5765443448694E31553070663478786B74484959395761567238724C4F717931346255617461386A5658586478453943355A38764F6564534938714D6E49624D7635573870387679682B30744C476552354330667549456F687256707667704B4B7956524E6E65646D64585567614D3157413930326B384C56356E76306C6A684B785A5A4C317943385A7653693430415268556C4C37556E43323265366E726148614166514A6A4B416856693270716C5A324673594F566D75554C7846424B353831344463764935666B57577366563474672F7665504256393353536F4D423174435561796D71625074573335687234367363352F75334561592B304D6434546C76474E6548744E4E55374533624266624B4B4B6A4B4B614A5A732B69582B5A71756B3666615562505A304E6134394F5379706F57525935484B58316A7A397779764E413169397349434C796975757975794E313950456238705335556D7071656D48315172704A427076644F36574D4F485A6F75322B734D666E42794B2F485262667A5076783764453633306E684F577039726F3166593273647648366E3163646C57314C47616F334763707934307042716E6867565A524A615437484F666A4E7031777A6F7951504B516A6136545567306873453846376F7736556F39655067712B4255623639673272507350782B3863412B522F5378376C52576A6F475633454F706D393565537771442F554F74427273433150355662597A6F58384756354D4D49596D726C74414B7A345A585265766A3339514F536A6C314C544672546B6D6566322B446B2B49356650363130614A7A736D7252486A756479624B7854506176336A61344A7374746B776E6D4D6D5A462F5A6B397272632F612F6245487965652F506F4238453843457A53484761344D5637464A46724C4D487058627276365148354F2B4A3442463454365977525A4B68554A615A6B433170544F4438466F456464723839776D38533754597A4E4F7930784937413050384159444F4A456C765931444C6F486C43686434702F315270397A38596E79566A75747554646E493036744F682F6362434F6F5A56794C4C426777317A2B466D387375496B4C53382F754B54646457733938563032626E355A30655359546759464A79574A43537A75467052707662525A78517A37476E525643675572305652565050774D39507A587033696C3874506F33756231506D686363766F4E47436B58466D73304E306D31794D7461386E6E537A45647A5068466F624D554854457576734B44477443746F4E6F70576F5248776A354A796E4938622F414F57755731635470786359377934334E7332395A345959694B593966495A4B612F4338556D39383456654F61475663324B2F4A376351324239633379444A6A7A365635624E437376765A4931586A4955716D73786A357047614B55486B3351376F35627962786E6C704D682F7137635168546A7A677A704E52636D774D4C76364E714856686D71724161313246707834312F4F567A504661513371363451566A42637749455773697672694C72553154707535503544626A32796A486E6B6A47686A53715A613856424D2B615854577A5A365876727030374977536E3276716D4C30704848474755636F75537870523676727256715756486C464B726F64717379684674706D6934595470496D692B7162734B7A696B66765631314F4174314461756C6E646B736770684B674E656D6E6652384E7A4D665055644F587A535372446A4B31554C61475877613479774A6365582F41485A4C6848576B724874554142684F4C344C4C6334766C76503634385A4F466263686B706C6E6268366251592B44306C5330547A664A5361636E6A4F334A364D625477646A4A786E436937783157646D32716663354D6943716C466C5131593157452B785645396131664A44794C534A6B68717261555547746E6B716F6F6431733833674D6731394239596F4D656D4961416A65355549596D6F79646478335354576D6F6547336C7752456A3141473363416C64586642714F7244616E387270304C476B724C6278487959307838536B59773436766B3974387673384F632B646B4F703575496A624F727135767555463371564E74344E4A68784B48546C5A58713465756B46595A3172344E556A6F455674516E775666344764565A332F42575A413747577570393039372F4B723071724B6873574F567950794D705834354C2F6853727857666A2F5942514576777877694F4D3945317272714D555A68795577464B54565674354B336731585763376E48526C6F354138626A61766B59377A6F7468744376492B6B70562B4B4176654E4F506E7432686C334E674D6F5A2B4F77785632324852317055335177783554743353533031376E4A39452F546D706F643161735A4C54584A6C7A347771794678533939416367314C73596F3938562B4E5A4762715531584F7230397A573645322B74765A736E704B546B67784C4A36416168336677703541616E2B616E4768396134326F366B727138326376724D2B4D6E4A38384F4D346D36385A7875586C644D374F4579576264796C4E653564434737636A79475053363543385A6164427A6E627233586E3474707A5A74456E784F456972624E4B74714C7967562F596D6373734A536272785152625050533141543278454D4B414564544237365A446E7A3363344C5173616E4A4F4F326D50716846637773716E57426F37574D595044373273356157724C577A65614E66534943737A445A4D716E6F5372536A63567153474B3852616650772F4C7079324C5074775635506A3347624E794C715959705A63757A5444496551686B62476C346C4F5035453763416D65526F63636F79313877596A62474D4A4E48485A3576347961564B5330746C5678545346632B6D4E784F79556F613561704F325A34374A645A394B33644A68705461726B7262436E75553454447A303166546E68626861566C576A47736172582B5959564D6179384C737558556E77625A52304D775864686F47743661456151365743424865382B376D636C6535534759764F75343168624B314E6D7A374F50704F536B476F7263747847634D5777366C66376B316C457A674B787A445358726F5A71564F4E313353396B4354656C3258484E724F716C6E663841317A3653696F724C4A3654524756534744646B6841656D4A3566734B4D306C7638754D5236625258455A66454D6349376F4D63446C352F7A5635754F4236574244534278457932766E527545744A54614173512B583337733248534F705A4C4870476A57646D586B5A627561354F476966694957726164485437665A7947534E45795355412B32747561727A556F6368346C4A537A666662485331544E334D773077654758325345314C6D536F6E6663314C7972726D35702B735A4B416C494D793044576F36715968516F41395235316832674870347046345756302F6D30334C716C7A56595170455042514E4B58666E5446572B46422B34426F675777436E4935664F774A53636D477471442F726A6D326B3850765132323076773266664B6568655945394152436A776A76305A674F575430477974374D504A3863334C764C33656B55324C6E4550384166312F46424B5530592F4D66626979466D3746696F706E584F5743716F64644F6653325A6E4B6B6F36796F72396D6C51435139686B666B33576532735235626856736B79326E5656314B7979376A6864486E756F49746634363231665A5763492F6B36574E5A776D4A4B4B6D6E3937724C64414C5955543462446D7A63697533694E313438572B486C495A593634504F7556755278702F627A4F4D3655382B71546A67746C55744F6F317974524B50437872487639743872786F706251446B763751574A764F4C69577033596B4666494B7852453655426771714F75674D5A6F752F4A3658687034332B48616F6E504D34424C4B494D61777848675368784556584D69774D69435579736D4E374D4F367A766233627765756D563872562F627A2F50384141592F6B5042624F4435656D545A44566654782B7964352F633866654A66544454576D657A7361515944616C585878444A736D55634B6D5635684B31706935444C624D7A4C4F457864576E557959327A32724E66423250676A716F6B333767685669314B4B5538324E70632F2B534756517349475444675178716E6470466C34725262506A43413970444F6A4F444C684E4D6E30557168622B7A56717452546E3154637761366D376A4B566E5A4D6138776E2F517A4C4453756E6A4E367375373752742B4E7A73704C4A57474B474F6D36657975546C50505073544C4B333243636349707070625777303774477262727670386C304D794B77456B4263793772367737476A4F554B7A654D2F464333556E69386B5359544F7172434D3042412F332B6D3361476435306B61774E7375715055645A4B6F5A6D2B3634593073796F6A4D6A6D54596E466863457471586E584E5867514B2B78516451725A4E3653685669566B3450346678664762754F354B4F566A6E7961746374464832386A794E434E4338664F4B3643334638424C52707672347457555074746535394D4734766A6E557479564452737657645259317135505571516A6C38555175796D51456E3171466D74726C51424D463673344C75504A4B762B736B6B48334A4F5A3056482F5358306D577652522B6630794C4A56752B52574833734A314C676E71513230512B75356C57494333586B534E4E46746D577542744231626874636134747364632F5270736F66447339556336367674355458592F4855796368716839796B326D372F484C6368794849337247635865414A3548366F53664F6A4B7765356B6E59395643577372563764545646535646422F59715569696A3976493941644E31513859764D30746671345A316958546371796D6F624F6148764F353871414B2B394B4C706C4377537A366C77305A32452F7742705855794C6F597137375A6930436D3764557477332B3159386D336C4D47665879334763376E666B65533454694A47654F504E35644F576C4C76774C366B68566156774D5633664862436A445254325A5636687757376153304832796A37555238376B46362B4D363056782B55463041594F367341557569735549414E4659396657744F5A395577326372575168706D783461784F735664737A77526D6F4A5469476B42723657674C4F6D5A704D595847546F76686E4E72534D31707544496167436D5856396F3033686235422F54586B4F5A35376B4D7138646B3454567A744E4365664E6364546A6C306A496D756F79387277334A386877736557344B6436577A385A386B2B4C363852345848582B337072343330374E3347616E6D35386362677A55444A746869486B5A54762B686C344C4E546D31353433746B35487753546238664977316F5844625677326450445932485074324E786156336F343762344641413462626831593645716D345973536F65534F5650394243614B387059536D642F414B44574F674B346B685345675A41654D732F542B6848493565647963586F34546D3476707A624244692F6A4B333570466648716557693348612B6458504C54786D70566E63616E3031673349563076424B4973474A71507A6A37376A6E305A4F513432565936516F767A45526C4832394A6A77525934744136304376366442336D5230664A7833394C48532B304C4741466A432F5459387857774B4649755954634E4E434C774F4673476463564F477A6F7951353630736C4B7351516E51746667586C2F6F302F6F772B4F345337622F41496C2F51766B4D324F6E3233786A354E70304C716E4343374953342F64506A536D5A72614E6E50307738746C6E706747354C4F4F4E346E6763314C3865384C5735504E57546367795679667A443262507439576A43505A4176534B4D39637A6167656F55455A553931706D59537766534C4A48596B4173725457735871356D745939662B76346251576D456864646158503336523073536C4D4E526F7962332B51577138384C66644C4D6B5A44434B36364354377074536243536C6C784B2B494A4A686853416A54766E2F41415042634A2F536254782B624C6866627873476C434A305975503476682B4E797967703272782B545873626B7558334258342B4D4A486C50732F5872752B6A6A4A6954336D2F702F656D7A35707839473161554265746D6A4A744F3274644E6B5A5746395678415356564331766F664E6E536A555353506F6F4738524C644B6C4E2B6E3369756570475276564C6F695139484731676875686F624B6C42556C7649454E67775154704B61364C2B456746447868786C32484970352F4B43744C634E7478637838442B47636B654831374D7263586D7857354355364A506A3966484D5A62386472797A315A636D653779354F54506A3356367A32624B6E4971326E666E702F4A4F4C70506E766B475A3958322B6A48794F6E6B4D344C466E6F6D3331744A6E552B55436D6D556F532F5671656D4563384757496D696C4261487938523864586F3833633638323943466D3169696370687A673865356455314653634561685744637330796D464E313477466869676857645659646355774F6D6F475631453662774F766C6356363855646375593471714E5638334A4A6C35476E494E5A616A4257573643506A5A36556D7A32305732342B51323645433573576A543449697253307979437332783667776D7854395538764A52565A2B3158664A5253662F4145615A7159574C41336E4D45614A2B432F592F6B554D7353513276684C7065582B317462774E5273734A70305231555966582F415057304B6832314E542F3575684D67696A2B515752614C624731644F45727769717A4E644843586759624E6E794468764273343079347A6A4F56303030656C306158703544646B7A5A644B526F73774A66334A355A756B564D346D4864624C4A364E43744B32486B455A624E4A6E42616B5333354966486E67424175656977554B6E6B5148563238574270365A31476977326430576C5758497944397235626E756A4867562F544942646568357A4D4D627674753136335457676A44734B37324C4A33576A677968634554585857475755737253766B6E79663544686E6A30386674313234314E306378586B586E786E4C5A785A6C5071494E4A35644D5347694D37597879506761314636395A6D636C2B4B346646513238796B6244485A354A504F3973646E36597A4B4F4A5366505651504B7958435163416A4D7A3944764F542F79556568376363424E3533426A394C4D764553703431565270494D746146726A3369396363592F466F3753584D596B4D41696F455373524F435641436862534E5443596355502B7074682F65636D4E5531536D33485972467A71612B625262526F307963794A715A76616177704B377A6D7A693861702B695438566150694834346132315A794E4F7551526D43496A42597778306D766C2F74365870523649766637647230656830552F77442B4B43303033652B3059615861435652695A4A7053346D47544358566679584E34673062435131627177596D6339504C6F31336149316335565A4169304179305764664839506152687A65725138344D384D745054647742624D312F474C506D734E6556386E7652516C396969766C4E6655363053615346663543745734664436334D3550715A6E41496F704D34496E6249456F7A48785571416F3750343638543079374D6D714B386D416272647071306E6E75537A464434374D686A45356B63516F7148474B77566861417748593064435832783637302B6F31484B7A434F414A413456584E62574A494F6C7868397531586B59614E6B2F5862576D6C672F45386443544E594E703161664636545353506563705477534339746C79366E7A7753436D7654734333736B4B493635684E694E756D72667176716D356F784C555A56653274715738694B577172737A6C5465522B7034725562515455433967474D48314B395532376C7630495A7A6A775333375030503067312F7741482F566D703467427936594D5A66386C65614B3144422B6638674B76727650725839577063752F486A42533875587936632F70706E6B7456737572566E77614F4A7A6664314754693462742B51386A626A4B32304E68786D3345537A58546B4E756656794833685935764A644248323170324C5561686F37556162307A7049775764644F664D743646397A70415865636242336E4F554675382F77416C35346E542B537645766E61456364573256555A6462647775486E7930386E2F44445A704F3274565A2F482F387147427A307768483151342B483152646F4F616B3672764D5A2F486A662F6837342F354A702B523470382F6652514C446D394F386F726139477669644737626C725559732B6A526A3172486B2F746A794758504B2F4938584A4E4C66614E6F664B4F6163506D2B6E687056545669782F6153446363786D77396C6375672B6C58307455356F7A6E336E6F31596B39757358536C30516B65564A667863794764777A484C4B6E4D4F514B394539437271304A615253456F4847433044774C493574676B71643364704A44475031534934752F53694D475177575A4B54454B36466E422B696572742F474F4F493553416F2B476C513070706C6B3266754B65336C6457613173374C4D726642672F742B72526D71747055327843616B6D4F4F434A474F793775527A3661794635524A4B51304837706D6674356F7269766E536F6E6330706D617864712B454C7157387A3575695456416159754872412B32345A3255314E33793768717153322B33634E6354566C6B4D4C5432656C624C73707A4D36515341534A59714A62566B723252546C545957736667415834366558315A49705775506A72386A782F473564457377617263566B743458615454706E6C666C334C55316264763378724846526135625432316E4B634D62643264314875684C62707533627536363778745575656D5A3268467973305256536637765A684E436670714C495A7A302F4B4439444579687A75697252597130642F4335554C764D716B7832555865665A79304F6C51534F76344A4C4E3647384B797531686F46724A64696D466C62663562706956495A642F787A6C7450474C4C666B342F48545653743031575A6C4B617879476E64787A55556E374B314F5A3238626F5866796C4450506C6562484E4C536570792B546B5A51334769486B44514C6F5552616257672B66507875544C734B73755A6D7954342B4277746D386756322B4C555A7741793479375A436F4A65514F46544E57554269505232596C38784633326B326C31653255734D3879434A4B2B39515170305441716F6B6C64426756525569615449495731307278695878646C392B722B33517A6144645750464A716C4337517133476A5072524E4C75696C45354753496969714350397233514D42376E313163493261556F35396C537664524C59364F33675A6175373536695866586B303057624C304366502F4A2F42486663516F6B78655A6A626F54792B5975397036326272687270322F653047416177334F30546A57774A4E43503671634D387671474336564B756B474A6979706E5751762F59654255477642644835446976504D74494834746A34362F7366702B524F726766696E76553947553944767A50486D32657A65323045617946765337665669546F5A5330674E556158326D714D68424D564F6A63554858514B75736D6A48722B486B7967735559437A4343704B35307A5A6536527236303269695A6E4E51653848374E4F31547073506354684866444B56356C433046517742456574486E324645526231513434786835456141696B616C73326D63746565742B503279343348746872723578686830636C7A4D64584F304E47366C4C58666A6D726D554D464953644C6B654159676771566D68562F586559314F6C45386D38394762486A305179496E7250736566754B5842514E352B714464394C33395A6A666D4346596C73324B50443464596F7631666D6D54665447716E3369784C51736175646D766B53786A43396465564A466A424135337A4B37397134477177437635463970467A706F30616E34546C337A303076726C7975704D4F683053576D7632633857724E707A4A454D4551737272494B4738424556505A3736736362365832597A566B53445A35436E524B7A5261684B56527A516768306F57556875757569434F782B426254713264325979495A33537062466868564B375A4368453345703657773667554C6A475374654C46686656792B722B7251754464416C786F2B714E4D4D5771497130787758532F476F324736592F666C7A70576C4570624F5671616D626C643846335547514A6D2B34544C48416135305357327531632F345A574E452B3464773647633964436A65495A5648697443456D4133666E35586D58494D7A4C33525064576B486B52454F784E584A4F7670616862786774486B4254537A624272474D2B5458445646324E327734564C4F32307136766C31696274644E426B61763168472B6775675935782F4F424A556250717963696C614D4B35686F484A38703972496B57534C634E6E6532796A55492F4967646171514851654C65492F524A567173783549746C397155706C6153735859674F5931615069683643715150576576494E3332507071776C7A4B586B4836497032365050684141474B66526D6E4D71724237685265466E4A48396435675570516847624A7451776D474856304F795973425A4C59454165533332747130567A593972596F4B3846764F753948566B574E6149557A537A6234482F41434A4B3971634351706D5A6A57316D3235637350706730347874614D6853706159726C796D666944346D626A3236507943766E3132684B755077774834417133576B6A706E6371442B50382B4472574F646744724130374131517758586942765935396D464B616C786E43566C363035796C65504D36334D584E6C4239794B6F696C657A49726356727948453253326662444C704E47307761357572365434744E4E73574E4C4C526E644C5A655136634A4C79384E756C72445070496145575946413044566655676154474B4E4D6A7837456D5554434D464874704E416F48545544414B705A466333694F67707167417557484B36754C58366B67755A695A6F706C706C362F2F414457664F35657A7141586B6C796A53526F366A794D324D494D32624E6D675939356842305A634E73732B50355849334D50346E565051737343636C69324C6E3072646347432B7175656D7A546C4C484E6C346D5454313657795A37337473333773384259307257706C6C7559544C4266516567514749483631444E496F3153434544462B2B6966345966526C6C4A784A75564576786F69764E47517473474F704A5A474B6E4135634C6F57464C4E59736A61744E68385A496C384E51535341485A793455316B717644737547573952347A4B755748493561624A63654D366F2B584C676A704848756C63355A4E504657564F5166465363733368673476506238514557305A486B78705571745573385156396E7662717257704B642B67657657383257614D336E527661795648666E2B766E616A4D65553776516A524A356C3732796C6153425659476A306F4E4A7067375953692B3868624134644952555359354F6A534D736A32786570595374456A506E5149584D4445546C6358413533305835666A5535765750597730344977344452544B6965306B6E6671726D394F554170642B5730615074616A30306371726F4C4F65727A737558486547474C4258714B445A707A3271507965337A524E697762793739665858386C522F483070774E502B517567304F693773306532774A654741744A46542B745A756C6D334D7663584B5A6C6A55695A48523276515A2F41507933746E38557572677767567247796A70744A4250336A7878742F4C2B306362584A6E597372713950686D704236333671756E4C774F50565855513673396135437A6B6B364E44546B4C49705338336A4D7254526D3152397173526E504F786E4F724546624C546C4D38344934592B506A6F723633385373454E6D6C322F664637454C623258474F576D4A6370476E64643957396C70466F616E566A6B6E4E676B716C366C7543343347767A54715A5244776368687055326C6B4D76756A586B7A7A7844676B6D566631627A6370722F7031386930343234724C78763972764F6A5937353068706C6D554A767A744B5570684E57656450597674797A53536D4E57334A357A6A52772F70304D57543566775833743932796C6552476A4F6F386B674C392B45614B744F685A6C654C7A70524A2B5A425A45634A313333656A2B3065656F766279383277746770594A426B43566732594A35447773586644596252583351477043563952454244446D4243375377704A3648637A7458566D314E6F437445542B6B7678586B2B562F70356B66466E35552F63727135564E6D48616E32415469395169324C6C754D316435774D31457631707836632B69324F7A4F4A5A394367686D2B63374A512B576369584F66787A504F547931796D7459746F684C517A59644F634B3633704B303372464B56614C4D434B556A64455230512F306C355455454E6F6C626856455A597957724861323972534356476D386672436C685452623643677442462B5165567132346B49454B662B4A364A476E76696F6E70476566495A715934583439526F433672372F375479384265324F554B3170717A38584F31307936794B7433564F4D6C4C566F734D6D70655A314F694F6E54726C3168694E314B5A5434444F2B7146487A5430503545792B34374E48386770416931515A644D524C4E324A562F6F57593437506F4F4F343944494872764773475346337342377630374B337042616D74506641476B7A3435533646534D707435794639646739764C724B494549636A44496D6642753544466A68574B506C35506D7466435A4E7632396F70524D39642B586D72507630543743455562546C487150746F686842507142754F64364F384A627161464C2B2F4C786E33564A754A73464C434E4D7A714A7354356D696B745073544C41304A4E4E2F7A33496F732F4854307174524D6275685574736730484457726E4E7851354344573564794F45564F516E31456A435958494F4F66636E525A324E556F6A38746C43332F4B3138316B7A38466B746E3573624658536954536E4938467174576E5455526B666A70306E794B5A4B6F6B4A53796239545A566F6E74795A2B6953642B4F654B38703476674B46346143664844575473494937504C2F4937576C35795667744C7A536568797151656864564F4E48356C2B6972505358475530796F4959617737793555623952645A797365706F78474C635344736F6F734C3450494A6B7776717272766C79325167396335776E4B347175724E2F6C664B6E6E393348627976524846634C6C5A336B6B337474784E7147344B383051614658566F72414F43784A6B57373664656E4C686F78346E507377417A5A4B36756673776D65314752784A4D64434357616130684F6569666D6677722B41374D585030642F6842364A337A6C7236553043736F43326D674674594979624578726F71795A4A6F56685443715336714A51664F47526A304D386B69756F616E687652624B61626A422B7458394C4935582B5837446F6E71394D754966774D644663614E6250544E55696A536361644D6A4F395762375565302B6C357944556D564B72386B2B3462674D3834574533586C4B4B344C4C50796D305562786D3771792B53452F783473313648307938617A636B7A2F4972614E46336D5A4E2F7133704B485A6D3672624964642F4866494A57353176784A6459557034424D4B644C76625A32357A4F7741544D736D42795232554259384C6F5539414B6342374A7A3975416E6766567A433573356B4A337772574A454532696F706E6E5468634173756A655561656D4D4C336E5431746B30637A714873584971377730647633526E6A6C5246744B304C4F75727A304349364E6174625133634976305A7458504C75544A565A72375A735477666A6C3668706B77724A68644C6A6E63495544703572632B694746756D334152524179772F4E4F5376477658553878385836304562447132464332625A6774436667716D3075527236347A666835506A767365522B357479776C7132756D575A4C307641704B2B7575644E454D7A61693152683856716976656D6F484D6176706A5035796E48756D74577A675A384657534D4C6153784D5A306D396B58477759564B306D746D5852543232704362316D7738505A395746562B69376A31325379486F4C4A6773466536536857526B2F3371614A696F6B4E527672494D2B505A473961786138355655344D6676724475757148465936725336334B6F576F4C6F356C346B6366673061636E4638526B53767353394531534C70347959556C58516935454D49545776726E78686E6D645762314D4D564A365842626461476F4B48526F6545475956535A6E63556D4371314C7378663255494154324F336E4C78486F6946436E5148796A454A5749766558716954383957446D394F6A5A7969636D5968746B7A643057334C724F684967786831617244724B6F4B2B65774E392F4B557442624F7869514F4F732F4A433864374C6E616872586B4F597A735570374A6E4C726269644D306E42417354585639716A6C34784D4C4A527A49317A6B71724E786A5439546C48445357454237676F6D476F677341783876797171784A4A4A483741646B4653506F6366344F64567A4B754656304145314E366D366F4972704234354C445A4C7455617A2B4C3572362F3858763047685758555476487167577750494A2B456178695A79546B4F61544A746A6F584F5A564D4D6E4B7A524744726554496D486B417245454773646C4B54444C324C53303532516456566E6F354D6C485775646D38356D43356978386C55654D6C4345483844776F67425872734D543270385431395665714930506E322F7859326D4E6E69782F53553157626457314B6279524D76366F41307264564D622F764258726E39377836434A4264585256527768502F535470722B31323131576E4E624C794F584A7932574232365961705452336F633761347A7A7567784E5A57394D6C315974754D5A4E4E4F3062646C6E5738586B6C5A55675250424E65657A424641536A4A2B56506F5676554B494F2F4E686A304A6F647072322F713254557361556851543537516F693172744661425136646932317674676B626F787131356E3831693761327167444930734B726C72466E6F39732F77416578626C79714A2F324852494776516449766F5876354D4C5134614D7377767577783254624C6C3335554F7264695A495A4D4F62714453726D7639726E3476467832764E7042624A7269544B615275363436786F4E3941627A6E6637656C6231513048322B6D56584E692F61744A76334E566F71535052526C59555944746E666E4E495855594E72687839486C724F466746704D7A424767507245615531766C74614E5A72737947516E6E6B59323670384977627433663332512B70505A4D414664696D41786F71364C3731787671346254524E6130666B447579507376796367326864472F4A79644D64303558476E6473796F79594F4C72687869576E77314D756138476F71766150766E4235656B5247656F6D384861612B6E4E6272784345683038764A6D49766466496C683446337075303041744432704E2F72344F6F794F584B315467346C6D714F6643307331416F64536B4E4D73596C444135794B6C324E5772363462464A545973637A6C594E59457437324B756A6B6A486B6F2B57723769382B543859314D6D795234335A486A744D2B574D4A362B2F3764575466323950423838327068455479476C654D724A38734A48517A6F437A4A4E6372433457696430536C30384A442F41434272776D5A306D46533176592F746E464A735A5573316473396B647150644E74366D32643648306A51517049513541414F765368785A4D4145796E4D6E61517A4A5761466153697971644C6B69636B5866784D697A4C5177396D45487132736D4A7878376C7564342F4C4236635258686F5963776E585274303867325A4E4C5171303534736C4979303178343174497679554A79466135534D4D34307953715956796C374837577961626143306F2F61355A4536416C57414863676661475A573755736E5835423649362B6D532F3850686E504F6B5870667350704A2B595261676461517350633049636E352F70445769613838436C6473465262477059794F58424667444C654E666C663372673179367532776763574F6662766C48502F4A723536635070743865736951462B552B4D38382B6F616F74616D654F535042436B384638783231595530533058506B59564F736F4A42474442782B546A545765336970626C396C55586A75533475796138724C366E4C4E766776334973733571383544307A4171586A4B74714D6738342F696577696E56747346763859346F32366168316C42633254646567334F6173416F506D626C747A414B49326B5954414C374C2B57636B6F594D3139386D77594C43734F4163422F412F49755A5466713063763873352F663574504A7635665A706C746E6A5458536E32712F49666A577A537A766D30744E35597551346A6E754A704D53365563696B744573642F6B632B4338353556344C446C5A7A3759526B645761316A4F4D3174666A655539553674664E49534F6E5070347A5A5A6C5A656B6E5071374C75486B597947796464775768795A496C512F3841657A784245516D567256585838597A4A4D70466E793930704C5664597467356F5258567645564264736D6C67436D56434C5363664A6E6B444B472B76486255394C364D664D5A6D304C4B3666636662556A2F634B4A6C35506A71594E434A6A336364746C4C6268303738506C6D30354E5744567552397348776E786B312B33627A6E4451717A304B71717264556B7250476A64576C534E706D304C5A2F4B6B32556D6B34386D586F7A774E377272497736346D772B69515A617673704D4F695654735872374F43797344705956385869696B69427433593549367571514156386132786E2F444353355155656565646D7164634937754D75487A762F41484335304B707A5764524357336661597A78555363366D384E464B54487352684669456E45464146366F73714A344F72722B6F595545313738706B644C3056364C487366545A616F4E6132756E7846506A6B5871394E326E58714F6B4253346150456367496D456D41314E6F756E44463450786D50544B544C684973622F75686E2F757A70766363375A564A75314A794173706E7A654F6B587A354370453461364D36747134347161536E5759706D30776573746D64305067772B316371556D424E7131566B4C527A494E49723251657A366D55534942374D33633162726F44733969444E475371394461743266704E796E5666542B5656646F4E7969794A5A56663679754E766C57675A6A4E4957543756524F3563326830306F57795A6C4E3573622B7444547544596C6D4B594A32694E6B777A56342B462B5177374654784E5269766644544959786E35686E625A4F61497038354966394A5A7A3249455A49552B32446B544C3553724B4435424256626E71627376663646764D644D7635364A48736D7A7251566263335330684D674C546271704D79645070424D3062302B306D6D7869494B73796A676651326C754F57576C4656746F3048316B666F584A59585751614D4F3138746D7873666235385A6D6B367066303465506B3263495373334E6458794F47496D36714C5A345678674F582F78394B77517947566A34797244546576724C704D526B722B4A413742564A6F356D4F68354F744F6750356638414A2B766E442F68643644364F786B517239413259795A73367176755435387A67516C7249596E74524953393970473274665679674C6266324B64514F7049763554437A73354D4B427278384F2B632F314F2B4566454C6F312B52354856795636316E6A344C4A69736261646D74486F67335330797955506C524B6146574F765078344571326264536B5839726E777646637A79306642654D78527A67496733624B696A4A36764D4259526C656B79565546504A6B75664D654B2B46763258543378583850734A35573970666B4E4C575735462F6D55424F4769555A77594430634B36345263734B3034627532636768574E424446706E78674634684D434F766D4E4469677175486D442B6F587A333544383278386C7354494D48443051783063634E2B7777615A7A4357576E497678744D6548625A4366766350483774664C577A57464B355A30774158306242384A2B50344F4D354843644769326A624B6E766C65634D3465565379646D6633423136456B797A585052344A6B526C50717150494B526C4E375867312F7033356B476F6C347A362F74756B536648516C754248444C655665636E58685775574671596D68537548466E726A484844496146694B7642664839542F416147564C66763655636C486866364D634C76315166456D4A4F53706C313358315A4C6F2F4F3872484F7153587A304C6F306236353847455A6E7A516C625A6D6E7169754F546163715A3838784A702B59387373767465726659725655413975613663586848763841594F7642476B6A655A58736B5254386A726F7533307A7A35742B4F636C666F4F41315950536E503950504B584B65376B784C546B4631717A544C58565A44636C34435856565572497554553850567359687353694B6C792F5053554D326234763834722F4146474848773544466E685048794C31614E625178377430776A47535A64475663325A644C304833466331384F6656434E38744D2F4C326F74504655354468372F487176717A61645144776733756974586E507A432B394E5330616C54436E6B6A544C73384C524C46704276457057727A3732543248545633646168523476504674447457797A6B7765557357356E3755545233434F79697546456D54486C4F476468662F7744646F45595755386E796B6C37354C4C782F7837687136755A356A6C754868665054436D376B75546A586179787A2B776D646555707A655A394D636B4E427A7A78343837565754734B71464A594D4B323361516D62506B30756A4A622F6F6F336E48775A676A31386373386154696F71574A57723573382B3647564A79557244666D423533374C643468736A484E4D4C415634647462684B737679307634716B4554686A6B6B32784C51554B7658667277747465464E6950614D346D7549356666635649437A43666B6639592F696679726A4734503437772F4C59754E4B666A6B75633475324C572F4F3575573163627634374D6550342F526A61576A3752742B666D7331646B71796C757A36736E4850687264334C342F77756E6A65536A713255796D6C5331456E6E315357644D6A4C346D6F4E72364E71724E36546A367A4C504E6E5A485271705A517545444F3168544F43353347564261397763684B416954792B6B4F2F6F53716F38575078484530524736644D692F37454F2F4A666447646E536632746C506D5955305761542F35475A494E4F7565583443546D2B70394868344B39414741413831396A4555382F49686830756D7A785262564164742F3161337A75534F75314F4D796E2B50344A416F70374834506944304166715A3833326832626B3359686C5539374E63586D61563534515267544F322B41444B6D6F30636D69647050463361537271434F31533579516B5A665A7276457037786F344C6D7458445630374D5734354C746E736B36546631477676746C6A50505A75774738306E666F642B50672F6A347366314B31486A6F376D7A3539634A31536A653353423542314B595758767944426B3763422B304B393967456A382F5767594C6377763267544E3256395642683261682B4E534361396C726F7447536F4E6374427A2B304B734F66646531694641446749385771612F787732504B70784374633978347670336A79314E55454F644963596D4264766E6A6E5142612B755536624D786E554F4C5A6B315A6F4A546A4B58497833706D707A57714D384F64637761797A77706F576C37626659754F66334659757857656B306F7A4930686B7A797236766663615645746C5538705A71334E32724E582B434F44324F4972725A42352F4C5A5771305A466D51356C54734A4D717161586E7862564132423236593562786B305674596B2F6479392F594858734A6B417364546C3965596268496172537337484A6834384C616363394B355746377A65614A7571767151556A424E453079354E43764B41637549784C4C79644E6554624E50523141614E4F385646394F696176476B533847427A6B394D79574D306F746D386E6272794A4C797A484E62667A76786E314F3530783943427A4774505672446A755231564D6261617A62624B374870765A47486C42464D75744A447A6D342F6E436A67746B39334B7A574C4E4E53686F466E354C35487747624458693947334E6D634C614B7456367375514C36304863386D564F50683641714945576E46355551357A4D2B794D586B4A4848374E6378664C6A7338325433564F5A514365795234666C682B716E2F58794250586635483866566E385A4630725374704B4A746B357974717364597579384A737942616C3573304D5267674B6943574B493271316F43356C6D4945714C623743324E2F30435973547171717246336B744D392B67587A306A7474664631646D6161366D5A73723571363430724975765A6F74616C4A556B6F315A5A70536D566462524E636264566B4A3238704232703679664C78536A4D57534E46372F4A6F57496D7748593848374A37374858706154326B44572B59636D7A796A5946723557365745586930624C4A635238736135457045786D784B3752617441744551325731737A653373555756714F4B346431797455682B53716E65436C56614F7A6A6448757961715A36665A3179365A7779377375687765317A61556E4E4E5569537259373776583431456E516E482F52326B3461624F50644661686E444B784D79704148516D4434722B6569423065782B506F4A332B543832394638384E574F48413141656251414B3737524C4C526A3865307A37623431627A4E4342677857356F77426A4B4962325661635A504E66426C513568796F435562316E6976376E68335270474B6270636F434A4C6C704A38386A4C326D5271386C41743470397869736C7155764F43354D48726844466E5557394E6F7245325A686E766E486A353152584E5A754F7154594145487A5A77782F482B79396A2B5071724F2B78486F2B6C545A2F6D42394C41627356616B376B7872733953767A70353156352F774234426F6E477159486A796251594C4243563962375865624E5236394F4C2F43567749724E64366939745663797436764A644E456B734B4947736A6B424A31396D6136302B366B76556D62486F7A386A4B4C49725264315A35416339755079574D365464596E3231416D6C533831637458786B3453716D4C7533734B4F45547A5975744A2B6669654D39582B51307632313237567938354D4B58337973665A62514F4B55656A564F3778423736562B6B714A5A73364B6847513472656A42636542517156324D5734325A346E345031545834726C734F78644F493079633362433155624A73343433706B3054444B7A31726F785A4A79693358676556313065766C36382B69743656464353736F677136733962786E6441355A576B6B7768554D43567A62614D335834422F77415A5066344948344B6B797A7A4C4E466D4A745076755033476D6951445970634F57714E7070326357504C59304D42726837786D6E45613964614C4F4D67544C5372374E4A56515155354F746B474F4C33386E7A6D5A74555069654C6863767057384E4F716646342F7475506E466B39734D32797342616D696C7337456E796C4F787A5A414A356C656C46695765634E4A647439695373345477697762537932374B33696C566F73704575417A757264416D6E52485944736D3979344F5A625A354C414E6B345170436D584C324F68624E31694D3452634B4163744E4E4D736B694B434E46344C583946677573626E6E396F306E6445727A694D6A515A35617A66424E57684D58492F494F4E727478614B765A4633323052796E7551445777385375764D6E49726C632F63747633316D61534179396A6B58615831626A79365A4A334847766E3433322B51572B525A616553734737416E6266644C654461423061546A4A5A426A313631436766532F77424777394C33634441543945486F4C786E437832666E7246584E5A56794171737845716C5A54736E443646734553733678634779424773616871784131355449364633617A6E624C783346592B5279316A6E35506A6232786E466D30797648693832724D74446F534D4D30593463634E693155567A704C52545A667855796372436C70413235547A7A61455154306F6C7A6F644E443330616C6F524E487037375057776A2B692B5466764B5A38794A483871595051737655736D3862736C3041786F6D334C72645534564C416C7A346658454773476F726C77585753417A6C7175306362527A4D5731774B43413166367155532F5A334262753772693277373465584E4C7362557375536D6D446B712F654C626A705862477252746F464674474F6E37552B78345A74346666484E705A3830337A6B6E72576B4D344D5243386C4D4B4C717A6F302F476C4A683241447537535A305A56465A316F705652544A63426E643765614D6C79395172744E5A59464A71454F7251614C51306B6656594C3249686C6A47324672336E79454835786731746A594F4354464B676F37744D365139446175426C6436345277326849614E695A646233777774666B565252637253764774794848335450496E79576D6A4666614E4C72514C6E797079736F536E6E3156616639797063776B702F5731476B71677437423657436D645451644B72524C7779785571614F615339544979757A567862426F6A644656705538526776364D484562686671566E733164595A6F7849734B7A4A45576C4C65646B5772455632315844774B4C456F36395532394C71445347644674384B4E776D68333062654B314C78577467717A4C78544E79723553735146507030444A707A744F7A304A6865366F564C6767436F6C6564536F6E4A5737304C462F4967546F5A6E6F46667A2B72745566676A734243667072596B4A3774754C30412B664C4E32424D61684A6955642F365479775A746A535836395838423763616346396249706A4B2B454B3452485646486A337834537A684C7335766A65424674504D3755793538654A625536786C7449746161326E6B5773664E382B68664F617779303074735A62656159696B36556C58546A745736685449686474476E316F6E3754447A44424F324D326D7851447959676E78627238646E3675766850786A717934686664646362714752425967526743386B2B70524D386E6C745674464B3565774370746859574E614F574753774A444F68584969674B69757535545041726631394F376B514F4F776E6A7549754B4A6B76573165523136724F364C357A6B57726F3558666D6E304C62654E776358782F46726232386C76343778494C314C2B6E2B624E6E4C58723933634873796B6969617168436C4254312B534A35455457746E73355971675739336D6C4C57342F423471674332676A495A3961724870724D4B4B6D71414E674D615958323562514F71432B4E625979744C68324B354C6277746A4530636D5A374163424E523257502F4D2F6E46506B75754B354F637679627831744E744F656C5A5A56306D51646330364C42395779306C41476D6B524C484E3159527A776B7651642B443475504777304B754B57645856537964496C3648722F583041416663482F387271395562767467335A2B6A666D49467342364D716F73564155316458485244726C542F4143566763415951514B62687279716854327342672F37466E6254427337557A734771565548514658496B4C4774453552373738384E4E4E43467A706B32687350734C6A30564131734C6174486D4E44566141793472656D64446C714B31706373307076496C61644366544E4E6E507448366867724D414178423638674F7741436F2F492F41716C59566B4F4145344C4C37426E33684F47586A30734C78694C686967725131423134664F3278726C50345238387259744B6C7178574666384147433861784D4E714E2F4D34616366446D3269546556636C546A47686B58534D4F7374492F617A716B6B6A41566A3436583475565471324668733165316A4E4376784B2B625879303554736E634E4D6D6F5A67306D6C6C384739566C4861726631754752375546524D46556738774B6657456E75423575412F4C666365694A787A4A456B7441786638774E4F704C4C6D516F515368524577534C5152594C4A5173346A6D41557269784D716D3149584E5A52584B6F72765458394D7541484E2F3052346A6A745849777269734E327565485678757A42624B2B506E743371746B35486979592B474B744B61636D36385938676A3662593351594E57755049356A382B33766B2B5A38685A4D76366F636B585957793655737938666973726E4C756B374F6C4730464B51675748726B706F353969425072542B35366A31725173304770597034545A3537744B6C48316C4332356E69795A49716931656B716169684E644D4651787A3150533344416A526E4232782F6B6A4D63346D4F6B752F356F6E416643654C34466763396375717531636537564A71636A706E755845424C4A5A387A535467354D6B5457454A543159355A354C37312B2B31587274316F5849386871322B317844776E41694361426D7A5131796E3057456A6F43326F6632415A6E3641375839466D77566C612F34357979672F706965746C2B3357735242787136654758714F6C717132717369343839465A47326C7956306346696C72584C3168556F574E4B334953673439634757426D582F41496C323545384E776D7057724C6A654535516138537A343952444A766868706834756B75536F7332795376505A7279636E795A3335526C347252747A594F5370797572484D6B5068765176735345344E7132356B6A526E766476754A74593032687066634E665452437562534549305061735638383179536875722B5444447A777A78545A6D755A7A6F514565573734626331634D4C2B684D63394C6149774E5551563274784B53536C6A6435517472564A414B773174774E6445474C727437493777313858452B522B5463667A452B633354367A636473484763613164792F77427353705664757952354E4D35795A58304D6D7478786E465A74486E77324C5671573261673558614E78796A4A782B5844697970744631784E7130796D7458304E4E374973334D5352577555497A4A477754786E533842717830672B5838554F7642594957646F663078716D69566A7049364549652F37583064477458433930565065544A6E5A5A455851444F497872712B4D436D77547443327931645350644C304B6F5073324E5A6E71394C68466F36716A4D41354B4D796F41716C354D722B4956504838722B4433316238335776474874536B576567587A38326164536B31554F565872774D777659422F4236483548356851564D3445474C344546786746705071567265516A4B6773686773324E6133744E56664F3251743675456A41576757337343793770634B6C2F6D557235307943654F576F552B4C527A585A6753424E445A39464738774750556B4C4D54347235424F7955425058574B535435585550776656703077556B45686E387177387567542F414F6F6E725472382B50683332516568743335495A756E32674132684369684D6B653435424F334B34564D6C6132335372454248766365696278347634514F774B454B7075745149724D666C6B364A53657463566D614777765353395A38424858544C78322F6C4F53726D56384F65597A482F704D6D50724C56442B62716A33333170564A5A627167386D57586E6E3053385A7267584A766B6D2B6E6A38574A62306874733530364B4774485A727348574F614E614C4F4B4D434B2B317645714F7144772F55616A2F6A6A35706D76535662467A705559526C326E35556A5645304E476F6A484F3335746D5A4C547067433661704D79744373544C59784E6158552F7A7968626D32635533356654467570565A2F38322B61637067354C546D347A546F662B322B2F55314A334B7A6F644953634D7567476E6C396B5132765338517A75394D3249337471795A5534756866677546796149752B6C56574A6E6E566C5A716D31616F624D504874714E49674978396B2F49464A696179374259336B4138617A6243796C34374F566A5741354A686773326E6564304F354148544B316C695A65666F466D6930426F523271436A4F71352B354B4D642F30346A304357334A514C2B7744784750384155476A426E6D73416C314433704A632B5972645176713035326E6D71794343434E38654D32666A387A36644A72697164426F644831634C6A654C566F3172737266625A54524C3649704F5354374E44574E3479656A4874396A517473594251756C6633696B5338386855367371567855375858784179767066342F6A4331707A73466C64483677705952596F4E6147734F706B7A514A394648635670696252674F306168586376542F77444858342F3832685242786550654B37725A36626C6E59566A6A716A3661754C79303179523872336C6E654F7A566C6C42365179557568396D62543541393341697444656D583149744A79566B2F5A31716B5A4D5334436774352B7732565141344C6D6168334B42386C665258445879787A73556B534C4B3371566C705667366F626B4451753049334C764E44326D42646273596E413156696635412F51387438477173456230646675535450742B71754A6E6D356E6A65503550445365364663575433584A6B477361344D7572526D55315178307A6E3979324F39557A5451617339357974306E6E395A6C6F576D4C5458506F5978386274494470673078354655505A2F43396B6558374D6F2F344250386946387839337A2F414B6E64425A745A324B3945762F5955495A697676367A422B4F7331674B317A446F345344706F49415337457044514E304647757A3143382B2F554C564970644B79356635626A52783770713476506E7A5A5175704C63577A7A7050554C2B6C466437573146737A5A4D36616365544E336E454A57487030666135306556396F43675765686E6F6F594E4B38777865533965494E38366E74664A75794C64327A3042566C5A325A6850304E394D774765316338343832363975716F59697231476F795634354C34714E747074416E4775687A326430574D6C4F64726D6B4A5633677958726F796B43446C4F31474462424B4F6552776D324765676366664B6A4A485250467A727A355868395A65633347646270624C794D707A594D6F7A446B6E7952387573725031533171734D396864704C53624C374B725673376661335761762B74554B797443374F76355A317A4853702F46444975794D4561723339554B736E6B556555772B782F716E5A6D303978326C53714B6D4B7659587A4548764F7A4B644D545332414C466F4B3553424D31695378625167684F47436C614D7434772F4464664A643874794C612B4A53557444527834636E4444446E396B356F744D54614F523358793556575469693868746E6A30706F7547536D305963784A4862564175545064504F6C41713174546C467351474245326D6B38514A62706B5A6F44783857597370587348727A7A716A576E324957546A502B656974687635612F695A56706C2B6D31733242514462744256374556314A63554D503336464C62553075307A352B533149797967344A6D4A70446A4F69475469493561347A75353538636F586D4E6C4F4F354869384C394C536D4C6A49386338385370714570576532505530384534343875794A6F384A3347333834745A39453470503248797A6575304435715641725633647462655837655557367A394B523353766947343861747A526D723047554B68616969444F323346725837346777786F3548732F5550523664665A5131484F367A615672717141376253564B796A394277565139434C4E7362696D6E6C4B3379347132454A7A61326337724F3034796164364A445333494E432B64727978794C476B4E4E3579704A577763646E7245543432564D4636364156527149454C2B415149443041306F79395A426A4E774172644669516579536678395850315773546F52446B3869566C4142516A6E5244576B675874704C4B4E537A307948454F766D4956686B77377167427A395270587A59566A6F325478356E6D446A5861634E745935635A35386634657475577A382F7562536C65536A786878783037364D4E4179385A70747574546A6338767464476A486F30664730346E4F2B434F486838536234384A4C42504B56697A63727369754B6553516B7563476A4E576561526144577457656559703047686D303570386731464A6F57312F5A73574A6D682B6C3367526F536256456E6939367161726C4B382B756D3870395278675670456A2B674A5663776959436E47716D754C34533462573231536F45594F4B78625A324C5674444638687852767435545657534A5254616E486562506B747654506E6E4C6B646B756C693978766558454C4A476C524D383832615264353676484B497863684159736D59457146634C5A682B38353571566D3348354B4D43703873386B326457362F795276616953387333717357756D2B633051336F4C6A6C596F4B41764E3035736B51755379417259416465794B71767335624B4249456170706B326C36555948564E646E354D6C6C6B596E4D353846546668354E4E764C63626F704C5463362B51703931434779426C6D6669386E46386C504C4A6B564E6B5635372B37517A363458706D332B4E4E4766566F6B567251357A69505448786D3546724955785A5A4C6C4A386E532F333276626B4E616B714256735032742F56362F77424545694862326A77715435456D662B6F62526B6978617939684E70625853505A634F524F685A4E695350466D487065536D544373482B47726751664C73356C523661534F6F6C596465726F4A30583570386B34503475334E2F4C2B574D355A3556674A7851463957376B6D78766D7938646A54763136623637394F3037497334353846746A587A6A4F4855466E773332506734334F6E2F5531566770386679385638433953652B7A414167682F2B41573642503173743431354F6877326330376A496C4D5632694D443053716E526C58555075436C424D37523332756F674A4F32624D5978714D4D436E456E62623273444755797A3533314C416F4D76496679623564796679586B736D546E71716D584E5A366E692B4D726E7835633174516175654873743451686F7949394B6378794B68615071665454307373495A672B6364784D2B4B78323359774B364B7A4B4A723179766F5578526C6E70764B4F5A57635A744A5257343645304C7046637A6E515462545174456A63634757476A42314770716C672F774276556B685878724D4769774B3757757867636554494A4D4C592F414F63387044497372345A574E5563775972626D5A3943386543342F58754776546B783752624E316B777A3678533338586E464B5135486C3045557258684B3647755A3862734A6A624E6D305435584E707A55307855686D354734794C6E57707947596E5064705644555A4E7447614C59735445326E54564A4A48333256744541356446657045394C467933665A6650303152594347635A46546D4149505552456C777A6442734A58796773736E5952594B796D4B4E61766375507567696F317638415234455970354A696643665838613255562B54784A6D396563497245706E6A6C347A47364B776C476D6A764B72445354544E6D342B506F664F4A36366A552F6B36544C796D444B6F7946622B62642B74616D68747049413868543952517151504A334E5A6B393965785351434E452B676D753674526E4D597558706B71756D794E30574C4D344553365853577637323641345379336D6254693257416B6E354F4441625A3679553254375345566B4D326A4D79324F4B34376730342F5879723672374F5162512F2B424A614C756E51644A38646A317963366162434C6633506B72354B63582F6B4F624C6733565236436D4E32376D48307978724347584B714A5A6257655339754738726237356C59593068507A664C6D61733675766C58612B645A5761675635763657746150356F4D42734D766F51355531785A565A37525A6A566E5548724B36657562574F66796870684763672F4B417364515555475850444C586256706F48796876786A546176664E2B4E7778343754793234327072614E302B30726B3254785276614D436A597A79386462375248376159666D61733763686F4F6A6949384E6968786B755233736677366D352B5578344645316C4E387A5A69746376616F4E496252326E484769725730324961482B544C444B325737367447682B6F594B2F6E5474474358313575695A566D6D4C476A672F72706B4B6F4A6761735744384A7471676F747A5A4F57307134794D6C794764505765757A735877567046777A55793062516F4E4636612F7058796D5358394D506947546A386F4B32794A4C6B6C6C626C4C47374E73302F63306F32586B4F54544F5A36512F67625534374C6B4B4E6E6A706961353164412B57594C36506D4879577471736D69653752396F6C457A793973307A5A66747A4344796F6C6C4548704672724374625031585137753366307532663841617A53304E686D39493073735779474F4D6C713846714E5053776B4F6F5A77702B70564D776839637844465A57334561497838324A4263394344745A4D516D4C6B5733544E6649757335726F5039747965544A78504931354B4F32566C38534A7679654B7649594F527936575A6B4D7033765A4F307442727256453969646E7879733654624E3977336A3561594B7632394955527755453338573748512F62317845774F33506756432F54516E367179427478784A332B7533365275494330724F422F704B68316A546E507668465A62764C30354C4D2B7A676868686932762B6A4D436F6C6642695445796B4971523175463437354A78756E48796B3235434F6A4458467034356C6D6D486C63327A472B656B7654795337356D445465767347586C3170624F4A5A54476B66665130425052783750584A3749614A6C76525A5746327A2B464141363355514C734642516D7371775A57506B724D5649576E35582F6B56727150474749326E306A2F743772514B6151726B7477717458545965794A754B5764584267306D7352354B517A4639394262454D5871736932325942424A396C74486E332B6F2F384154663841703338492B49787238543457326266542B3366476F5735506279584A387269342F6A736162446B5466736F71766D544E7843653832686256666363393662574D476E665466677649624F54353349327571706E7A70723350434D3879353637744C6E41756969797A795946746C78523344685638665077494858316958704C624343375038456376725A41774949764F764F716C4A6F2B43445A507A49544F6A6264477A374E35532B3879372F6F737445744A70376654564F306247384A4B78395242445A79633437505A704F506335585038414852305343574B2F6B4B6165506B33585A304C5154626B5A5856516B7461523243617156395A755670575A485A36614E326554392F77447652763155666753426C38576F674C73443734346C3237596C776F6950794E644E2B614571304B776E6E775778466A7961396F326F4A3552776D41396F6A433667657171756D697A764E6E4D4A776B4844436370356D6F5145414956563968375967667150507838762F7742506C2B652F714B64774B36394367542F366D6D787579534A68726D34556B44732B485942594B4F2B752F4564394462484565685A584F35484570335A69306C69787A675170496677375852724667594659683044374D62676B6B53544271425270386D58657A46464673706F4D705A5831466356332B712B4D35366450696E426154376B65664338564F4764633065714E4869355A64586C72444F2B5A54644B5A6D74565978624F4E63766241586538634F355469336E7A752B4B6570595079476F45317375654A4461584E543556414E6936734B6D4577614D4B69616C6A3054744E2B4575317950706D6267344F7939447461356238394D76304172775171424D376258796F486A4F57596A626C43576B4E4F3930624E734A6B6A6A4F6F3764556F57676A3045394A617A38372F31427A7A797732614C56724C4E715472524A637462364C5A31706B4F627171695930432B75664770577149512B584A462B6C4D5856744C2B4D64497952704B656B2B784B303045685A69786A73656738443279734C62576467706F69304B5456714A35326E6233595461695A42756E5473676C3751634679654857526661496E5642304D5354625454506D6163343958674B354474445478724B4F46424C394D514F66594A57307076387266504F472B6331347A4F76776E37375479754862782B2F30634C742B313335467A5578746D71454F445A70746C30706D726C705847737135644F695355703464733268634674346361394B387056446B6B64666173474D457461317150494E304861662B5A6656644A46612B4C487851672F5570386A532F4F64674B4D4D726353595A2F7276715167396F6C5157644F4A5836656F6168624A47635057697173726A535950585931766F47583064464A4E7673536D61467773337A4450586B632F4E5A4A7655367447645A616B354755447A5645766A6F6D475738476F342B5550766C71757A42524A6134624E2B3670727055546F632B797834385A7A4F5271364A656155683977623059735A7351574A5636364234756E694838435736382F72467A387167575872526D535962736478503259776B38566865684C3169644B4549692F77426135694A4B63365567586B687356516E3958486B6E31733337712B655563477730367478392F4967657976674B3234584A3657304C4C4F3262323368713359374833695A7A367056354F6B7347665177744F4C73632F45635730626248513864342B797934787A57713137753678745A6D416E4266732B51523634776573546A4955306D502B4D4E496F396834527A52587A6277506452302F6E33744743767432696630505A6442626146764C6435346631487A676249364E6D74734158724C58532F5439307A337A34717364614971547679733431313546673464364D663562694C7A5876626E34343872355354647637795330787961636B736E48794F715A535266616C4C7A644A734B3330612B46706D6E4F4D7656737A36395661616E676A756359796D6D4D73336852346451576E337739624B42555271734B78586F6C417474614D2F6B7252427A2B61686E2B677476515056585373335265552B644C31495341634A6A6672644672642B6B74624C6A6C744657794D307144574A5051395461357A77315A6336337931716B4D44754B72346A724C4D576A6757766A656547484634386873684F7474576D2B766C4F4A4846364D445553705450786D446A577953684C544F43713939576E576C624E5261616156457446506F547632675845785053516638617A74505A6A306C4837497237467271786C3243447379554B6632396142442B464257702F77424C58724458615262626F6A5157494C304673464C4A4B626858716E62707578645A314B486E726C314934356565516B4B662F7744546D61484F6E466C734E486D66354274746A4876354F6D7144444A713330493941484961367A316A4457416F472B322B2B504A5A387A537136477448456E6D6B50424D7236464161724F39476F2F707173565141474D2F614B454B43534B756970616E6C2B5134576965616C6C494B6B71596C6C6B6243665245326D5571376F72696852562B567238314D2B7271426C457131435179644B744C3151656741544B7A2F73744643336D5254324B367542614C5956634464584F55666B4C5A345A5774794678526D61636875354A366F4B58397761615A746E4A326F655474656364464C764D37717A4269322F4959367963393347314E633252685478566D4A57553073794F5379465768315A637972527655473173693141466C6F6F704E7670715A47492B7459357A523441466F69724B4B4E587034435A6B73622B6839383239514451496D693558446C5245454C4747576A744E764335324F4766306B6F49467865706F72624E3244506D5033644A50787534565536655872706E697A3439444B42613973382B5530787A7648786A4B384D4F546531644C2F5A7778695A334A786A5632752B56574B336C525366746947735751676F76364C574B55516464465872494E30534748612F5672365038416663686D67526763616F32426B3151524F6D7771334F334732457A6D41754D762F77426F563574515774556C4C316C3145614F425874712B415344723559384246474D5057654B355867743944486D506C3248506D7A624A374D2F4F7275674875627557316135753273623761396D32656A5A726F4D4E4B355A3076746E6D666D3665344D4550764A6634686C726F465257547870685A524A476F37744C302B7435506D6E4B67456B656B5674516570714A6D51784B754E394864506553545A7A787878383974584151535368465759573571344B487874435779694747764C70715A314F7052576830363153387645715A4C71793471524446793473326268487A614735503568476A37632B666B73392B4C356E6D393047676C76386554507A57376B636576526171685A3078484458426E746F737768586B4478356C32745668575A79347030624B3955654665503478555A714A4E762B75343643484254772F4C4373394D745254314433544B4D614546766D667058706F4E7144496F6D7557475A30736C7A4E7A645157536D7A734372427137762B316B765368324D53612B6A2F4147475A4C34324D4279364C68316A41315657442F774144354F622B5066446E31376551337776595A6B6E784D754D3172626476314C56584E52484A4B677A5A6354506B764856727278737236386D6849354566507574722F725731387261633535532B614A3974614D377151537273314C3173496364355545784E48466E304755306E625261634D795375332B4E3334382B63666A34676C516859776D3163534A4F4E31556D2F44436E6D672B43664769697579636D5973673246644D494E5779364268356C2B634D59684370684768567A4842506C3379626E506C664C4B764A357375584878327254614751515566614C794E4D7A563036484837573272635A637543466154706E6B737031673133652B6C6B7844426B52745361616E56534D504F733238665A4755716F633261434655534C7451313154486D4B4F3549437436326E5A3750766C56615A647A693067547247495269355A42574F69594752583158396F44585A636F3530496D41546A5356563173697966694C4A4C36336F736A617753394C55396E476761547061706555794973332B586B35776651664837596144306D2F5A6254507949615454316573656B2B6A4A7131386865504B4B324F4D71493833735456596C5A3537364A5264534739457779386645526231657554433265476969334572363553773161305875717078416572484B656E5A376870496D59633855456D68584F624C696B7A5430344A62457268623877687A645046594E636366384C42335733305767627031646B42544E667766475A516D5533314539454B793138356D316234527676317769326A6A666A75703346576C6A342B4872354C6C633265464F53307A67754C4643345A39386C72527672326B6363566D466E524D71435A645546764747726571545646726F7154364D7964796D736D72556C3148714E4C74682B515850474D2F75504E7766592F4E2F47765A3877714F676F76394E30574F62385358707259737163786F6757726933546476726F587562584567635932314769306D6A347A555A4C724770626A42372F795376446372672B2F6C794762586D70476C587778303731722F41484459724A3552342B49794A4A4E512B797470724F76686C79386650695A4A53564C616154635278334A7732724F76476165783659307461575A41305A7230306E6F5A31536B313866595A656F43747958425253452B767A3165762F6C522B512F744951654F322F72626739426252416165647A74362F5059577466535A4E797261712F4E3865727A7565426673567858414762717567725636494146656964334168554267574A79347732375456624E37744C58576D787739744C515233454A5631567058565351564A674A53314A5458706B67624B482B744D53555A35356F734A724B62726157645A786A43644B3965645A786A4B4D6C63436A4D78564237434353504A3266365A2F34415A736E4D666C4E3436384E653167307264376E7742536E7573497A71385A3438755A43435853637279596E42577761716247643959417434705171776B51317453505262572F6D2B516354466669335030523030306867724E764270554C584D46306A4D794E4B3858704F59616D6D725174544B4443534D5A614A55573367724A2B5634365641366557756456632B795A6D69304D6A526154724635737A6668554651537242764D676C5474582B525834312B36656C2B77656737493330584A2B635A314857516469306D5670394262613330534B535367596350536F4C39524E4B6E52304B6D6C517A37584C4554592B5447437862444B6D3539744D32437A2F546A2B70314F50782F47666A33782F674E2B7165566D7A63787975336C754C34766A5272734E4F38795331734649357A645671364A796A35426C4D355130372F62767A5041443877346474484C63786F73732B53617A46355A63632F764E4B35352B4D3143525270626C5A5A6E7576322F5955776F4862324E6C577A6B382F786D4C766B6B786C477733457636425A4E56315461666E52494268726A76424B4A74484B484F633169714E45496D52524E4C78526D6B5A384371746E57424F336939352B5463742F556269382B33355879362F4775546A4D30477A69754F79507032506B4F334F6C4B596A766C702F76456F516F32726B636B75657834373435374A5A7452354E735748556953792F4836316A43457457625171713837366C6F59464742366E3579306A77633143716E746B7858385033354C35697133752F77434B752F794F6E3232367A6835547066637A6F594F3072746E6E584271755A704930376A3277453157636A6F5143575631336175795875563832647679564F6C37514D6D4A6D346630732B57384838672B4D384E6E76364D6F35444558342B2F48346D7863666E30775232726C7A574A33746C3547576676384136546473676B702F322B76475A6454477232584F615238326A51586B306E673643304456723165586B47612F3673767369373949624A4F7A57703261364764574C55462F4E4F383548354E6D2B6C684343576D767847463977386C4C6D465A69324D6F6731587444436D44374D6B393653564535482F564D6B4A38612F6762466F6E50466845482F4146706F626366784F6437652B75626D4C3537336233537064563436345675676A5A64324F30746B3279636A6D74524E44543054715A3673396F6F7866302B517072354F71744E314F424B716B48536867573235474D6E38542F6A4B764679554A48356238674D5736792B504B57736B585A786F486C2F4C6E51344A354972347A326B47794A595963706A6464635852554F457A6F5957696B3344386C564D387635656E51355479767A4B6A5879587A7356636973587A55423638552B3375632B577037502B3567797A66762B5430523233352B746939656251622B74774B5130797649396B6C6C31522B3632512F486B50466441726166583448593736425031786F7577726952582F6D76717064462F46635257565664584B6A6E4375684D596A3258433269777348504547684A68794D2B796C627930614E7739596343624D476D41542F735A6B6E384566374C2B54326576343742372F774343667065307A6565696A5466394C3056566E2B515347364858512F42486B66482F415077422F7744476E766E766F6F6D6877766D5764696966617038354C6835374169356D39564A6C5A394930745A532F486D506E6A30355277713863766C7861622F61644F68514632576479576D67616C7A522B786645506B4E644844634477314D79785674504F3435636A7070534F5257783658332B4D4E4535316C6D444A756C4F2B757967342B354F45494D7979567A764578472F6C75554E57557768775661536A6D4769396D313865792B6248324A52316C584255706E4C786A5774437A5752763254552F384F5058424D7A36506F504B3761454755304B444A65516C485149546D5047724430566139584F6A73376E31707857456A4C57432B66365367645963562F4E5A754A36596F6B5043475171727845682F505974504C52316368444A432F466345336871305270735A57303646734C6D5A68472F334B386657324B744F6F30397265504A3147524D6A30683168306E6A434A33726F6254794332766D7A32624D72536A4A51754D6A7A624C534C36504F365369756563345A2F47536D355433313362776A6E2B6F386F6F7A6B3154432F6965356B376133495051732B4D425946624541734F707A445036516F433564624B7A36554A697169516A4B4335584358464577716E6D792F485A305756374E49766538476752504A716D3252764B6B34317951316E5A4B583459556D4E5530566B55796B735754506E596A75536C7A4F4C4A526F5136302B67305459475878376B4745585173704A43656F75766A333573724836725A7550794C41796D6561334C656344624D6D4241364A62637945305773622F2B745534584D3830717879704F314575746E55754C4A743043544E612B5953694A4C63425A594176674579532B47567457767532524B34316E7130622B51315134334C67525A566D6A5633636E7130616E7A65545042304376542F4651526C6F6748536F36337945536D6E6A4A524F31486A6E56495061742F57307649685650614571565879634C3335644567412F564364726966596437576352445031594B7444644374663074797376626D55734347425531716C6A6C375737374A356F427352706A30747A30367846395A797A7148692B482B7A6343642B4B6631632B4131474F65486D506B6E794F4C7136367561783847324C34374C644E79732B506A4C355279584858316279473970452B4973514B70625138445A4A6C64356267755771787132446938366B67527932336557347936495A33574D32385A79424A5A7661656C5036715353506F51586554767466356E4C4B4F6651712F72717A717447516B71474C32326D755932686A5348725A4D6C3959644F534441574D4C4F4D4D3639536E73416D5A745A5A59677A4B4D686832412F774254634A35576D7A427842746F72374F4F6A742B526378693475574E6B76725056654F6A6E39316B3958704C35386D366B56446F754C457931716C616834473534393172554E504D53576878574C6B646B33486655323973726662686E54794764715A4D35645A58625675596A504A534666345035356E574B76364F6B654D77537759316F704C6F2B657233567866514F7436794361366E456E7770684E79794664476570525847325475717464365A536E416E45744D352F2B75584F3862786B793258342F576262544C6B6E30703868346A47565857566C6644732B563838654B33344A695A6F366364545A314F49764C506C6F73586E4C78767866693947326B366E66462F43696A7463322F3250482F41485775664450512B6176345072392B695A7A394E4F353875766F5276384674322B77594A644B5A536E7A3942684853346D77435A3766557156593530686C374D6D6E735638563041716167704231735556544A54665A433970785457396A6336582B66593763485056786647366562354D534A6D73644E4A38546C383065394C3850506B677474734A305246536B457A354950534C57575753697A4179664131546B476C58516D4B4A4A634D5973316A48386C5730444A62787974535161693072654B6C556F564C4D42476C7977664E63583575454B4E39744B6F7A55683136645470484D74476548635562594774537143746B3170305957666B7A656C6F36565464396136675753774756303275644A563870654C302B55664C2F6C4F7A7968445651786C546B6C3437467950434B496D57674E6F3157346E6963427A36646363305339444858794D6336795A2B544F41766A4E476A2B33385A6E52674C4F736D48714F367156525A7A6441706B75725653696D6469774C474C514C6F356B44587A43754B366242354255566C32766E4165653074656D6B475455315332616F315351746E436F5A665945536F695A6E6A6B3057503674587845476D637375435758694946725053426770536D4F32376B4F516930506B6D726D3946446D5A504464796B6F79523359354E3836776D4D4E64414B42357A78364D75354D31564C4F6F7A46574E542B33355973736549456B6C32584A7A5A71546B55682F6B696B716B4E56334E42323769544B366B654966766F7537492B71527A314936685A525751563963646858425170704B76306265505A6B7378413630544A3877484A5638377975386D644E64413952772F2F7744564F585852497145562B4D2B315A6C556C677830304E6A58372F6239676D42305A66745672472B506A36743759657261466A485457336B3456764A476A6E4A5A2B554F56664343567659555565574C4D2B68626F43504A6853496341762B306C62523975345A503841496B3568614E397376544E49794A6F4B6E686C6B42346D4756694661306F544B4A362B664A645778342B624542487445356A4B6B63526C574D6C4A50596B4C6F314D4C4C65675832445176772B49634F714C4F584D32303671424259384944796579392B6E4D3535346155626A6D7931516C4270304C4E69733345364D696F6F7256356A6B367561577770434D792F5461534D794B6843696156724A35586E583265786A4B4E2F4571364D564862456741667239797869394E4B382B67622F5A6E4E4F4E6F497036736D736F58496A79775955746C44666175586A525A576339756C587565765665633136793853615653705654735A7569422B4C4E575764493764453534686254544757707172525359642B72626C684C4E703255385664385045635731634B535A7432696F4F5970522F75365170646A78386C70654D3162574C65526E3679564E4C6D7A4E5357614A714161364C563967592B6F76347639634E507346677A61705774797241747944415344346F533447737131505656586459436D506E6246626B6338575A4A554D5762556C72494B5878734C4A315652364A52635861312F4270506A477658386A7A63636C746935654F2B3469393672537265696963644D7159376555544F394530326F583038617049305A525072566D463575627558705050787436744542745A68576466466D38684936726F7A53346A497844704F437331714F536B4575774956473666315A4E7A6D79642B36657365622B505A646F726C61566934656C3539526F58564173684C5A34396F31493034463939594D4A64714E78666D696653506D684E724B46652B434131624B4A424C5A78324C674C385068347267666C4F2F566D684E63764933346E5A5459743730676C392B4B4B777A69584C6172364E4174795776626F66375270662F537A756E6B54364B6358486B2B51585659694B5630734876616D6F5A5A545743763638633371713162466D426455557953746A52316F6B2F4E6E2B7157666B542F3542664E57586C4F78383938722F77423366366878357758673866714D646D4934587A7A504E544D364F756643584E665154736C36456C53354E457759515738572B66532B3962615061553456736D4A6A5147434845383779677734635044726B6A796D69316465766B747065326153367272646461516A5359766261457479504D4F4A476D676B5A35307A5A6334716634336A50733934336368716E515A6C55546C6B6771524632516573544375366E4E4F4A565972354D50416B7630345879784B4F513559414A6E7031756155784654416F5539416C4630706C53634669455732775973424277374C794B726747347A4A76584B69566449466B612B68396A515774614E615970385474302F77426A77347A6E7734754C77536C6D567278635A5A4E576C71504E644C324F6B747163466B5A3658732B67766D546A4168364E4B476B4974656C487158765A794F6771456B42552F7743784A503442556444386B396E7236444B6C673941496E46346B72434346304A4F62514B44724C6F576C33556D647175712B4470464A465959734347466C7852596C66627262425A397074473553453433466C383447744D364A56414C2B577250433072546251725A38384C3154773036684271476A4E3472532F462F676558357555743439737A4D66456749664676796F4958386B416A3841454876386667662F414150706A2B517267515053764E544F73454B715A446E50756E4E576761427052513430736A68776541574675467435613956584F37745A4244616B516D30792F706C714B69424A74464C646E52634849665A79796A2F3652532B763238686C7A527A76656D6A4E50504B3271305533766D6C4A494E444E377278314A576E724F6937776C4B74664F6B79377544397A4A4A67535964684C49702F656972456554723541745544783642506E3076312B716633496A7A444F624C51724747515373487A65482B77744A386B7348624652744E63795773613454624B355359436C727A6D41467446397A5367304C6879305336564D4B345A662F53766A756635486A593874712B53386D654A783734597A78564E647034475352454D7977626B73726352766435306E33686E723065694C585367672B6E4F7336587A3352782B4C6B394F622B79547662526D6178325A6C537949585879713269576571615136436E6C37374247304E53744D344D536F2B6C2F3578752B5A5135524D376D7245797876794441725442575138795030435A57464D6A55743976474A535179792B516C2B70667A6D47704C36445A4452697A7069426675504F3854486E59636E4C486E346539384E4157337A6A784762546C6168422B334E754B6A6B6A486173513978476B30325767706E4346766369746D4F537877306C70712B75506B726C3836364E534A52554943766642704E62764D42764956594C4B616E79706161456E367474646F67744653542F6B657467554238775631544F30546A657545716554694F6455556458585A53635064636456514E635651304645747643343176487246376B55766A756E34356F5848787236557A74756A5336344A37615966754A586442614F624C424E6645386E6E30412B355A5277616C6F536C707853387554632F536B646B58766455445468334F5650434636426D5666504D394B7444556A546D6A476371763250576C55396B61353078432F38414A7069387570386C6D3355446B736F30365243367065464C7072675667735258536669312B4D624C2F466C78456A493167555739494A68516D71352F522F7A453630317A2B576333386735486A4F437838316E3059487832713468665A5058353172426143307842544753744C7572746D5A5A2B2B74707A576D595A326A592B485A75507A374E3759396B6443614D71716F4554463548337377566835755341514153664A76496A736E387363446C4C4155515956686657544F757357364572524371712F77423430667968567459393158446165327237626F58532B5436306F5832534775767574354D554E41315362544E464643766249532F386E2F485A4B4E30502B664D7A48354A4835364A2F49483036386658375A326F794633593141527951504B736A4253783737445244502F486669657770364C665536726B614F416742694661535666492F595833636E5154426D6A45744A67534B5866595658326F57692F4530435341726D4D51535445326A746661344257585275302F5657592F436D7632762F4373724D694D7851642F68784A69387976345767485A58727353536D744F6E634E314B587644742B5742542F496744666B396967423742412F3537372B72622B556135517362594A43547A3537737A75576864756A6D56456D5A56336F4743445172524F44574D3177396430373836773678504773494F4B6F2F536B6F57676B617357626638413031354935666B48426148413965625A734379436F55464E6344436F6D724478437454727A3641376D464A566A30763076664A7368624879794B5742752B47536B4E315143454875673866344A6C373643513749514F517669476236737A2B437537483946317574784647774A797233534F395636706C5136574766525163474E4C67514E4F67715975703157326B4135622F57436C594B776467594371556E4E52783661315A68565A72343338367467354C666A3134635732756A5165526E6F31513162446656574C77704A703532524A52644459477A4C41465337614E447A387054692B546648314F446A6475656A52686B69654E756E757A5A6A6D544F6F38614C657146364F394C4A495152724D39746B6B6E47597254523962495A44796C5365777075653658614E7A33526C6874684A4F6E48756E30766E4A68483358785369434D51534A46553378724B504E44594678694E2F4D50344F5879795A486D4F6635465670624E6D346649776B346B59385472394450346C6F53797679764958624B45636B57766757694B4736534A37436C53684B56556C436832763237482F4A6161755A41394F58544C422F617A6B677A4E4C54506943436F48342B6D656E35356635765334613143305A316F52333637485A7337553754534F534357667773354D484A35537A2B4D525155445A43364137634D5739687A3774716564746245535757362F692F795035512B5963317957723565356374626A64657A526D3475663234633534352B425A386E4231456F65617A6D4D443776436672476D745033715A6A795844635931416B44785A5645535630534F6A565633387677396B38372B62654B6E2F4A726154452F34306A302F6D46452B3759616C7964414C53544B50536C7743434B30676A42425851534852564F7350506845437162324447345868737769626672583331326C3377496D484D38533567786630722B51526E4A2B5077327A5A2B5254794F376A715632564A6D5863547272356736615A3156714F797244476B517A4F30493553354268763870342B692B3275696C2F5151717932434143686A2B544B65475167542F33363046523132303348362F5363622F6B677579682B675A4263786768683539374B3352613330796C675059515243556A4F682B666254627246466C416179584A556C517A4844365378425433456E53307A746C4C746E2B414B4D7561504F626555317246497A544E6C34666138354E45742B75766B595974465A306F30344E5437625A6E642F4B34676B2B707542632B616170753346346F436E624E53314E545564672F6B67367A52746A784F6F54794A5730535A3941646B6A72365945325236644772305779307A5538582F4141784A4C7A4F6553707A33477062733131465761476D546C6877636F6B727251386258437364584775706E626344776D6D306D69372B6D736A346F6E4F38786F7938507765506A6441756A4C386B3170586A717A342F4F6D6A2F6F36364E306263317472626B49454E7875425776676A50785848476D79756B536A6B345A5972625875617A504549325A524B7667774C4C374D3059457779754A4D5662526F70545457705A6D4F6444365667435064716C79664B7855347055754261504C517A4B4E4E36446E304F4B7A685263794C526C6F6C6D61564B48506F76705450694667654C355A67305064493930744465324654496763526D4978582F414B61344D71583136644231626C342F3768316E78746B355338525232306533547330325468755053637464616374796C596A3035337873587470684B667A4A7A726261704A5947555A4D713531746F7A306D682F43696A4A44775575563659684A31713150384151476E6933315472326A3066446E61524836523664364E6D314B79477166335A487A74684463626161704D4A6330523872626759764A5A645972326A6F6A4B534D4D786B72474732307467344B7A65612B764A4168686A742F774153342B33476358504E782F463773304C63634530636D6D6A682B4F333835723070616B5A354D314D334A386D63696F32334E6D303563474B6A4A505776465267542F635A2F6479614E487345676D6D6E74552B69666E4F5766784446716D744E4538787458734D3039476839416B37443071774556535448383874536C3478413838776D6832505A396569587664584258352F6D4B4B4B52616C516C57657959794568756E7A646973472B766B65432B616C554B3654703246326B4654594348443861666C6430343563754C6A32754E4A41354C52666B4E6A36734E4E737555576E46787253756A6D5471596F636E794B46746D33556A614D575374485450384158796648427776332F49304C7030776A78774B73785052433033576A316E457A2B6F475750386439324C644D6562532F6D542B584765536B61586D71796138476B69713752304C467A514446554132575756647071304F736262646E364552396969745946566D724E4576726F715853574F6A6158516E626C376B766A6B5A746B6C4330744F6A517A4E43394E4B354F524D38367578324C396839786E342F462B7449666131614D70566C57657145726B5363706D79386552526651586B737972494B33744B6A4E32436A7066576942776F486C5A2F613639687649674B69536E6D582F414A50505873384D313774736A352F726D62514F497550304B516E565A7251357942646470306D41615851436872586936736569642F595A3066476D4751486C577932566F316767316731506A304B317A6633586B72372B4B5457757666786D4C6D5A4D6436725368714B33706D5264476B75664E6E32706F6D66576B7644775A6E5056654D7A6F6130775A2F7437744E707A305538484543797166386452537A77482B775068343964396764456E3659724C386957465752703131487471696843365A576C78477A2B5279714D67356D454343577A567449616C65396C4969424E4D6A617864414B786845677134704C45364D615267322F545034725754366F63595A32664A36434F5335666C7462546971736B382B594A664650476C706F69616F38636D424742744A68463070457271385261656D636E7742765856624F364B355374657A315374566B567345505A522F4A796E626442652B2F716B6D702F496A3237584D746C514D2F39505A594F4647614F32426A4A3530315851334E63724138786F6445436E36737A2F5352537A5278557932336C724D75356E77646665444E6E4330315734586D654D6635496674734846346F4450707A5A6159734847354E744D38665853695372787556746D33476768455A386D6230353944576D4C366177536B57636E34305A384D2F625236584C43744564724C6E6C52757731364C51796947362F7744557032585964416558353672457872394448754A636A5A445941727951597156644E6175792B304C4F566851736852514A437370304E617945762B63306A6F4371686E56566679552B417A687751786E3450355673356E647A2F452F477553676E766555786A787931624961496D6561582F77424F7A365532773152306146394570795370336149706E577A6632374C6D734C75346555557A5075794631566754536F696A446F396A32574530667339414947596C657A3134676E36737A35332B506D72326864626A624D576D597A4930754B71522F6B4B37725837425A594A773469754C41436F704145575A654F44594D32444831424672414B6C745A6E6A577165524C647758785866654D74584C445844696D6C6B7944454E41546C4E66485178757A374E2B68644B316E7876497872726644782B564E472F646C5456706D3257497A616774386A386B686D543034505657785975316C55746E6B394F3245356A763131644141724F474D6955375248486779336B7A336A666A6D4E437A344E2F6C2B584E6B7674675143784B7A332B7A36533933665A4538576565646E2F41484E693962552F2B755365337475444144766C514B755457644B58312F384144642F692F77415770683361383345355A744D6C32626E4B485A48484E334B546E70586B5532776C743547376933463848784F65396F777175336B2B5332744B686F76486D4F5873302F4C66705174314E765135672F366B646C3267737977444D4432475058352F4250307844636B456645394F4C6C314C654A505A467478612F77445837563872413779526C774E54486F7461494E654153624676316461542F716F55366D6B61316D68637565686B5133347A682B4E78597261633344526130633838764835666A574F46636D50565046794849367235734D6F5856396F666A63733950736E73743937784F3735447334766A394F484E737372733250536B6D30614C424377745274466A3565414B646F5862736843766B2F6E306631666F4D514152684435366D7432336E2B636D444F375350645771537242637A6D5233494E70464A42776C4265587931674B697067644B32665156756D323572686F35623133413574414C515774674D49357A586C786646766C476E48677A5A2B4E686772473233524935385355614A6C71666B4F5334374661756D50466536626367754A75482B4D386671764C68637162747A3463536D654D396C396D463656717A7265546A774C5057675277774B646B42504D4B41726C67667947626F393957572F4C6664624A48724E4A2B734669644A47663841337863694643526456514B6B65767634304A7275435A6A394942754B5770753974624233633533397152536C55514D4B2F6F4A672B50542B50344F544F336B4C616748384C777452633343574F6436624A787A4B42444847754C624757376B514976624F556865376553532B692F384155692F4955356E526B624E504E4B564753666C6E644B374D7838497A6F396E5661323765465234574A4D774F2F4652546F714C786A3148533766572F78644A4C524F6D79326B75796E4F5075614176346A565646584C43543950654E6F474766724742725A523436424C573958516A327567674F6B6932752F592F6B6646344F4D346E48796D4F66455A4D46744762462F63734E632B635868734A456F53475733484C7961616E524A506A315A394B6156426E64617A54782B732F7A50707271703566656137786B39444F303661306D6965506D7864316F4A546D6E372B324C697353675A463658723664516D704F6F65584C73684C5253746A55583164354B3969764C3143683357523232316E3573654136696A394A78373031657850617046623478745833373755324E4578656A56426365646152392F4F4C6C303853586547766E4D6F6F6E47637869684C566F706B354E386549362B5035626A7A567674613234326362536D4F4F574D632B6C59503841644B714666504161467179654C34305370706A72516F33596A657557486F734638724B6C47566E43457A7032614B672F79757A737468346E3661736868566D44645A764A6B6B30444D68674D4E7162534B614F7462772F706D4E42342F52615A716731504E556B464F71373168777172516337506B2F38416C4435664A755834495577664A4F61355756327676696D65334B6649654B746C79314D617A306272716144557568614161644D73395943645950464F69506F74386430307863746E6E7479386245744F634433364D6D6B653039796F4949786C3467655063785267542B657A55646658357259304663434D4C6C5A4B2B7054542F5346444B767435326D71786D4E4334634B763972707971744D4E485A337745756F723541637134667074665A3353774A72427142542F7437614C34714F6C56514764662F6A7465677635362F492F2F4147477067463773772F416D434C487944487A444555716856696F386D376F7842374138752F7A3339476D4F364648507346644E634C475A4E796D6A6A5136736357665634636A3734782B396264506B415362336647523156646474336544675858567A496F68796967586D323153503243725377364A495542524E76312F397246355541422F4C45676A2B52394657696673362B4A3637694A4B4376526F52576C54346E2F33426F5569535233332F414B6E387166707265646B6F31507053632F546E46383742796D704A4149557361624251354B395454657A5A776370376736317562644D56596D6A48753766644A594B3235574E66306569795A7A3431664E782F4B63512B6B71735A376444325A53503066335A7A4B6843676C6C416E6469657639572F2F4146396B4C7A475732766A2B54704A663868706D764E4358446B547A7443714A312B71476A657441542B434343663158364470723942353571693138536A6B6D6D3870626D4975584173375672494934447443533479695956394E73424461776C4C79445162767756417172794B7A78717A786975554F55796D5849506B432B77433743565742615A6557683947566B6272734354544D6C7168426C50517855674872364B5A39614E4137656E6D7449777252517968326C6F6B734E434F6A65537577422B346164415661304A65665A436E3631772F48332F77416765735959346849387755745A36326769455079724D536679576134432F74494D4E4C464D6F4563444C3231724F736170794D4746576F72494D426D6D546871326B7842485434664C487A4172446B7564664D4D676D4A35646B7354372B527057706C6E77773156354C42576D695A3879693548585665414E58736F6B51556A354A786E326C6C766978526B75777652394F6374504C497A547A7070544F453959466831324C706F53565179537A6B4F534C4357652B4D76575677444E7958526B434C6749312F362B747457672F537336525A62594D62384E6C3434676B2F67675359546375584D5070436D696457466933396B5474764866484966483838644979644B6169726139387161444A70586D302F38417133766D534E4D2B685A556C56305235314572446B315A466F4D3233563061744453596C7A2B456B75554C44324B5147375245636D724F434169414770495A55566944315848542F414A4C35664A5756413451432F66743754694B726639536E61765844664A4B49684B3472305A30766D797550433755534466334A3561716C5A476D4A5A646C56643145762B58625A4F5A354841334C4C78445779397349376562456357656F5479466D793866364E33334D664A576151623261626B65714B3548456F6D316C34427659734B3735345656676643455274336C43414232397732645750582B526D506E3253307645396441366A3832664F7933746F666F486D32713876342B5972367442733852717958576C5A324A45787743796E55765A713869364E3541597959645931476972484A45676C4C767052444C59542F77434350544C4D324C525846674E784A6355744871783638575A4E4F6D4647764C4E7134367557434235395430724274524A49665752537A4D77446774556372777A38672B334C4E686F6650564B79745478444B712B32327251784B69705068334F44417356696E36714C544D4E566763437575644D4E566E43382F4E69744D54776237566A796732626D735851716D447878364F6670475439537462584F793651637738304373696F365A67466479327776514C79583357335A4E5A6146584966526154374D754B5441786E566D4B5170776448783450515A6C712B547256472F4E6F6C504C436937626A373748594A6E3032506D6F453552686E6C354B773969335964416852354B585873742F782B472F4B47632B33486274736148354D685257426D6B6C417739486D6B302F6E2B4F4445647154614E4749426D416E526571335839436765356979647633344B362B3162614B337A70365A6B3354647534754466385A5470704F596E3933664C567375336B4B6159615163744D7A6368436B654F32576F356C6B664E6A572B697A70506973393979746E4A574F444A6A587A30546D6A7A70354A6D7A554B6C4738682B62325565646B41506C362F2F4149364851412B6C507073656E70314B35773155496E4C43774651655953305956534F6B4F2B5235765A536B4B4944333659425A6B4E45564474467A6F59497371343273554669305A30676A6C506A6E334363587953665A35704775376D49623962544332305A685A72327A61644849775674575A4930656D396F5A4C5A4D4B4A6C4F6A646D6532344E62354E676173425169564A5A37546770487041414B753337644D437A723541456439394C3334394436675237636B6B623238667A4C44307835354842337734704A4E4645796A4B49444D56746343546A477A4D6F582F414C4635676C677A51776D4B6A6C4E4A56584744416A76626F325A726566473853734E4C7A584E5A6457464E4775506B4E426B2F493868794F6A4E4C56736F66755A54545041517A2B716B634F2F6C4F623476466C7A52524457414A702B7145667554347A48582F4148516B41394541487273482F77446F666F4932484B4A4D577767334B777168476A414472336C315A33574453776F617667793278557A735845537274447369454D416378594D4C704545416B6155305551634B74714F662B79592B6135546B4B543037636E6E6D464932692B6F5671745A316C6B57523576546132696E76795A78624278324C5A76754D5843635562724E796D656A7452306C4661674E3354784C6A77525562746768366B714539457550334854666E70462B6C39682F44394C75697A7A3744576F755836585145652F49706354712B3149754677536C58554F53316C63315A45316472556733474D78703157784F2B754A634C6465744638563855747A4F69572F6E62636A68343535353945593074576E4D616F4536476B305674586B2F374E787A4D6C4A55354B6B4C77706167797979624E2F32633173362B5A5847706C6E43563067416B414177516E6F443244727876304F75302F6B66386E723673706E76444D64634C61753474526A79444A70596C327342726D52684E4A63792B316E5475756E614C554C4575732B685839586B56787039627634626D4B716F4E624C5164487837347771347345506A2F4835386B3163497A79524E4F7A64467A6F33533033493037394774714F2B7252433235393873744D48443863637A70795049626C54547A48497A5A3650536C4B30486A306A45536D74575656434B4430697232542F4851556B39644B5439476937797A796E49754637556D435542716158326C4950584A57745A4D7952312F6279654B7170526E6361357555544C4A75477059644B73673072595731515347646F5978354E5043384A7955654D6D2F4338566257776D4871305A76587476553146475A6A6F2B336A74536B59353873357855596E6A786D75652B4B3867304C366556335A48736675625454396E363968436C5079782F502F4D2F77582F446549594838416A364F6D4E614851584133554C434C43666D76726A534C6432634C7831394D434C4B7A5478494345587251795676435A7A474F69717269716132415353667A6D4F734630444C793339687A37367835464A592F55324E45592B7431725452712F4F5747566B347648653368544A6C656563646D6A63666C666C74474F777A443454314547587271585A512F73554E3134737066397776665867696C3338756750486F6675565575544845723251687A4555572B70576A674E5A6363465479776453425545776E66322B75345770646E6C455A476B6143735379505252553857376C327342557462633035564535506B787648486D76766661576D324453586361726174554658335656304E64764A6170773433587976767A4F322F705A36654A6A77324C6C707974692F43457561467679575874674F682F71417049594F54356551596768523054332B62443539586D7A4E4B63553263576732304C4A5545546858624931414B4E5174675372426F37664968726F52334C6B525362655262515250623653536F697871395747632F77434C576E6A3330595A79784C42495872614931666350474461364E6535306D6345773078596366463461386C6C6D493862364F472F744A615076356655597A4A2F6A5A56596B4B6A4934554B565A52324738533351486C5667716F533355795353516F4A2B675273357A3346625A345366516855687750754D7069665345434D5251524C706C6C6A692B6F55495768653345706736656E774E744A5A7132314B63762B526E525753503779474A75433430352B52694E61352F2B6D4F693265574F6D544678466178633663642B717A313534636A6F6C4E4A54584277757A6C367849626D76376A57733673326D7663466F6650756A70502B6536663556546F666C66466D5058342F59495377486B41774E6C392B6E70317557644A6D7774693456674551477A5546317A725A3258335546337948506754437472386B684C44625350737A6B584D6930636D75745831705463752F4B6458413833384931386764504532314E39364D544E416246666B4D79363630315A654E6B4E6C492B35646A35754F5837666A73484838527849624C6F76797A65503062344F57374C793845725051414B785A2B68363338624D7173725662395A7A43654A43452F6C3646783266716A5835576262302B6A3869505A6D71543062634B4B6D327431414C4A444B4F5979395457774D6E69325938564B45674D64762F414477466761395977597850653856687971625059794E4C477338392F417551584A38523451614467354638574F656448627735626A5A52325A3864476D7A61754749313167444E4332626B755254427644707156373474504858634F647A59395049636C3763364962373944305A52367454504C525666597971566F705768666F6C523751523135717145474F622F414467314C56696A48313856417A384661542F3379725A554B7A77346473444E364D4B6161616A7270674A79565A49592F774245474E44457A355530374B6577463333344654343331796F33386E6834692F714F795048486A636E4635786B4C5674683257356A447757376D4E725A4F67797A2B372F754450474C6361645374706A4241356E342F6469326A4D64744A73516C4B6A514E565035364D337861595044702F48776678695A2B6F6C47374C416652357266796678565764446D783830385576565757396B4B79306139705A4E6B6438553548716C63557A2F4C713530313876726E594F6953775943307A456D5965585A543838693730347954563543767A3759756C764E654E774456786E49354B7969353875533138576E45636E7A4772584E6574555A32325A6D7545394F5A355A2F7744537048672F66347A48456E336F4174745068536273784137563269634D6B6E4D6771503257593641452B6743696A612F6D3363353833753864583575744A6C6F35585A6F4637564A547273344E4F68324134595361587148476A7371653030464653756F57475A756E733139386868617152615069467A44355638722B45374D584C446A4D4F362F4C636D76573752756878633876754D676B336869752F4E636A78714B463656633165504F783266626F5A373171475A754F2B4C366C32594E4E4E435458465362724F4662733367484666437268717A7151522F4A76554941516A646464356C4E5142575367616F55556E743537426A66514E626256545A47424F74507472706E6662384E50624B5243415633503249736854574A567A6B3678526C39506343524769585A6D4254786944356673346F6D65596344387566454550346A2F4146384F67414F2B672B5571747247714D784E6663394F324C42312B34663173436579515A2B494B7365782B65312F42364754336B2F354531673964484B303976313452347444695A614E6156786C4F5A4E74644D7045784E59515072352F514C497669465A5252542F364D524B71654A546975383141486C706A4D6739486F764A2F59656B4A3866776E725A6C38656E374959452B512B7241725638534B616B6A4E715A3158784138557167556F5743676C565A5452537A454155434B51714B712F5453326D7864776D56724569622B4D71374945665973476B574552513169772B334F633446314D37697A684C75676A694531527049374B346D457241714A2F584D50324F6D61537956516F38576D6E586F446E2B4F776939416E73756679783762382F5830476A725964465A755041396E7A576755426C58384D534F3250344A4142503450592F4830524D4E4A4C596754734C4C426732347043684B362B754E527A737363306B4F3430386F6466434E35305644473447794D37592F597A516C793033682F51672B7A2F727652744B65363171686D64664A696E63773035496F556A723943794B502B574238322F5879596D494E3634694D3549692B76395638522B61436A74542B4F2F77412B4A41365034363643672F67446F5856746C4241583859382B4C436F4B762F4D36625346563476327149784B442F72644D427248357A6C6B78474970646E3657574569674264766A664B582F4958552B7A376D44556E645649566F6C30596C4758396B3843416C5151504336654E55425A556F466467654A58654577746D3975636C614C4D6E736F442B516635495A44312B5A30386C492F42516A3866547A6C36303976427472317A4D7071354C4B596A467072687173336E364969456857667365446E454E594A68564D6F6345354C51726D556F586947317873575639726D54766678622B70735A63644B334C384879585066497550534B5835545239766F34656661306C6930517A5A4C79457270412B4E313544694E67656F6530747972536D624D6E37666A75504C6F70586A4B5A385048364B6C3164435733686D5A6D7448376E56587A6C4E326F4F35776449743130796C556D414E722F527935663841375A4C733363723554534176705663702B74545656324E34334B714773704A5165672F56352F303245683232533544366456643042417247757638415650527A634E634F5A3432572F4471517A76586935446B6D775A54564C32577A2B593075794F4574544D6E46696165417056553866616B533841736E4435394E73376A392F47762B4E5742412F4B42514649372F41423043564A2F31556E2B573769664F5558726C4E6164574B4D6E594A544F6958352B305779446F382B6349564A3064726F645546435533527846696D6B4E6C414E367861784743577A5A6E4F6C77523065333542776B3837364D6B37616B7A6D41342F6B633270632F474E6E6F6F4D394168483036726176576449577647637733457A4B4849396F6145737231744436385449474C55442B565337576F41714479424B2B586C4C7A4C465345646577766E30423131394D567A355141686543564C764C77787A77416C6C465343465779335A4F684C736744306871776965394E70713437505454585775504E62386951746A56654576736D563034726E782F6D574C456C644B35755635506D617070676C4B5A6D31616352793546793645764B6A7078304D5154513348547A6370666D4E45636174353536614D314C36716B4E314E59716C61516C4F444258705235524E4451446F7A5171476F414350466969396875336345646654417972676D304F504430705172496C3252615549493531435974566244364A6245567730656630496D52747469496531414E506261525A46516A4C62543777537377426F346E355439376977636D7A385669766852734F7A446C32484C782B43326A465374632B4357724C386634582B36636C773865526E7134374476352B334C59773872634F384A56343978396F786D396F2B64684B692B794E66536C54516971546373734C58746E6B724E2B744C536D6C534F6B5A67535156363237567A304F515734377A317A726D6C2B43794F6E41735231746D3179784E566831617369365646617877554F76726A33697538716B774771587A324A2B6D544E6B4A574B48344C354E6F6C7159515842504F656432386B6334427A5A64642B5162512B5556744458783752766E5354337A365A334F6A6A723576754D57724E34626E7554315A4D666772334A527842596C3270525176705A4232796E6F44746E554951774239696E736F44394A505365652B6F4D7962645A576C7379465656564976394267436349517156486C42386C584D38332B4C32304D726B36702F535855444C4A462F486456777337735A335844544C796776666B656234364D6F77577464457652656B736A4C335332366A79346A6A4D6933794154653748566D755A4A585A44573832593059614D452F44504B577A58576A454B4B795953656750384143307A423159442B4F67374D66345A664C736655694A6852634A5742756E715451624E2B7A724747564874386654477453446E675677536B316657646E314F57504D4B67454E597A4A5259386654364B69306A6C2B34347A36794E5977384E6D2B4234487A58563932724A6E52686C35625279562B51774C4F6D613061586A73344C44752B4C2F4831694C7674704C647A553536624A626258466E4B2B346B623674742B6F6C34357074313535346F6957597165784A576F737446582F774343736C736E5444734D5764424B61417A526A35536B697574384247635759697A4D7443576A65314767696C46704E346B4859466374545A34345159544F33324F44644272663153316F4E433573536B745175792F4950366D386C7334684D2F41787073343874486B74764C707847584C787649366154304C37345A5A3765524E6E572B673058654D387541396D376A7553344663776A68304C516E6E78727149706F68376B6F42544D576F786C34723556397450465A74514930326650354E5A454B763441456658584465334D7A722B6154724B49546C642B6D6A477A37492F4F755468524C6C576179646F6869346F35416E5A414C63776F4B493038737977314A51316D684159614A6E56724461524D703550352F66696F5279586558757930746B504B6274567030733034725857625876654F6D6A3639545231364D6A36596E50544C786D7A2F41413732334856617A3537555637444F6A7569545950444F697134614B4944343051497930734E4530647765764E714966425664544246364271566E6E4D71746C35466F39535766574B756D613742622F774372362B79426B336469746A526E4F7A4A326753357564707847626C38342F71686A77785953545A496D707761345945666D65446B526B4E78696E6558486E4F706166322B7A633761724A492B4E36497034334A78734D4756654C724F6D624B734D34673861552F4A4A2B4F75534E4F505252416C474B4A374C545A465A55387631644A426B714553336E2B7770354E4C6F2F62717A3946486F7974726A5A4A4D756D61496B7479733871746B73376F484C644149506F63336F553574326A3035543432743037637037454C45777164415175445A5835304241316C614D4A49772F79576C34592B4B7A6262386E57576A516B4955677253726D796F524C4E6F787A6179576871646A6B716D35646566466D7256627935506B615A75517A44753952307471584973584244556F73776C58703047496C536279624F3731536272584F30326D796771792F6B6876654E374F377A6A302B7A4365666C724D396B324D743358417A55745339457672566E564A36564B7A4D51595536613570656732475867367A596A59363966415934624E5070616242334E31476C4532355442723076757938302F4D6648754F333034376B4E6D6266435737487874444B576A566C343354726E7678643437303259384B34713578704B5173314A30314331323874326E4F37567A67617171706B7A6F77576F6D53577657692B585A7348587433666F7541657958386D5978756D394B7A76724E57684F7A75724A4162715437486144633150426B6C70426A7468302F5267436C56523465724B4E646158517145366361684770596D475A2F4B64585A4F2B6C57434D72386A3566514D2B4834627174583542586A42716246566552586A754B3548546F4B376D67317159412F47303063586835524C4F2F44364D766F3475656E636E4A635A48624B444774374F64584E5A577977526E514C35534833455548556F4E4D714637482B705A65685653797531464C4B516656355370325A6E624E6A6F7A614772706D4E71614F4F62324145434F7142654B783352574B3050565764594358637644637930506E4B6E4B6F76304543764A6771614A525167465A65522B57303448624C66386E356E6C613866706B2F4A342B5149744C54766843535577634C7477486A65467A5A6E754E4134666A617776734A354559645079572B5A327347436370495431444C4661416574706F5459656249336257636D6A50514B6A326279507464464C46697164455741387378326A3945533036516C7A765546756E793362687A4268503958306747664F6A4B746F5848785830633952754271796C6C56544E703647723946745849596F41646C323146664D65436A7962326F4F517863585869382B5837476E455078584661646646353837354B36566C562B522B5541304C4B2B6D2B4E4D6D486C3551723456527336377165656735786A2B6E5A6B6F7A2F6D645A6E32656F5650697267394F477937423130504C756B4B6541412F313851567A572F4A48533242657965785161433677677870365875614B66374B704345464C747A6F7556746B4C567357432F684E674D6153694C56345534476D7A2B553455722B69614D586F4878485648692B4334334373796772782B4D614530386C79546675614A61395A5A65523261625A37315068444F316B707865664931355A38342F784746486B312B353337617051466675395A38677041557273305438652F4565425A5A6F472F312F3144742B54354D6F4C53593941566C4E567178524E63645842565774435A51592F2F4148625752434930394142596A6D34493754436E744C624C75495343706E654D52483949527131657566666977323034614A784F546C65517A4E30733174576558542F6D324A6C3547764534754F692F686E5A2B53476A64786374736B46546A726968733042666137765A686E566D50595568375345772F2F424D6B38322F4866387261702F5052682F4C4A316935355177744E7575566A51434B447444576D73486C6C6D675745784747355962334F43732B474D782B585558584A6872326930543962657971587770732B765A4654676A7A484A3642776D7A486B2B4F38646E7A486C57745443312B537A49626F39396E434E70356A664F717042716A2B31366C7A546A4E7465616D6A4F6A344E557233726C6E36395456745A36414C5245736D547A596B4A4E4C684A4B614C3252324A326F414746494269314A684F6E6D5749314D7055464D6F30583972513339736A454F3230616730556D75644E49382B56454C6A4C357037516270316939726843766B71364B52724A323566386935534F336B43734A536E6C34334F4D75503152797235354974306C4C5568673430364C7569675070726A686F703545504F6635514D6547646B79674D416C74444656587A6F78566D50724C453070512F68695346396A4C2B5035362B6F72513272714B307152584D723575782B7157535A476F6353787365542F5158583157644F4A6F4958797341556C58535075684B70685964526247304767646E46636B614E4E725736386E6633497036386B6D574A43654936527643482B496B2B5249376469582F5031616F737056457066736B5A4A6E6469474330496D714F2F342F6A7A71577150456A38394C2F71664836434C77536C49597848425A326B7936514E6F6C4C6856506B41695654436B5375323863327930636D5846747741314E52413967346B6A69366554695247457066794356337568666F65534E6D594565637A524559394D6842483841644D522B4F2F782B53444D4845446A496D7036554379743565757858523679437048524B787241676A2F6B672F37426D487549685037594575345350444F7574634F647850597A70454570745868335578347849594E71367871414B6464585257355A5863685455344C724C504676424D4C71724C704B6D725757704B7864426F6B70366F5638694136392B412F61662F3439666A2F35374A4775554E3275536965624D782B337166486F68795543762F37682B56364262382F6A73482F6A2F514943764959795857516F347172474F6752336E373030336E3331314E5A6738414C497175747230444C7341653332777041527A2B45697574674B4C794E7678444A4E7A5479442B4B4D6678325235465737362F436B41396672313130434150716866767576696E675A55625168362F436748706C416273737057666637646A6F392F7A39646E62716161573836426837506E5A416A446B4E4C4C724C496A4164566D79736A794E664261364C536152706674325A746E41325061727A32564E6442743330564B4A4D6745734A55566976344A667764302F4938657639536678304366352F422B6F48694765732B77714375627837372F41466931706F2F2F41484A42446744736B6A792F424248594F4D7577466C6657564947346D7A3431356C67775443514536616766764C5738366D567A53454B696D49793558457369664731464E31747856494D4B516F517163506865685532386C6E724B57695A7979323038687730326D4D746E6F4A70626C4F50334D74474672654563735765355652514F4A534145386C455777354756564366635752554D615861332B4E5232716F514636714347382F782B51423076386C574656412B6836384F316C636F346B456A786D2B504C76586630586C6B4A6A6B566F732B32654534776E513232565469725035454D6B565976726763513861733731314E725439747948796E6B4D782B4E344E664438466D30685A636E70624933495A6A522F4E3031637677664563527331667936755A63514E4F667A5661386436364B51477158344C46706573324F30794D7357517974706A463256567062586B7A68327A736A6B6D553561576D7A427646423132625A3666417173384167314F415A68343135793945485A666658442B71576376444974464D41476A705035364D7063575658506E3851425742645556486F777631346953704F53346A6875462B5135462F763349546F4E315237636C4F49614C31764B575671306C7A6E4C2F4141696E496141756647574F6D756B7A2B326A355061736B2B686B4C63356544507965505066493869386E6E683572485769783852356A4E6244724156774862376E3767715842525A4546696B5070665A7661316F6F4F647533725A615657747A71366F502F55745262575370446D334A43454B737134596F764935653276724D744C6169727A346A4453594D325542772F71304E474C6D5257714A504B4D387A4657354239474745373978717137476147376E3876755276646E7469625170573742335A76546D4C79352B4F3475365574584E2F6B764E6736753961474E5A304254785270524B6C51694B766A46657832706E4575314A2B377A536C5A33743631526A592F5932574972554A74614B394955427679566A706F6D474A707171574249524551476A7A79506D3842725631772F744445644750794333714E636F4A37766B63754B546B2B56345170505069346A546C695579317A38725659376451706347564F597936636670704265564F4A6344504C43424C4E676E72394E7154634944664A6E7670754A44616C362F3435547A547052474B70564A326870656A5250696F6F4E57566E38452F4E414B6838342F335879725761595739726C6F595172432B664359374D39624D7A64595356666B676B6457654C30574C78687143417562624A485253506A4164735144596D6336326431317456484969723378376B4E4849386763746F47317057326F734A69756C644E6C69744B564863596B764F55394F76517A5472476B5A7174505332524A2F524C6D4F4D6F754E627059674D375570343953555175364D735742495A57426D69486F3939304449665551667064593731454430424E6F436A6A736373646142796E415572694B54367073654631466B32674D79575730304F6E437A49476671724B70724A6F63316D667545714A616A39434B61474E756E56666B49506E5361795A6D2B336B673853756A545368524A5477724E6B564C46676954684A45717651514564644B562B4647653036702F31526E4132445A59525656372F5948334B70587A502B762B48313338767948382F774276723263753949696D4D4B6B5235634D354649496835715967525042594172714D2F582F575835366B444631515174336F356876663156454C3469736F5A32364863744B4E5266576E6A70434F515877343944356159563161575869744D65504C7743616552785A4B36737870666A454931544B364D4D7443554B6E6B426D53725A37504572785465746C7252644634304C52476D2B65704C56716E3239624C6D75387955724B626871676C4A45744D686D4E467331743968434C4A7342394B5361714A7970566363356F6B636B616838465A4D53326945454A35473959364E696E7572764B7663567269545273324D312B3956624169517172726E7A66336B3538666E3338316772664B3974385277764836674861363674577558492F4B465738306E314F676E7965697574436372796147644F7A63762F41432B396C4C59732B625A4A58535555313173684A582B576E48696657344C2F414C69547155464F36716F70526D502B797635506D34476E75666535484873327449386F4C6E786E2B7450376751624744716A564857486B304E513943796776546A7163307463727A425639374F393371694E5430656F4E352F636C58666F6F4A386C4746525758513158746D31716C5338386233746F3061747562524449694B6B5978583754506D5356445337362F59506B2B41783645476A4674764C7655396A456D755A7972435379676C504B576F6F6D68644E3675796F2F2B694C354A2B6F4F73442B546C2B713259424452736E52723259376E503243506959656F593049356A6342596A4E79716652713947656E6B6E762F6731364A5842717A495A55396B4A6C776376654B7258687A5934384E50436E465A63517838616B3631335234314978626C694C55302F666374772B656D666A6432752B5756573436584C51355069666A38734D526777374F513331577333495A2B546B5873723171424E425271536A4D545A4234677452733573614B6F4874614E355670306F3047766A50316D473939704D39333270593662505445417A3952696C653670785447483262616C776F624A6E484872586A744B6E616858456C56564E30646773314D33785A69654B746C577366446E6669732B4D34482B3637754D7A59655232664B3763516D7A68746D556236342B4B616C48347A4458552B624C77334C366E665862354F764847634D4F666D6548346E6B2B53626B636E46656C4F646A616B773557314D46516C5357704F6E2F7039395574594B68395069766C31522F43616F535334596A366E457A484757314C5158674C45744B74506A573561506B326458614D417463594B5A3337684A766D7265355542556975695934464C2F77423170566A514B61315A626A706D76732F355170657639343533654D392B45357A6C4A767535486C654A326372697A4E4C584C5479323457747635766C7176467052706F3163396E66695944374A754F79385A48566439786F7472323542464456715A465A6C686B74466277414B4977315658784E613968696D53636D67555262567453346158727348366C6539785439442F6F7A7A53705567517630576B39796D3873583471414A53697538365852734C6C38484D71305377577758736A387936717576734B4E6D73766F4934734F475A666A50426574732B5834377858334C5073747131374D584531356D793143544D4936766B48462F4964454F4F575561564554785574394E6579646C356A492B536D6A5A657A38707267686177536F415549695572424B4A2F7778654C796B39575545305068362B2B2F57414F6A39427276314631374E71644A6B526D6C6E6C586B6F6773385372794F45466A5472572B6749447A363073396C5348574833304B7A534E7A724B737354617A3879574E63697775307A757A4E7430526754315A347634783859347147354834676372727A4F697A2F4150563053342F4F45797044466B7934396B424F2B3148304E6F466F36764C4A5273634E47546B634E4F6532326465346D6D557A71364F456A667A583849467455716E622F6A796D682F46656954305042757936713675526C362F4365754973666749446D596E646E4B3357583237394235627639746D42632F577166476B626A5342634C486977554D5669374A4C50762B6F69524863446D75432B6F7A6D5370486D37664C795866677979335A644C78346C4F646C4B3074584C3549624F4B32347A4F50476A4A6C354F71656E4863455A783972612B714E735047637A586B4267773670464D5774693148535559616B746E444F3743666C56646442536B4F2B69676561796F574B71416A466C2F4C4836727836746C384E73665474303062586E744A50473756694A79553432386C47313861786A5678717457476C69636F6F6C5A4B3563782B716645437969325973534B3769676B7A4C386C625262446D31374E66444C6E79525452666E754E58586D624376725363366368776E49727133614A526B516D544277357950724D354A757852765231765677624261394D55633774576A30526F615555467A6133646B533169376535516A6B576B4B416A7A61614369396771584865554E6D6655755A5A4571697A4B69457A416C493274616A3130446738594E723334624E3441596168574B314A72707150514D4C776D4B363051626B7A4C784B613344696376796E33776C782F793165513466354279334A63646269427A5638553866474E5A35344C7A2B4B3134542F7741795A38713649357559666B4E337944626B626A796D4D596F6367396D79304B2B32586B646D5830336B71643247563651396A68692F2F577A6973545544384C50306A7862382B5A3638544F4C6C643338394365494770716C61494C535375356C5869315748525658527A6C5152624C514E786172694F79684767363555464732496B7073444B42626F2F732F635638583544674E334B78796172387458644C6C346F754C5438626E794456486E62567258443859354747375046345A664357376B626174324932507331636A5A326F3947326D476834397A715A7870487861314C31627855396E78652B6561534C4D464C536C514A3243466E307661566C4A73456F2B726664322B6B4F624648393256644849664865546D704D474D364C5933325679742F76467442363563377975567759665951726A2B7456486E31765931544F67434D7A6156646532506930644C5445777A394D517141392B514250586C3050775070357046596757582F41466C4F437150352F774456674C65522F482F466A30435078305176382F514B2F7742427A6A6B79364E5131417A735A5664415A586458494261654971704136554F4E32322F6E2B526D2F47522F59586434446358664B7975646E776A4556395452476C344F44374A4F51542B535168597541422F77426D552B4A413637553966382F5661727358536967424C51536C466239554C4D676D2F774353663970314259447679566C412F4C64676E374E777761343349584E7972376F3235566B737A5646703130786C436C31714E417150524331537472715430587365614E33634554623831397A6D62557156685473677769704B61537073434B76626145632F6A784942684A6B37486636674D7848352F774356363748522B7056576C5634384D7A6D4545307547492F46432B6749732B2B67504A446E446B6638414D3244666A79422B6C34507043776A4B706956416930574D7A687033476A414756516739543735584F364D5741784E5670315765627A6C515643717977453452635976375553497475716E394B47685278352B47596C756D6272744E453744384B5144323336734F6A326A46442F50314E513977752F37416F3877726A734D684B55506B43414F6D38677652492F482F414748313668663446484630526C554F446C5245574158306C7A4A762F7741704A684E79676256707045656D424C41594A4265522F6133734370416474706855535038417238436852584E4E535374536577435157736F5A55586F2F7943472F412F5069442F42552F5862305A6B687070312F6D7A6B6B64425171794C426D62732F68534F67574A36386D37372F492B764669505542446866616F6C67477772624C567770504F6D5258586C4D6A34774C72345061534D514B44514776374730576979495A59422F65667975636B54325748377A59684248334C356B6A38304D7A4F4C416467737174526A54723864442B52313061775564535964757A53794B56582B586C4733756F6F49372F7741726841462F4866663436505948313955584E417379617647685243733863442B74417169692B6372714776423631344D4B7553767048496D624F4D4C425978486F596672584F6464677763522B4D36557661315A4D3642685755695031396A716A4E4A675748362F6B48775966736532384758383932585757555A3430524861415853515850554574596531514177386D37374237363843716767456B66546A5A374E7651757A4264345A6D654543446F583550535A6A6165695547716C584B4F68745761764C707338456D615456566B54574F4B425437524B3342566C524862787A37435974343238346E475974484762575852484A41355A5135516D7565364970635677446671686C57635A317053557973774657435A755044706E55644446776C655265664A34564F46744E573342386B3239304A73315539645A51576A6C6976716B5254715A736266734A73702B39446F455A5A6B614D74716A32393763313559365A6137514F37425751782B6147457071366E57744170544D43355862524D6E71635468313575634A71732F676376717575773558354963484A446B4F53314732673170624A545671624D452B32676455365A654D6F7457654769666361545753363554577038335439374F2F4677555868446A4D6F3963764A55755949366D637255766C544B313262776D636C6B576D657664427372656669536A424C76654D492F57634A6D6E336E727279644774316D2B3956582B42673666536E6F4E6A566746376E43662F41435771737A374B662B7A504C466F6D4A63337642724B474D5553317865746B514A545A557748715375433533682F6B6E424A7A66783679614F4F355464736B6D6D4F5A38353930642F4935745A6E4B7152354A4E656251546C7139556C657A7237336568636A366F363839632B31426F656E7378356339684270536A372F7A4952622F41427A5255563249642F454247515034414C30514F65644644376E4A356B4E70687237504A5052505468567949337A746136635765632B6B65634B637266746F794B555879304A4B58302F79556C746130765742786A50565A6C7134615A37366A6C735661343846713048586E3439633757777939322F75564555776B73426A713571436B5A52334C7045644171776E6F545177506E636F34473872414362366864527339627455556D6658555663744A575870697A5266396F46523542454242483562365458765A7248522B722B305438367A4B504D4A4D2F6A4D38614B4652514F46517738393835565430352F3879744C476D74464E2B3438384930733637416248776B53567566767355337A3049726B346B2B527A55354C6B4A306565334248487947615332507461584B795A59453334353072344B4B7A665132512B39764E706F445A31552F492F616E4A696E646D744F34704F7250325253306747556B58362F5A656A4A4650583456516750362F554F426F4D6C35396F3833364B6C4F46754D754C653545774C57657870646C315A61385145724A6E52696B774766314B78556E5059704764656E564C372B694D566E7742534474764661306E766B51763861356962612B51347A6C4E5673643354547866507479756369793677414C61702F77427A777374557A65784E7039683879617A634D50716A48496E4B344B352F54534D78706A352F2F542F51436B645756364D71566F7961434D7A334B6F464B3064507947437343483065334E57357A674E493573754F763676557236754C46396A687145366D4132305A67307A4C4C68617A4C67727A6C745662455551616D5438695256394A414E633677334F2F4A365A68797A344E30385747756E37724C6E7A683659732B544D4B56545137305A3651744F41435543555852514170537A732F313148687072444F394D696663497173394C2F73453276355252504253336C6E524B5054715156576153497168713973304632462F492F574F54637874624E3358504B786C4636477230576362707A56757479334752497A593451576757564C544C754242794C6A6A767232684E5361566E33766D4A75377A77767954682F6C2B54507965506D63664A356458747A77727838615968794C3564527A614A615962636D666265754C624F6D44553173677037496D53693555462B65577761506A6C394B4A6B575767736C57386F476A786B367156367644327743736746554374327173412F69776236496B32616661764C74306A6654666A31687873753539417863637436743764714D51354F43704B496F6F76354C2F64434D79356D72464A5478543371327871677559454A4D75483132466879453854675A4E764C364E4879446D4F524F39345A31776275523156793855654E314E465478456B784A5A564B49384E6B6446626530536D725A73725362794B58315465654A6F59475238386339507638414845562B35466C61716E54545471564F777242304D2B764A612B546679684B323331447A7957334E48472B7965562B78756A7847414367504536425236425A6B413877475A4E594D655967737347452F324532394F4D75756C6265555A57537A6C47344D72377473585A6554666A4E63745665516C714179375935302B31746F6F6F7A5936306A4F544931475133746D6C676437677A456132595569382F636772374F58496F3262374F6E467839733633444B3256644972654D366C3238553832456978556B6B4A333242305433794C2F616E794A7053444E6D51684A35614A316978755545306D433374394B57724E5A4543724B496E694768356F6F74704B4646425037743350534F44575246723650533138396A534B317A5A384F6D3138366A58473037504463427130445A6B323030497957666576466347396B6145754E71646C55504730624D4E456F6A38657452497A4230566E436A66627A656A39794534353635696C57636D6145767070525A36463172544F6D53644A3073434C6C5962307462736B75645176582B674742643870734D694959547244633049756C31745654357A6B3437584834624A67454D655348637347785544324646576C30647A66724959444F6D326552793376367375486262376A5878747447375254306E4A6650792B686E4776546A572F33504E7A48367A7A36484F582F41414E70785A42664C6E32317A67317A2F59306F4E4578336A75695A6B395379585052566278583768593030614E56307331394C3165307076525A656B4E49466B546F2F79434E7A2F6F4C484A4A4E317452504D4D7779705655326C7063733333444B68492F6E576F47664833696139656E63684A53694674376250444F31704F735841317769305757386371776E494851587147314D39615730583548564666453664466D5A672F57523246664F354C74582F414B707657575A5A32594B68615278305769614A475275794270793057646C4264652F46714A4F50696F37506450524A522B54363048362F55614A374A356F4761785A38792F70323476627A34344E632F426E6B6D746A6174354F764A72356658636D496F716C57626B56324464626D732B784F4B4A4E4E4C6C4A5877414953584852654A76573332493566544F39495A564F347968534F613176527372396E41736446774A33624F763353354736696D72546E523957697475342F5A706C4263577A4478375267594F4C5A58314B4A5565544F6B58545143664F305A3976534936492F78672F687935736C2B5647566A626E6B594F4F3239796F747346546345413038717A30537333777142787731726A755350704E5A58573258444B6D684977704F654B476B514C57642B71304D555A7A575A7553346E6B686C53584336755379745A6330467A36386D4B32564B6F7174577A7735476933787A54374D52706A6E6B30737A744E6E5A646D69586938464D2B7A506666766A71564E456A574D70556E423038774842616B6442516E736C75792F51444142562F43702F664C633046726452585A45573565707550454D6B6D76793543446E4257454B6A437936382F2F41455938357975327372354A7A5856783764584C72496556316637414D49686C34666A7A72334E6B6F46694A3965745830614B5A6B31474574463534365A4B74464C4E545856396C614A36336E6B764F4F686C59744468646C2F464B4F6A564C65627148416D507754315057364E344D36454B6F566D587A38652B7530426A663963725935304F685233514B4C576745303477383731326350472B384361776763594948774D5A53554E435379356C5466772B753032756B5965386A6B356359372B7268754B586C3975546D7345394864356164504374626D686C5259726F7A3465557476346A6A2B5A307466627836354D554D7054634E55784B72627A48425963574E3657553169346956466B6C56705A6D4C642B446662586E53385351435174616E79364A552B4950303231686E6D4557395344555974586C437A78776C39446E4D6141663055474A4C4D534E367A7479444F726F624B766A4B46632B43434A364E435449364D4B684A5757536A4D6C5379664B34622B476C6F7A63705A5772486673315974756A46692B326E7875694F546B37636A535732756268767471616C533065656E776A56616E516C646C7359664B59364C54792F51545A70686677784157674E5A6C66384147675A537139705164686B486B766B7042465139764661765A3757437332645156424D6961553546466C5455616D6A6847687653396A566344614A4A66456B565352535155755A5645426C555669446B5732557855527059306E71564B47626832387168353972656A736A2B4E5653696D6A493455754F32434E3050315030795350747973664A5737554B542F493838783962442F774354344479492F6E76382F6A2F68545644324344562F4E45573675796B323166456369746A305557746A643256645661356753534B505A476F327546787659524D57333346316634704F41756D5337496F53762B4E6D51437336667157566B444A525333694F77437242767970556464646E736A71316D387656634646596B357241674B48556E75585A42424473472F55667435734F6A2B65684F586C514A4F6F36386B594D4F596378754F493446594A4761387548392B566F64645A56734C376A3174705159773377724271375A436D574D724F6E457771364D6E374C64493742566678436C532F51432F6C69656A306E37646E7364674564413966566D564A434D2F79416954506B784C6553763548384B4F78312B333436495038414A2F3548304F5658796A62543230577733363072666C2B314D6E734B546A415378524C4234786C4F756B745A322B5271367674684E5248524F7A756F4B42494E58632F6D38314C4762654648575A55394267735A7637483976382F2B6F51554A42554F6F495839683339665566764B5871434A686D62782F3574526B4B4A5072722F73515648354B7333355058512B693068554A7A4E44323068454E524967336C546E5354624778655879777977716767616B59797136696B5A5A2F734C697971306136537345552B5A583658473871717A506433506B454273372B5A374964564B4B744351663558317346363636566A2F7752395664656D67614D474A4C326C6E554C3241732F2F6436356F65323848393078354879444D56554D434F69506744736D69773569505352454A5878536F71364F4B51545A46675947784C472F77543063696A70526E553749794B7564764F6E4553746F44456B4645336F4D6471546E534971536B337353314F767779686C5874696677415764564866386C67503559416C7373624E375169697470774156414F314661412B705146364C414657616E6965776973515141534A65796B57654D5674374C4B7039507073587278685A6A6650523337447156556F3231773579316D51634841697142635033422F61692B4D51366D59425A52754D71546D31484869703266705967456541692F344B7230563857667862763841355058585A50613664597076544D6A4E354C6D6F4B7A594832456D766D72465435446F6C50313858702B4F2B7A2B515479596C734D7563565876414A64474675414861475556316E5871672B696C44584D5667306568646A4F497A6379794934724D57366F774F71646C384C42625335335A624B794262497947315652524B316E6E6E724A4844576D7A6C6242446566636E5A6B70374A75384F6C536C4748797153744F6D6531717A685279525A56396A79722F414F3153504F66344A362F786B6F5741622F4B684138697135536C306F6B56676A49314A316B78745A7A4B70375A5A564D68585750626178505847736F6A536942646F7179775A5A6D2B367541725932343455686D4A6643646D2F4D5331724761534B2B755958545375623261323541786C6D5A576C4E796C4E4A7A786D3774585A47447172755858327157346E6B35546A6C543273746A3439515A485A354E4556765362545877556F76546C4337752F67735A7A5038416B44466D325263396572355A357474645670426132696B7A2B575A715778513537704D754278693173735776622F37706A52616D67416D686F6862782B70454D437032444C31433677557637484C786644547944446E58426D3052304A68793473635844614675314E326D6A30736D626A696133397776484962563167655756323745717336637676726330526E6672796C656E706566724E47524946342B4E485759556D61465150575A6C72416C53372B77486A483545654D744D3430776572796A6650342F5A73644B717A55646D3065346B3351334232686D334E4D2B34545A464545305A354D713156653554364770374A555144466A4969564970464557666E4F48343352374C4A624F32795737464B466652577534327574757336583135664C7237655478444D61534446765865697045327135744E35475656616764314873624F38615339534870566159735642506658736453796B66743065696B3944364672326832675A365A746B665058544A5874387579596379493137512F4E624D676F49354F31662F414B514550754167577957554544553836414254773847636832616F7A742F627A664B563969764270347463596C6D394D343347624B6F6553423345573963765A4B6A544D306561704955364B73446354426D7A70456C35706162426F7930585168364D6E52384A6663456B6E31734350466A327239424F6A34716B2F4A597953305564456553345A456E526238306446726669354A6C5153656B4D313456384C71713644794336783564447449614F614638574E3035703736774B6E587A6A2F7744367A523359657459312B33537253724B6870517555526A617A466E7065644A70344C2F6B38584577537036352F7A5A314430704D67717845702F7176544B56375A695742365873674172312F7A2B41666F6376783370695978697A7053475748544C59576A397A565657695743473342474330583274414C53684664514A6B4B684B673278596A424845686A52436F526D4B64664C7254584B6B2F476A34547139774A7836587A586731656B6D3036513036504C524B70547945765657566B634955743575703462646B6A61634B36466B394A426835452B353171532B637A5478496670614C2F6B436853354938514F6839644E614C3054584D6F57445050356B2F67426D4B63526F394162326F67336C413050736C55565047436D464C5934594336322B774A6477323371346B7274397734395676487035586661324C69382B486A593558577272786F30635A6867426F543766545478314C447A6A544F7152494D3164336F2B6E33305A57487A51754F4352313744585775704C6661746F6C4453396C6D47627869576757654B716C2F77414B53564D36394D416A654E6A2F414256486F30703430394D5A684E6930715774364B6B326A2F647A31555A707A732B307130704C4B68704D456F3233696538554B2F6B4343432B4573793131313837314C626C724F4E4F4732336C2B537A774A6B68785476796C363576764E72624E373056705470665866586E304856316B78547139632B6531394F6A486E7A61644D67504D6369503762484C4664474250655856466C6C55776C4357574E463833444C41576C4F586D396B7559563959394239775836592B2F38415279733778774258352F35326B5675387A66352F4D31614B41766D424E766D424635527A427A715646366130756F69796A516B6C31615A497745764B4B447573436D585A31674C356E346C6D54347A772F48636946354858506C3848796A4E79584B386C53484F594E412B517479687666426832556B73754B79366A78574A4B4B7449634E6E41305373636E6C6558684E7958317064767563666E67304975567070614F6C4D786C6E377A765373374F62504439336A6D304175534236694170643576347635536A79776E30476A4465714E306C32564E30395A536E6E34357345584C34495374465736426F532B754C4B7963334C6738793659415A36786845437552775336633675516B4C5852384670386750416648666C4E4E6E796A4F712F65635A666C4D43363844697561565676782F47614D6D32456732764E4D2F63676857303567573837524C483035446E477A705458687A35736A56455958474C6B70537337646C4A432B6F3267316A31304167567951656C3642483157356C346E76624E716D794D50517351413532417A35367579516D745235326C485766426A46776F6246714D435A6D46315A3143672B4B6849385A70756C52457273444275764A3543624A486A4F56303638517A636C45766E696B736E726A6F6659635A4C50484D624C62513153714F3562334937655A6F3566793748304D47705746726567556E375661366A4E325765514D31724E6A756345497653422F74704B7946535651394B5A725365655A377A4A6E6A38372F72336A7A4D34344E54652F3136746B3032366C5247646E3838386E524E77722F554271724C4744456F34414C465A6C76714B676777347242365930773549396E35663476674C77336350613146594B64584638394F6C4C55396C4A4D50734478627A522F664B694B747239653148694C423138685476707652316565725A4F746E385A5A57795A58382B6C444C344D75795A434B6E544D66442F5474764141644577326B6649384A7861512B772B513271756B6844464C2F385970445050627970766A757962444E6C572B544D6A2F51577751744E56597766635A6A37506B72765851764836565A774F6E6C3250794E34564F445A7875473931384479416A6C72544B74575A4C4F32334F735A30764F4E4D73315A444F657162457657586954646B4B566C5877764E725458736C624C7055564148696C546D6158715074413752627378583953796E794136664C504F50505079433948794E586D65497775626B4E736C416B4153505431597274776C574E35475755485947436C784D306C696C584557795270655130727747736D364C6B4F345A2B77444F387238543474754D33316E794F2F692B517A4A536263666F2B57635666526A3851665A5452786D623464695847656C616950586C2F51303246425A3246704A504C5A6F79364977704D5564335874343858705A5871514345462F3776537A6A6F2F67547A6C7568312B7944794E567654556C6444357242696D4A424C47623343486739477537656C6E4F6F43323036516C3479325571367568334479713746634A4F327334746A32676571797165544A79656A4644457643636F6A50757A766F5373647865503347485A7A6D5559387570646D34444C5A742F48637270724E755665573573686872536D474E596B4E4B426231396B374C344F716C57516F564E5556696632503766383964442F6A722F414A4852586D356866754B393477734742544E7A624170754B374C4C464B7255755342795371774C3735534C375354442F594C2B412F4647746A32346736776D7567716E2F69707A6474326538654D6565376E4E756E6A4C4A794363576D6D727679716648754B314E4456727835706165506E79322F6B3976782F5634434E7450477A303865362F6663744F6D69744C785035436F6738756B4256664D6F7A6856616A442F6277485954792F34596A3664656A54724E566D4D327A454A543233716238576136484D5756316A30695065476F53545A4245646E4E74516B4746736749505A644E4D5833684B2B6175612F6E52475346775079486C7547333870777335386B324779664B7134786C357A6D4B365037707771366558347A4930384E6D79635870357A376D326662727963586A35584E675A39754C6B4259616448314D386A534B57556F43724953517669335647587A36364A374937416E324434722B41423330617437764A784862386967744A754B5A6E667766367A6961454152674F79716B47425865507949314338716D4D6835516F747563766C4E3834794F496751505353426F68342B7561534E73546A6171734E64524468466C5661506754766B4534756B36333138686852304F544E75744659302B784E6D6F30354B7A637733566B31446D2F486A3474344542765A346B6B41416E6F4F3358376679472F68767833394967685A59726D77447642462B59697465554758515A33734F667452432B5549586A6634417376747176684A674D52514D66417969496C526768596853786A6156533035687663477A7334417573786270476563362F3436566E544B7A41484F363162327A61624878566942302B74664B6C5A654B4A52432B6A4F72457A4A43655643794E324134364A2F514149362B512F6766556C6571436C6D30624332303236316D5A5841696B7569644E595634707074664A4C3750767A724F67516849452B573634634F2B4A4E4D783455573056566D6B64437230576C682B50576149656A30475A49436A6E6F486F4271466C38522B4F7568306638416A2B5A6B686434414149595A4C4B542B7863614C316D46495034486A4F616B45646B6B6E79372B6851612F2F414742674A41573051497371556A4F3332475642696A394D734870706A79795664513076686E2F68654E524F36454B6F2F77417A344B6F786F35794571703631636E7963307053592F77434F676C58514B50782B416648792F77446773542F4858313376734377485956454B79542F73415564724D772F354C4B4655487674662F61652F7275594D4F5669456930512F78466A4D466C486B652F487969696B492F7744594B766B7052374C2F41424E6A665554524F75717555313958363258776C564B326936504E6D6D775872792F42422F496D522B5650663437424C642F3866555535707162447155396D4372485170506241794D575371642F67672B70464A50665442682F3237675158643052795A422F574D4A6C45793646426446462F4F634E444F556C3130446B7776684D345663646151734D47713463764F7170614C72686D4B2B427773326E775375536A4B47676F564B416A3864683432422F6A2B65346748763841674D652B76342B69755832556E746B6A4D4E485972465662787051535379306E4D3967686A4B7A4F762F486B6F483137576B4556724C614B72706C4B6A65676B3352483557504C7038722F316E3961712F6B4F576B446B38364C615458436D3838657179325A2F314C6834783538625455547A5761614479716B4859746E412F4242414A4A5479412F6278627469462F2F4836674E383139486C74684E712B4254376D612B4772316E727A4C4D423151722B50487941385357362F325052554A2F566D7236327176476278504C3552584F767464724330646A4F77746B545A38354E7A41486B796C2F4272355268795061626D6349455633386C5A5A336D3171786E4B6B326C5A533069724564725252332F4950384545662F7743752F77447455316363306A66556A70584E34705531587677496F78576245663841424C41673964666A386E2B506F33784B43316D58784171303639626355764A63722B4E71323179363734466C5043346457717A775236476345354C7655716D5239773453744C51774B752B4967676A3630733834313761522B344F645444376C775853615772507A44423370574B414F765149386A2B4648366B6A735746307650686C643570663136486A357561646F4F6C64544E6C6C5A3043554C425355483675774A4866695756516F4F52484A58344770796F745334456765386D334A756572796F5757443232784F686E76514E455458794C47644E3476516971515468464832496852576370424B765478536C56627279484841476B715367757248724F554A4E556E4A704A43717A6D523358304B376C744E645633656C7275374254766254376F5579776433444D354F7231686D39726F3765544C507075783331344B33354A4B676A782B75582F414744654D47457147586F6D624E7662467953544773777348676367435749626F6C63614D66352F6F67597079476B513242413174354E4E354D5A4D62366A722B5857317345643630712B61764A63524E74434262613334534A317A55666B684C4C6B476A504E514366484E6149552F757A4F6E6B6A66667457486F4D706876536F3955473567305253333867357875496638416B396557623966392B6C38665950347457354844343573496B2F68764E4B7A7030576176304756457A59684B753958726A6236486778374552557872577438626C4A52446A66785563654E703445437746704934504A634D3076795843624E46466242786D712B747A6F6C563538686E7863527279536C587A7250395365597673556F386E576E48533868523449724E57665A396C6932794D352B7A5A444E6C597A5648706C3874536133614E4F6A344F37346336457233334A717A4A367451462B7367635036675732626A496D4354796C6F4B45387257662F6C616249476C59767275766C643032345668715034307855792B5A356B79486D6D303558663247364D326D7556766975546B2F6A3345797761655262546F342F4A70545876676A344279417A5531557579724A36736936644636347370562F435667693061556B6E5577636A644C615661655A545A68436373305645314F6E53526E787A426274564C313730336F3359584E4451782F594C3942745868506C68696B37554772644D58416B6832564A52586F6D3145536A71476664467071785269626D6268624653754D5235626C726A52506A376D4C797A52486B2F4B4C4C3744704C6B4E45637A5330577066796F3148677431317941444E59726D526733707A555373567A684750556D72566D616B724F31576C4A614E476165664C6E6161793073327751746E386F496A5A5936505A4B382B7162725331625972342B32436E504574314C3851655538472F324E69586E7650374877326D564A4B4F3530686172633967363056686436725A78614F6A343349465943612F4F6C352B5656725346444B3045394B595059534E5230546A4458666C704464446B6153325730516A61656744516A51554D704D6F793837776355614E414A354C52303055546F7049486861766F79576B6374384F643565707174544C464A3157396646707976517161625A4E41766D4461337464592B436D7A2B4B6447493252395658336E6A4643655A65634F693079514B38347656752B6C58357159625233616143695131796978536C4C364F364B7A706A59772F736C39773546356C563441636441305535546E5866623631394732314471537965636263686973706861656E654E5768593854584A79754C695578615A38527876435A2B596E544C704847636D37704B63586A6B5A546F4E466A4668536139356F416B314E574C6D63555A3259424A2B5949724A554871704D306679474D643642594A6A526368494630385A66745351637A4A723477705967616F51335170482F42656C695778445972725639794B45676F7A3751557143454C48752B6E4F6B743857354162396E4534316C665465657A467462374E396566663939676E546A31354C52574F325A307978344C5A6379346F636A4B476964644D5634612B6A567276656C794843546C757679413070496151495254775477424867306F53526B614D6E5363714E4F7335537437475A785257592F556A6B6654643671615A337A77543042706C734873562B6879546A4F5A54505A6F6F44754E6544756C4C62764B486934774C684D5878487748533671574555307A465930775346425274374A7A7566683972573376686878466C3361657776464A7869613838317A356A584A704E4830566A6E76417731306771536E735A4A4D6B4E65612B6552484B6A724E6A3158577942586D317248546F6E6444357A6B786D454941514E516558732F4B67656658616D65422F4837444A3331476E74393331536C386E3543437130314773563948354F6E6F644D4259556D5A364167354642784551526870534674462B5355715A55455146733650466D7A7A5963744C537338787A4C4E4B32304E484B384B5141564C466C6C5030554D765A4179644379724D6F6A4D70674F2B6A6F596A696D39596F664E6A324F6E442B5861457343727177374148384479422F6E366B2F5739457A4C532B64507274486C396F355755573542665141307835532B536C4C33676F523031475A6A56517551305376374B7879556D5758484C79357A43756B41316E4B33496F2F4675412B456838664379305A65507479572F6C394357466E77523137647874702B31313633755A7773374D6B755079744C506B566B6D6B30587A38795674642B5275327A6B6142524C4E43515A434571597A364D6F563961714F7045443849716A762F4A51505A76615548647357496A38645A764A617659724362354B55644E6D707A654453317252682B435757467264436932764C4639414A63594C322B69765533536C327363773576557249704C47353265577A52666A58686D686154704A44526C354A586A52696F7079546367743572436C4B6478686B544B707457535739676F7462366947764D6F52795044387130344D4851642F367156364238782B74435157594F354A4448384E414452796250636D702B674D566E4D30306F6E6B4D6B39596148594541697634517264756B694B682F6C504945797978765A53573166364B2B4C4D787730465570467274496F70526863374E393866486174634E646D70782B54524B6D3277395344523672574F5831353435784A6C42577561614C73386B6678695971794C4B584E6E68526B7A744766685635426F704266476E6B792F765356765948505A382B6D414162382F723050717839582F6A753931327248566157375A2B6347434978337A413052767176514372574E5366355838684F2F647937614D493973553363726E4779767430377566633566565A32464B6166366C63556138654D504738686B6F79536C66616C4D69625A75636473387277744A4550746C2F6B5A476C396D387056766E7A76466456334C52663431755931616D724F35536C6648796651336B574A632B7A7956752F2B77492F50386B67392F6931655A2F3841485437673058304D6C642F674F6449315762566967696A4750696F46506861376D687A7877786F3873556B4330465257475864546A697442696144345A396E61654D4E7878596A74756E6A47584678577A3542446838504E3872767A3557356E624765642B5434322B565A354D4F4F38703548793539676E485848594E456E7A53305A767433643048612F467456704E56744756413030526B535A2F4C4A324135645A7A4A37424938534350342F4A2F34723770507845332B625A3664795070736E584A457A315149393879586A4569324B6263356E795A7958326931534643717954467143315730534B49744A4168654F637870767068307658726331583439384C33664936386278664A5A676E434F2B4E63326669334C6A4C38702B575A764535636C633651433850797645624D55495A386D6A4A71796E4E4C4242577778576458445653375A317369766D6479376475566F526F7A5A536F42414B41696F7035646B677155385344356778786E34462B7A2B6756633163746A35367345555A375061307A344732702B353966734F73506F44436636723059766C6C4E5A4B3739546A49387048766C5A473232552B56306F4B2F503437634A48453851617A61584A61694F59314B4B2F32336C4254506B7A6938632B717161494630315770466F7637554D6F335548332F52576678545771466D315A77716C434376744C4E2B523043436967412B5037667366352F4150315372333338614E586A6F5836306C766D6942576531634C6D3949397A4755704D6851696E7A416F63416C523855344656514B49375A4E6C5238683134343042517877596C4547666A6679413868773244505A6167347359796869456F7A5368542B3351426F706761656C4D794A494F6738454E6E6F317257566F55746E45577831465761424E6A592B4D3264564937396E546B7A486D475767566C3636494444766F392F56532F50786A652B6A6849744A554C6F786C374E756C4856476C45667A4973575656693857324A4651744A6C53305A3662426E594E43767637382B325247754A786C396B7A326A6C497A77765246716F655A71716855506A354B4736374E423266795365756832534F756953596E342B2B68515130565A586E4C7679636636585A5156416E2B716A73425637627856514F7A2F7835616E793173675A7636526D5964412B644F716F58445533485368436A51424C39557559527437585462537A5779757A415078393652543055592B6E6C396B52517046566C2B533541716E77314F53697454796C494173436B7567426F494949364A37412F774333582F5030562F734F6E5373614F2B587339457035554B6C5046356C536655435351784A5051372F6A72366D376650482B6C305368654E626E4144737A6B79474447796973735155376D4F4149734F4B2F36526262533242314B366F336E32496A6A46735A6369584371757670466C5333797243736A52733273697477696A2F436641757A4F4F75332F7742522F485150386B6E3866556D443472746A57796A546D43466579674E6950487950536A75592F77425343663841352F672F6E3867434338705A6B4475697247777455317134307969592F4C59337A4C34434B627A76625A55642B474978423146316336345336524769326A74516E7A51767036743873784651446E3039414944334F4A4A3736482F38662B4F7A2F482F2F4142754C38563545744B6B37343038714E346E325838314B6E70572F47666F666A7673442B4F2F3549412B6A66572B566A70333759484D4E3775786F5949684A6E73615A686B46486373634E2B4E715252796D55466B34713039593877356C742B334778723555634544436D6B6172503566675363532B6659774D793441575036673964494F372F414A483866742B502F774333386E75793377336B6275376A5268446F77593974634B664D6E7942555149505A5665696639656A2B44333050344E3535702B466B71494E6C5931714C76614169612B6C5864734A6F7662334231546A30556546495938414C65386C32425038416E3961785A4354474A6E77576B6E7A4469546F612F774272764C6D665149584F7055725077373747672B5866382F6E7272382F7A2F4974562B4A3874546A4A3542707769494C462F4B6D67732F644177375032352F436B6E6F646E2B502F32446F542B4E743056394871583965744D465A366F367843696E4D7457495767584F4D756A5476474E34724D56656F347058324461425A4657576C6D48614F52536254576F42487245736C62346E357A785358625465504A6F30786E56526E6E6D4A3841614D6632625650706979686A2B702F503146742B43386848476D4364654D724D47684C615075535063584A4C6961792F494862414B61644548766F482B4743673634314E4A73584F7A394D6543573976466D4F6636546F49516B556C726158777676714F7130464A4E49793971634750542B6C457979434C696A727671586C4C43576D6E7A764236536732664A2F39454B744A736B43336658586D667537762F7A2B794C54774A3650514948532B7639502B5A69664A6A3864634F6567795476467569437737384D666D7836424238724E33332B336B663248474D7136463376526547334C617834336A674E7A38712B7172734A4E4D7646716E546F504E5734566C4537712F6B4F2F794A79306767635973695A743337526A45666E664669697830636A38774B4E3471424E734C414665714B66323249784159412F372F414A362F50342F58363748774C6C6171576E2F597735516B6B3035464741492F49444C4A782B562F422F786A384872722F6E36416464356A5152746D577048535A704278706E6D4C4570536F746C6171586C6C667A5262624541567149622B50307563374C437068584432777174764147737256465872705236506E504556762F68586D4C4C59546B673253792B774E482F497A745365352B677A676A78436B654851502F494A4166422B566E6A5150586A4A744E6C667A6C6F3230386C596742536C4D794C3269742B704A50354149386576707457666A6D74597676414D6B4670644A7A6E7147573273644D794A656D52763470774F53564F6B61345375796C6A336759366668536D433232365156634A435631664430586863712B7235506B75686F2F47347675415843557078484836505A6D542F314A33597645753555425A73513369503969782F50314D764362352B614E7946337A7936377A7074764766735251555A56456E5542612F35435048742F79704B392B58314A6E2B4E366A4A2B6937584C51314C485177544973436453497930397767374D335236624E3575396F364D7479547759357149485142614152666E6268616A313638356B45366D485A536277337A4C45337062546B4E584B6D616C654F347842474B7368684F49413656592B505244412B31543473796741437533783358534C4E50544B58536F435139667A3630632B50697331376E354F536B2F496543425A426A34682F6F7055656B31697377566D6538567A6F61656B46656E70436E374C705235434B5831524D79676B7433504C7A356F2B7355797269396756583038697668544B4E4572626E6A38396D3538527A454B5168716A546C5A555346337A4D7238524F6556304851704C4F6E456B75386B705A73744E4F6E52624A704B6163316F756844697166483951485874794838394F4375672B5A436867652F50736679507830522F492F6A386D532F494279532B38784B4F7677364A4862443436376D412B3730727473564C5562444133754B69374B4D2F6B6743422F6F70554143326D4949345377664E6F4942727162567442556539484F353876476164443665517159354D2B55545846782B64577A4E396E4B4F565778317A4757624D637275732B7174583772556A3044624E74744D4F62677446724C342F5A4953584959477849655346764C706B494A6238674146664838487476705565752F37676A72533967556D346A773269332F6E6D65674C56456476484755317374666B365437654B2B7179446B61444B686F7871713131495373344E6133577836574E4336716A782F7741366E6C7439336C585A6E72526B6C594C2B5A58574649616373724A6E3259744C34303378585670785432786A756E336B312B32444D476D6634705779566D37355848684B70444768487361644135482B4C3865586D762F482F414C4F7575695047766D6C4D4D3554566E694372754A74694D682F6C32695142704E4672597471744762786A57514158443943587378575A554678513745737065737374656369766856656335503535683279334C486A3957615772516D6E524D316A553030495642306F3457586F7261636B467077536555737147554A546E4B61525A50696C344F6A2F63796377526B684D417A6B4A737636436757524E476B504A4A73535047624665767A39466D36385A312B42584C394E623648716A535354562F4C49513254614E3352656830463138724F70556746314730527647364F5264595A525264567958314C4F30317A736A6E38747452377050547A45637378517245636A5A304E566431566A4930565548676A2F3655437035654B7A49364B386E685641452F484B6167647344456548537153784473485A6D38756742366C37424A4C44727850653838633265535763307A6A596465493556443069515A73474C3532445353387451386A5A466B474F705952417634536344564F6B5165466B75536A56544F2B7A34685935562B5934752F4A4D3136426131525A617165776F385A73355A61667632727343504572324230537A483866583356786135644359335344454C352B79532B48514B6C694150483866782F4838456B2F774144726F6B43383066585258744233565336444972522F5370425A3651652B4B31492B425830326C4869734254494F694B6A5267373241743379314251732B6E634E5A5146476D4C6970313061494B7151616372474C536F316F7066384177524C69787A4D6C66555264763853565573792B544F42526C555072557853596A2F6A4C736A6533794C504C39704143616549422F6477784A646678324F757A33395846782F6979743858356D2B654A38316F51462B31793452466C30326D6263326D753362496171714D387A3951592B734E6A6D792B4C58656A6B2B5A6F616A724779775754497136696C5A2B5363726B34343835785049543137615A755030413657615676626F474C6A34787236626A37574D455775497444506C6C5930342B5644745A4B587A3150634A7874577478746F585552315657336F716F5A566D744E515A437756714D376E4B77386C704F5957674C52646C4A502F32513D3D227D7D5D7D5D2C226E616D65223A226D61726D616C6164652E6C65646765722E7472616E73666572227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: marmalade.ledger.transfer, args cannot be displayed on Ledger", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | WARNING : Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?", + "9 | Transaction hash : TX4rKze978k7T-MAzSJfTTHy1WCwAK8yi4RhZfAQzQE", + "10 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: marmalade.ledger.transfer, args cannot be displayed on Ledger", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | WARNING : Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?", + "9 | Transaction hash : TX4rKze978k7T-MAzSJfTTHy1WCwAK8yi4RhZfAQzQE", + "10 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" + ] } -] - +] \ No newline at end of file From 86ccf9e448e19bf76e2f899c6843ae7e026105be Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Wed, 14 Aug 2024 17:21:07 +0200 Subject: [PATCH 08/34] Item functions cleanup --- app/src/items.c | 409 +++++++++++++++++++++++++----------------- app/src/items.h | 16 +- app/src/parser_impl.c | 16 +- app/src/parser_impl.h | 3 +- tests/testcases.json | 31 ---- 5 files changed, 273 insertions(+), 202 deletions(-) diff --git a/app/src/items.c b/app/src/items.c index 22711ec..088ce8f 100644 --- a/app/src/items.c +++ b/app/src/items.c @@ -19,19 +19,32 @@ #include "parser_impl.h" #include -static parser_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_signingToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_requiringToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_gasToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static parser_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_signingToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_requiringToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_gasToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +static items_error_t items_storeSigningTransaction(uint8_t *items_idx); +static items_error_t items_storeNetwork(uint8_t *items_idx); +static items_error_t items_storeRequiringCapabilities(uint8_t *items_idx); +static items_error_t items_storeKey(uint8_t *items_idx); +static items_error_t items_validateSigners(uint8_t *items_idx); +static items_error_t items_storePayingGas(uint8_t *items_idx, uint8_t *unknown_capabitilies); +static items_error_t items_storeAllTransfers(uint8_t *items_idx, uint8_t *unknown_capabitilies); +static items_error_t items_storeCaution(uint8_t *items_idx); +static items_error_t items_storeChainId(uint8_t *items_idx); +static items_error_t items_storeUsingGas(uint8_t *items_idx); +static items_error_t items_checkTxLengths(uint8_t *items_idx); +static items_error_t items_storeHash(uint8_t *items_idx); +static items_error_t items_storeSignature(uint8_t *items_idx); static items_error_t items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); static items_error_t items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); static items_error_t items_storeCrossTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); @@ -61,153 +74,248 @@ void items_storeItems() { parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; uint8_t items_idx = 0; uint8_t unknown_capabitilies = 1; - uint8_t num_of_transfers = 1; uint16_t token_index = 0; - bool unscoped_signer = false; - strcpy(item_array.items[items_idx].key, "Signing"); - item_array.toString[items_idx] = items_signingToDisplayString; - items_idx++; + items_storeSigningTransaction(&items_idx); + + items_storeNetwork(&items_idx); + + items_storeRequiringCapabilities(&items_idx); + + items_storeKey(&items_idx); + + items_validateSigners(&items_idx); + + items_storePayingGas(&items_idx, &unknown_capabitilies); + + items_storeAllTransfers(&items_idx, &unknown_capabitilies); + + if (parser_validateMetaField() != parser_ok) { + items_storeCaution(&items_idx); + } else { + items_storeChainId(&items_idx); + + items_storeUsingGas(&items_idx); + } + + items_checkTxLengths(&items_idx); + + items_storeHash(&items_idx); + + items_storeSignature(&items_idx); + + item_array.numOfItems = items_idx; +} + +uint16_t items_getTotalItems() { + return item_array.numOfItems; +} + +static items_error_t items_storeSigningTransaction(uint8_t *items_idx) { + strcpy(item_array.items[*items_idx].key, "Signing"); + item_array.toString[*items_idx] = items_signingToDisplayString; + (*items_idx)++; - // Skip item if network id is not available - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_NETWORK_ID) == parser_ok) { - strcpy(item_array.items[items_idx].key, "On Network"); - item_array.toString[items_idx] = items_stdToDisplayString; - items_idx++; + return items_ok; +} + +static items_error_t items_storeNetwork(uint8_t *items_idx) { + if (parser_getJsonValue(&item_array.items[*items_idx].json_token_index, JSON_NETWORK_ID) == parser_ok) { + strcpy(item_array.items[*items_idx].key, "On Network"); + item_array.toString[*items_idx] = items_stdToDisplayString; + (*items_idx)++; } - strcpy(item_array.items[items_idx].key, "Requiring"); - item_array.toString[items_idx] = items_requiringToDisplayString; - items_idx++; + return items_ok; +} + +static items_error_t items_storeRequiringCapabilities(uint8_t *items_idx) { + strcpy(item_array.items[*items_idx].key, "Requiring"); + item_array.toString[*items_idx] = items_requiringToDisplayString; + (*items_idx)++; - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { - array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_PUBKEY) == parser_ok) { - strcpy(item_array.items[items_idx].key, "Of Key"); - item_array.toString[items_idx] = items_stdToDisplayString; - items_idx++; + return items_ok; +} + +static items_error_t items_storeKey(uint8_t *items_idx) { + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; + + if (parser_getJsonValue(curr_token_idx, JSON_SIGNERS) == parser_ok) { + array_get_nth_element(&json_all, *curr_token_idx, 0, curr_token_idx); + if (parser_getJsonValue(curr_token_idx, JSON_PUBKEY) == parser_ok) { + strcpy(item_array.items[*items_idx].key, "Of Key"); + item_array.toString[*items_idx] = items_stdToDisplayString; + (*items_idx)++; } } - // TODO : Cleanup - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { - array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CLIST) == parser_ok) { - uint16_t clist_token_index = CURR_ITEM_TOKEN; + return items_ok; +} + +static items_error_t items_validateSigners(uint8_t *items_idx) { + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; + uint16_t token_index = 0; + + if (parser_getJsonValue(curr_token_idx, JSON_SIGNERS) == parser_ok) { + array_get_nth_element(&json_all, *curr_token_idx, 0, curr_token_idx); + if (parser_getJsonValue(curr_token_idx, JSON_CLIST) == parser_ok) { + uint16_t clist_token_index = *curr_token_idx; + for (uint8_t i = 0; i < parser_getNumberOfClistElements(); i++) { if (array_get_nth_element(&json_all, clist_token_index, i, &token_index) == parser_ok) { uint16_t name_token_index = 0; if (object_get_value(&json_all, token_index, JSON_NAME, &name_token_index) == parser_ok) { if (MEMCMP("coin.TRANSFER", json_all.buffer + json_all.tokens[name_token_index].start, - json_all.tokens[name_token_index].end - json_all.tokens[name_token_index].start) == 0) { - if (parser_findKeyInClist(item_array.items[items_idx - 1].json_token_index) == parser_no_data) { - unscoped_signer = true; - break; + sizeof("coin.TRANSFER") - 1) == 0) { + if (parser_findPubKeyInClist(item_array.items[*items_idx - 1].json_token_index) == parser_ok) { + item_array.items[*items_idx].json_token_index = 0; + return items_ok; } - } + break; + } } } } - } else { - // No Clist given - unscoped_signer = true; + item_array.items[*items_idx].json_token_index = 0; + return items_ok; } } - if (unscoped_signer) { - strcpy(item_array.items[items_idx].key, "Unscoped Signer"); - CURR_ITEM_TOKEN = item_array.items[items_idx - 1].json_token_index; - item_array.toString[items_idx] = items_stdToDisplayString; - items_idx++; - } + strcpy(item_array.items[*items_idx].key, "Unscoped Signer"); + *curr_token_idx = item_array.items[*items_idx - 1].json_token_index; + item_array.toString[*items_idx] = items_stdToDisplayString; + (*items_idx)++; + + return items_ok; +} - CURR_ITEM_TOKEN = 0; - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { - array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CLIST) == parser_ok) { - parser_getGasObject(&CURR_ITEM_TOKEN); - items_storeGasItem(CURR_ITEM_TOKEN, items_idx, &unknown_capabitilies); - items_idx++; +static items_error_t items_storePayingGas(uint8_t *items_idx, uint8_t *unknown_capabitilies) { + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; + + if (parser_getJsonValue(curr_token_idx, JSON_SIGNERS) == parser_ok) { + array_get_nth_element(&json_all, *curr_token_idx, 0, curr_token_idx); + if (parser_getJsonValue(curr_token_idx, JSON_CLIST) == parser_ok) { + parser_getGasObject(curr_token_idx); + items_storeGasItem(*curr_token_idx, *items_idx, unknown_capabitilies); + (*items_idx)++; + } else { + *curr_token_idx = 0; } } - CURR_ITEM_TOKEN = 0; - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_SIGNERS) == parser_ok) { - array_get_nth_element(&json_all, CURR_ITEM_TOKEN, 0, &CURR_ITEM_TOKEN); - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CLIST) == parser_ok) { - uint16_t clist_token_index = CURR_ITEM_TOKEN; + return items_ok; +} + +static items_error_t items_storeAllTransfers(uint8_t *items_idx, uint8_t *unknown_capabitilies) { + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; + uint16_t token_index = 0; + uint8_t num_of_transfers = 1; + + if (parser_getJsonValue(curr_token_idx, JSON_SIGNERS) == parser_ok) { + array_get_nth_element(&json_all, *curr_token_idx, 0, curr_token_idx); + if (parser_getJsonValue(curr_token_idx, JSON_CLIST) == parser_ok) { + uint16_t clist_token_index = *curr_token_idx; for (uint8_t i = 0; i < parser_getNumberOfClistElements(); i++) { if (array_get_nth_element(&json_all, clist_token_index, i, &token_index) == parser_ok) { uint16_t name_token_index = 0; if (object_get_value(&json_all, token_index, JSON_NAME, &name_token_index) == parser_ok) { if (MEMCMP("coin.TRANSFER_XCHAIN", json_all.buffer + json_all.tokens[name_token_index].start, sizeof("coin.TRANSFER_XCHAIN") - 1) == 0) { - CURR_ITEM_TOKEN = token_index; - items_storeCrossTransferItem(&json_all, token_index, items_idx, &num_of_transfers, &unknown_capabitilies); - items_idx++; + *curr_token_idx = token_index; + items_storeCrossTransferItem(&json_all, token_index, *items_idx, &num_of_transfers, unknown_capabitilies); + (*items_idx)++; } else if (MEMCMP("coin.TRANSFER", json_all.buffer + json_all.tokens[name_token_index].start, sizeof("coin.TRANSFER") - 1) == 0) { - CURR_ITEM_TOKEN = token_index; - items_storeTransferItem(&json_all, token_index, items_idx, &num_of_transfers, &unknown_capabitilies); - items_idx++; + *curr_token_idx = token_index; + items_storeTransferItem(&json_all, token_index, *items_idx, &num_of_transfers, unknown_capabitilies); + (*items_idx)++; } else if (MEMCMP("coin.ROTATE", json_all.buffer + json_all.tokens[name_token_index].start, sizeof("coin.ROTATE") - 1) == 0) { - CURR_ITEM_TOKEN = token_index; - items_storeRotateItem(&json_all, token_index, items_idx, &unknown_capabitilies); - items_idx++; + *curr_token_idx = token_index; + items_storeRotateItem(&json_all, token_index, *items_idx, unknown_capabitilies); + (*items_idx)++; } else if (MEMCMP("coin.GAS", json_all.buffer + json_all.tokens[name_token_index].start, sizeof("coin.GAS") - 1) != 0) { // Any other case that's not coin.GAS - CURR_ITEM_TOKEN = token_index; - items_storeUnknownItem(&json_all, token_index, items_idx, &unknown_capabitilies); - items_idx++; - item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; + *curr_token_idx = token_index; + items_storeUnknownItem(&json_all, token_index, *items_idx, unknown_capabitilies); + item_array.toString[*items_idx] = items_unknownCapabilityToDisplayString; + (*items_idx)++; } + curr_token_idx = &item_array.items[*items_idx].json_token_index; } } } } else { // No Clist given, Raise warning - strcpy(item_array.items[items_idx].key, "WARNING"); - item_array.toString[items_idx] = items_warningToDisplayString; - items_idx++; + strcpy(item_array.items[*items_idx].key, "WARNING"); + item_array.toString[*items_idx] = items_warningToDisplayString; + (*items_idx)++; } } - if (parser_validateMetaField() != parser_ok) { - strcpy(item_array.items[items_idx].key, "CAUTION"); - item_array.toString[items_idx] = items_cautionToDisplayString; - items_idx++; - } else { - CURR_ITEM_TOKEN = 0; - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_CHAIN_ID) == parser_ok) { - strcpy(item_array.items[items_idx].key, "On Chain"); - item_array.toString[items_idx] = items_stdToDisplayString; - items_idx++; - } - } + *curr_token_idx = 0; + + return items_ok; +} - CURR_ITEM_TOKEN = 0; - if (parser_getJsonValue(&CURR_ITEM_TOKEN, JSON_META) == parser_ok) { - strcpy(item_array.items[items_idx].key, "Using Gas"); - item_array.toString[items_idx] = items_gasToDisplayString; - items_idx++; +static items_error_t items_storeCaution(uint8_t *items_idx) { + strcpy(item_array.items[*items_idx].key, "CAUTION"); + item_array.toString[*items_idx] = items_cautionToDisplayString; + (*items_idx)++; + return items_ok; +} + +static items_error_t items_storeChainId(uint8_t *items_idx) { + uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; + + if (parser_getJsonValue(curr_token_idx, JSON_META) == parser_ok) { + if (parser_getJsonValue(curr_token_idx, JSON_CHAIN_ID) == parser_ok) { + strcpy(item_array.items[*items_idx].key, "On Chain"); + item_array.toString[*items_idx] = items_stdToDisplayString; + (*items_idx)++; } } + return items_ok; +} + +static items_error_t items_storeUsingGas(uint8_t *items_idx) { + uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; + + if (parser_getJsonValue(curr_token_idx, JSON_META) == parser_ok) { + strcpy(item_array.items[*items_idx].key, "Using Gas"); + item_array.toString[*items_idx] = items_gasToDisplayString; + (*items_idx)++; + } else { + *curr_token_idx = 0; + } + + return items_ok; - for (uint8_t i = 0; i < items_idx; i++) { +} + +static items_error_t items_checkTxLengths(uint8_t *items_idx) { + for (uint8_t i = 0; i < *items_idx; i++) { if (!item_array.items[i].can_display) { - strcpy(item_array.items[items_idx].key, "WARNING"); - item_array.toString[items_idx] = items_txTooLargeToDisplayString; - items_idx++; - break; + strcpy(item_array.items[*items_idx].key, "WARNING"); + item_array.toString[*items_idx] = items_txTooLargeToDisplayString; + (*items_idx)++; + return items_ok; } } - strcpy(item_array.items[items_idx].key, "Transaction hash"); + return items_ok; +} + +static items_error_t items_storeHash(uint8_t *items_idx) { + strcpy(item_array.items[*items_idx].key, "Transaction hash"); + if (blake2b_hash((uint8_t *)parser_getParserTxObj()->tx_json.json.buffer, parser_getParserTxObj()->tx_json.json.bufferLen, hash) != zxerr_ok) { - return ; + return items_error; } base64_encode(base64_hash, 44, hash, sizeof(hash)); @@ -221,10 +329,14 @@ void items_storeItems() { } } - item_array.toString[items_idx] = items_hashToDisplayString; - items_idx++; + item_array.toString[*items_idx] = items_hashToDisplayString; + (*items_idx)++; - strcpy(item_array.items[items_idx].key, "Sign for Address"); + return items_ok; +} + +static items_error_t items_storeSignature(uint8_t *items_idx) { + strcpy(item_array.items[*items_idx].key, "Sign for Address"); /* Currently launching cpp tests, so this is not available uint8_t address[32]; @@ -232,14 +344,10 @@ void items_storeItems() { CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); snprintf(outVal, address_size + 1, "%s", address); */ - item_array.toString[items_idx] = items_hashToDisplayString; - items_idx++; - - item_array.numOfItems = items_idx; -} + item_array.toString[*items_idx] = items_hashToDisplayString; + (*items_idx)++; -uint16_t items_getTotalItems() { - return item_array.numOfItems; + return items_ok; } static items_error_t items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies) { @@ -355,7 +463,7 @@ static items_error_t items_storeUnknownItem(parsed_json_t *json_all, uint16_t tr return items_ok; } -static parser_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; uint16_t item_token_index = item.json_token_index; @@ -365,43 +473,43 @@ static parser_error_t items_stdToDisplayString(item_t item, char *outVal, uint16 return parser_ok; } -static parser_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { *outValLen = 1; snprintf(outVal, *outValLen, " "); return parser_ok; } -static parser_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = sizeof("UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds."); - snprintf(outVal, *outValLen, "UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds."); +static items_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof(WARNING_TEXT); + snprintf(outVal, *outValLen, WARNING_TEXT); return parser_ok; } -static parser_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = sizeof("'meta' field of transaction not recognized"); - snprintf(outVal, *outValLen, "'meta' field of transaction not recognized"); +static items_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof(CAUTION_TEXT); + snprintf(outVal, *outValLen, CAUTION_TEXT); return parser_ok; } -static parser_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = sizeof("Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?"); - snprintf(outVal, *outValLen, "Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?"); +static items_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof(TX_TOO_LARGE_TEXT); + snprintf(outVal, *outValLen, TX_TOO_LARGE_TEXT); return parser_ok; } -static parser_error_t items_signingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_signingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("Transaction"); snprintf(outVal, *outValLen, "Transaction"); return parser_ok; } -static parser_error_t items_requiringToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_requiringToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { *outValLen = sizeof("Capabilities"); snprintf(outVal, *outValLen, "Capabilities"); return parser_ok; } -static parser_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { char amount[50]; uint8_t amount_len = 0; char to[65]; @@ -414,20 +522,11 @@ static parser_error_t items_transferToDisplayString(item_t item, char *outVal, u object_get_value(&json_all, item_token_index, "args", &token_index); - array_get_nth_element(&json_all, token_index, 0, &token_index); - strncpy(from, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); - from_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; - from[from_len] = '\0'; + parser_arrayElementToString(token_index, 0, from, &from_len); - array_get_nth_element(&json_all, token_index, 1, &token_index); - strncpy(to, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); - to_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; - to[to_len] = '\0'; + parser_arrayElementToString(token_index, 1, to, &to_len); - array_get_nth_element(&json_all, token_index, 2, &token_index); - strncpy(amount, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); - amount_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; - amount[amount_len] = '\0'; + parser_arrayElementToString(token_index, 2, amount, &amount_len); *outValLen = amount_len + from_len + to_len + sizeof(" from ") + sizeof(" to ") + 4 * sizeof("\""); snprintf(outVal, *outValLen, "%s from \"%s\" to \"%s\"", amount, from, to); @@ -435,7 +534,7 @@ static parser_error_t items_transferToDisplayString(item_t item, char *outVal, u return parser_ok; } -static parser_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { char amount[50]; uint8_t amount_len = 0; char to[65]; @@ -450,25 +549,13 @@ static parser_error_t items_crossTransferToDisplayString(item_t item, char *outV object_get_value(&json_all, item_token_index, "args", &token_index); - array_get_nth_element(&json_all, token_index, 0, &token_index); - strncpy(from, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); - from_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; - from[from_len] = '\0'; + parser_arrayElementToString(token_index, 0, from, &from_len); - array_get_nth_element(&json_all, token_index, 1, &token_index); - strncpy(to, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); - to_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; - to[to_len] = '\0'; + parser_arrayElementToString(token_index, 1, to, &to_len); - array_get_nth_element(&json_all, token_index, 2, &token_index); - strncpy(amount, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); - amount_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; - amount[amount_len] = '\0'; + parser_arrayElementToString(token_index, 2, amount, &amount_len); - array_get_nth_element(&json_all, token_index, 3, &token_index); - strncpy(chain, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); - chain_len = json_all.tokens[token_index].end - json_all.tokens[token_index].start; - chain[chain_len] = '\0'; + parser_arrayElementToString(token_index, 3, chain, &chain_len); *outValLen = amount_len + from_len + to_len + chain_len + sizeof("Cross-chain ") + sizeof(" from ") + sizeof(" to ") + 6 * sizeof("\"") + sizeof(" to chain "); snprintf(outVal, *outValLen, "Cross-chain %s from \"%s\" to \"%s\" to chain \"%s\"", amount, from, to, chain); @@ -476,7 +563,7 @@ static parser_error_t items_crossTransferToDisplayString(item_t item, char *outV return parser_ok; } -static parser_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { uint16_t token_index = 0; uint16_t item_token_index = item.json_token_index; parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; @@ -490,7 +577,7 @@ static parser_error_t items_rotateToDisplayString(item_t item, char *outVal, uin return parser_ok; } -static parser_error_t items_gasToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_gasToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { char gasLimit[10]; uint8_t gasLimit_len = 0; char gasPrice[64]; @@ -514,13 +601,13 @@ static parser_error_t items_gasToDisplayString(__Z_UNUSED item_t item, char *out return parser_ok; } -static parser_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { *outValLen = sizeof(base64_hash); snprintf(outVal, *outValLen, "%s", base64_hash); return parser_ok; } -static parser_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { +static items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { uint16_t token_index = 0; uint16_t args_count = 0; uint8_t len = 0; diff --git a/app/src/items.h b/app/src/items.h index 96aa2eb..71ef436 100644 --- a/app/src/items.h +++ b/app/src/items.h @@ -20,23 +20,27 @@ #include "parser_common.h" #include "json_parser.h" +#define WARNING_TEXT "UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds." +#define CAUTION_TEXT "'meta' field of transaction not recognized" +#define TX_TOO_LARGE_TEXT "Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?" + typedef struct { char key[25]; uint16_t json_token_index; bool can_display; } item_t; -typedef struct { - item_t items[20]; - uint8_t numOfItems; - parser_error_t (*toString[20])(item_t item, char *outVal, uint16_t *outValLen); -} item_array_t; - typedef enum { items_ok, items_error, } items_error_t; +typedef struct { + item_t items[20]; + uint8_t numOfItems; + items_error_t (*toString[20])(item_t item, char *outVal, uint16_t *outValLen); +} item_array_t; + void items_initItems(); void items_storeItems(); uint16_t items_getTotalItems(); diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index e79eb87..f89bc0e 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -43,7 +43,7 @@ uint16_t parser_getNumberOfClistElements() { uint16_t token_index = 0; parser_getJsonValue(&token_index, JSON_SIGNERS); - array_get_nth_element(&json_all, token_index, 0, &token_index); + array_get_nth_element(json_all, token_index, 0, &token_index); parser_getJsonValue(&token_index, JSON_CLIST); CHECK_ERROR(array_get_element_count(json_all, token_index, &number_of_elements)); @@ -51,7 +51,7 @@ uint16_t parser_getNumberOfClistElements() { return number_of_elements; } -parser_error_t parser_findKeyInClist(uint16_t key_token_index) { +parser_error_t parser_findPubKeyInClist(uint16_t key_token_index) { parsed_json_t *json_all = &parser_tx_obj.tx_json.json; uint16_t token_index = 0; uint16_t clist_token_index = 0; @@ -59,7 +59,7 @@ parser_error_t parser_findKeyInClist(uint16_t key_token_index) { uint16_t number_of_args = 0; parser_getJsonValue(&clist_token_index, JSON_SIGNERS); - array_get_nth_element(&json_all, clist_token_index, 0, &clist_token_index); + array_get_nth_element(json_all, clist_token_index, 0, &clist_token_index); parser_getJsonValue(&clist_token_index, JSON_CLIST); for (uint16_t i = 0; i < parser_getNumberOfClistElements(); i++) { @@ -101,6 +101,16 @@ parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key) return parser_ok; } +parser_error_t parser_arrayElementToString(uint16_t json_token_index, uint16_t element_idx, char *outVal, uint8_t *outValLen) { + uint16_t token_index = 0; + parsed_json_t json_all = parser_tx_obj.tx_json.json; + + array_get_nth_element(&json_all, json_token_index, element_idx, &token_index); + strncpy(outVal, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); + *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start; + outVal[*outValLen] = '\0'; +} + parser_error_t parser_getGasObject(uint16_t *json_token_index) { uint16_t token_index = 0; parsed_json_t *json_all = &parser_tx_obj.tx_json.json; diff --git a/app/src/parser_impl.h b/app/src/parser_impl.h index bb7a5d4..a781d28 100644 --- a/app/src/parser_impl.h +++ b/app/src/parser_impl.h @@ -52,9 +52,10 @@ parser_error_t parser_getTransferFrom(char **from, uint16_t *from_len); parser_error_t parser_getTransferTo(char **to, uint16_t *to_len); parser_error_t parser_getTransferAmount(char **amount, uint16_t *amount_len); uint16_t parser_getNumberOfClistElements(); -parser_error_t parser_findKeyInClist(uint16_t key_token_index); +parser_error_t parser_findPubKeyInClist(uint16_t key_token_index); uint16_t parser_getNumberOfTransfers(); parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key); +parser_error_t parser_arrayElementToString(uint16_t json_token_index, uint16_t element_idx, char *outVal, uint8_t *outValLen); parser_error_t parser_getGasObject(uint16_t *json_token_index); parser_error_t parser_validateMetaField(); diff --git a/tests/testcases.json b/tests/testcases.json index 9ed090b..31dec81 100644 --- a/tests/testcases.json +++ b/tests/testcases.json @@ -778,36 +778,5 @@ "9 | Transaction hash : Y2q38WX4sd5fWzw2knr7mfAltsaYxhWnDGtFaZ7NV40", "10 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" ] - }, - { - "index": 26, - "name": "large_json", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B7B2268617368223A224453395F587857495239416D38584333584541374A39396B546431354F614259486C6834506A5849707A38222C2264617461223A5B7B22646174756D223A7B22746F6B656E5F74797065223A224365727469666963617465206F662041757468656E746963697479222C226E616D65223A22544E20434F41222C226372656174696F6E5F64617465223A22323032322D30312D3031222C226465736372697074696F6E223A224420434F41222C2270726F70657274696573223A7B22417574686F725F746F5F43657274696669636174655F6F665F41757468656E746963697479223A226174636F61227D2C2261737365745F75726C223A2268747470733A2F2F646E612D746F6B656E732D746573742E73332E75732D656173742D322E616D617A6F6E6177732E636F6D2F7075626C69632F336538633865363833633339626463396632643337353535383365303562333366626436623234646465393564613061393564323065653239643338376632612F36613132303038662D353738362D343961372D616337312D3833633863336335363939322F6D61696E5F61737365742E6A706567227D2C2268617368223A22556E6847325848462D336947624B7944333062484B44506F5F4A6D547A5865484C645F50774432747A4E59222C22757269223A7B22736368656D65223A22636F6E74726163742E736368656D61222C2264617461223A22706163743A736368656D61227D2C22757269223A7B22736368656D65223A22696D6167652F6A7065673B626173653634222C2264617461223A222F396A2F34414151536B5A4A5267414241514141415141424141442F3467496F53554E445831425354305A4A544555414151454141414959414141414141517741414274626E5279556B64434946685A576941414141414141414141414141414141426859334E77414141414141414141414141414141414141414141414141414141414141414141414141415141413974594141514141414144544C5141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141416C6B5A584E6A41414141384141414148527957466C61414141425A4141414142526E57466C6141414142654141414142526957466C61414141426A4141414142527956464A44414141426F4141414143686E56464A44414141426F4141414143686956464A44414141426F414141414368336448423041414142794141414142526A63484A304141414233414141414478746248566A4141414141414141414145414141414D5A57355655774141414667414141416341484D41556742484145494141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414146685A5769414141414141414142766F6741414F50554141414F5157466C61494141414141414141474B5A4141433368514141474E705957566F6741414141414141414A4B414141412B45414143327A334268636D45414141414141415141414141435A6D594141504B6E4141414E57514141453941414141706241414141414141414141425957566F6741414141414141413974594141514141414144544C57317364574D414141414141414141415141414141786C626C565441414141494141414142774152774276414738415A774273414755414941424A4147344159774175414341414D674177414445414E762F6241454D4141514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241662F6241454D4241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241514542415145424151454241662F4141424549414A344179414D4245514143455145444551482F78414165414141434177454241514542415141414141414141414147427755494351514441676F4241502F4541436F51414149444151454141674D4141674943417745424141514641674D4741516354464167534652455741434D4A4A4263684969556D2F3851414851454141674D424151454241514141414141414141414142515944424163434341454A41502F4541446B5241414D4241414943415151424241454342514D4342774543417751464552495442674155495349784278556A4D6B456B555167574D304A684A554E53596F4654564846796B6248772F396F4144414D4241414952417845415077443877617866626B613948324A335645627878712B304D7147346B5856386D7748506A4E5968366939554C43564854627850754678582F574750756C583934566358483038666A4F484D4D327A6B36586D3962352F744C38686842592B55577247625378364C78684852476250314E3656554C354C4B364A57735542392B7651436B6C57614B74467373744B795A4F774234714B6D486C33346B66674F52312B66456B41364766682F6A42505339315476476A4F746D362F6E303354712F74417A617141377A7877394330456A557452525869716737755857684E4654662B716B4B4E564266585A794530464A7A6C5938644C6A4D6F6C684E413179324C7877336A783164475448753379483771677977794C6C70734E4E73386459766C55496D344837625342625271693946466971644657633064616548585A57564730336531572F432B6B654963466943417652327051656655797A756556454F317469656B34624B5A3451616770584F316B4C6D37446557716A4D6763506D776253424C3765384F34706E6D4C702F73514B72702F59557133387750366F663841695A356A345038414D666B66413856774762417A5830303565396559315A366368616B5938324E526165534C514F534C536A3662366B306161543034476A7850486A506258715878332B6E37383578546367327679584F6C6254696B51567A746E765447464170755479566E4B7252356A7A6433567657656A3955472F4D663864764B4E48354C734F72466D507A7030515038413546714950796F437A55616E512F57586659596A3649654668414F6761434B727864455451497945315139775549683373496A4E464874332B6B6536667A7A6A3839647A55307455583053706D4E41636D64355A392B46394456664A66544E754E726855353936593957567256766F7A6F6D6B6E466E3939476A69392F5A4A5A51476B4F325A5659546F59754A7A64696F424339723266314250586C304F38506D334E614A634E4A6872776D537345664F4C6B444A615475556F5151614B7561505041475246515A425A49384D476F51615443326C6B524B2B76356675322F594B6C627358462F4865514D744F6A6B4D57434F485079523436476E4C4C782B39536D38596B4D3749725A725A37316F48563332337A316F33724E41484D6C766E524E764C375A726C6D5132716E6C4E4855703253796B6C6C634B69427569422B76354838666A5A5478447A5250702F4A30326630564F55395946626F422B754559724A726F6131594A792B444B757464714A4D3632556A6F7343375158737236547245514177744B673561534F6B734477622B73337A543550384C3450487950776E2B6E664E664C7276384149353844795043344768786C6F354C7457543837396E506A64644B38626D655764633530553466446F4C3664756E564C484871584878666A754735766E75546838692B56532B4D7A6878577266782F4A636E35585458727A306A464D4156745766484A4C516131586C6C4E74395A79595A634F725456433142667972387731506A6E70726B524F7153414B5848474A55782B3062636568656E4A747546574D61564B336C63653350684A384F5A5668694D7567367752735749654C5266554B44726678336B6E33596C70776152305A4D546D572F536468317A527A6F75306F764C696A65365661496B4A70335654374A5675454676754B69634E66646E6D646B644757722B44712B69555A6B71305A5565623330754775633958706E56716C624E4B4B7136794938456D76786E614C644D646C3834337A757174655230744D3161664A6B7636484A514862444765694F5472576D6359703656314E4E43706B564E7A71316C4B2B39516339376142477467446F744B336136772B4738687A656933783768744846523261487A66493957376973313661593538304E6272593177335437675A56724D58626B4E73306E6C77563472653265756D6E584D48354431647657466D6A5037684A38645A315658636959384E3874456C5A7148792B3155315038412B5665316B753157637953764A5A79656643726843796B326C2F5A6145445364336B37714B47417179347472493868736166415773436C613159736F6C565742567A737170725773592B42666B50384155787A38703476463868484C372B653576527A47763435386A307358343369317763436D57327A35586D79614F4D4878374850567630657966454C784245386464323348505A4D32354A69783852717678664A374D6A516C6C343663786F77314C666461546F6F7935353578424C2B35724251664A3362774C65514C775A4E464B6D2B3365595A5973737348454C77424E5A767A5837524A6831764F53465949732F645A4D6A586C5646703637365857516A774E792F376B4732324A54715979573851374F6752746C306672663464387530592F6A7462664B7562572B2B4F585267546D655234666A3461396C37584A6878504A61754C6C7866783766316F704362386E796E48384454546A5452574563334943764C6653774F5073614C504A4F727A6B5775325A4C5830474A6D7432397561415339764C2F4630544B62685356382B2B674772367338653950556B4D5164646C6D71674A4369306B787953374164644A50704641796936696878633033574E49467A4241354A3832494C4D497734583535782F644F4C496E71692F7750395475492B585877355069584B634E6F47756132504166494872385A30614E47744B737263546F35586A2B6235506C4D324A595258313168384D354B33336E48362F37766D3037754D2B2F6A32594C345A5530626C33544A30685A36345A3375726F44347369434C53795438663841536C30725759667365725249436A54436E6371514D2F6C4B646977646D6B317431757A6477754330574C4E304F636A71484E612F45695243325272586A39717049574D4C4A71466E704B7063762F6E3277394D42316D7071795931586277764A77356A6B736E49706F792B2F44727A5A2B576D634C63636C324E5768796375503558693771795A4B5A426C5364644D314F736D2B6E42697877727072657A617339566D6D617371305367634A625657704351626F5130307754534B32594E5630635A5A55514670676F6F4B744D616E3061706A357049434B564467627242726173737477316E6F363070797952545062443846566143787471744569323868444C43744A76562B754253696F7138375167584F5169714C325868666966473857495679386A54355475303657333530732B4A306C753163666C74397A74315963795A4F4376687A6136564845634E6C305A66647235476B392F4B2F646270374B2B726C4E463954534758524C464B58707453527565347237566E4E5A583065796A4B375A2F583750585230704F7A684161424B397448377477742B67637758366551553351544A6E6B7445787064756975543555464C2F58545674347346676F2F42314548656A32724B74307862417553327158515A6E55556D76334834506B4779766A586A35386C683433466A305A65576244484D747447657255306A4F642B572B58573058675963667733485A70344A35644D4E334A4C69305A495261764F554942625456386461316F72356156632B764B2F5A495757634E526E4E5041765853556B56526B6C576A6C5239434E586A54317A693352376C615A592B4A724A4C5455507445305A4D5858467663384853483045582B4F4E593848715A336C485A716E515979584C5A676D484A6E533739476E42653648466362786C654B586B783939796F676457684E484A38764C4C654B30767374716645726263343155666A5A367348483474467033336553743750556C724B37772B746171674F65552F4479564441416A39474B2B35622F6C66797A64722B78552B4A516C575764472F477076656B6D45324C62523343486C425A6967415453416851514D30356B3677527A4C4D595A6D52725A63476C59664A6F39736A584D676D6C6E6F7871687A5A7238777838373862707A4D4D642F6A65733239644B6164546362385830513471385A6B2B4F7A50723030356573744774384F6157737470475775735574736E5A4A517354473757456F36326D63374B33714E4B366D6478312F414B3245507A2B51415A6C51503967514F696534484C71494A6E464B4955756E516A6B4E413352323349594D54382F7741416643566E704B637962554F434977574C7539714D4B694D304A49306777776B4C6C77524256713578336E646F764854445057756A5642707275553257306374526F462F736C6850526E565550635A47584B61703433573276513031395765677757667A555870366F546F72797A54554756616B677A585255756F56584D3355683056724E34536774543754494574387A6F43796264694F2F2F6D4E4E415456596B2F74504344435745795639495649794C505756755A643458644C7451756963747968614B727872436B6F4E3959394453505A6A315A59424D64305461456254626B5871786E6B62323534786D3176747130705366334450363569654F5A36584C6E393373496C6C712B347150624B6A7A6E51675A306D776E2B6F56757977627859487936494B4E2B4F77535177415A424530474551347441666578724849574456506D746F6B35754E4F5A77496175796B632B4A51685A534D77383962544336446F61746945577043725932424833564D4F545A707A79386275305672504E6F7A4E4E4C696A576136415736304272367374744D355A526A462F612F7742766F6D374E782B656C4A5572545756713231363541493946704F61746279476453524E696F385653616A324B56524A71534638664D394B524C7646514256347A742F705A4C56397A5A446E51716756633257625539704C75756F7576456F376656765846444155674A666977314A3941355455686D34534738343344512F643269667257397061566534654D567A74374B67565A54424B55646C664B61774476596F7A425A476B2B676A7A3958396C576B7738596D48656562566F3268326D7458566B48636945703332574A6E2B5237542B4641385366707A69302B694C4534323479705252655346667949465576476B6D6A5A757147414B3044433869734A376E51696161786D526E38775A2F6F5632566F6F6847344742644E59684C634A6F6C506B745839765345347A3872322B356D49766F6156367047326650525A31553031657571695372792B7A4D38355661655671346C74463930594D396E4C5566776E4D5A32657338797365777232486B7A79507355744C777047746C526A4B73365430546830346F50327661735749624448764E425152304F59316D36395050684D79446C6B41526130623541634B79355532496E52776E2B654B69775A61704B474C6D304C7A57313063505A664C5A2B43346F486B4C5A634F7049776158472F634A6E6E4F65724D7A5A38556365336C67526D5856536B38724932664F32625A62506B78356B536F6839526164744669596E64544F77713164644A446F326E594B7851724A7336306373504A4F323156756F616C576E5257523249442B4D33734F50524D46563744464358394C67367969372F414F52582B57774F6B44624D71656B724C384472736B7537646C724658436273357A535836756E35716178547A62362F2B2B6854332F314E2B4A444C4B6357356D752F53697670624677764B36493462357948734C3379726C30466F736C4A375879794E5256435A5A3678506D656368473359544B4E467A53444961364D7169724D66785070613164314C45666E705556663841384142304F483062386366517377456873556D4D6D5936397143547965623852784F473071696C6D5661754D706D2F56614C557078514B4C7A725A4C6A42324E356A527143324668414563594D32737238562B6666472F6C6E47625532387A697A664973314B36386E7837647531636F764963646B363155315A467A786C7A764A3763306C6E576E45357542315869615A70713462334A6D76616374386575544A6A76584C64525056704771616A4D3764717156674F357A53732F44787070706B517651416558613065522F43507A4E6C6A667958382B61485A6E59455079644C73304C6E52734E4F4D7852504973636873706D4679377947647559436A6B67304D4B756B42374653334A2F58525159564D716337515A6D332F6943706C35502B6D75375A6B355450644D7649635A5A505A6D72476A39624B52434C445845746B736832786B495A6254304C3974795571706C797930513036462F5461314A664B4D735769555775665A457A445470362B6F7432704D4E46554A553550456E7756475A2B314C4141766A67323872655A7072303850526565444B574964786451663977652F7744726766537259667A78314335577331424A5264504153616F38414358664C5241776977634B2B6A73396E5A4C34615A726D5354386C6C4B6D42613859716474364D3936506F354E385748526D4969706B7336624B54364C694B2B78425A58585450514B524D3959756A743557536435757172312B6F3770725669522F7430553641485A62384262306669555A6F2F4C64504C7139666352557A42454562326B4C596F732B4C56317A565663614539434A666168384776424E4D663670566E7330325A5859784670544F4A775138385A70465250354877694C783738687333635279455634336B317A34654A32357552354444783973656A46796C4E7644592B427A7A7A706C6D63692F65323251774C64307A4C794170726A4C534774346162546C4D75617133744E4E45554C72584D65387A6578697634414C72565041456B6A2B65752F7255764F666B46677738786C474D333747496D717461684C654F55786F57376331676D32695774544D63717661756E525176424373312F73435755515137777156777854494B51427666482F7A722F77702F452F6C587947752F526C3477547952524E433562364D6D5363377A61613274756F2F42744E546D70455A55744452796D754F595553664534615631497859506D334F63564375504B6451576C486D5436552F436A7067382F77412B48355A7954306569573869584944696C58354F2F6C45704A386962676735424F61667164546F38754A5851794B46615A6F7A47716C414A4C49367368434259644777646D4664534B762F78634D4F305875754D5672416B5A636D39472F7742492F77436D6E2F6C746B4F5262374D4F444E677754354C4678577A4667354446624971797A684F4866614D34783434724661636C713431363673576E6A38632F586D6E79664B6874567162486D4E547A5164745256616E334454642F324D7A4F776D30694366796B3173696E7365776A396A6B35366770376A385038413749394461666559444139584432456155537A72476372724B7067574E77466B6961523442324D6546425271586374344E574D6556542F2B502B4F503957766C76473854384A356B34646373334A386A7A5338666C79386679756262494136583546655931797863767532357445345A4B31684C6C4868757A3634786E704769684C564C2F48636A37755A654C534C5A63325639467265734943705431724A656A34455670525A4E2B3358697A663841752F48313735585A366B484D69644233445A4851794257324E526864646D6871467046677863436F44776C4E33314B77694F364F2F7741644D4347495857466B4553684138595572707A6A666A3254357638627866494E4F32383755346A4261375453322B4B33654564466B70504877736A6B6D4B554D61526656704D4B4B3033494B66714D30526E6B32326A396F725047314A74316E31555069724870566F75716379416E366A755869414348527A356552737163725666446B78724C31726236643876737458514F554C66635159426B57314F625749794857674A534262326375633777746149366F5047746D58595A58773271714E6C4F456A77325262446A2B5371645256547434336A376334734B4B366961777873534A71377547724A594A5838483157446E396174484E5439784B6E48353838484B654C56504756586F416D5833556F305675682F774462574D4A6A767678374C4D575A2B4F694C64346E6351304A4757625457726F4E5075556B4B55695A714C54454B75686372767A424F75546B3567797132415A6D5734366C315455376D6F4E67476374725752726A7277504862654A315A5262377A6D48717564724C68666A382F48795736766279687949547A7A38686E6575486B636D476157334A58546966546D6B77716B75766B3574346675697A2F4141543432315642506946383130537A4F6A644251664E32414858624144386D34726E38764665664A496F39447A627644443170583971596C50663132626F4E494F65746F457157636E6D32712F714B4130794769786B373078524E4A4D72686E6B6E66624673684D7935622B672F4C62453348447134725877796F6A374D462B4A2B51374F536B6153555A6475656D6534655239307854547177533265764D755747564B5178504858336D3177306B56554B39774158314C5A524D656661364A76566577656C502F546D714B2F6B614676782B666F4C7833355A656538334F44636B4E6E4F61525A514C52417032543870684634516A3338533732613356464C4B6D514A4177424447565A77626879594A32336C624D4E54417859422F6B6C386F2F70507A322F2B6D2F4F386278755965345A744C53715A51347565486644504C413135614E484B55305A7A797244556D4A4C78532F47365679617556464A7149302B514E4D764A523176346147383358546D674A3266524A2F6234647942587631415239674241594E52657972416D7A32362F4B6678484E426C4C7A745736664D563634594B51794170514E3973753853786D76766F61324A486C4C6D687A323664715A6D70434B7A2F4146567967317552582F6342437438692F77424D6636456631482B502F4B7637357A657471526A793276646B356A6536636A74694E57483278782B76424C6A65587A38577576633265462B65355746755434726A38723449543470754D303533626E6566346E6B384351793553486E6E793572704936383074617874493272662B3578324E376174426D716B4D7553596F687A6F73725330374E4F626D62625A712B7658754C494535374C686A30467136307A696F466B6531354379367A6A676F4E766B78336875667261687748556B672F7A364C6144547831414A31374131702B692B6E4A6C3065726B4B2B6D6D6D454459303435593774734B5238564D556A6B6577684971714E667A4632684B4C464C353541794F5771747945684B53366A356456577147307768506854313166776F41366B6B426B38565967422F486F2F5378594B426E6F69397064706E6479675A4B32564949374C587168306775584A504C4D4E5A5A374B4A694F6C62566163795767574D62316F5639314A36792B6D7069796B6874364253342F67732B6941313850485679306444636862667A6D712B78636D445A6F4A396C5A352B5354684F4A3262375647596239584A61545430354D385346726A69624747303152764371434C685A536E444A6C393755385254317A6579392B72504A6E71796F6F364C6161466A2B464C44494174726D616C6176656A31566E6D726C514C596D6B5561324D62544C59784E6B3268424547745839764D5A5171417368587973526178592F455A525945344E74486C2B4E33507233616236755A7068665A374953692B794D35347055756A307738626832345A644C3630504A4743745058597A483373586C4235586A6143394A6C6E4531583245716E525066384173664F683756694F77663142503558766F6A363373384B38342F30727A5448494734674E7A6379534A654A4363653272776732636847476F674C5A2B7930347375466A535A4270634C4A73727638674B6932734A674A4C7266422F2F41496A666D48796A457A364F41656E336B4D47376C3234714F333063323779342B6D6A69703854585276647261353077595533634A696F6332764F6330396B4D584537743153552B503473577654474F6F5461643948716A656946344A4A2B3130316F6577717A485143316F516B763270526B565366706D3666425A6E5144584B43314B79655A73704572716F48737354306A6C44584363714A57513658487135364155774A6D6B4B4244725944394443734B726C7A355664506D542B6D763957666B6D766C636E48387662646C686E332B7235487235484C737258546D352B617254354E727A7A32506B78384C4C527A7646773439743934572B55536C4E4E766A6D546C5075487A6E766A6D4B434E54497A5772574E446D45434B4C50506D4F6D333279546354633661665A364B55556F45556C476B37653251624D7232594842433775323748737574556A2F542F414D5762566C4871797068524E2B6E494D4C7471697157437869396345617063757653446D4B52424D7970477A4E7558433674574B2F30382F706E7A472F3548384F6933794757626A2F6B4F4854796558354278484472794E786A336364546B4F4D467074724F6A5A664E4E754C347938374A37485A3971636E706657326F386C794754386F424334564574554E3458794738676A6A75526378372F414E56704D6969654C4D437275796B39487636724244525A656E305A686F387451744B487A4B38666F5862716762417A6D427742795A51717558584541554570726D647A49316E6564332B663855726F3056387A36344354467174363377364468385767567A6E704353786544765844494B574655706C564458446E6678464B2B5457362F56767153464E434A49615359567432397641412B434E306150332F414B71417A6678333564466567423139634F5774312F732B687843506C46594D596E69614579426C42386C6377614F7743716448313030642F5353494370784E554150774332777936336C52394A7A465056476D3839764A553471346B305074564E625171464F6956643374527462554D314F6965305A36305773794D7A58795A68434A726F545765624E6C775133466E386C6F77694B4C2B54526B5A4B4F7171656D3868354B50775035505A373650316162594B6A572B6264436F4668413670645A6E564B366B4F73455A7555446F6C4E4C6869476D4743716A4E4D796171486563342F614D3646415342622F52486F727370517743714938727838645571365948546F30344D7956615A6F326242475769516361615034654664364A4E733265516233547A7A74564930735168455971444D6B6C71516A4F657735506B794762764B49494834394B544C64412F735730544A582B5374302F78552F4775686B745631376878496255714155636B4143515170316B6B412B776C2F7445677A5A6C6D66796F776976594C4F4C78626151534C72416A447236584C536B75516E6D37354E2F556E6B50696E4A5A4E75506A736C655031354E2B57563274687A4233747031596B544A484E49366A46354A706650374C39374A62495A2F66435A324C63705446486B4D395A7A2F4150555778506B6F4A634B68565865374146566D4379466E4A4858536F417A6D614E714C68636C5666515567525A4B58414570304A476D2F454F796B786330517349735064335747444D394D376B4A5647774A534A5A6E314B364A4646466C464D714B6157486B722B70333959576850544A6551355358496246306574736D6C4F45305A635370555A72515A6375367642636664483166597A56644849366D6A71466C6F32684E4A62666A6E7861396172563832616D4F5A487666564536553644713173346B4B7969394659544F7330616D65467836534864653163516E6D43343452704B6E6C414443674D6F46655973564B466C43473076675A526F705242436B593565563273635932644669327A6B544B617162724C4C78756831594D333953755658586D706C72796434546E6D4779764C61642F49366A355156612F625A71636854546E616B325A6158595A6D63435863774A465765352F4575505850584F347A4A656839795334355A5A596866456543335753565370444438303952512F7A365344307162622B4D676A467063724D5655574A574B3134706A334F32374B746A497731494262585775457642366B465655584130466D416A6B41467774674F33575772467352774E512B4B664E655230527A633177764A32305537642B52342F496D4C6A2F7439383776523161575365722B35616442667648493538476D5A305473334972717070584D4735486849427447545A45516F714C574F7A3257325A6849716F37517A704F3076556578616371316C354A516A436E35525539347A34497378767353746C4B72536F5178644A6F656F367253375775564C657345423439746150546A4468743649324B6C357050554F714735566F78714A7645626836695071457233502B70487A486B75642F70787836386462343974347A6B632B585A386767352F74507954696E7A624D41785774386435584A36393736744E714A506E4F463072386A785279633377334A35636E41356E7835655036657979792B5543656B4F4E6B4A324F5371306A624E63506B704E6658726B732F5762357446644538645A71746B44566C617A536F422B665038767644715553454A384F54627131626C7A615176304457326B72524C795A325772726B5474355A576259554D47514454476F6973355748466C45774F394F4A654547342F3536362B4C3868797679663772376A695A7932594936704469556C695448792F48594B6C6C624E696C6F7A30342F5569576B397036387A504C78677963346D666B6B74544E736E4A496571686E5636325931556570446E64756C56573845375A47536174352F6C326F62466C2F686D51766C754B6368416E6A7671376C7A6370634161706F4B6F4C6F4950424D3459766B73664B726852654E6761686531734B37434F6B644971504841695849717A3767326F2F474533636F61577A71357A594B4F5A6966326D666B49624F4F4C35304A58496375336B5867367668664C74554E782F49767250756A7950465A2F5A4879476D45626959506B614145734435414D7A4141796F667A34676B467135775648526D7A677631394E4D73455050586C535854614A4A7848496753596E307053366D4D794C4C6844437865774E5733776F4B574646687352722B3247786F6E5A5130684B51355862587A4E7864484B566A7458666A6F395579356466474671343839564F686F614E47666A4F51686B545264625672355A557A57315370727A52573276546A634F312F6376666D766B4372426E436F354A36444D71304B2F6E2B50466B2F58782F68674F67517652484C7A3268377875385A766D527058776B616257466C61457373384D586E367A697A74444D706E5A32644931564A6E48744850716A5668786C4F6D2B7273415578666A79634B4E2F6236586A5743386277752F6B4D633535622B79766A396C783050546C6B62315A7A6E74777331612F3630576A46766F6D504E47486B4261617376386D5374526D36424939726F4B42542B517973773650594A42422B71352B7A334C474B525463427A3445634E574547514A3864635271544F6B79695456562F4D754F5845575844326B45546F58736D742F614466334C4F6D564C6C68586E542F414D51394E69635838597A63672F6C79454E484955302B7864454E506E4C694D3634565A64744A364B6F633757394E6E7935423553595A733063787A7158623464347071354D3036565450444A584A5667462B36397267504D73414435795677442B5654706766465239573538682F446C317373516F5A486A614244595A6E73345253785A4A487A684B5763554F75734E746F4A756B4B70576956634B67354A2B446870636171596957424253675151537163702F586234682F5448682F6976457478477A6D4778386268687A69347559347555654E302F3247644448624866733236484E75546157484376433864446A70787246655A3177306C354C46626964584B62646C35317A7846644F6973425658386A4E72315653676B305A736F436E7637697257382B6C684A356C443963587148342B36767878424A30335A597A71386B345A654A3243656D78766545534554664234485A566B4F2F354758474279574E3759522F614E6A5A5059744C6531574E703576572F36572F31302B4A2F50696E413563484B486679574854736C6770796575764559633251306854427647626E4D6D546A36766F39697967687A373757687679307878767864546B466368784737454670536A30514F6B47385961306F77645379465673486372305756624A4F73765A2F69543255563566536F797059347271646F697564497474786368544668594F6659326B6B417773684C6875714665577844354551716D32536636384236344553674F445564544B7A5A394848356B6775574D724E6D61733246447944387077753977792B314554513735415674374A654230764B4646724E3531302B4E3834472B6859654E6130436D53654C686D6D4C5338575A2F462F745537566770567731455777386747494868394D41675566527A506C736C745A626D6D6B6D73617355412F5A484543304557454572656C6D74494F46315951743978554F4B72726A37795A397548344C79565A38612B6E6E487A346A6C33327938626C7A2B327A7443764163655663756B3761684358444756372B7368376D6671692B654C554D4A4E507972556E376258576E472B7A51395848534C536B30596B4574354D6A7165695432786451436568332B5439664A344F3730747464614E44414149536B69674666726E2B6579676B4A442F42483536463173346352387576675155766F64636F357753754B2B68686156544F457763506D6C6342773854787473327957694770355135567475765A707973774D724C587748716D564A386270566F612F636E3279714A56376C45733356394654526151704F6476736B566C6A5A2F4D5751305257705A683472374A6F725569517674524336643845634436465265484C5535425A78575A336E66375376514A646C62586464495767546C4E5766726733717071747335476D76373836413665336D3345784745742F7A58354C3535584A6B4F47756550456256593261504757476939565439372B7A4E783347623756643136375A4B574A50384473665575515A645069324853375338764165344E697A4C3245542F66566F7A78413855566679515046564852436A366B63583537704654576378733165784D5858534D34783045684671494E6C52796F73456C63462F74496A4237634A3264647768676E396F61726B72343264444D6952585175312F71723864767843636E702B5155796B33755979354464506A41396372556C5543504F7938616662487A566732425450537330654D79744A71546269747676624B324F326C436B2F50374450713544744B4B744A6C623456305A7A4E68346B736D6C5146494966384159426F72315250736E35785654756576346B6A384A38704668624E39352B43624F32775A3637626B73697A4E414F5A5439336C6C354B2F4F4D4B436134544837647867444B776D37772F7958682B547278395130666C51327377342B57766C634739626172542F36444468344E4E75546A425679724E4257356173316C6D335562504E566973356F5954466D6C364A594B7949536F6E6E305A64424B416833387445687157666B76344952704F536853722F676B4A5852477736685A656537514F61475443747742415979684D4E4C34715A30784B485336714352583049736763674979386A686C2F7741426B687252372B78732F5A694E4279657654786E496D36356C696730384938707A7944585241692B5563334A6A49744D72452B7071504B3261797A53316978523531475A714E35795270306B572F77416A4C52366C515744394F5A557541362B514C534553454C452F674836314838512F4A367A53446D785930755157334B34774C31527174716852467252466F3079774C2F6B627677325A714B3233686C56515A713148624E67465575624A68334C4B6872676E7A5834496E4C5245487955354C6773744E71624F44354837446E4E493544592B6E4F64676854674D57724C484E69315643386F75377962377A54474E686D463232663036694C654572543939444D4938464A62775878366955397A314C457236562F547075673147434652426C50505A527354556A646D503833564A6A624B3350675134704175656C74576A413230363131337448333759576E386239746F304646375A2F4E684E697546735947336B5A2F77583948313551386A364D484A5A4E327A6B6F383361322F6D744A6A7332344555724D516979356D746C333347614931636667354C4C6C766B68585654586D6E46374F6E6D674756714F624B4D394564597A5374704476716857526D7A2B687044313230514E496B44706E38514F71442F6C6637472B395764465A42577A49465A7131705776515A7A345572774F384B3965712F704B68356B324161463352424349482F55596F556B426271787A74415143765A437571526466345834566D2F7039486678484537595A506B48494345742B522B4F7A3563476C7355306E794847614F46302B7666786E4556476A4E63364F4F385534693272637A6537464F394D644F4F366E492B725673672F39754C6D45765A6434756E636C6C4B6B6D69687A4C64417330584E526E7138414A65455661625058584A44624251764F71634466454D497641646E754A6C7279564E38446770506C677A61466A70614377485563624752424D722F77665263416F414671486F54574B6C6A7250686561456333487A512F6663546B35434F62545356704F73392B5335664B2B57636E61726342763361636D585662504A61527A354E4A5445637934566C747477412B586E357776584F706D7A466E2F77614D314E425568564158544748545A5A66342F46336733364F6C344F72787434783475664C374C347178753562486F37536F726635786C664844425375594D5253534F4446586B4668727068356D6D346A6945794C526B34684D4568717A69593063586E354F634C52724C4C495A2B4B79766A6B30615444506C3437626D7A37454C666270654C557A364C3539716B727131596F346365337974706777766173614E6E634B584C626444466530363832513156714B366C417273304A304962747567434843723370353475666D434C526938306A37306F696E6A46356B3252453877566F4174303370755A5A5A6334737149764E70636A4F57536D4177347076314D2F3070777643754D466749636A66314131617545786E5237364B615577354A6265504131557930303147534632796C6B6F66744B776C70342B61784C7276586A576F763259327959504A6230317A677A722B71733559442B5679684A6F68626F64436C7972575139686B5257506B77432F5770486C43785A464D5655414A304A434D74754C5963543845583132434E4C544F524D4E6C4F4D677A4B69732B70496645557365745A414E4C466C6F4B336759593950507A742F7131386C35445674304F6557726831307054496C6C3967785A71634E544F75365351704A5175654731734848346674587856783864743362456D776C3672614A386578355A796B4C514E2F4372423139684E6D42376D484C4D4F3631435572632B316748764F43305A704B366C34663475774B6D70594E59594F6166473477756F4F7273513166626875567868476E2F4D37595376756A4555416367695A70545074374B5566737265782F7743654566366E664F654C2B4D6A52386853513238787962546E78574F3154433349557935387A507965775A2B714F364F683238695A556B782B36484835486B434E4758646669587837547A4B5478566335736D414B756C35723569585A5970677A4E5257444A4B624F4D725542514F473033685571326534797479545461724C4C436A544F35796D3079674A43717444735A74757065324C536F696D6B32577145514142416B6C6632534B755845486A483141564B523167316A544F2B443454354C387A7A53332F4E506C76794963613147315A666A7646624B594F47584E6A7A6D6157474752474A6A63536D4A584765657651576252713150735A744265655133636477464B5A2B4634726A6E326A384E7430536D32696232426F366A556B6C3131636475444E334F6554396955546D4D63756371633559664A6D414A6B44707077454775336761356C6442374131725A5A58594E413078774C66564E704359465953632B5447432B7070634743594464574D67595565716636632F5952305A38584C614F59746877356C785A4E4F6E6B3937614F49764454467675346164464C6139666952742B377932707334783855416D6E50555A32787A79506E7A70306A56584B32576533525A4E46516D624A4C336563475363486C4F4F664B6944754B2B63704A6439526D357331474A2B6B6B7658764D7836646D64477A376F6A6B2B67667178376C563935626C4F424B6B316D6F4461446A4D32444C533567685959554375595167774E7A5A6430464A797453733638637A522B6E4F63336356752B4237735746382F6A7865584F387463466E69306D7035476566626732506D6839687A3064465830622B50315557484B7779496A57354371356C7762466234676C34664D735458554A54544737307A4643565161493171727A643239733771326435624642614F6C315452307063536A69662B5143326B52646F76503444746973746F6942376E46516733474647652B6345512B7A525A79456135576D556B6B56495744414F41316C6F6C4331794F724B67327442703736382B4F637A713476354C6A6A7131486A4E2B2B7470635A5837745A594E664A5A396D612F4734723869456A2F625A38356732626348446F2B6175724E79756E6A6D545478755869535A3548486A744E6B336138792B5538464958654A6F42656B4B31306F3268592F2B71304D7A5139656877684557645050704F32464C415535515577306431736F744D7742516C646A7737786A594D556C7448725943337A4B2B6D524965587755667147303732785A796B503434555663576E422B684D37533134587552654930366E72686F4C726F397A504339704E53534A66485446794F5263373231354D3963327854544E4A3544694F502B33724D7853336446386F4E2B796A312B6F796E324154332F4150615A4B45456B663741487339483838597755576E394F376D65496853766A654E53514E3974644A59314B702F53714E356B31354649592F6630724970483071744D445067316C3844414B766B726C65316370747A4E6A6254757A342B547A6436787172397272394E6254664E39335868395736504A6E6B566C65655A745848385A7A686F316853754C5273625073705A704879556D4B73366B66705364416B4755646674562B6C384A6678354B74386C41785252622F41476C586A30366852386341456A4270564F79786247342F4D774372646B323169534835426E5450746C682F3177706475704B417472467171732F6130777A6C6E65633534375279525A6D454E4F36545A612B6E4C795232373046467231374A63686262733078307533356E6E7052737441567236636230535A34446B785075584E4E704D336D686E724D664539716856576D47566A332F414F354638667754312B657137653072615437734B69746A66542B2B6A4168554E497367695630376D4B385930343063362B2B366C6877506C5A6B364159336A56386D544F464562624B4343504F333962654F354C5A38672B465235436930626C746C654F616338383833704A3034637335744D4E584E356761624A57745549435A703648444D6567362F4562537A38647A4E5A6D79744A4A5549667A615A644630364F35712F355A46436F475838427644312F78342F58364E2F4D52734374576E71566F794E685A656B4756673356694F697A5176352F39792F6931396C5A63466E5576744C733634625A316653425343362B2B69736F5846444667312F6C482F5776354C2F557250763576675069334D6649754835536679546A63554D30766C6D79664F313059632F4F62394F7A507957677732765631354434787263354F623561755044782F48366F766E7A6378586762374838506A774F6B35646E4B797937386C636C6D304B3058664B7765734A5043736D30766E4764477A62575764636F7A7456375439564E46546455312B5831496A4849613753575646476946724C69394F4E593351646D3459335476554B64462F77437A2F6C7A624E4473746943535262556461574B785932325868473157464B6A7651662F676E347A356A702B646350623567334B5735336865482B515572792F4B386D2F4A34776E4B56345A384B464938687277386A386735766962386C786D726B72307863684F4847636878393965343231507861542F55362F4743646F38544F4D734436754F5978674A5150746E6A61656E7A796D6336356F79454D766357587A7446793868475A387457554F6578314C693533484E6758642B74477A5457576C556C6B38355547445A414D2F516A49383447706231514675376578764B6442536F4773754E6C38634C6C66625031683237632B58796A6F3058546B6A6C7A48586F42317834384B59786D41772B3769326B724B4D7A4D316C7A4D5957612B5A4E50694F382B4E6F354872616844414930556D574B763449376E73616142327A5A706C6D7133614762715838456479564C6878766B724B71377035512F584E336171766D546E566931336C4C7552352B684C6D6852514945474E3334724F314372616856643967466C62462B316C412B6F464432556876726A727532367132784E3935484E4147634D6C37797043656C4576376334524939745058796B396430643374787646384C656A314D3339796E6E6B38634D35776C6F55712B6854524B57554D5379426778306850496B6C5252315034583358525A6C625A2B652B634D587A674E566E4D6651337045717134773146515937693669456F45644B6F7A69376770797743484A797570487642506B46644C6C30546D786C766136346F2F49664A2B4B2B4D787452395846634E68566C475A64584A446A7378742B5048714765713031586D56514D793474496F336A307965503751665A374F5A7250324E73317561487631544E364476727A5476522F695131364837762B4155505866524831594668344235556F37387532333565524C76723754656F45376D7373303547634C72426F744B6C64545437415A512F2F594C5A48693471507964456A5A6632377450635A356A2B75485038707638413766783332584D5943505364326D6D75654B674A557A544B2B7A5A69755A722B783961592F477850673551447636656358777A454D38646D6D584A544D794B7A486E4A714B7737386D64705A4E4D434841554878434838416C6D364831474A764A2F7877644C3249465A646A38417571394D585941334A73637373387872355177524D46696D654A4D70576B32577A366343764162707A316A426A583951786C793271707A79664C6F326D47397678664A757A72477A68716A476B4E456B58306A316A6C2B52684C5A4953524D3463783049717A395555524F6B704A782B6E49314B522F75387331364D717171544B5564324A65676F6D586A74524250624E31643545487A39626B4C524272334C774879697A46484D6B37484E36504F6B4F56414B6C4D703065674C7078634B627279644C3957462B6F69486E5762566832794C526D743569543254426451755076456A2F646D774F66482B61316A6C5257625479374E4D74466E66556D5A363674463076484E6F746C626833504E353833336575584879337935584B303733317A49766E5657683173384D354F6174626962654C546D624250476E6256387866527179785A6D56545856565932616E6A5037706156384B4A5144385A5049647431756A732F7136454D61584866415764676D573256416647496C4E746B32564A68714C52307736324770593663392B4F2F65457A7575754D4B4A6E576655667A62656534505650666B2B53636C6C533670464A5532506F34352F3762426C544A6A6E4E3436654C78704A4E58574F6566486E79694E5935796A726E673946755262564D6555704F30674850362F6261445076784272436E334D616857364B4F37563968554B367942383057686E3469453538356B77387230626D7933496879494D566C3535454C535573565731736E7148554C7131616F7047355333394530595A6D6C362F48766E5173304374343362444541726D4350795162396F34726C394E792B37546E6B786E70327457644D2B7330466744704B704451367169365A355A306E646873526D312F39536B5654524D314B746C68634B674C7436653631526941515065396F7036304A4E65364C4A466D356D4A5456565372697A5857656673337557595A476E4742682F7A2B6D497A78675231622B5638347058765246484C426B5A35626B45694B712B6B79746444376F553654674F79733070436E37656A52793763754A70354F4F533659744E49357772587A586B5938646A2B7848636B7A33443279726E6A474E3533725A3875377A777A7A5934355A6F616E6E5974397A57694D353866654B7156515034566F34476D62716F415755797358554130426D56597662475949375A36734170565364714F714E446E563167527566577742534F4D33565A2B326D43444B482B79777A6A64635772715A386B785933574236456432495575306633666C6F443544777646636479334B367553354D776E6D705062787A576A68356A6A4E45444F56394F626B50736C7931342F5A43756662786C67457A356D4B5A4D73737959353764504A6C726B595A356A4C4339414443302F4B7374634C4D616854454D5565734B397A4D4B67395462736A7770313950363338593879573352584836646A31566C346F6D51576657554F53686335656F3557704B74436C45544E7459584B344B62594739733450656D6D484C6F44577868625936454335503633714D66737734585238795339656E655A306774597733593552555A6D3063584F7543704978594B4856685736666376796B7A5238305A42772B6D4C50466A416664417053636E6F326831554C5667304C555754414D2F6D6F566646442B713946666F45632F6A33487A335867736869644176444E30566E4C476951673754493951744F6B2B59576F7A3162774344582F41474257503276716753777076706A4B6A3268674A554B533751527457346635745035784C4E794B374E45744848796B3170326870714E4B36493463614B575456746763675561386D655258486C6E64727A7A5A3872576139684731375A68614E424B6F646741394645715A544D6C78656A52414C7052316B7441652B3155666E3848366365497937485A47357667366F39356F38446B6E4D71594B4B72474D594E41456E386842764F7943746C414C6E523632675630624F4545324C5739304C62362B71614C626B7635334C54676976494732544E6B7A377331343539636E4B5335757679586848787765737730614E6A56504C52476F5958686C746E7A6B51714A2F55755769466E50734476533833426D43504C4F58647241446F476A4635534C70332F6F34592F3764665737666E344661584E542F414A42465569446379774D5767484B626F44512F6855564133334E4C7946304C3156384F7337714F634A4C45746A797A764B367272344679752F4B6A2B72643950397A347950694E474C37326F354651596B7076484B784E4D354B6B4C5244786579466A454D7764356F6569306C4B362F77444634526250617A6F466F526D7450784E474E4D3134753632434F5333726F5A4D69743467467745372F414755486B39474B614161522F4B377637485444584571767279743545684A794E6B362B42664A5832766C3162455745595532536A395969306A7046454B696F6B33666E462F57366536487A4B4F6A6139577A4C78395268314936305657476B4858437975336D6C49353753764A326D7661317936354D796F43767033344E624E54686973464332545536366C4B2B4C4276436254666F6764683163736A48736B6551483442374D736D6375306551445641575556456F4C4B2B64452F5330417A736147426871776D56463059546D4C5A53543949726C6B7538375A38737271724F46443278307A2B6D76797244796E7879334732746D6C7966485A6F3861386741762F41452B4F6569575851674446546B317957446E544E557979722F67713661454D6C57666C48466173664B6A52344D2B53315271533338675052696154446A73417A5675696A4654312B76582F41476A76564E496C47574E64424736716246434B65316F706F4F47444E2F76726B787467693232646E62755573654844446D683173424C7136623468457A6F756A396B65375575452B61352F6A366161373631582B366B4747615556536D6A54535168796E477053384B32707233354E6C7656544A43723635556E6C6C354E324B4B72385333496134516773316F715765326B7A745357584F434C3539756961556C4D51686F6C4E585A714A346D666D4F7941434335375047412B674A574A4A716969426A6B30323550597935773249526E33514579565546565A2F693842666355712F79736A52645172696B723554395436456165656D39717972385335616D6474506E505238577A4E614E5A323437516D4C67635044367A563079776E50585938506A354D643339724E794A695A503231614A48785A3248797269612B4371746676564F65716B61594C71666B392B5974374873364361376B68306145764A4663644956515A5237584C6836304E70394B73342F707831725657504B46512F77415951485A6B44327A745751714C753055573134354B67786D556D6D4F57776F492F704576312B587A3166743766784E74324F382B5765656657553452577678744E4B6E467A574C6A6A726C79664551716C5A3549343832617955484768712F59584531726A7754684E4D767937703439304E504868394535486B554762596B376663386457786E6648766F6C46725958745266536C4A364A7A734249696C4B796539612F642F4D48572F716B357976793237634E545A4A32787A63317A4F6E6164426D41477231396D5A586F6F4657777469464E646F316F706C6D677A7042566F5143346D4D6C66454C2F384141766C547A7862666A32336B493852386E77306E435656795A576A644A78454631525851622F3271764B59357A34726B6B726E544C463761382F494E68625278653263477A42504B36616F4A5452772B74455A505A52326250554548546A72634B52536B542B36436A49396C4A5A4C45717A44507A6574396635315A4A6436506E6E4975325542572F715369416D786B74695443715A775A77376368684278685038304379434C6B32506943634C78584A4D43454C43517A506B2B545635504678657932486458506E6C6250765042774F6A4E6A354A596F3064656242656D724C2F617232446A52524F573433516D6449356E2B5059786C78386A762B486A497057733832716564584A7368766F654B32586F2B416D5657444A74513968336A436371705539326F784D30367469794830566F54724B324174344D716F794372447A2B565A69536F467435536142303264707A2F414F312B316C455371536D466A652B42526636775657387671453047463879546C6A344855546974347471586A745047364D7A72374F3437456D2F47636E792B335A417359484F4C504E4A494A492B6A77565641786B716D7962533853617347445633794C4D345A67675A477A53524F6741515A736E5859382F782B556A365553644B7A43504C56316566676931306861684A634C446843756A6F42465A524652612B694E6476787242367638694E4367784B6F7A476A306564304A6377762B7544327A38723851354B7370537838507A4D3174593030734E692F6678327470716C634F4B71326250783136624D366D695A57304A6A434C4758742B6E54346B4A50506B4D2F73466A707A4B4A73765141427A506D645A394D33734D7161344F545245387A3539653155632F5768534633374B4A6D52497247776775656369703230444E3646644D35797A6F586C4342674B394B35424773694F525254474E4F5657793551304F7168457574786376587958752F4D2F4466365638775938792F7737682F6E4E38366A4935313438334D35754E717A6D6C78586A4B633571474F6548383044796A6C6E6870536D69797A4F7A5575685279624F5979307641636C7634672B527236466F754E6248384772437338394F6D656E54503272765954676F566B686E564472586554652F774471484D382B30704B656C4D74587271714C6E584C306165746148584C746F365A42526569736274613158364A7A47656D4C5551476A77475672703647726945482F4148456266696E78443778666A66784C692B4430364A5A637A3868783676546B613430304E5938667532592B582B357078434B7A764C6A4956354C42697130644C3861737655715356746F32395633636C61346C37444B626F566B7856663261667578794343674C45306E6B69533750525A657A746E592B49386841554C58675341654C61465A4A6633724C484C713065524E504B437157544E6C63796B694553567A6D59324F6B314A5A6E616674415757794E565756524D5655512F5038417979504853562B5A3548565462632B5754445A386B6559306172396F4A5350637255714751524231556B326453712B65616753384B6B385639317130575557797A4B71616B4E534D355342495854546F4A706C4B61696E71365949784C306B505A323530566E716B4E4577373538643151574C6857333242346F46516C30786179324C5969303073707762546652496D35475459483070536F6E475949536C6A46637A725374504B38676E47766F35444664326A5237767850483672526C72616C48656558527947694C6A79706E65424B65726253644A31436264437353743265614461784A64416972703632326134445138422F77447A4563674D47704B662B6B6B72655567683638572F6B4F587A5849614C4E524A7663364353564C7A2F414262537658613634415A675432456F2F58504A586A7544625630712B31566A696752526C5655772F534E667A3937565A6C5079567458796A487877773857493239355A44666A4B2B634D72443277686E35625679464E76492B74337170744469654B45572F456F3052773461754F664C7831744C485139314B2B4B4F2B73555636426748595A6F516E47434253544F644E58494F5639684E56395A4C566E39453944764239524E696E7368666C59463263712F3139626D787731485261714F3348755865317663764778444D7235436241434554763841534E334B4278612B56444577316E3458384C34392F6A6D584C796646346238776F44366447365768394D7155486B6957654849635A5A4B4D76526B6D59386252683134534C666B72484B66496552665A62526E3562566B784E306B7338724A49614A2F6B67796B7547324A523253504B77756842364148386C5A442B715A3238687464626B7359767A3541455531566E504D7373444853534B45357A73614E426D632B6D34537A4659464573612B4D61714D31433062363978682F4B682B327A637238447937587A6354766A386C304C6C44307050627A504F6E68636B44704E7A666A6546356A6D65617248797A792B785776336A4E6C7653622B69453630307A7338567A5849343536644F62586864362B44646B63653349394D565678656D546A3859744A4F78576B786C5479724F66576A706643682F6939776A6349533362465178356C736E504D78644B6334784A3839324F4C374D736C4D654B4842385A2F42577347433875356F6F4D324378657659663639464A6D4866567A2F3841714D4A7358444E69327A34444856786F31436E54636B744F545851632B6531736B2B58346E5678774F31446E6A464B614D4E746766557648626A6B4D4950677631625375684730327A4B6D64614A52426C36514D78465574624C716E71314B6C7A526834686C6E655157672F78646C545065702B6241706173356F6D5A6A37622B66324341574B584465564E6670586D7267674D6D33697436566771314E476B745A4D3155535264534D4C477877616A2F6C75694735616C645777592F6A652B757166497A305A44772F497073716D6B687870345035426C307656447958454862647371324F62434B484865715069644E564D6A6B614879786F3871444B6D54375461756E4E584F6F386E6D396235714E35443136335755744A5A712B74556F79326834462F593475794F4444772F3134474931656678523144417A52564B4B316F656D30566C474F3032675355327250394B30613230596C346965614E4A3052566864466E37375030664C56716468416C646E784457342F6E754F75744A6377364D557A353366504B47466978393464495231614A6966397777356473566E396E79574E744D3875725137364572542B333535654F5942725A583973326F775779766F6171544B487361502B556A524A6B466E7A473356492B2F504A6E656173682F796338777A4F6D7874756A544C437964506B3962616B3034773152796737684E4E50467774676C413574797759516A4A69357732685A686C5646686D744B577163364B6D554D70496C78626A746D66587A5753394461454F5479353377336C64367643734A6F5961616C6A5739625A2B51686F6E543776372F41454E54426134616D2F6A453576584A4133797A644153505739537A73473830594977575A5A574952612F67457A6F303571336E35646C704A362F2B502B675942695171666C3356465747464B6D65646C61635046657343495A7954335A364D4A685245513172586A466D56316150617A6865794D6173624F477A4476717A542B75325A754E2B4B7735445469706E34334E7A6478767A5A39584958694D6A5631666338524E4A7074464F467669454D643948323333554A57777834324F66566B674549634E6F6C6F35634B6756413675325A776B6C2F79746C67387145644967744773365441556F6171454E412F3673646F736F6D3839594374474F6A6F54482F644456734C6D2F47743635364143316C717A584D32697361765367785967306C704F4669776168306B31324D313930334443504F7550487564766B2F48383938632B4F38447864642F4663695A386C79476D4A357250544C7962362B526E72354B32576C383975503170464F4F7A4C6B313673734F4C6E6C31636377356A50486A6F783065492B4F617358493739326E50506B592B557336565742706F7A686C7031356E3246697250535331784F505031717945672B5270563664683563795A434938692F50536530304F4C366C734677594B52726E6D6B4B4B2B6A4E597A7466786177764D5769386F704F5839442F303149794273364E5446634C36392F6F357A7235393249766C577257484E5151364A556A6D2B3132706C31307A2F41472F545A786C7A484A614F4E623571577A66333572354579507356375A4E3870797A6E6F6F2B61733238446D4E5A4D56647571436A786F772F4A6F6C46636F51504A41594E35674D72665651636271343563314270576A6C6F7473745A49346961767448564C455266635347385255617671666B70716C48574154515056423369317164557131723961563967676F7342707676796250506C506A6E4D63522F5A61386E614E496D334735743142706B4D6649492B585A416C6F732B30614E484735632F6F5335316263305464426D33585231374D686C5A486E547070653167474C504E327173354D716C757976677564515370414A3662386B6B6E553379503369366F786E6A39746F346F4E5550734D6E774731714E394C4B6D55537934704A717A70767A7356582B74625731526F616A35644B5938516C46454D4B2B466D584A44672F7A2B2F71722F41456C6A7347586B6C34322F4F2F46322B4D3765513357346D6E70307A7078307475444C386D6C697A312F754539754D3179636672342F4C52323543756A4B38354E57573632563434623544397356514579354437694F664D3162734A306E3746745069727458774B7258524F565A394F694B69556E50524975715676753947576268564A58475676476179345555636775756B637050647858776E3454756C53467374574D6F5531697974434A7470734B73724546726D484171363338362F366E2F434D584F5A4E504237695A5662564563667A3634473333794A50544A76474F65577A4B3971636A6957674D6136327A614D39636D333137715A494B665166772F354A664657657042376C724D7271342B31714B586239764F61575A4F6B7044516A52374D314B556E54505154496F71563757354C634A4845514C514E434466566432344667474462455373574674383667676D612B35634C7A6C6361363547556B6E31522B4F7A6764637170333168562B59372F30372B623854794666737344617178386F76795844386F6B6A5955386E54596A652F4C73775939644F744353725045636870396D6D564168493170506B664261594C536D365353636A7A7A36354B72696E38736C49654C7A6571742B4761516F7273503064683139534E7556315474366E6A6F717A36465368384B2B364B385A554D57424A41304B7A6754575161716651314765727646425A326E316E4A696E52416F717A35566F747852764E652F70442F52333572752B58384A38702B567061655067655254646A7958356D6D31655335434C4C5357666A332B363178655A354231767A4F69433131726A6C737979342F57394D6D2F696C72355838362B505A2B41356269754C306F2B2F6D4D46754F314E6E7848476E4863586F6B38646C394A57475859394B77616B63614B426E573170616A756E534968546D6E7432314732387A7162715753377266584A464766415A7A7A58505148513062496846367077506E49445246564A67475452664E4E5259496842556D4D7458795A4C516851676A2B6B50495A70362F6948796D4F505A7732795845436374584F6344673544423856575935474E44785878747551385A587A55305A6F53466F7072325A6C342B5847364E4C3774484A3666727A31385A372F38363850734539635272656C35354E64703232656463373051367847746651717A64774134696C664C4B3261617957694C6D46724B724C64467532713056714D53446F68544649634B7937565A5377317959534D433346477437314C77684D4377704C664A46356A5941706338587141443744714C6F6530666A572F5765443448694E31553070663478786B74484959395761567238724C4F717931346255617461386A5658586478453943355A38764F6564534938714D6E49624D7635573870387679682B30744C476552354330667549456F687256707667704B4B7956524E6E65646D64585567614D3157413930326B384C56356E76306C6A684B785A5A4C317943385A7653693430415268556C4C37556E43323265366E726148614166514A6A4B416856693270716C5A324673594F566D75554C7846424B353831344463764935666B57577366563474672F7665504256393353536F4D423174435561796D71625074573335687234367363352F75334561592B304D6434546C76474E6548744E4E55374533624266624B4B4B6A4B4B614A5A732B69582B5A71756B3666615562505A304E6134394F5379706F57525935484B58316A7A397779764E413169397349434C796975757975794E313950456238705335556D7071656D48315172704A427076644F36574D4F485A6F75322B734D666E42794B2F485262667A5076783764453633306E684F577039726F3166593273647648366E3163646C57314C47616F334763707934307042716E6867565A524A615437484F666A4E7031777A6F7951504B516A6136545567306873453846376F7736556F39655067712B4255623639673272507350782B3863412B522F5378376C52576A6F475633454F706D393565537771442F554F74427273433150355662597A6F58384756354D4D49596D726C74414B7A345A585265766A3339514F536A6C314C544672546B6D6566322B446B2B49356650363130614A7A736D7252486A756479624B7854506176336A61344A7374746B776E6D4D6D5A462F5A6B397272632F612F6245487965652F506F4238453843457A53484761344D5637464A46724C4D487058627276365148354F2B4A3442463454365977525A4B68554A615A6B433170544F4438466F456464723839776D38533754597A4E4F7930784937413050384159444F4A456C765931444C6F486C43686434702F315270397A38596E79566A75747554646E493036744F682F6362434F6F5A56794C4C426777317A2B466D387375496B4C53382F754B54646457733938563032626E355A30655359546759464A79574A43537A75467052707662525A78517A37476E525643675572305652565050774D39507A587033696C3874506F33756231506D686363766F4E47436B58466D73304E306D31794D7461386E6E537A45647A5068466F624D554854457576734B44477443746F4E6F70576F5248776A354A796E4938622F414F57755731635470786359377934334E7332395A345959694B593966495A4B612F4338556D39383456654F61475663324B2F4A376351324239633379444A6A7A365635624E437376765A4931586A4955716D73786A357047614B55486B3351376F35627962786E6C704D682F7137635168546A7A677A704E52636D774D4C76364E714856686D71724161313246707834312F4F567A504661513371363451566A42637749455773697672694C72553154707535503544626A32796A486E6B6A47686A53715A613856424D2B615854577A5A365876727030374977536E3276716D4C30704848474755636F75537870523676727256715756486C464B726F64717379684674706D6934595470496D692B7162734B7A696B66765631314F4174314461756C6E646B736770684B674E656D6E6652384E7A4D665055644F587A535372446A4B31554C61475877613479774A6365582F41485A4C6848576B724874554142684F4C344C4C6334766C76503634385A4F466263686B706C6E6268366251592B44306C5330547A664A5361636E6A4F334A364D625477646A4A786E436937783157646D32716663354D6943716C466C5131593157452B785645396131664A44794C534A6B68717261555547746E6B716F6F6431733833674D6731394239596F4D656D4961416A65355549596D6F79646478335354576D6F6547336C7752456A3141473363416C64586642714F7244616E387270304C476B724C6278487959307838536B59773436766B3974387673384F632B646B4F703575496A624F727135767555463371564E74344E4A68784B48546C5A58713465756B46595A3172344E556A6F455674516E775666344764565A332F42575A413747577570393039372F4B723071724B6873574F567950794D705834354C2F6853727857666A2F5942514576777877694F4D3945317272714D555A68795577464B54565674354B336731585763376E48526C6F354138626A61766B59377A6F7468744376492B6B70562B4B4176654E4F506E7432686C334E674D6F5A2B4F77785632324852317055335177783554743353533031376E4A39452F546D706F643161735A4C54584A6C7A347771794678533939416367314C73596F3938562B4E5A4762715531584F7230397A573645322B74765A736E704B546B67784C4A36416168336677703541616E2B616E4768396134326F366B727138326376724D2B4D6E4A38384F4D346D36385A7875586C644D374F4579576264796C4E653564434737636A79475053363543385A6164427A6E627233586E3474707A5A74456E784F456972624E4B74714C7967562F596D6373734A536272785152625050533141543278454D4B414564544237365A446E7A3363344C5173616E4A4F4F326D50716846637773716E57426F37574D595044373273356157724C577A65614E66534943737A445A4D716E6F5372536A63567153474B3852616650772F4C7079324C5074775635506A3347624E794C715959705A63757A5444496551686B62476C346C4F5035453763416D65526F63636F79313877596A62474D4A4E48485A3576347961564B5330746C5678545346632B6D4E784F79556F613561704F325A34374A645A394B33644A68705461726B7262436E75553454447A303166546E68626861566C576A47736172582B5959564D6179384C737558556E77625A52304D775864686F47743661456151365743424865382B376D636C6535534759764F75343168624B314E6D7A374F50704F536B476F7263747847634D5777366C66376B316C457A674B787A445358726F5A71564F4E313353396B4354656C3258484E724F716C6E663841317A3653696F724C4A3654524756534744646B6841656D4A3566734B4D306C7638754D5236625258455A66454D6349376F4D63446C352F7A5635754F4236574244534278457932766E527545744A54614173512B583337733248534F705A4C4870476A57646D586B5A627561354F476966694957726164485437665A7947534E45795355412B32747561727A556F6368346C4A537A666662485331544E334D773077654758325345314C6D536F6E6663314C7972726D35702B735A4B416C494D793044576F36715968516F41395235316832674870347046345756302F6D30334C716C7A56595170455042514E4B58666E5446572B46422B34426F675777436E4935664F774A53636D477471442F726A6D326B3850765132323076773266664B6568655945394152436A776A76305A674F575430477974374D504A3863334C764C33656B55324C6E4550384166312F46424B5530592F4D66626979466D3746696F706E584F5743716F64644F6653325A6E4B6B6F36796F72396D6C51435139686B666B33576532735235626856736B79326E5656314B7979376A6864486E756F49746634363231665A5763492F6B36574E5A776D4A4B4B6D6E3937724C64414C5955543462446D7A63697533694E313438572B486C495A593634504F7556755278702F627A4F4D3655382B71546A67746C55744F6F317974524B50437872487639743872786F706251446B763751574A764F4C69577033596B4666494B7852453655426771714F75674D5A6F752F4A3658687034332B48616F6E504D34424C4B494D61777848675368784556584D69774D69435579736D4E374D4F367A766233627765756D563872562F627A2F50384141592F6B5042624F4435656D545A44566654782B7964352F633866654A66544454576D657A7361515944616C585878444A736D55634B6D5635684B31706935444C624D7A4C4F457864576E557959327A32724E66423250676A716F6B333767685669314B4B5538324E70632F2B534756517349475444675178716E6470466C34725262506A43413970444F6A4F444C684E4D6E30557168622B7A56717452546E3154637761366D376A4B566E5A4D6138776E2F517A4C4453756E6A4E367375373752742B4E7A73704C4A57474B474F6D36657975546C50505073544C4B333243636349707070625777303774477262727670386C304D794B77456B4263793772367737476A4F554B7A654D2F464333556E69386B5359544F7172434D3042412F332B6D3361476435306B61774E7375715055645A4B6F5A6D2B3634593073796F6A4D6A6D54596E466863457471586E584E5867514B2B78516451725A4E3653685669566B3450346678664762754F354B4F566A6E7961746374464832386A794E434E4338664F4B3643334638424C52707672347457555074746535394D4734766A6E557479564452737657645259317135505571516A6C38555175796D51456E3171466D74726C51424D463673344C75504A4B762B736B6B48334A4F5A3056482F5358306D577652522B6630794C4A56752B52574833734A314C676E71513230512B75356C57494333586B534E4E46746D577542744231626874636134747364632F5270736F66447339556336367674355458592F4855796368716839796B326D372F484C6368794849337247635865414A3548366F53664F6A4B7765356B6E59395643577372563764545646535646422F59715569696A3976493941644E31513859764D30746671345A316958546371796D6F624F6148764F353871414B2B394B4C706C4377537A366C77305A32452F7742705855794C6F597137375A6930436D3764557477332B3159386D336C4D47665879334763376E666B65533454694A47654F504E35644F576C4C76774C366B68566156774D5633664862436A445254325A5636687757376153304832796A37555238376B46362B4D363056782B55463041594F367341557569735549414E4659396657744F5A395577326372575168706D783461784F735664737A77526D6F4A5469476B42723657674C4F6D5A704D595847546F76686E4E72534D31707544496167436D5856396F3033686235422F54586B4F5A35376B4D7138646B3454567A744E4365664E6364546A6C306A496D756F79387277334A386877736557344B6436577A385A386B2B4C363852345848582B337072343330374E3347616E6D35386362677A55444A746869486B5A54762B686C344C4E546D31353433746B35487753546238664977316F5844625677326450445932485074324E786156336F343762344641413462626831593645716D345973536F65534F5650394243614B387059536D642F414B44574F674B346B685345675A41654D732F542B6848493565647963586F34546D3476707A624244692F6A4B333570466648716557693348612B6458504C54786D70566E63616E3031673349563076424B4973474A71507A6A37376A6E305A4F513432565936516F767A45526C4832394A6A77525934744136304376366442336D5230664A7833394C48532B304C4741466A432F5459387857774B4649755954634E4E434C774F4673476463564F477A6F7951353630736C4B7351516E51746667586C2F6F302F6F772B4F345337622F41496C2F51766B4D324F6E3233786A354E70304C716E4343374953342F64506A536D5A72614E6E50307738746C6E706747354C4F4F4E346E6763314C3865384C5735504E57546367795679667A443262507439576A43505A4176534B4D39637A6167656F55455A553931706D59537766534C4A48596B4173725457735871356D745939662B76346251576D456864646158503336523073536C4D4E526F7962332B51577138384C66644C4D6B5A44434B36364354377074536243536C6C784B2B494A4A686853416A54766E2F41415042634A2F536254782B624C6866627873476C434A305975503476682B4E797967703272782B545873626B7558334258342B4D4A486C50732F5872752B6A6A4A6954336D2F702F656D7A35707839473161554265746D6A4A744F3274644E6B5A5746395678415356564331766F664E6E536A555353506F6F4738524C644B6C4E2B6E3369756570475276564C6F695139484731676875686F624B6C42556C7649454E67775154704B61364C2B456746447868786C32484970352F4B43744C634E7478637838442B47636B654831374D7263586D7857354355364A506A3966484D5A62386472797A315A636D653779354F54506A3356367A32624B6E4971326E666E702F4A4F4C70506E766B475A3958322B6A48794F6E6B4D344C466E6F6D3331744A6E552B55436D6D556F532F5671656D4563384757496D696C4261487938523864586F3833633638323943466D3169696370687A673865356455314653634561685744637330796D464E313477466869676857645659646355774F6D6F475631453662774F766C6356363855646375593471714E5638334A4A6C35476E494E5A616A4257573643506A5A36556D7A32305732342B51323645433573576A543449697253307979437332783667776D7854395538764A52565A2B3158664A5253662F4145615A7159574C41336E4D45614A2B432F592F6B554D7353513276684C7065582B317462774E5273734A70305231555966582F415057304B6832314E542F3575684D67696A2B515752614C624731644F45727769717A4E644843586759624E6E794468764273343079347A6A4F56303030656C306158703544646B7A5A644B526F73774A66334A355A756B564D346D4864624C4A364E43744B32486B455A624E4A6E42616B5333354966486E67424175656977554B6E6B5148563238574270365A31476977326430576C5758497944397235626E756A4867562F544942646568357A4D4D627674753136335457676A44734B37324C4A33576A677968634554585857475755737253766B6E79663544686E6A30386674313234314E306378586B586E786E4C5A785A6C5071494E4A35644D5347694D37597879506761314636395A6D636C2B4B346646513238796B6244485A354A504F3973646E36597A4B4F4A5366505651504B7958435163416A4D7A3944764F542F79556568376363424E3533426A394C4D764553703431565270494D746146726A3369396363592F466F3753584D596B4D41696F455373524F435641436862534E5443596355502B7074682F65636D4E5531536D33485972467A71612B625262526F307963794A715A76616177704B377A6D7A693861702B695438566150694834346132315A794E4F7551526D43496A42597778306D766C2F74365870523649766637647230656830552F77442B4B43303033652B3059615861435652695A4A7053346D47544358566679584E34673062435131627177596D6339504C6F31336149316335565A4169304179305764664839506152687A65725138344D384D745054647742624D312F474C506D734E6556386E7652516C396969766C4E6655363053615346663543745734664436334D3550715A6E41496F704D34496E6249456F7A48785571416F3750343638543079374D6D714B386D416272647071306E6E75537A464434374D686A45356B63516F7148474B77566861417748593064435832783637302B6F31484B7A434F414A413456584E62574A494F6C7868397531586B59614E6B2F5862576D6C672F45386443544E594E703161664636545353506563705477534339746C79366E7A7753436D7654734333736B4B493635684E694E756D72667176716D356F784C555A56653274715738694B577172737A6C5465522B7034725562515455433967474D48314B395532376C7630495A7A6A775333375030503067312F7741482F566D703467427936594D5A66386C65614B3144422B6638674B76727650725839577063752F486A42533875587936632F70706E6B7456737572566E77614F4A7A6664314754693462742B51386A626A4B32304E68786D3345537A58546B4E756656794833685935764A644248323170324C5561686F37556162307A7049775764644F664D743646397A70415865636242336E4F554675382F77416C35346E542B537645766E61456364573256555A6462647775486E7930386E2F44445A704F3274565A2F482F387147427A307768483151342B483152646F4F616B3672764D5A2F486A662F6837342F354A702B523470382F6652514C446D394F386F726139477669644737626C725559732B6A526A3172486B2F746A794758504B2F4938584A4E4C66614E6F664B4F6163506D2B6E687056545669782F6153446363786D77396C6375672B6C58307455356F7A6E336E6F31596B39757358536C30516B65564A667863794764777A484C4B6E4D4F514B394539437271304A615253456F4847433044774C493574676B71643364704A44475031534934752F53694D475177575A4B54454B36466E422B696572742F474F4F493553416F2B476C513070706C6B3266754B65336C6457613173374C4D726642672F742B72526D71747055327843616B6D4F4F434A474F793775527A3661794635524A4B51304837706D6674356F7269766E536F6E6330706D617864712B454C7157387A3575695456416159754872412B32345A3255314E33793768717153322B33634E6354566C6B4D4C5432656C624C73707A4D36515341534A59714A62566B723252546C545957736667415834366558315A49705775506A72386A782F473564457377617263566B743458615454706E6C666C334C55316264763378724846526135625432316E4B634D62643264314875684C62707533627536363778745575656D5A3268467973305256536637765A684E436670714C495A7A302F4B4439444579687A75697252597130642F4335554C764D716B7832555865665A79304F6C51534F76344A4C4E3647384B797531686F46724A64696D466C62663562706956495A642F787A6C7450474C4C666B342F48545653743031575A6C4B617879476E64787A55556E374B314F5A3238626F5866796C4450506C6562484E4C536570792B546B5A51334769486B44514C6F5552616257672B66507875544C734B73755A6D7954342B4277746D386756322B4C555A7741793479375A436F4A65514F46544E57554269505232596C38784633326B326C31653255734D3879434A4B2B39515170305441716F6B6C64426756525569615449495731307278695878646C392B722B33517A6144645750464A716C4337517133476A5072524E4C75696C45354753496969714350397233514D42376E313163493261556F35396C537664524C59364F33675A6175373536695866586B303057624C304366502F4A2F42486663516F6B78655A6A626F54792B5975397036326272687270322F653047416177334F30546A57774A4E43503671634D387671474336564B756B474A6979706E5751762F59654255477642644835446976504D74494834746A34362F7366702B524F726766696E76553947553944767A50486D32657A65323045617946765337665669546F5A5330674E556158326D714D68424D564F6A63554858514B75736D6A48722B486B7967735559437A4343704B35307A5A6536527236303269695A6E4E51653848374E4F31547073506354684866444B56356C433046517742456574486E324645526231513434786835456141696B616C73326D63746565742B503279343348746872723578686830636C7A4D64584F304E47366C4C58666A6D726D554D464953644C6B654159676771566D68562F586559314F6C45386D38394762486A305179496E7250736566754B5842514E352B714464394C33395A6A666D4346596C73324B50443464596F7631666D6D54665447716E3369784C51736175646D766B53786A43396465564A466A424135337A4B37397134477177437635463970467A706F30616E34546C337A303076726C7975704D4F683053576D7632633857724E707A4A454D4551737272494B4738424556505A3736736362365832597A566B53445A35436E524B7A5261684B56527A516768306F57556875757569434F782B426254713264325979495A33537062466868564B375A4368453345703657773667554C6A475374654C46686656792B722B7251754464416C786F2B714E4D4D5771497130787758532F476F324736592F666C7A70576C4570624F5671616D626C643846335547514A6D2B34544C48416135305357327531632F345A574E452B3464773647633964436A65495A5648697443456D4133666E35586D58494D7A4C33525064576B486B52454F784E584A4F7670616862786774486B4254537A624272474D2B5458445646324E327734564C4F32307136766C31696274644E426B61763168472B6775675935782F4F424A556250717963696C614D4B35686F484A38703972496B57534C634E6E6532796A55492F4967646171514851654C65492F524A567173783549746C397155706C6153735859674F5931615069683643715150576576494E3332507071776C7A4B586B4836497032365050684141474B66526D6E4D71724237685265466E4A48396435675570516847624A7451776D474856304F795973425A4C59454165533332747130567A593972596F4B3846764F753948566B574E6149557A537A6234482F41434A4B3971634351706D5A6A57316D3235637350706730347874614D6853706159726C796D666944346D626A3236507943766E3132684B755077774834417133576B6A706E6371442B50382B4472574F646744724130374131517758586942765935396D464B616C786E43566C363035796C65504D36334D584E6C4239794B6F696C657A49726356727948453253326662444C704E47307761357572365434744E4E73574E4C4C526E644C5A655136634A4C79384E756C72445070496145575946413044566655676154474B4E4D6A7837456D5554434D464874704E416F48545544414B705A466333694F67707167417557484B36754C58366B67755A695A6F706C706C362F2F414457664F35657A7141586B6C796A53526F366A794D324D494D32624E6D675939356842305A634E73732B50355849334D50346E565051737343636C69324C6E3072646347432B7175656D7A546C4C484E6C346D5454313657795A37337473333773384259307257706C6C7559544C4266516567514749483631444E496F3153434544462B2B6966345966526C6C4A784A75564576786F69764E47517473474F704A5A474B6E4135634C6F57464C4E59736A61744E68385A496C384E51535341485A793455316B717644737547573952347A4B755748493561624A63654D366F2B584C676A704848756C63355A4E504657564F5166465363733368673476506238514557305A486B78705571745573385156396E7662717257704B642B67657657383257614D336E527661795648666E2B766E616A4D65553776516A524A356C3732796C6153425659476A306F4E4A7067375953692B3868624134644952555359354F6A534D736A32786570595374456A506E5149584D4445546C6358413533305835666A5535765750597730344977344452544B6965306B6E6671726D394F554170642B5730615074616A30306371726F4C4F65727A737558486547474C4258714B445A707A3271507965337A524E697762793739665858386C522F483070774E502B517567304F693773306532774A654741744A46542B745A756C6D334D7663584B5A6C6A55695A48523276515A2F41507933746E38557572677767567247796A70744A4250336A7878742F4C2B306362584A6E597372713950686D704236333671756E4C774F50565855513673396135437A6B6B364E44546B4C49705338336A4D7254526D3152397173526E504F786E4F724546624C546C4D38344934592B506A6F723633385373454E6D6C322F664637454C623258474F576D4A6370476E64643957396C70466F616E566A6B6E4E676B716C366C7543343347767A54715A5244776368687055326C6B4D76756A586B7A7A7844676B6D566631627A6370722F7031386930343234724C78763972764F6A5937353068706C6D554A767A744B5570684E57656450597674797A53536D4E57334A357A6A52772F70304D57543566775833743932796C6552476A4F6F386B674C392B45614B744F685A6C654C7A70524A2B5A425A45634A313333656A2B3065656F766279383277746770594A426B43566732594A35447773586644596252583351477043563952454244446D4243375377704A3648637A7458566D314E6F437445542B6B7678586B2B562F70356B66466E35552F63727135564E6D48616E32415469395169324C6C754D316435774D31457631707836632B69324F7A4F4A5A394367686D2B63374A512B576369584F66787A504F547931796D7459746F684C517A59644F634B3633704B303372464B56614C4D434B556A64455230512F306C355455454E6F6C626856455A597957724861323972534356476D386672436C685452623643677442462B5165567132346B49454B662B4A364A476E76696F6E70476566495A715934583439526F433672372F375479384265324F554B3170717A38584F31307936794B7433564F4D6C4C566F734D6D70655A314F694F6E54726C3168694E314B5A5434444F2B7146487A5430503545792B34374E48386770416931515A644D524C4E324A562F6F57593437506F4F4F343944494872764773475346337342377630374B337042616D74506641476B7A3435533646534D707435794639646739764C724B494549636A44496D6642753544466A68574B506C35506D7466435A4E7632396F70524D39642B586D72507630543743455562546C487150746F686842507142754F64364F384A627161464C2B2F4C786E33564A754A73464C434E4D7A714A7354356D696B745073544C41304A4E4E2F7A33496F732F4854307174524D6275685574736730484457726E4E7851354344573564794F45564F516E31456A435958494F4F66636E525A324E556F6A38746C43332F4B3138316B7A38466B746E3573624658536954536E4938467174576E5455526B666A70306E794B5A4B6F6B4A53796239545A566F6E74795A2B6953642B4F654B38703476674B46346143664844575473494937504C2F4937576C35795667744C7A536568797151656864564F4E48356C2B6972505358475530796F4959617737793555623952645A797365706F78474C635344736F6F734C3450494A6B7776717272766C79325167396335776E4B347175724E2F6C664B6E6E393348627976524846634C6C5A336B6B337474784E7147344B383051614658566F72414F43784A6B57373664656E4C686F78346E507377417A5A4B36756673776D65314752784A4D64434357616130684F6569666D6677722B41374D585030642F6842364A337A6C7236553043736F43326D674674594979624578726F71795A4A6F56685443715336714A51664F47526A304D386B69756F616E687652624B61626A422B7458394C4935582B5837446F6E71394D754966774D644663614E6250544E55696A536361644D6A4F395762375565302B6C357944556D564B72386B2B3462674D3834574533586C4B4B344C4C50796D305562786D3771792B53452F783473313648307938617A636B7A2F4972614E46336D5A4E2F7133704B485A6D3672624964642F4866494A57353176784A6459557034424D4B644C76625A32357A4F7741544D736D42795232554259384C6F5539414B6342374A7A3975416E6766567A433573356B4A337772574A454532696F706E6E5468634173756A655561656D4D4C336E5431746B30637A714873584971377730647633526E6A6C5246744B304C4F75727A304349364E6174625133634976305A7458504C75544A565A72375A735477666A6C3668706B77724A68644C6A6E63495544703572632B694746756D334152524179772F4E4F5376477658553878385836304562447132464332625A6774436667716D3075527236347A666835506A767365522B357479776C7132756D575A4C307641704B2B7575644E454D7A61693152683856716976656D6F484D6176706A5035796E48756D74577A675A384657534D4C6153784D5A306D396B58477759564B306D746D5852543232704362316D7738505A395746562B69376A31325379486F4C4A6773466536536857526B2F3371614A696F6B4E527672494D2B505A473961786138355655344D6676724475757148465936725336334B6F576F4C6F356C346B6366673061636E4638526B53767353394531534C70347959556C58516935454D49545776726E78686E6D645762314D4D564A365842626461476F4B48526F6545475956535A6E63556D4371314C7378663255494154324F336E4C78486F6946436E5148796A454A5749766558716954383957446D394F6A5A7969636D5968746B7A643057334C724F684967786831617244724B6F4B2B65774E392F4B557442624F7869514F4F732F4A433864374C6E616872586B4F597A735570374A6E4C726269644D306E42417354585639716A6C34784D4C4A527A49317A6B71724E786A5439546C48445357454237676F6D476F677341783876797171784A4A4A483741646B4653506F6366344F64567A4B754656304145314E366D366F4972704234354C445A4C7455617A2B4C3572362F3858763047685758555476487167577750494A2B456178695A79546B4F61544A746A6F584F5A564D4D6E4B7A524744726554496D486B417245454773646C4B54444C324C53303532516456566E6F354D6C485775646D38356D43356978386C55654D6C4345483844776F67425872734D543270385431395665714930506E322F7859326D4E6E69782F53553157626457314B6279524D76366F41307264564D622F764258726E39377836434A4264585256527768502F535470722B31323131576E4E624C794F584A7932574232365961705452336F633761347A7A7567784E5A57394D6C315974754D5A4E4E4F3062646C6E5738586B6C5A55675250424E65657A424641536A4A2B56506F5676554B494F2F4E686A304A6F647072322F713254557361556851543537516F693172744661425136646932317674676B626F787131356E3831693761327167444930734B726C72466E6F39732F77416578626C79714A2F324852494776516449766F5876354D4C5134614D7377767577783254624C6C3335554F7264695A495A4D4F62714453726D7639726E3476467832764E7042624A7269544B615275363436786F4E3941627A6E6637656C6231513048322B6D56584E692F61744A76334E566F71535052526C59555944746E666E4E495855594E72687839486C724F466746704D7A424767507245615531766C74614E5A72737947516E6E6B59323670384977627433663332512B70505A4D414664696D41786F71364C3731787671346254524E6130666B447579507376796367326864472F4A79644D64303558476E6473796F79594F4C72687869576E77314D756138476F71766150766E4235656B5247656F6D384861612B6E4E6272784345683038764A6D49766466496C683446337075303041744432704E2F72344F6F794F584B315467346C6D714F6643307331416F64536B4E4D73596C444135794B6C324E5772363462464A545973637A6C594E59457437324B756A6B6A486B6F2B57723769382B543859314D6D795234335A486A744D2B574D4A362B2F3764575466323950423838327068455479476C654D724A38734A48517A6F437A4A4E6372433457696430536C30384A442F41434272776D5A306D46533176592F746E464A735A5573316473396B647150644E74366D32643648306A51517049513541414F765368785A4D4145796E4D6E61517A4A5761466153697971644C6B69636B5866784D697A4C5177396D45487132736D4A7878376C7564342F4C4236635258686F5963776E585274303867325A4E4C5171303534736C4979303178343174497679554A79466135534D4D34307953715956796C374837577961626143306F2F61355A4536416C57414863676661475A573755736E5835423649362B6D532F3850686E504F6B5870667350704A2B595261676461517350633049636E352F70445769613838436C6473465262477059794F58424667444C654E666C663372673179367532776763574F6662766C48502F4A723536635070743865736951462B552B4D38382B6F616F74616D654F535042436B384638783231595530533058506B59564F736F4A42474442782B546A545765336970626C396C55586A75533475796138724C366E4C4E766776334973733571383544307A4171586A4B74714D6738342F696577696E56747346763859346F32366168316C42633254646567334F6173416F506D626C747A414B49326B5954414C374C2B57636B6F594D3139386D77594C43734F4163422F412F49755A5466713063763873352F663574504A7635665A706C746E6A5458536E32712F49666A577A537A766D30744E35597551346A6E754A704D53365563696B744573642F6B632B4338353556344C446C5A7A3759526B645761316A4F4D3174666A655539553674664E49534F6E5070347A5A5A6C5A656B6E5071374C75486B597947796464775768795A496C512F3841657A784245516D567256585838597A4A4D70466E793930704C5664597467356F5258567645564264736D6C67436D56434C5363664A6E6B444B472B76486255394C364D664D5A6D304C4B3666636662556A2F634B4A6C35506A71594E434A6A336364746C4C6268303738506C6D30354E5744567552397348776E786B312B33627A6E4451717A304B71717264556B7250476A64576C534E706D304C5A2F4B6B32556D6B34386D586F7A774E377272497736346D772B69515A617673704D4F695654735872374F43797344705956385869696B69427433593549367571514156386132786E2F444353355155656565646D7164634937754D75487A762F41484335304B707A5764524357336661597A78555363366D384E464B54487352684669456E45464146366F73714A344F72722B6F595545313738706B644C3056364C487366545A616F4E6132756E7846506A6B5871394E326E58714F6B4253346150456367496D456D41314E6F756E44463450786D50544B544C684973622F75686E2F757A70766363375A564A75314A794173706E7A654F6B587A354370453461364D36747134347161536E5759706D30776573746D64305067772B316371556D424E7131566B4C527A494E49723251657A366D55534942374D33633162726F44733969444E475371394461743266704E796E5666542B5656646F4E7969794A5A56663679754E766C57675A6A4E4957543756524F3563326830306F57795A6C4E3573622B7444547544596C6D4B594A32694E6B777A56342B462B5177374654784E5269766644544959786E35686E625A4F61497038354966394A5A7A3249455A49552B32446B544C3553724B4435424256626E71627376663646764D644D7635364A48736D7A7251566263335330684D674C546271704D79645070424D3062302B306D6D7869494B73796A676651326C754F57576C4656746F3048316B666F584A59585751614D4F3138746D7873666235385A6D6B367066303465506B3263495373334E6458794F47496D36714C5A345678674F582F78394B77517947566A34797244546576724C704D526B722B4A413742564A6F356D4F68354F744F6750356638414A2B766E442F68643644364F786B517239413259795A73367176755435387A67516C7249596E74524953393970473274665679674C6266324B64514F7049763554437A73354D4B427278384F2B632F314F2B4566454C6F312B52354856795636316E6A344C4A69736261646D74486F67335330797955506C524B6146574F765078344571326264536B5839726E777646637A79306642654D78527A67496733624B696A4A36764D4259526C656B79565546504A6B75664D654B2B46763258543378583850734A35573970666B4E4C575735462F6D55424F4769555A77594430634B36345263734B3034627532636768574E424446706E78674634684D434F766D4E4469677175486D442B6F587A333544383278386C7354494D48443051783063634E2B7777615A7A4357576E497678744D6548625A4366766350483774664C577A57464B355A30774158306242384A2B50344F4D354843644769326A624B6E766C65634D3465565379646D6633423136456B797A585052344A6B526C50717150494B526C4E375867312F7033356B476F6C347A362F74756B536648516C754248444C655665636E58685775574671596D68537548466E726A484844496146694B7642664839542F416147564C66763655636C486866364D634C76315166456D4A4F53706C313358315A4C6F2F4F3872484F7153587A304C6F306236353847455A6E7A516C625A6D6E7169754F546163715A3838784A702B59387373767465726659725655413975613663586848763841594F7642476B6A655A58736B5254386A726F7533307A7A35742B4F636C666F4F41315950536E503950504B584B65376B784C546B4631717A544C58565A44636C34435856565572497554553850567359687353694B6C792F5053554D326234763834722F4146474848773544466E685048794C31614E625178377430776A47535A64475663325A644C304833466331384F6656434E38744D2F4C326F74504655354468372F487176717A61645144776733756974586E507A432B394E5330616C54436E6B6A544C73384C524C46704276457057727A3732543248545633646168523476504674447457797A6B7765557357356E3755545233434F79697546456D54486C4F476468662F7744646F45595755386E796B6C37354C4C782F7837687136755A356A6C754868665054436D376B75546A586179787A2B776D646555707A655A394D636B4E427A7A78343837565754734B71464A594D4B323361516D62506B30756A4A622F6F6F336E48775A676A31386373386154696F71574A57723573382B3647564A79557244666D423533374C643468736A484E4D4C415634647462684B737679307634716B4554686A6B6B32784C51554B7658667277747465464E6950614D346D7549356666635649437A43666B6639592F696679726A4734503437772F4C59754E4B666A6B75633475324C572F4F3575573163627634374D6550342F526A61576A3752742B666D7331646B71796C757A36736E4850687264334C342F77756E6A65536A713255796D6C5331456E6E315357644D6A4C346D6F4E72364E71724E36546A367A4C504E6E5A485271705A517545444F3168544F43353347564261397763684B416954792B6B4F2F6F53716F38575078484530524736644D692F37454F2F4A666447646E536632746C506D5955305761542F35475A494E4F7565583443546D2B70394868344B39414741413831396A4555382F49686830756D7A785262564164742F3161337A75534F75314F4D796E2B50344A416F70374834506944304166715A3833326832626B3359686C5539374E63586D61563534515267544F322B41444B6D6F30636D69647050463361537271434F31533579516B5A665A7276457037786F344C6D7458445630374D5734354C746E736B36546631477676746C6A50505A75774738306E666F642B50672F6A347366314B31486A6F376D7A3539634A31536A653353423542314B595758767944426B3763422B304B393967456A382F5767594C6377763267544E3256395642683261682B4E534361396C726F7447536F4E6374427A2B304B734F66646531694641446749385771612F787732504B70784374633978347670336A79314E55454F644963596D4264766E6A6E5142612B755536624D786E554F4C5A6B315A6F4A546A4B58497833706D707A57714D384F64637761797A77706F576C37626659754F66334659757857656B306F7A4930686B7A797236766663615645746C5538705A71334E32724E582B434F44324F4972725A42352F4C5A5771305A466D51356C54734A4D717161586E7862564132423236593562786B305674596B2F6479392F594858734A6B417364546C3965596268496172537337484A6834384C616363394B355746377A65614A7571767151556A424E453079354E43764B41637549784C4C79644E6554624E50523141614E4F385646394F696176476B533847427A6B394D79574D306F746D386E6272794A4C797A484E62667A76786E314F3530783943427A4774505672446A755231564D6261617A62624B374870765A47486C42464D75744A447A6D342F6E436A67746B39334B7A574C4E4E53686F466E354C35487747624458693947334E6D634C614B7456367375514C36304863386D564F50683641714945576E46355551357A4D2B794D586B4A4848374E6378664C6A7338325433564F5A514365795234666C682B716E2F58794250586635483866566E385A4630725374704B4A746B357974717364597579384A737942616C3573304D5267674B6943574B493271316F43356C6D4945714C623743324E2F30435973547171717246336B744D392B67587A306A7474664631646D6161366D5A73723571363430724975765A6F74616C4A556B6F315A5A70536D566462524E636264566B4A3238704232703679664C78536A4D57534E46372F4A6F57496D7748593848374A37374858706154326B44572B59636D7A796A5946723557365745586930624C4A635238736135457045786D784B3752617441744551325731737A653373555756714F4B346431797455682B53716E65436C56614F7A6A6448757961715A36665A3179365A7779377375687765317A61556E4E4E5569537259373776583431456E516E482F52326B3461624F50644661686E444B784D79704148516D4434722B6569423065782B506F4A332B543832394638384E574F48413141656251414B3737524C4C526A3865307A37623431627A4E4342677857356F77426A4B4962325661635A504E66426C513568796F435562316E6976376E68335270474B6270636F434A4C6C704A38386A4C326D5271386C41743470397869736C7155764F43354D48726844466E5557394E6F7245325A686E766E486A353152584E5A754F7154594145487A5A77782F482B79396A2B5071724F2B78486F2B6C545A2F6D42394C41627356616B376B7872733953767A70353156352F774234426F6E477159486A796251594C4243563962375865624E5236394F4C2F43567749724E64366939745663797436764A644E456B734B4947736A6B424A31396D6136302B366B76556D62486F7A386A4B4C49725264315A35416339755079574D365464596E3231416D6C533831637458786B3453716D4C7533734B4F45547A5975744A2B6669654D39582B51307632313237567938354D4B58337973665A62514F4B55656A564F3778423736562B6B714A5A73364B6847513472656A42636542517156324D5734325A346E345031545834726C734F78644F493079633362433155624A73343433706B3054444B7A31726F785A4A79693358676556313065766C36382B69743656464353736F677136733962786E6441355A576B6B7768554D43567A62614D335834422F77415A5066344948344B6B797A7A4C4E466D4A745076755033476D6951445970634F57714E7070326357504C59304D42726837786D6E45613964614C4F4D67544C5372374E4A56515155354F746B474F4C33386E7A6D5A74555069654C6863767057384E4F716646342F7475506E466B39734D32797342616D696C7337456E796C4F787A5A414A356C656C46695765634E4A647439695373345477697762537932374B33696C566F73704575417A757264416D6E52485944736D3979344F5A625A354C414E6B345170436D584C324F68624E31694D3452634B4163744E4E4D736B694B434E46344C583946677573626E6E396F306E6445727A694D6A515A35617A66424E57684D58492F494F4E727478614B765A4633323052796E7551445777385375764D6E49726C632F63747633316D61534179396A6B58615831626A79365A4A334847766E3433322B51572B525A616553734737416E6266644C654461423061546A4A5A426A313631436766532F77424777394C33634441543945486F4C786E437832666E7246584E5A56794171737845716C5A54736E443646734553733678634779424773616871784131355449364633617A6E624C783346592B5279316A6E35506A6232786E466D30797648693832724D74446F534D4D30593463634E693155567A704C52545A667855796372436C70413235547A7A61455154306F6C7A6F644E443330616C6F524E487037375057776A2B692B5466764B5A38794A483871595051737655736D3862736C3041786F6D334C72645534564C416C7A346658454773476F726C77585753417A6C7175306362527A4D5731774B43413166367155532F5A334262753772693277373465584E4C7362557375536D6D446B712F654C626A705862477252746F464674474F6E37552B78345A74346666484E705A3830337A6B6E72576B4D344D5243386C4D4B4C717A6F302F476C4A683241447537535A305A56465A316F705652544A63426E643765614D6C79395172744E5A59464A71454F7251614C51306B6656594C3249686C6A47324672336E79454835786731746A594F4354464B676F37744D365139446175426C6436345277326849614E695A646233777774666B565252637253764774794848335450496E79576D6A4666614E4C72514C6E797079736F536E6E3156616639797063776B702F5731476B71677437423657436D645451644B72524C7779785571614F615339544979757A567862426F6A644656705538526776364D484562686671566E733164595A6F7849734B7A4A45576C4C65646B5772455632315844774B4C456F36395532394C71445347644674384B4E776D68333062654B314C78577467717A4C78544E79723553735146507030444A707A744F7A304A6865366F564C6767436F6C6564536F6E4A5737304C462F4967546F5A6E6F46667A2B72745566676A734243667072596B4A3774754C30412B664C4E32424D61684A6955642F365479775A746A535836395838423763616346396249706A4B2B454B3452485646486A337834537A684C7335766A65424674504D3755793538654A625536786C7449746161326E6B5773664E382B68664F617779303074735A62656159696B36556C58546A745736685449686474476E316F6E3754447A44424F324D326D7851447959676E78627238646E3675766850786A717934686664646362714752425967526743386B2B70524D386E6C745674464B3565774370746859574E614F574753774A444F68584969674B69757535545041726631394F376B514F4F776E6A7549754B4A6B76573165523136724F364C357A6B57726F3558666D6E304C62654E776358782F46726232386C76343778494C314C2B6E2B624E6E4C58723933634873796B6969617168436C4254312B534A35455457746E73355971675739336D6C4C57342F423471674332676A495A3961724870724D4B4B6D71414E674D615958323562514F71432B4E625979744C68324B354C6277746A4530636D5A374163424E523257502F4D2F6E46506B75754B354F637679627831744E744F656C5A5A56306D51646330364C42395779306C41476D6B524C484E3159527A776B7651642B443475504777304B754B57645856537964496C3648722F583041416663482F387271395562767467335A2B6A666D49467342364D716F73564155316458485244726C542F4143566763415951514B62687279716854327342672F37466E6254427337557A734771565548514658496B4C4774453552373738384E4E4E43467A706B32687350734C6A30564131734C6174486D4E44566141793472656D64446C714B31706373307076496C61644366544E4E6E507448366867724D414178423638674F7741436F2F492F41716C59566B4F4145344C4C37426E33684F47586A30734C78694C686967725131423134664F3278726C50345238387259744B6C7178574666384147433861784D4E714E2F4D34616366446D3269546556636C546A47686B58534D4F7374492F617A716B6B6A41566A3436583475565471324668733165316A4E4376784B2B625879303554736E634E4D6D6F5A67306D6C6C384739566C4861726631754752375546524D46556738774B6657456E75423575412F4C666365694A787A4A456B7441786638774E4F704C4C6D516F515368524577534C5152594C4A5173346A6D41557269784D716D3149584E5A52584B6F72765458394D7541484E2F3052346A6A745849777269734E327565485678757A42624B2B506E743371746B35486979592B474B744B61636D36385938676A3662593351594E57755049356A382B33766B2B5A38685A4D76366F636B585957793655737938666973726E4C756B374F6C4730464B51675748726B706F353969425072542B35366A31725173304770597034545A3537744B6C48316C4332356E69795A49716931656B716169684E644D4651787A3150533344416A526E4232782F6B6A4D63346D4F6B752F356F6E416643654C34466763396375717531636537564A71636A706E755845424C4A5A387A535467354D6B5457454A543159355A354C37312B2B31587274316F5849386871322B317844776E41694361426D7A5131796E3057456A6F43326F6632415A6E3641375839466D77566C612F34357979672F706965746C2B3357735242787136654758714F6C717132717369343839465A47326C7956306346696C72584C3168556F574E4B334953673439634757426D582F41496C323545384E776D7057724C6A654535516138537A343952444A766868706834756B75536F7332795376505A7279636E795A3335526C347252747A594F5370797572484D6B5068765176735345344E7132356B6A526E766476754A74593032687066634E665452437562534549305061735638383179536875722B5444447A777A78545A6D755A7A6F514565573734626331634D4C2B684D63394C6149774E5551563274784B53536C6A6435517472564A414B773174774E6445474C727437493777313858452B522B5463667A452B633354367A636473484763613164792F77427353705664757952354E4D35795A58304D6D7478786E465A74486E77324C5671573261673558614E78796A4A782B5844697970744631784E7130796D7458304E4E374973334D5352577555497A4A477754786E533842717830672B5838554F7642594957646F663078716D69566A7049364549652F37583064477458433930565065544A6E5A5A455851444F497872712B4D436D77547443327931645350644C304B6F5073324E5A6E71394C68466F36716A4D41354B4D796F41716C354D722B4956504838722B4433316238335776474874536B576567587A38326164536B31554F565872774D777659422F4236483548356851564D3445474C344546786746705071567265516A4B6773686773324E6133744E56664F3251743675456A41576757337343793770634B6C2F6D557235307943654F576F552B4C527A585A6753424E445A39464738774750556B4C4D54347235424F7955425058574B535435585550776656703077556B45686E387177387567542F414F6F6E725472382B50683332516568743335495A756E32674132684369684D6B653435424F334B34564D6C6132335372454248766365696278347634514F774B454B7075745149724D666C6B364A53657463566D614777765353395A38424858544C78322F6C4F53726D56384F65597A482F704D6D50724C56442B62716A33333170564A5A627167386D57586E6E3053385A7267584A766B6D2B6E6A38574A62306874733530364B4774485A727348574F614E614C4F4B4D434B2B317645714F7144772F55616A2F6A6A35706D76535662467A705559526C326E35556A5645304E476F6A484F3335746D5A4C547067433661704D79744373544C59784E6158552F7A7968626D32635533356654467570565A2F38322B61637067354C546D347A546F662B322B2F55314A334B7A6F644953634D7567476E6C396B5132765338517A75394D3249337471795A5534756866677546796149752B6C56574A6E6E566C5A716D31616F624D504874714E49674978396B2F49464A696179374259336B4138617A6243796C34374F566A5741354A686773326E6564304F354148544B316C695A65666F466D6930426F523271436A4F71352B354B4D642F30346A304357334A514C2B7744784750384155476A426E6D73416C314433704A632B5972645176713035326E6D71794343434E38654D32666A387A36644A72697164426F644831634C6A654C566F3172737266625A54524C3649704F5354374E44574E3479656A4874396A517473594251756C6633696B5338386855367371567855375858784179767066342F6A4331707A73466C64483677705952596F4E6147734F706B7A514A394648635670696252674F306168586376542F77444858342F3832685242786550654B37725A36626C6E59566A6A716A3661754C79303179523872336C6E654F7A566C6C42365179557568396D62543541393341697444656D583149744A79566B2F5A31716B5A4D5334436774352B7732565141344C6D6168334B42386C665258445879787A73556B534C4B3371566C705667366F626B4451753049334C764E44326D42646273596E413156696635412F51387438477173456230646675535450742B71754A6E6D356E6A65503550445365364663575433584A6B477361344D7572526D55315178307A6E3979324F39557A5451617339357974306E6E395A6C6F576D4C5458506F5978386274494470673078354655505A2F43396B6558374D6F2F344250386946387839337A2F414B6E64425A745A324B3945762F5955495A697676367A422B4F7331674B317A446F345344706F49415337457044514E304647757A3143382B2F554C564970644B79356635626A52783770713476506E7A5A5175704C63577A7A7050554C2B6C466437573146737A5A4D36616365544E336E454A57487030666135306556396F43675765686E6F6F594E4B38777865533965494E38366E74664A75794C64327A3042566C5A325A6850304E394D774765316338343832363975716F59697231476F795634354C34714E747074416E4775687A326430574D6C4F64726D6B4A5633677958726F796B43446C4F31474462424B4F6552776D324765676366664B6A4A485250467A727A355868395A65633347646270624C794D707A594D6F7A446B6E7952387573725031533171734D396864704C53624C374B725673376661335761762B74554B797443374F76355A317A4853702F46444975794D4561723339554B736E6B556555772B782F716E5A6D303978326C53714B6D4B7659587A4548764F7A4B644D545332414C466F4B3553424D31695378625167684F47436C614D7434772F4464664A643874794C612B4A53557444527834636E4444446E396B356F744D54614F523358793556575469693868746E6A30706F7547536D305963784A4862564175545064504F6C41713174546C467351474245326D6B38514A62706B5A6F44783857597370587348727A7A716A576E324957546A502B656974687635612F695A56706C2B6D31733242514462744256374556314A63554D503336464C62553075307A352B533149797967344A6D4A70446A4F69475469493561347A75353538636F586D4E6C4F4F354869384C394C536D4C6A49386338385370714570576532505530384534343875794A6F384A3347333834745A39453470503248797A6575304435715641725633647462655837655557367A394B523353766947343861747A526D723047554B68616969444F323346725837346777786F3548732F5550523664665A5131484F367A615672717141376253564B796A394277565139434C4E7362696D6E6C4B3379347132454A7A61326337724F3034796164364A445333494E432B64727978794C476B4E4E3579704A577763646E7245543432564D4636364156527149454C2B415149443041306F79395A426A4E774172644669516579536678395850315773546F52446B3869566C4142516A6E5244576B675874704C4B4E537A307948454F766D4956686B77377167427A395270587A59566A6F325478356E6D446A5861634E745935635A35386634657475577A382F7562536C65536A786878783037364D4E4179385A70747574546A6338767464476A486F30664730346E4F2B434F486838536234384A4C42504B56697A63727369754B6553516B7563476A4E576561526144577457656559703047686D303570386731464A6F57312F5A73574A6D682B6C3367526F536256456E6939367161726C4B382B756D3870395278675670456A2B674A5663776959436E47716D754C34533462573231536F45594F4B78625A324C5674444638687852767435545657534A5254616E486562506B747654506E6E4C6B646B756C693978766558454C4A476C524D383832615264353676484B497863684159736D59457146634C5A682B38353571566D3348354B4D43703873386B326457362F795276616953387333717357756D2B633051336F4C6A6C596F4B41764E3035736B51755379417259416465794B71767335624B4249456170706B326C36555948564E646E354D6C6C6B596E4D353846546668354E4E764C63626F704C5463362B51703931434779426C6D6669386E46386C504C4A6B564E6B5635372B37517A363458706D332B4E4E4766566F6B567251357A69505448786D3546724955785A5A4C6C4A386E532F333276626B4E616B714256735032742F56362F77424545694862326A77715435456D662B6F62526B6978617939684E70625853505A634F524F685A4E695350466D487065536D544373482B47726751664C73356C523661534F6F6C596465726F4A30583570386B34503475334E2F4C2B574D355A3556674A7851463957376B6D78766D7938646A54763136623637394F3037497334353846746A587A6A4F4855466E773332506734334F6E2F5531566770386679385638433953652B7A414167682F2B41573642503173743431354F6877326330376A496C4D5632694D443053716E526C58555075436C424D37523332756F674A4F32624D5978714D4D436E456E62623273444755797A3533314C416F4D76496679623564796679586B736D546E71716D584E5A366E692B4D726E7835633174516175654873743451686F7949394B6378794B68615071665454307373495A672B6364784D2B4B78323359774B364B7A4B4A723179766F5578526C6E70764B4F5A57635A744A5257343645304C7046637A6E515462545174456A63634757476A42314770716C672F774276556B685878724D4769774B3757757867636554494A4D4C592F414F63387044497372345A574E5563775972626D5A3943386543342F58754776546B783752624E316B777A3678533338586E464B5135486C3045557258684B3647755A3862734A6A624E6D305435584E707A55307855686D354734794C6E57707947596E5064705644555A4E7447614C59735445326E54564A4A48333256744541356446657045394C467933665A6650303152594347635A46546D4149505552456C777A6442734A58796773736E5952594B796D4B4E61766375507567696F317638415234455970354A696643665838613255562B54784A6D396563497245706E6A6C347A47364B776C476D6A764B72445354544E6D342B506F664F4A36366A552F6B36544C796D444B6F7946622B62642B74616D68747049413868543952517151504A334E5A6B393965785351434E452B676D753674526E4D597558706B71756D794E30574C4D344553365853577637323641345379336D6254693257416B6E354F4441625A3679553254375345566B4D326A4D79324F4B34376730342F5879723672374F5162512F2B424A614C756E51644A38646A317963366162434C6633506B72354B63582F6B4F624C6733565236436D4E32376D48307978724347584B714A5A6257655339754738726237356C59593068507A664C6D61733675766C58612B645A5761675635763657746150356F4D42734D766F51355531785A565A37525A6A566E5548724B36657562574F66796870684763672F4B417364515555475850444C586256706F48796876786A546176664E2B4E7778343754793234327072614E302B30726B3254785276614D436A597A79386462375248376159666D61733763686F4F6A6949384E6968786B755233736677366D352B5578344645316C4E387A5A69746376616F4E496252326E484769725730324961482B544C444B325737367447682B6F594B2F6E5474474358313575695A566D6D4C476A672F72706B4B6F4A6761735744384A7471676F747A5A4F57307134794D6C794764505765757A735877567046777A55793062516F4E4636612F7058796D5358394D506947546A386F4B32794A4C6B6C6C626C4C47374E73302F63306F32586B4F54544F5A36512F67625534374C6B4B4E6E6A706961353164412B57594C36506D4879577471736D69653752396F6C457A793973307A5A66747A4344796F6C6C4548704672724374625031585137753366307532663841617A53304E686D39493073735779474F4D6C713846714E5053776B4F6F5A77702B70564D776839637844465A57334561497838324A4263394344745A4D516D4C6B5733544E6649757335726F5039747965544A78504931354B4F32566C38534A7679654B7649594F527936575A6B4D7033765A4F307442727256453969646E7879733654624E3977336A3561594B7632394955527755453338573748512F62317845774F33506756432F54516E367179427478784A332B7533365275494330724F422F704B68316A546E507668465A62764C30354C4D2B7A676868686932762B6A4D436F6C6642695445796B4971523175463437354A78756E48796B3235434F6A4458467034356C6D6D486C63327A472B656B7654795337356D445465767347586C3170624F4A5A54476B66665130425052783750584A3749614A6C76525A5746327A2B464141363355514C734642516D7371775A57506B724D5649576E35582F6B56727150474749326E306A2F743772514B6151726B7477717458545965794A754B5764584267306D7352354B517A4639394262454D5871736932325942424A396C74486E332B6F2F384154663841703338492B49787238543457326266542B3366476F5735506279584A387269342F6A736162446B5466736F71766D544E7843653832686256666363393662574D476E665466677649624F54353349327571706E7A70723350434D3879353637744C6E41756969797A795946746C78523344685638665077494858316958704C624343375038456376725A41774949764F764F716C4A6F2B43445A507A49544F6A6264477A374E35532B3879372F6F737445744A70376654564F306247384A4B78395242445A79633437505A704F506335585038414852305343574B2F6B4B6165506B33585A304C5154626B5A5856516B7461523243617156395A755670575A485A36614E326554392F77447652763155666753426C38576F674C73443734346C3237596C776F6950794E644E2B614571304B776E6E775778466A7961396F326F4A3552776D41396F6A433667657171756D697A764E6E4D4A776B4844436370356D6F5145414956563968375967667150507838762F7742506C2B652F714B64774B36394367542F366D6D787579534A68726D34556B44732B485942594B4F2B752F4564394462484565685A584F35484570335A69306C69787A675170496677375852724667594659683044374D62676B6B53544271425270386D58657A46464673706F4D705A5831466356332B712B4D35366450696E426154376B65664338564F4764633065714E4869355A64586C72444F2B5A54644B5A6D74565978624F4E63766241586538634F355469336E7A752B4B6570595079476F45317375654A4461584E543556414E6936734B6D4577614D4B69616C6A3054744E2B4575317950706D6267344F7939447461356238394D76304172775171424D376258796F486A4F57596A626C43576B4E4F3930624E734A6B6A6A4F6F3764556F57676A3045394A617A38372F31427A7A797732614C56724C4E715472524A637462364C5A31706B4F627171695930432B75664770577149512B584A462B6C4D5856744C2B4D64497952704B656B2B784B303045685A69786A73656738443279734C62576467706F69304B5456714A35326E6233595461695A42756E5473676C3751634679654857526661496E5642304D5354625454506D6163343958674B354474445478724B4F46424C394D514F66594A57307076387266504F472B6331347A4F76776E37375479754862782B2F30634C742B313335467A5578746D71454F445A70746C30706D726C705847737135644F695355703464733268634674346361394B387056446B6B64666173474D457461317150494E304861662B5A6656644A46612B4C487851672F5570386A532F4F64674B4D4D726353595A2F7276715167396F6C5157644F4A5836656F6168624A47635057697173726A535950585931766F47583064464A4E7673536D61467773337A4450586B632F4E5A4A7655367447645A616B354755447A5645766A6F6D475738476F342B5550766C71757A42524A6134624E2B3670727055546F632B797834385A7A4F5271364A656155683977623059735A7351574A5636364234756E694838435736382F72467A387167575872526D535962736478503259776B38566865684C3169644B4549692F77426135694A4B63365567586B687356516E3958486B6E31733337712B655563477730367478392F4967657976674B3234584A3657304C4C4F3262323368713359374833695A7A367056354F6B7347665177744F4C73632F45635730626248513864342B797934787A57713137753678745A6D416E4266732B51523634776573546A4955306D502B4D4E496F396834527A52587A6277506452302F6E33744743767432696630505A6442626146764C6435346631487A676249364E6D74734158724C58532F5439307A337A34717364614971547679733431313546673464364D663562694C7A5876626E34343872355354647637795330787961636B736E48794F715A535266616C4C7A644A734B3330612B46706D6E4F4D7656737A36395661616E676A756359796D6D4D73336852346451576E337739624B42555271734B78586F6C417474614D2F6B7252427A2B61686E2B677476515056585373335265552B644C31495341634A6A6672644672642B6B74624C6A6C744657794D307144574A5051395461357A77315A6336337931716B4D44754B72346A724C4D576A6757766A656547484634386873684F7474576D2B766C4F4A4846364D445553705450786D446A577953684C544F43713939576E576C624E5261616156457446506F547632675845785053516638617A74505A6A306C4837497237467271786C3243447379554B6632396142442B464257702F77424C58724458615262626F6A5157494C304673464C4A4B626858716E62707578645A314B486E726C314934356565516B4B662F7744546D61484F6E466C734E486D66354274746A4876354F6D7144444A713330493941484961367A316A4457416F472B322B2B504A5A387A537136477448456E6D6B50424D7236464161724F39476F2F707173565141474D2F614B454B43534B756970616E6C2B5134576965616C6C494B6B71596C6C6B6243665245326D5571376F72696852562B567238314D2B7271426C457131435179644B744C3151656741544B7A2F73744643336D5254324B367542614C5956634464584F55666B4C5A345A5774794678526D61636875354A366F4B58397761615A746E4A326F655474656364464C764D37717A4269322F4959367963393347314E633252685478566D4A57553073794F5379465768315A637972527655473173693141466C6F6F704E7670715A47492B7459357A523441466F69724B4B4E587034435A6B73622B6839383239514451496D693558446C5245454C4747576A744E764335324F4766306B6F49467865706F72624E3244506D5033644A50787534565536655872706E697A3439444B42613973382B5530787A7648786A4B384D4F546531644C2F5A7778695A334A786A5632752B56574B336C525366746947735751676F76364C574B55516464465872494E30534748612F5672365038416663686D67526763616F32426B3151524F6D7771334F334732457A6D41754D762F77426F563574515774556C4C316C3145614F425874712B415344723559384246474D5057654B355867743944486D506C3248506D7A624A374D2F4F7275674875627557316135753273623761396D32656A5A726F4D4E4B355A3076746E6D666D3665344D4550764A6634686C726F465257547870685A524A476F37744C302B7435506D6E4B67456B656B5674516570714A6D51784B754E394864506553545A7A787878383974584151535368465759573571344B487874435779694747764C70715A314F7052576830363153387645715A4C71793471524446793473326268487A614735503568476A37632B666B73392B4C356E6D393047676C76386554507A57376B636576526171685A3078484458426E746F737768586B4478356C32745668575A79347030624B3955654665503478555A714A4E762B75343643484254772F4C4373394D745254314433544B4D614546766D667058706F4E7144496F6D7557475A30736C7A4E7A645157536D7A734372427137762B316B765368324D53612B6A2F4147475A4C34324D4279364C68316A41315657442F774144354F622B5066446E31376551337776595A6B6E784D754D3172626476314C56584E52484A4B677A5A6354506B764856727278737236386D6849354566507574722F725731387261633535532B614A3974614D377151537273314C3173496364355545784E48466E304755306E625261634D795375332B4E3334382B63666A34676C516859776D3163534A4F4E31556D2F44436E6D672B43664769697579636D5973673246644D494E5779364268356C2B634D59684370684768567A4842506C3379626E506C664C4B764A357375584878327254614751515566614C794E4D7A563036484837573272635A637543466154706E6B737031673133652B6C6B7844426B52745361616E56534D504F733238665A4755716F633261434655534C7451313154486D4B4F3549437436326E5A3750766C56615A647A693067547247495269355A42574F69594752583158396F44585A636F3530496D41546A5356563173697966694C4A4C36336F736A617753394C55396E476761547061706555794973332B586B35776651664837596144306D2F5A6254507949615454316573656B2B6A4A7131386865504B4B324F4D71493833735456596C5A3537364A5264534739457779386645526231657554433265476969334572363553773161305875717078416572484B656E5A376870496D59633855456D68584F624C696B7A5430344A62457268623877687A645046594E636366384C42335733305767627031646B42544E667766475A516D5533314539454B793138356D316234527676317769326A6A666A75703346576C6A342B4872354C6C633265464F53307A67754C4643345A39386C72527672326B6363566D466E524D71435A645546764747726571545646726F7154364D7964796D736D72556C3148714E4C74682B515850474D2F75504E7766592F4E2F47765A3877714F676F76394E30574F62385358707259737163786F6757726933546476726F587562584567635932314769306D6A347A555A4C724770626A42372F795376446372672B2F6C794762586D70476C587778303731722F41484459724A3552342B49794A4A4E512B797470724F76686C79386650695A4A53564C616154635278334A7732724F76476165783659307461575A41305A7230306E6F5A31536B313866595A656F43747958425253452B767A3165762F6C522B512F744951654F322F72626739426252416165647A74362F5059577466535A4E797261712F4E3865727A7565426673567858414762717567725636494146656964334168554267574A79347732375456624E37744C58576D787739744C515233454A5631567058565351564A674A53314A5458706B67624B482B744D53555A35356F734A724B62726157645A786A43644B3965645A786A4B4D6C63436A4D78564237434353504A3266365A2F34415A736E4D666C4E3436384E653167307264376E7742536E7573497A71385A3438755A43435853637279596E42577761716247643959417434705171776B51317453505262572F6D2B516354466669335030523030306867724E764270554C584D46306A4D794E4B3858704F59616D6D725174544B4443534D5A614A55573367724A2B5634365641366557756456632B795A6D69304D6A526154724635737A6668554651537242764D676C5474582B525834312B36656C2B77656737493330584A2B635A314857516469306D5670394262613330534B535367596350536F4C39524E4B6E52304B6D6C517A37584C4554592B5447437862444B6D3539744D32437A2F546A2B70314F50782F47666A33782F674E2B7165566D7A63787975336C754C34766A5272734E4F38795331734649357A645671364A796A35426C4D355130372F62767A5041443877346474484C63786F73732B53617A46355A63632F764E4B35352B4D3143525270626C5A5A6E7576322F5955776F4862324E6C577A6B382F786D4C766B6B786C477733457636425A4E56315461666E52494268726A76424B4A74484B484F633169714E45496D52524E4C78526D6B5A384371746E57424F336939352B5463742F556269382B33355879362F4775546A4D30477A69754F79507032506B4F334F6C4B596A766C702F76456F516F32726B636B75657834373435374A5A7452354E735748556953792F4836316A43457457625171713837366C6F59464742366E3579306A77633143716E746B7858385033354C35697133752F77434B752F794F6E3232367A6835547066637A6F594F3072746E6E584271755A704930376A3277453157636A6F5143575631336175795875563832647679564F6C37514D6D4A6D346630732B57384838672B4D384E6E76364D6F35444558342B2F48346D7863666E30775232726C7A574A33746C3547576676384136546473676B702F322B76475A6454477232584F615238326A51586B306E673643304456723165586B47612F3673767369373949624A4F7A57703261364764574C55462F4E4F383548354E6D2B6C684343576D767847463977386C4C6D465A69324D6F6731587444436D44374D6B393653564535482F564D6B4A38612F6762466F6E50466845482F4146706F626366784F6437652B75626D4C3537336233537064563436345675676A5A64324F30746B3279636A6D74524E44543054715A3673396F6F7866302B517072354F71744E314F424B716B48536867573235474D6E38542F6A4B764679554A48356238674D5736792B504B57736B585A786F486C2F4C6E51344A354972347A326B47794A595963706A6464635852554F457A6F5957696B3344386C564D387635656E51355479767A4B6A5879587A7356636973587A55423638552B3375632B577037502B3567797A66762B5430523233352B746939656251622B74774B5130797649396B6C6C31522B3632512F486B50466441726166583448593736425031786F7577726952582F6D76717064462F46635257565664584B6A6E4375684D596A3258433269777348504547684A68794D2B796C627930614E7739596343624D476D41542F735A6B6E384566374C2B54326576343742372F774343667065307A6565696A5466394C3056566E2B515347364858512F42486B66482F415077422F7744476E766E766F6F6D6877766D5764696966617038354C6835374169356D39564A6C5A394930745A532F486D506E6A30355277713863766C7861622F61644F68514632576479576D67616C7A522B786645506B4E644844634477314D79785674504F3435636A7070534F5257783658332B4D4E4535316C6D444A756C4F2B757967342B354F45494D7979567A764578472F6C75554E57557768775661536A6D4769396D313865792B6248324A52316C584255706E4C786A5774437A5752763254552F384F5058424D7A36506F504B3761454755304B444A65516C485149546D5047724430566139584F6A73376E31707857456A4C57432B66365367645963562F4E5A754A36596F6B5043475171727845682F505974504C52316368444A432F466345336871305270735A57303646734C6D5A68472F334B386657324B744F6F30397265504A3147524D6A30683168306E6A434A33726F6254794332766D7A32624D72536A4A51754D6A7A624C534C36504F365369756563345A2F47536D355433313362776A6E2B6F386F6F7A6B3154432F6965356B376133495051732B4D425946624541734F707A445036516F433564624B7A36554A697169516A4B4335584358464577716E6D792F485A305756374E49766538476752504A716D3252764B6B34317951316E5A4B583459556D4E5530566B55796B735754506E596A75536C7A4F4C4A526F5136302B67305459475878376B4745585173704A43656F75766A333573724836725A7550794C41796D6561334C656344624D6D4241364A62637945305773622F2B745534584D3830717879704F314575746E55754C4A743043544E612B5953694A4C63425A594176674579532B47567457767532524B34316E7130622B51315134334C67525A566D6A5633636E7130616E7A65545042304376542F4651526C6F6748536F36337945536D6E6A4A524F31486A6E56495061742F57307649685650614571565879634C3335644567412F564364726966596437576352445031594B7444644374663074797376626D55734347425531716C6A6C375737374A356F427352706A30747A30367846395A797A7148692B482B7A6343642B4B6631632B4131474F65486D506B6E794F4C7136367561783847324C34374C644E79732B506A4C355279584858316279473970452B4973514B70625138445A4A6C64356267755771787132446938366B67527932336557347936495A33574D32385A79424A5A7661656C5036715353506F51586554767466356E4C4B4F6651712F72717A717447516B71474C32326D755932686A5348725A4D6C3959644F534441574D4C4F4D4D3639536E73416D5A745A5A59677A4B4D686832412F774254634A35576D7A427842746F72374F4F6A742B526378693475574E6B76725056654F6A6E39316B3958704C35386D366B56446F754C457931716C616834473534393172554E504D53576878574C6B646B33486655323973726662686E54794764715A4D35645A58625675596A504A534666345035356E574B76364F6B654D77537759316F704C6F2B657233567866514F7436794361366E456E7770684E79794664476570525847325475717464365A536E416E45744D352F2B75584F3862786B793258342F576262544C6B6E30703868346A47565857566C6644732B563838654B33344A695A6F366364545A314F49764C506C6F73586E4C78767866693947326B366E66462F43696A7463322F3250482F41485775664450512B6176345072392B695A7A394E4F353875766F5276384674322B77594A644B5A536E7A3942684853346D77435A3766557156593530686C374D6D6E735638563041716167704231735556544A54665A433970785457396A6336582B66593763485056786647366562354D534A6D73644E4A38546C383065394C3850506B677474734A305246536B457A354950534C57575753697A4179664131546B476C58516D4B4A4A634D5973316A48386C5730444A62787974535161693072654B6C556F564C4D42476C7977664E63583575454B4E39744B6F7A55683136645470484D74476548635562594774537143746B3170305957666B7A656C6F36565464396136675753774756303275644A563870654C302B55664C2F6C4F7A7968445651786C546B6C3437467950434B496D57674E6F3157346E6963427A36646363305339444858794D6336795A2B544F41766A4E476A2B33385A6E52674C4F736D48714F367156525A7A6441706B75725653696D6469774C474C514C6F356B44587A43754B366242354255566C32766E4165653074656D6B475455315332616F315351746E436F5A665945536F695A6E6A6B3057503674587845476D637375435758694946725053426770536D4F32376B4F516930506B6D726D3946446D5A504464796B6F79523359354E3836776D4D4E64414B42357A78364D75354D31564C4F6F7A46574E542B33355973736549456B6C32584A7A5A71546B55682F6B696B716B4E56334E42323769544B366B654966766F7537492B71527A314936685A525751563963646858425170704B76306265505A6B7378413630544A3877484A5638377975386D644E64413952772F2F7744564F585852497145562B4D2B315A6C556C677830304E6A58372F6239676D42305A66745672472B506A36743759657261466A485457336B3456764A476A6E4A5A2B554F56664343567659555565574C4D2B68626F43504A6853496341762B306C62523975345A503841496B3568614E397376544E49794A6F4B6E686C6B42346D4756694661306F544B4A362B664A645778342B624542487445356A4B6B63526C574D6C4A50596B4C6F314D4C4C65675832445176772B49634F714C4F584D32303671424259384944796579392B6E4D3535346155626A6D7931516C4270304C4E69733345364D696F6F7256356A6B367561577770434D792F5461534D794B6843696156724A35586E583265786A4B4E2F4571364D564862456741667239797869394E4B382B67622F5A6E4E4F4E6F497036736D736F58496A79775955746C44666175586A525A576339756C587565765665633136793853615653705654735A7569422B4C4E575764493764453534686254544757707172525359642B72626C684C4E703255385664385045635731634B535A7432696F4F5970522F75365170646A78386C70654D3162574C65526E3679564E4C6D7A4E5357614A714161364C563967592B6F76347639634E507346677A61705774797241747944415344346F533447737131505656586459436D506E6246626B6338575A4A554D5762556C72494B5878734C4A315652364A52635861312F4270506A477658386A7A63636C746935654F2B3469393672537265696963644D7159376555544F394530326F583038617049305A525072566D463575627558705050787436744542745A68576466466D38684936726F7A53346A497844704F437331714F536B4575774956473666315A4E7A6D79642B36657365622B505A646F726C61566934656C3539526F58564173684C5A34396F31493034463939594D4A64714E78666D696653506D684E724B46652B434131624B4A424C5A78324C674C385068347267666C4F2F566D684E63764933346E5A5459743730676C392B4B4B777A69584C6172364E4174795776626F66375270662F537A756E6B54364B6358486B2B51585659694B5630734876616D6F5A5A545743763638633371713162466D426455557953746A52316F6B2F4E6E2B7157666B542F3542664E57586C4F78383938722F77423366366878357758673866714D646D4934587A7A504E544D364F756643584E665154736C36456C53354E457759515738572B66532B3962615061553456736D4A6A5147434845383779677734635044726B6A796D69316465766B747065326153367272646461516A5359766261457479504D4F4A476D676B5A35307A5A6334716634336A50733934336368716E515A6C55546C6B6771524632516573544375366E4E4F4A565972354D50416B7630345879784B4F513559414A6E7031756155784654416F5539416C4630706C53634669455732775973424277374C794B726747347A4A76584B69566449466B612B68396A515774614E615970385474302F77426A77347A6E7734754C77536C6D567278635A5A4E576C71504E644C324F6B747163466B5A3658732B67766D546A4168364E4B476B4974656C487158765A794F6771456B42552F7743784A503442556444386B396E7236444B6C673941496E46346B72434346304A4F62514B44724C6F576C33556D647175712B4470464A465959734347466C7852596C66627262425A397074473553453433466C383447744D364A56414C2B577250433072546251725A38384C3154773036684271476A4E3472532F462F676558357555743439737A4D66456749664676796F4958386B416A3841454876386667662F414150706A2B517267515053764E544F73454B715A446E50756E4E576761427052513430736A68776541574675467435613956584F37745A4244616B516D30792F706C714B69424A74464C646E52634849665A79796A2F3652532B763238686C7A527A76656D6A4E50504B3271305533766D6C4A494E444E377278314A576E724F6937776C4B74664F6B79377544397A4A4A67535964684C49702F656972456554723541745544783642506E3076312B716633496A7A444F624C51724747515373487A65482B77744A386B7348624652744E63795773613454624B355359436C727A6D41467446397A5367304C6879305336564D4B345A662F53766A756635486A593874712B53386D654A783734597A78564E647034475352454D7977626B73726352766435306E33686E723065694C585367672B6E4F7336587A3352782B4C6B394F622B79547662526D6178325A6C537949585879713269576571615136436E6C37374247304E53744D344D536F2B6C2F3578752B5A5135524D376D7245797876794441725442575138795030435A57464D6A55743976474A535179792B516C2B70667A6D47704C36445A4452697A7069426675504F3854486E59636E4C486E346539384E4157337A6A784762546C6168422B334E754B6A6B6A486173513978476B30325767706E4346766369746D4F537877306C70712B75506B726C3836364E534A52554943766642704E62764D42764956594C4B616E79706161456E367474646F67744653542F6B657467554238775631544F30546A657545716554694F6455556458585A53635064636456514E635651304645747643343176487246376B55766A756E34356F5848787236557A74756A5336344A37615966754A586442614F624C424E6645386E6E30412B355A5277616C6F536C707853387554632F536B646B58766455445468334F5650434636426D5666504D394B7444556A546D6A476371763250576C55396B61353078432F38414A7069387570386C6D3355446B736F30365243367065464C7072675667735258536669312B4D624C2F466C78456A493167555739494A68516D71352F522F7A453630317A2B576333386735486A4F437838316E3059487832713468665A5058353172426143307842544753744C7572746D5A5A2B2B74707A576D595A326A592B485A75507A374E3759396B6443614D71716F4554463548337377566835755341514153664A76496A736E387363446C4C4155515956686657544F757357364572524371712F77423430667968567459393158446165327237626F58532B5436306F5832534775767574354D554E41315362544E464643766249532F386E2F485A4B4E30502B664D7A48354A4835364A2F49483036386658375A326F794633593141527951504B736A4253783737445244502F486669657770364C665536726B614F416742694661535666492F595833636E5154426D6A45744A67534B5866595658326F57692F4530435341726D4D51535445326A746661344257585275302F5657592F436D7632762F4373724D694D7851642F68784A69387976345767485A58727353536D744F6E634E314B587644742B5742542F496744666B396967423742412F3537372B72622B556135517362594A43547A3537737A75576864756A6D56456D5A56336F4743445172524F44574D3177396430373836773678504773494F4B6F2F536B6F57676B617357626638413031354935666B48426148413965625A734379436F55464E6344436F6D724478437454727A3641376D464A566A30763076664A7368624879794B5742752B47536B4E315143454875673866344A6C373643513749514F517669476236737A2B437537483946317574784647774A797233534F395636706C5136574766525163474E4C67514E4F67715975703157326B4135622F57436C594B776467594371556E4E52783661315A68565A72343338367467354C666A3134635732756A5165526E6F31513162446656574C77704A703532524A52644459477A4C41465337614E447A387054692B546648314F446A6475656A52686B69654E756E757A5A6A6D544F6F38614C657146364F394C4A495152724D39746B6B6E47597254523962495A44796C5365777075653658614E7A33526C6874684A4F6E48756E30766E4A68483358785369434D51534A46553378724B504E44594678694E2F4D50344F5879795A486D4F6635465670624E6D346649776B346B59385472394450346C6F53797679764958624B45636B57766757694B4736534A37436C53684B56556C436832763237482F4A6161755A41394F58544C422F617A6B677A4E4C54506943436F48342B6D656E35356635765334613143305A316F52333637485A7337553754534F534357667773354D484A35537A2B4D525155445A43364137634D5739687A3774716564746245535757362F692F795035512B5963317957723565356374626A64657A526D3475663234633534352B425A386E4231456F65617A6D4D443776436672476D745033715A6A795844635931416B44785A5645535630534F6A565633387677396B38372B62654B6E2F4A726154452F34306A302F6D46452B3759616C7964414C53544B50536C7743434B30676A42425851534852564F7350506845437162324447345868737769626672583331326C3377496D484D38533567786630722B51526E4A2B5077327A5A2B5254794F376A715632564A6D5863547272356736615A3156714F797244476B517A4F30493553354268763870342B692B3275696C2F5151717932434143686A2B544B65475167542F33363046523132303348362F5363622F6B677579682B675A4263786768683539374B3352613330796C675059515243556A4F682B666254627246466C416179584A556C517A4844365378425433456E53307A746C4C746E2B414B4D7561504F626555317246497A544E6C34666138354E45742B75766B595974465A306F30344E5437625A6E642F4B34676B2B707542632B616170753346346F436E624E53314E545564672F6B67367A52746A784F6F54794A5730535A3941646B6A72365945325236644772305779307A5538582F4141784A4C7A4F6553707A33477062733131465761476D546C6877636F6B727251386258437364584775706E626344776D6D306D69372B6D736A346F6E4F38786F7938507765506A6441756A4C386B3170586A717A342F4F6D6A2F6F36364E306263317472626B49454E7875425776676A50785848476D79756B536A6B345A5972625875617A504549325A524B7667774C4C374D3059457779754A4D5662526F70545457705A6D4F6444365667435064716C79664B7855347055754261504C517A4B4E4E36446E304F4B7A685263794C526C6F6C6D61564B48506F76705450694667654C355A67305064493930744465324654496763526D4978582F414B61344D71583136644231626C342F3768316E78746B355338525232306533547330325468755053637464616374796C596A3035337873587470684B667A4A7A726261704A5947555A4D713531746F7A306D682F43696A4A44775575563659684A31713150384151476E6933315472326A3066446E61524836523664364E6D314B79477166335A487A74684463626161704D4A6330523872626759764A5A645972326A6F6A4B534D4D786B72474732307467344B7A65612B764A4168686A742F774153342B33476358504E782F463773304C63634530636D6D6A682B4F333835723070616B5A354D314D334A386D63696F32334E6D303563474B6A4A505776465267542F635A2F6479614E487345676D6D6E74552B69666E4F5766784446716D744E4538787458734D3039476839416B37443071774556535448383874536C3478413838776D6832505A396569587664584258352F6D4B4B4B52616C516C57657959794568756E7A646973472B766B65432B616C554B3654703246326B4654594348443861666C6430343563754C6A32754E4A41354C52666B4E6A36734E4E737555576E46787253756A6D5471596F636E794B46746D33556A614D575374485450384158796648427776332F49304C7030776A78774B73785052433033576A316E457A2B6F475750386439324C644D6562532F6D542B584765536B61586D71796138476B69713752304C467A514446554132575756647071304F736262646E364552396969745946566D724E4576726F715853574F6A6158516E626C376B766A6B5A746B6C4330744F6A517A4E43394E4B354F524D38367578324C396839786E342F462B7449666131614D70566C57657145726B5363706D79386552526651586B737972494B33744B6A4E32436A7066576942776F486C5A2F613639687649674B69536E6D582F414A50505873384D313774736A352F726D62514F497550304B516E565A7251357942646470306D41615851436872586936736569642F595A3066476D4751486C577932566F316767316731506A304B317A6633586B72372B4B5457757666786D4C6D5A4D6436725368714B33706D5264476B75664E6E32706F6D66576B7644775A6E5056654D7A6F6130775A2F7437744E707A305538484543797166386452537A77482B775068343964396764456E3659724C386957465752703131487471696843365A576C78477A2B5279714D67356D454343577A567449616C65396C4969424E4D6A617864414B786845677134704C45364D615267322F545034725754366F63595A32664A36434F5335666C7462546971736B382B594A664650476C706F69616F38636D424742744A68463070457271385261656D636E7742765856624F364B355374657A315374566B567345505A522F4A796E626442652B2F716B6D702F496A3237584D746C514D2F39505A594F4647614F32426A4A3530315851334E63724138786F6445436E36737A2F5352537A5278557932336C724D75356E77646665444E6E4330315734586D654D6635496674734846346F4450707A5A6159734847354E744D38665853695372787556746D33476768455A386D6230353944576D4C366177536B57636E34305A384D2F625236584C43744564724C6E6C52757731364C51796947362F7744557032585964416558353672457872394448754A636A5A445941727951597156644E6175792B304C4F566851736852514A437370304E617945762B63306A6F4371686E56566679552B417A687751786E3450355673356E647A2F452F477553676E766555786A787931624961496D6561582F77424F7A365532773152306146394570795370336149706E577A6632374C6D734C75346555557A5075794631566754536F696A446F396A32574530667339414947596C657A3134676E36737A35332B506D72326864626A624D576D597A4930754B71522F6B4B37725837425A594A773469754C41436F704145575A654F44594D32444831424672414B6C745A6E6A577165524C647758785866654D74584C445844696D6C6B7944454E41546C4E66485178757A374E2B68644B316E7876497872726644782B564E472F646C5456706D3257497A616774386A386B686D543034505657785975316C55746E6B394F3245356A763131644141724F474D6955375248486779336B7A336A666A6D4E437A344E2F6C2B584E6B7674675143784B7A332B7A36533933665A4538576565646E2F41484E693962552F2B755365337475444144766C514B755457644B58312F384144642F692F77415770683361383345355A744D6C32626E4B485A48484E334B546E70586B5532776C743547376933463848784F65396F777175336B2B5332744B686F76486D4F5873302F4C66705174314E765135672F366B646C3267737977444D4432475058352F4250307844636B456645394F4C6C314C654A505A467478612F77445837563872413779526C774E54486F7461494E654153624676316461542F716F55366D6B61316D68637565686B5133347A682B4E78597261633344526130633838764835666A574F46636D50565046794849367235734D6F5856396F666A63733950736E73743937784F3735447334766A394F484E737372733250536B6D30614C424377745274466A3565414B646F5862736843766B2F6E306631666F4D514152684435366D7432336E2B636D444F375350645771537242637A6D5233494E70464A42776C4265587931674B697067644B32665156756D323572686F35623133413574414C515774674D49357A586C786646766C476E48677A5A2B4E686772473233524935385355614A6C71666B4F5334374661756D50466536626367754A75482B4D386671764C68637162747A3463536D654D396C396D463656717A7265546A774C5057675277774B646B42504D4B41726C67667947626F393957572F4C6664624A48724E4A2B734669644A47663841337863694643526456514B6B65767634304A7275435A6A394942754B5770753974624233633533397152536C55514D4B2F6F4A672B50542B50344F544F336B4C616748384C777452633343574F6436624A787A4B42444847754C624757376B514976624F556865376553532B692F384155692F4955356E526B624E504E4B564753666C6E644B374D7838497A6F396E5661323765465234574A4D774F2F4652546F714C786A3148533766572F78644A4C524F6D79326B75796E4F5075614176346A565646584C43543950654E6F474766724742725A523436424C573958516A327567674F6B6932752F592F6B6646344F4D346E48796D4F66455A4D46744762462F63734E632B635868734A456F53475733484C7961616E524A506A315A394B6156426E64617A54782B732F7A50707271703566656137786B39444F303661306D6965506D7864316F4A546D6E372B324C697353675A463658723664516D704F6F65584C73684C5253746A55583164354B3969764C3143683357523232316E3573654136696A394A78373031657850617046623478745833373755324E4578656A56426365646152392F4F4C6C303853586547766E4D6F6F6E47637869684C566F706B354E386549362B5035626A7A567674613234326362536D4F4F574D632B6C59503841644B714666504161467179654C34305370706A72516F33596A657557486F734638724B6C47566E43457A7032614B672F79757A737468346E3661736868566D44645A764A6B6B30444D68674D4E7162534B614F7462772F706D4E42342F52615A716731504E556B464F71373168777172516337506B2F38416C4435664A755834495577664A4F61355756327676696D65334B6649654B746C79314D617A306272716144557568614161644D73395943645950464F69506F74386430307863746E6E7479386245744F634433364D6D6B653039796F4949786C3467655063785267542B657A55646658357259304663434D4C6C5A4B2B7054542F5346444B767435326D71786D4E4334634B763972707971744D4E485A337745756F723541637134667074665A3353774A72427142542F7437614C34714F6C56514764662F6A7465677635362F492F2F4147477067463773772F416D434C487944487A444555716856696F386D376F7842374138752F7A3339476D4F364648507346644E634C475A4E796D6A6A5136736357665634636A3734782B396264506B415362336647523156646474336544675858567A496F68796967586D323153503243725377364A495542524E76312F397246355541422F4C45676A2B52394657696673362B4A3637694A4B4376526F52576C54346E2F33426F5569535233332F414B6E387166707265646B6F31507053632F546E46383742796D704A4149557361624251354B395454657A5A776370376736317562644D56596D6A48753766644A594B3235574E66306569795A7A3431664E782F4B63512B6B71735A376444325A53503066335A7A4B6843676C6C416E6469657639572F2F4146396B4C7A475732766A2B54704A663868706D764E4358446B547A7443714A312B71476A657441542B434343663158364470723942353571693138536A6B6D6D3870626D4975584173375672494934447443533479695956394E73424461776C4C79445162767756417172794B7A78717A786975554F55796D5849506B432B77433743565742615A6557683947566B6272734354544D6C7168426C50517855674872364B5A39614E4137656E6D7449777252517968326C6F6B734E434F6A65537577422B346164415661304A65665A436E3631772F48332F77416765735959346849387755745A36326769455079724D536679576134432F74494D4E4C464D6F4563444C3231724F736170794D4746576F72494D426D6D546871326B7842485434664C487A4172446B7564664D4D676D4A35646B7354372B527057706C6E77773156354C42576D695A3879693548585665414E58736F6B51556A354A786E326C6C766978526B75777652394F6374504C497A547A7070544F453959466831324C706F53565179537A6B4F534C4357652B4D76575677444E7958526B434C6749312F362B747457672F537336525A62594D62384E6C3434676B2F67675359546375584D5070436D696457466933396B5474764866484966483838644979644B6169726139387161444A70586D302F38417133766D534E4D2B685A556C56305235314572446B315A466F4D3233563061744453596C7A2B456B75554C44324B5147375245636D724F434169414770495A55566944315848542F414A4C35664A5756413451432F66743754694B726639536E61765844664A4B49684B3472305A30766D797550433755534466334A3561716C5A476D4A5A646C56643145762B58625A4F5A354841334C4C78445779397349376562456357656F5479466D793866364E33334D664A576151623261626B65714B3548456F6D316C34427659734B3735345656676643455274336C43414232397732645750582B526D506E3253307645396441366A3832664F7933746F666F486D32713876342B5972367442733852717958576C5A324A45787743796E55765A713869364E3541597959645931476972484A45676C4C767052444C59542F77434350544C4D324C525846674E784A6355744871783638575A4E4F6D4647764C4E7134367557434235395430724274524A49665752537A4D77446774556372777A38672B334C4E686F6650564B79745478444B712B32327251784B69705068334F44417356696E36714C544D4E566763437575644D4E566E43382F4E69744D54776237566A796732626D735851716D447878364F6670475439537462584F793651637738304373696F365A67466479327776514C79583357335A4E5A6146584966526154374D754B5441786E566D4B5170776448783450515A6C712B547256472F4E6F6C504C436937626A373748594A6E3032506D6F453552686E6C354B773969335964416852354B585873742F782B472F4B47632B33486274736148354D685257426D6B6C417739486D6B302F6E2B4F4445647154614E4749426D416E526571335839436765356979647633344B362B3162614B337A70365A6B3354647534754466385A5470704F596E3933664C567375336B4B6159615163744D7A6368436B654F32576F356C6B664E6A572B697A70506973393979746E4A574F444A6A587A30546D6A7A70354A6D7A554B6C4738682B62325565646B41506C362F2F4149364851412B6C507073656E70314B35773155496E4C43774651655953305956534F6B4F2B5235765A536B4B4944333659425A6B4E45564474467A6F59497371343273554669305A30676A6C506A6E334363587953665A35704775376D49623962544332305A685A72327A61644849775674575A4930656D396F5A4C5A4D4B4A6C4F6A646D6532344E62354E676173425169564A5A37546770487041414B753337644D437A723541456439394C3334394436675237636B6B623238667A4C44307835354842337734704A4E4645796A4B49444D56746343546A477A4D6F582F414C4635676C677A51776D4B6A6C4E4A56584744416A76626F325A726566473853734E4C7A584E5A6457464E4775506B4E426B2F493868794F6A4E4C56736F66755A54545041517A2B716B634F2F6C4F623476466C7A52524457414A702B7145667554347A48582F4148516B41394541487273482F77446F666F4932484B4A4D577767334B777168476A414472336C315A33574453776F617667793278557A735845537274447369454D416378594D4C704545416B6155305551634B74714F662B79592B6135546B4B543037636E6E6D464932692B6F5671745A316C6B57523576546132696E76795A78624278324C5A76754D5843635562724E796D656A7452306C4661674E3354784C6A77525562746768366B714539457550334854666E70462B6C39682F44394C75697A7A3744576F755836585145652F49706354712B3149754677536C58554F53316C63315A45316472556733474D78703157784F2B754A634C6465744638563855747A4F69572F6E62636A68343535353945593074576E4D616F4536476B305674586B2F374E787A4D6C4A55354B6B4C77706167797979624E2F32633173362B5A5847706C6E43563067416B414177516E6F443244727876304F75302F6B66386E723673706E76444D64634C61753474526A79444A70596C327342726D52684E4A63792B316E5475756E614C554C4575732B685839586B56787039627634626D4B716F4E624C5164487837347771347345506A2F4835386B3163497A79524E4F7A64467A6F33533033493037394774714F2B7252433235393873744D48443863637A70795049626C54547A48497A5A3650536C4B30486A306A45536D74575656434B4430697232542F4851556B39644B5439476937797A796E49754637556D435542716158326C4950584A57745A4D7952312F6279654B7170526E6361357555544C4A75477059644B73673072595731515347646F5978354E5043384A7955654D6D2F4338566257776D4871305A76587476553146475A6A6F2B336A74536B59353873357855596E6A786D75652B4B3867304C366556335A48736675625454396E363968436C5079782F502F4D2F77582F446549594838416A364F6D4E614851584133554C434C43666D76726A534C6432634C7831394D434C4B7A5478494345587251795676435A7A474F69717269716132415353667A6D4F734630444C793339687A37367835464A592F55324E45592B7431725452712F4F5747566B347648653368544A6C656563646D6A63666C666C74474F777A443454314547587271585A512F73554E3134737066397776665867696C3338756750486F6675565575544845723251687A4555572B70576A674E5A6363465479776453425545776E66322B75345770646E6C455A476B6143735379505252553857376C327342557462633035564535506B787648486D76766661576D324453586361726174554658335656304E64764A6170773433587976767A4F322F705A36654A6A77324C6C707974692F43457561467679575874674F682F71417049594F54356551596768523054332B62443539586D7A4E4B63553263576732304C4A5545546858624931414B4E5174675372426F37664968726F52334C6B525362655262515250623653536F697871395747632F77434C576E6A3330595A79784C42495872614931666350474461364E6535306D6345773078596366463461386C6C6D493862364F472F744A615076356655597A4A2F6A5A56596B4B6A4934554B565A52324738533351486C5667716F533355795353516F4A2B675273357A3346625A345366516855687750754D7069665345434D5251524C706C6C6A692B6F55495768653345706736656E774E744A5A7132314B63762B526E525753503779474A75433430352B52694E61352F2B6D4F693265574F6D544678466178633663642B717A313534636A6F6C4E4A54584277757A6C367849626D76376A57733673326D7663466F6650756A70502B6536663556546F666C66466D5058342F59495377486B41774E6C392B6E70317557644A6D7774693456674551477A5546317A725A3258335546337948506754437472386B684C44625350737A6B584D6930636D75745831705463752F4B6458413833384931386764504532314E39364D544E416246666B4D79363630315A654E6B4E6C492B35646A35754F5837666A73484838527849624C6F76797A65503062344F57374C793845725051414B785A2B68363338624D7173725662395A7A43654A43452F6C3646783266716A5835576262302B6A3869505A6D71543062634B4B6D327431414C4A444B4F5979395457774D6E69325938564B45674D64762F414477466761395977597850653856687971625059794E4C477338392F417551584A38523451614467354638574F656448627735626A5A52325A3864476D7A61754749313167444E4332626B755254427644707156373474504858634F647A59395049636C3763364962373944305A52367454504C525666597971566F705768666F6C523751523135717145474F622F414467314C56696A48313856417A384661542F3379725A554B7A77346473444E364D4B6161616A7270674A79565A49592F774245474E44457A355530374B6577463333344654343331796F33386E6834692F714F795048486A636E4635786B4C5674683257356A447757376D4E725A4F67797A2B372F754450474C6361645374706A4241356E342F6469326A4D64744A73516C4B6A514E565035364D337861595044702F48776678695A2B6F6C47374C416652357266796678565764446D783830385576565757396B4B79306139705A4E6B6438553548716C63557A2F4C713530313876726E594F6953775943307A456D5965585A543838693730347954563543767A3759756C764E654E774456786E49354B7969353875533138576E45636E7A4772584E6574555A32325A6D7545394F5A355A2F7744537048672F66347A48456E336F4174745068536273784137563269634D6B6E4D6771503257593641452B6743696A612F6D3363353833753864583575744A6C6F35585A6F4637564A547273344E4F68324134595361587148476A7371653030464653756F57475A756E733139386868617152615069467A44355638722B45374D584C446A4D4F362F4C636D76573752756878633876754D676B336869752F4E636A78714B463656633165504F783266626F5A373171475A754F2B4C366C32594E4E4E435458465362724F4662733367484666437268717A7151522F4A76554941516A646464356C4E5142575367616F55556E743537426A66514E626256545A47424F74507472706E6662384E50624B5243415633503249736854574A567A6B3678526C39506343524769585A6D4254786944356673346F6D65596344387566454550346A2F4146384F67414F2B672B5571747247714D784E6663394F324C42312B34663173436579515A2B494B7365782B65312F42364754336B2F354531673964484B303976313452347444695A614E6156786C4F5A4E74644D7045784E59515072352F514C497669465A5252542F364D524B71654A546975383141486C706A4D6739486F764A2F59656B4A3866776E725A6C38656E374959452B512B7241725638534B616B6A4E715A3158784138557167556F5743676C565A5452537A454155434B51714B712F5453326D7864776D56724569622B4D71374945665973476B574552513169772B334F633446314D37697A684C75676A694531527049374B346D457241714A2F584D50324F6D61537956516F38576D6E586F446E2B4F776939416E73756679783762382F5830476A725964465A755041396E7A576755426C58384D534F3250344A4142503450592F4830524D4E4A4C596754734C4C426732347043684B362B754E527A737363306B4F3430386F6466434E35305644473447794D37592F597A516C793033682F51672B7A2F727652744B65363171686D64664A696E63773035496F556A723943794B502B574238322F5879596D494E3634694D3549692B76395638522B61436A74542B4F2F77412B4A41365034363643672F67446F5856746C4241583859382B4C436F4B762F4D36625346563476327149784B442F72644D427248357A6C6B78474970646E3657574569674264766A664B582F4958552B7A376D44556E645649566F6C30596C4758396B3843416C5151504336654E55425A556F466467654A58654577746D3975636C614C4D6E736F442B516635495A44312B5A30386C492F42516A3866547A6C36303976427472317A4D7071354C4B596A467072687173336E364969456857667365446E454E594A68564D6F6345354C51726D556F586947317873575639726D54766678622B70735A63644B334C384879585066497550534B5835545239766F34656661306C6930517A5A4C79457270412B4E313544694E67656F6530747972536D624D6E37666A75504C6F70586A4B5A385048364B6C3164435733686D5A6D7448376E56587A6C4E326F4F35776449743130796C556D414E722F527935663841375A4C733363723554534176705663702B74545656324E34334B714773704A5165672F56352F303245683232533544366456643042417247757638415650527A634E634F5A3432572F4471517A76586935446B6D775A54564C32577A2B593075794F4574544D6E46696165417056553866616B533841736E4435394E73376A392F47762B4E5742412F4B42514649372F41423043564A2F31556E2B573769664F5558726C4E6164574B4D6E594A544F6958352B305779446F382B6349564A3064726F645546435533527846696D6B4E6C414E367861784743577A5A6E4F6C77523065333542776B3837364D6B37616B7A6D41342F6B633270632F474E6E6F6F4D394168483036726176576449577647637733457A4B4849396F6145737231744436385449474C55442B565337576F41714479424B2B586C4C7A4C465345646577766E30423131394D567A355141686543564C764C77787A77416C6C465343465779335A4F684C736744306871776965394E70713437505454585775504E62386951746A56654576736D563034726E782F6D574C456C644B35755635506D617070676C4B5A6D31616352793546793645764B6A7078304D5154513348547A6370666D4E45636174353536614D314C36716B4E314E59716C61516C4F444258705235524E4451446F7A5171476F414350466969396875336345646654417972676D304F504430705172496C3252615549493531435974566244364A6245567730656630496D52747469496531414E506261525A46516A4C62543777537377426F346E355439376977636D7A385669766852734F7A446C32484C782B43326A465374632B4357724C386634582B36636C773865526E7134374476352B334C59773872634F384A56343978396F786D396F2B64684B692B794E66536C54516971546373734C58746E6B724E2B744C536D6C534F6B5A67535156363237567A304F515734377A317A726D6C2B43794F6E41735231746D3179784E566831617369365646617877554F76726A33697538716B774771587A324A2B6D544E6B4A574B48344C354E6F6C7159515842504F656432386B6334427A5A64642B5162512B5556744458783752766E5354337A365A334F6A6A723576754D57724E34626E7554315A4D666772334A527842596C3270525176705A4232796E6F44746E554951774239696E736F44394A505365652B6F4D7962645A576C7379465656564976394267436349517156486C42386C584D38332B4C32304D726B36702F535855444C4A462F486456777337735A335844544C796776666B656234364D6F77577464457652656B736A4C335332366A79346A6A4D6933794154653748566D755A4A585A44573832593059614D452F44504B577A58576A454B4B795953656750384143307A423159442B4F67374D66345A664C736655694A6852634A5742756E715451624E2B7A724747564874386654477453446E675677536B316657646E314F57504D4B67454E597A4A5259386654364B69306A6C2B34347A36794E5977384E6D2B4234487A58563932724A6E52686C35625279562B51774C4F6D613061586A73344C44752B4C2F4831694C7674704C647A553536624A626258466E4B2B346B623674742B6F6C34357074313535346F6957597165784A576F737446582F774343736C736E5444734D5764424B61417A526A35536B697574384247635759697A4D7443576A65314767696C46704E346B4859466374545A34345159544F33324F44644272663153316F4E433573536B745175792F4950366D386C7334684D2F41787073343874486B74764C707847584C787649366154304C37345A5A3765524E6E572B673058654D387541396D376A7553344663776A68304C516E6E78727149706F68376B6F42544D576F786C34723556397450465A74514930326650354E5A454B763441456658584465334D7A722B6154724B49546C642B6D6A477A37492F4F755468524C6C576179646F6869346F35416E5A414C63776F4B493038737977314A51316D684159614A6E56724461524D703550352F66696F5279586558757930746B504B6274567030733034725857625876654F6D6A3639545231364D6A36596E50544C786D7A2F41413732334856617A3537555637444F6A7569545950444F697134614B4944343051497930734E4530647765764E714966425664544246364271566E6E4D71746C35466F39535766574B756D613742622F774372362B79426B336469746A526E4F7A4A326753357564707847626C38342F71686A77785953545A496D707761345945666D65446B526B4E78696E6558486E4F706166322B7A633761724A492B4E36497034334A78734D4756654C724F6D624B734D34673861552F4A4A2B4F75534E4F505252416C474B4A374C545A465A55387631644A426B714553336E2B7770354E4C6F2F62717A3946486F7974726A5A4A4D756D61496B7479733871746B73376F484C644149506F63336F553574326A3035543432743037637037454C45777164415175445A5835304241316C614D4A49772F79576C34592B4B7A6262386E57576A516B4955677253726D796F524C4E6F787A6179576871646A6B716D35646566466D7256627935506B615A75517A44753952307471584973584244556F73776C58703047496C536279624F3731536272584F30326D796771792F6B6876654E374F377A6A302B7A4365666C724D396B324D743358417A55745339457672566E564A36564B7A4D51595536613570656732475867367A596A59363966415934624E5070616242334E31476C4532355442723076757938302F4D6648754F333034376B4E6D6266435737487874444B576A566C343354726E7678643437303259384B34713578704B5173314A30314331323874326E4F37567A67617171706B7A6F77576F6D53577657692B585A7348587433666F7541657958386D5978756D394B7A76724E57684F7A75724A4162715437486144633150426B6C70426A7468302F5267436C56523465724B4E646158517145366361684770596D475A2F4B64585A4F2B6C57434D72386A3566514D2B4834627174583542586A42716246566552586A754B3548546F4B376D67317159412F47303063586835524C4F2F44364D766F3475656E636E4A635A48624B444774374F64584E5A577977526E514C35534833455548556F4E4D714637482B705A65685653797531464C4B516656355370325A6E624E6A6F7A614772706D4E71614F4F62324145434F7142654B783352574B3050565764594358637644637930506E4B6E4B6F76304543764A6771614A525167465A65522B57303448624C66386E356E6C613866706B2F4A342B5149744C54766843535577634C7477486A65467A5A6E754E4134666A617776734A354559645079572B5A327347436370495431444C4661416574706F5459656249336257636D6A50514B6A326279507464464C46697164455741387378326A3945533036516C7A765546756E793362687A4268503958306747664F6A4B746F5848785830633952754271796C6C56544E703647723946745849596F41646C323146664D65436A7962326F4F517863585869382B5837476E455078584661646646353837354B36566C562B522B5541304C4B2B6D2B4E4D6D486C3551723456527336377165656735786A2B6E5A6B6F7A2F6D645A6E32656F5650697267394F477937423130504C756B4B6541412F313851567A572F4A48533242657965785161433677677870365875614B66374B704345464C747A6F7556746B4C567357432F684E674D6153694C56345534476D7A2B553455722B69614D586F4878485648692B4334334373796772782B4D614530386C79546675614A61395A5A65523261625A37315068444F316B707865664931355A38342F784746486B312B353337617051466675395A38677041557273305438652F4565425A5A6F472F312F3144742B54354D6F4C53593941566C4E567178524E63645842565774435A51592F2F4148625752434930394142596A6D34493754436E744C624C75495343706E654D52483949527131657566666977323034614A784F546C65517A4E30733174576558542F6D324A6C3547764534754F692F686E5A2B53476A64786374736B46546A726968733042666137765A686E566D50595568375345772F2F424D6B38322F4866387261702F5052682F4C4A316935355177744E7575566A51434B447444576D73486C6C6D675745784747355962334F43732B474D782B585558584A6872326930543962657971587770732B765A4654676A7A484A3642776D7A486B2B4F38646E7A486C57745443312B537A49626F39396E434E70356A664F717042716A2B31366C7A546A4E7465616D6A4F6A344E557233726C6E36395456745A36414C5245736D547A596B4A4E4C684A4B614C3252324A326F414746494269314A684F6E6D5749314D7055464D6F30583972513339736A454F3230616730556D75644E49382B56454C6A4C357037516270316939726843766B71364B52724A323566386935534F336B43734A536E6C34334F4D75503152797235354974306C4C5568673430364C7569675070726A686F703545504F6635514D6547646B79674D416C74444656587A6F78566D50724C453070512F68695346396A4C2B5035362B6F72513272714B307152584D723575782B7157535A476F6353787365542F5158583157644F4A6F4958797341556C58535075684B70685964526247304767646E46636B614E4E725736386E6633497036386B6D574A43654936527643482B496B2B5249376469582F5031616F737056457066736B5A4A6E6469474330496D714F2F342F6A7A71577150456A38394C2F71664836434C77536C49597848425A326B7936514E6F6C4C6856506B41695654436B5375323863327930636D5846747741314E52413967346B6A69366554695247457066794356337568666F65534E6D594565637A524559394D6842483841644D522B4F2F782B53444D4845446A496D7036554379743565757858523679437048524B787241676A2F6B672F37426D487549685037594575345350444F7574634F647850597A70454570745868335578347849594E71367871414B6464585257355A5863685455344C724C504676424D4C71724C704B6D725757704B7864426F6B70366F5638694136392B412F61662F3439666A2F35374A4775554E3275536965624D782B337166486F68795543762F37682B56364262382F6A73482F6A2F514943764959795857516F347172474F6752336E373030336E3331314E5A6738414C497175747230444C7341653332777041527A2B45697574674B4C794E7678444A4E7A5479442B4B4D6678325235465737362F436B41396672313130434150716866767576696E675A55625168362F436748706C416273737057666637646A6F392F7A39646E62716161573836426837506E5A416A446B4E4C4C724C496A4164566D79736A794E664261364C536152706674325A746E41325061727A32564E6442743330564B4A4D6745734A55566976344A667764302F4938657639536678304366352F422B6F48694765732B77714375627837372F41466931706F2F2F41484A42446744736B6A792F424248594F4D7577466C6657564947346D7A3431356C67775443514536616766764C5738366D567A53454B696D49793558457369664731464E31747856494D4B516F517163506865685532386C6E724B57695A7979323038687730326D4D746E6F4A70626C4F50334D74474672654563735765355652514F4A534145386C455777354756564366635752554D615861332B4E5232716F514636714347382F782B51423076386C574656412B6836384F316C636F346B456A786D2B504C76586630586C6B4A6A6B566F732B32654534776E513232565469725035454D6B565976726763513861733731314E725439747948796E6B4D782B4E344E664438466D30685A636E70624933495A6A522F4E3031637677664563527331667936755A63514E4F667A5661386436364B51477158344C46706573324F30794D7357517974706A463256567062586B7A68327A736A6B6D553561576D7A427646423132625A3666417173384167314F415A68343135793945485A666658442B71576376444974464D41476A705035364D7063575658506E3851425742645556486F777631346953704F53346A6875462B5135462F763349546F4E315237636C4F49614C31764B575671306C7A6E4C2F4141696E496141756647574F6D756B7A2B326A355061736B2B686B4C63356544507965505066493869386E6E683572485769783852356A4E6244724156774862376E3767715842525A4546696B5070665A7661316F6F4F647533725A615657747A71366F502F55745262575370446D334A43454B737134596F764935653276724D744C6169727A346A4453594D325542772F71304E474C6D5257714A504B4D387A4657354239474745373978717137476147376E3876755276646E7469625170573742335A76546D4C79352B4F3475365574584E2F6B764E6736753961474E5A304254785270524B6C51694B766A46657832706E4575314A2B377A536C5A33743631526A592F5932574972554A74614B394955427679566A706F6D474A707171574249524551476A7A79506D3842725631772F744445644750794333714E636F4A37766B63754B546B2B56345170505069346A546C695579317A38725659376451706347564F597936636670704265564F4A6344504C43424C4E676E72394E7154634944664A6E7670754A44616C362F3435547A547052474B70564A326870656A5250696F6F4E57566E38452F4E414B6838342F335879725761595739726C6F595172432B664359374D39624D7A64595356666B676B6457654C30574C78687143417562624A485253506A4164735144596D6336326431317456484969723378376B4E4849386763746F47317057326F734A69756C644E6C69744B564863596B764F55394F76517A5472476B5A7174505332524A2F524C6D4F4D6F754E627059674D375570343953555175364D735742495A57426D69486F3939304449665551667064593731454430424E6F436A6A736373646142796E415572694B54367073654631466B32674D79575730304F6E437A49476671724B70724A6F63316D667545714A616A39434B61474E756E56666B49506E5361795A6D2B336B673853756A545368524A5477724E6B564C46676954684A45717651514564644B562B4647653036702F31526E4132445A59525656372F5948334B70587A502B762B48313338767948382F774276723263753949696D4D4B6B5235634D354649496835715967525042594172714D2F582F575835366B444631515174336F356876663156454C3469736F5A32364863744B4E5266576E6A70434F515877343944356159563161575869744D65504C7743616552785A4B36737870666A454931544B364D4D7443554B6E6B426D53725A37504572785465746C7252644634304C52476D2B65704C56716E3239624C6D75387955724B626871676C4A45744D686D4E467331743968434C4A7342394B5361714A7970566363356F6B636B616838465A4D53326945454A35473959364E696E7572764B7663567269545273324D312B3956624169517172726E7A66336B3538666E3338316772664B3974385277764836674861363674577558492F4B465738306E314F676E7965697574436372796147644F7A63762F41432B396C4C59732B625A4A58535555313173684A582B576E48696657344C2F414C69547155464F36716F70526D502B797635506D34476E75666535484873327449386F4C6E786E2B7450376751624744716A564857486B304E513943796776546A7163307463727A425639374F393371694E5430656F4E352F636C58666F6F4A386C4746525758513158746D31716C5338386233746F3061747562524449694B6B5978583754506D5356445337362F59506B2B41783645476A4674764C7655396A456D755A7972435379676C504B576F6F6D68644E3675796F2F2B694C354A2B6F4F73442B546C2B713259424452736E52723259376E503243506959656F593049356A6342596A4E79716652713947656E6B6E762F6731364A5842717A495A55396B4A6C776376654B7258687A5934384E50436E465A63517838616B3631335234314978626C694C55302F666374772B656D666A6432752B5756573436584C51355069666A38734D526777374F513331577333495A2B546B5873723171424E425271536A4D545A4234677452733573614B6F4874614E355670306F3047766A50316D473939704D39333270593662505445417A3952696C653670785447483262616C776F624A6E484872586A744B6E616858456C56564E30646773314D33785A69654B746C577366446E6669732B4D34482B3637754D7A59655232664B3763516D7A68746D556236342B4B616C48347A4458552B624C77334C366E665862354F764847634D4F666D6548346E6B2B53626B636E46656C4F646A616B773557314D46516C5357704F6E2F7039395574594B68395069766C31522F43616F535334596A366E457A484757314C5158674C45744B74506A573561506B326458614D417463594B5A3337684A766D7265355542556975695934464C2F77423170566A514B61315A626A706D76732F355170657639343533654D392B45357A6C4A767535486C654A326372697A4E4C584C5479323457747635766C7176467052706F3163396E66695944374A754F79385A48566439786F7472323542464456715A465A6C686B74466277414B4977315658784E613968696D53636D67555262567453346158727348366C6539785439442F6F7A7A53705567517630576B39796D3873583471414A53697538365852734C6C38484D71305377577758736A387936717576734B4E6D73766F4934734F475A666A50426574732B5834377858334C5073747131374D584531356D793143544D4936766B48462F4964454F4F575561564554785574394E6579646C356A492B536D6A5A657A38707267686177536F415549695572424B4A2F7778654C796B39575545305068362B2B2F57414F6A39427276314631374E71644A6B526D6C6E6C586B6F6773385372794F45466A5472572B6749447A363073396C5348574833304B7A534E7A724B737354617A3879574E63697775307A757A4E7430526754315A347634783859347147354834676372727A4F697A2F4150563053342F4F45797044466B7934396B424F2B3148304E6F466F36764C4A5273634E47546B634E4F6532326465346D6D557A71364F456A667A583849467455716E622F6A796D682F46656954305042757936713675526C362F4365754973666749446D596E646E4B3357583237394235627639746D42632F577166476B626A5342634C486977554D5669374A4C50762B6F69524863446D75432B6F7A6D5370486D37664C795866677979335A644C78346C4F646C4B3074584C3549624F4B32347A4F50476A4A6C354F71656E4863455A783972612B714E735047637A586B4267773670464D5774693148535559616B746E444F3743666C56646442536B4F2B69676561796F574B71416A466C2F4C4836727836746C384E73665474303062586E744A50473756694A79553432386C47313861786A5678717457476C69636F6F6C5A4B3563782B716645437969325973534B3769676B7A4C386C625262446D31374E66444C6E79525452666E754E58586D624376725363366368776E49727133614A526B516D544277357950724D354A757852765231765677624261394D55633774576A30526F615555467A6133646B533169376535516A6B576B4B416A7A61614369396771584865554E6D6655755A5A4571697A4B69457A416C493274616A3130446738594E723334624E3441596168574B314A72707150514D4C776D4B363051626B7A4C784B613344696376796E33776C782F793165513466354279334A63646269427A5638553866474E5A35344C7A2B4B3134542F7741795A38713649357559666B4E337944626B626A796D4D596F6367396D79304B2B32586B646D5830336B71643247563651396A68692F2F577A6973545544384C50306A7862382B5A3638544F4C6C643338394365494770716C61494C535375356C5869315748525658527A6C5152624C514E786172694F79684767363555464732496B7073444B42626F2F732F635638583544674E334B78796172387458644C6C346F754C5438626E794456486E62567258443859354747375046345A664357376B626174324932507331636A5A326F3947326D476834397A715A7870487861314C31627855396E78652B6561534C4D464C536C514A3243466E307661566C4A73456F2B726664322B6B4F624648393256644849664865546D704D474D364C5933325679742F76467442363563377975567759665951726A2B7456486E31765931544F67434D7A6156646532506930644C5445777A394D517141392B514250586C3050775070357046596757582F41466C4F437150352F774456674C65522F482F466A30435078305176382F514B2F7742427A6A6B79364E5131417A735A5664415A586458494261654971704136554F4E32322F6E2B526D2F47522F59586434446358664B7975646E776A4556395452476C344F44374A4F51542B535168597541422F77426D552B4A413637553966382F5661727358536967424C51536C466239554C4D676D2F774353663970314259447679566C412F4C64676E374E777761343349584E7972376F3235566B737A5646703130786C436C31714E417150524331537472715430587365614E33634554623831397A6D62557156685473677769704B61537073434B76626145632F6A784942684A6B37486636674D7848352F774356363748522B7056576C5634384D7A6D4545307547492F46432B6749732B2B67504A446E446B6638414D3244666A79422B6C34507043776A4B706956416930574D7A687033476A414756516739543735584F364D5741784E5670315765627A6C515643717977453452635976375553497475716E394B47685278352B47596C756D6272744E453744384B5144323336734F6A326A46442F50314E513977752F37416F3877726A734D684B55506B43414F6D38677652492F482F414748313668663446484630526C554F446C5245574158306C7A4A762F7741704A684E79676256707045656D424C41594A4265522F6133734370416474706855535038417238436852584E4E535374536577435157736F5A55586F2F7943472F412F5069442F42552F5862305A6B687070312F6D7A6B6B64425171794C426D62732F68534F67574A36386D37372F492B764669505542446866616F6C67477772624C567770504F6D5258586C4D6A34774C72345061534D514B44514776374730576979495A59422F65667975636B54325748377A59684248334C356B6A38304D7A4F4C416467737174526A54723864442B52313061775564535964757A53794B56582B586C4733756F6F49372F7741726841462F4866663436505948313955584E417379617647685243733863442B74417169692B6372714776423631344D4B7553767048496D624F4D4C425978486F596672584F6464677763522B4D36557661315A4D3642685755695031396A716A4E4A675748362F6B48775966736532384758383932585757555A3430524861415853515850554574596531514177386D37374237363843716767456B66546A5A374E7651757A4264345A6D654543446F583550535A6A6165695547716C584B4F68745761764C707338456D615456566B54574F4B425437524B3342566C524862787A37435974343238346E475974484762575852484A41355A5135516D7565364970635677446671686C57635A317053557973774657435A755044706E55644446776C655265664A34564F46744E573342386B3239304A73315539645A51576A6C6976716B5254715A736266734A73702B39446F455A5A6B614D74716A32393763313559365A6137514F37425751782B6147457071366E57744170544D43355862524D6E71635468313575634A71732F676376717575773558354963484A446B4F53314732673170624A545671624D452B32676455365A654D6F7457654769666361545753363554577038335439374F2F4677555868446A4D6F3963764A55755949366D637255766C544B313262776D636C6B576D657664427372656669536A424C76654D492F57634A6D6E336E727279644774316D2B3956582B42673666536E6F4E6A566746376E43662F41435771737A374B662B7A504C466F6D4A63337642724B474D5553317865746B514A545A557748715375433533682F6B6E424A7A66783679614F4F355464736B6D6D4F5A38353930642F4935745A6E4B7152354A4E656251546C7139556C657A7237336568636A366F363839632B31426F656E7378356339684270536A372F7A4952622F41427A5255563249642F454247515034414C30514F65644644376E4A356B4E70687237504A5052505468567949337A746136635765632B6B65634B637266746F794B555879304A4B58302F79556C746130765742786A50565A6C7134615A37366A6C735661343846713048586E3439633757777939322F75564555776B73426A713571436B5A52334C7045644171776E6F545177506E636F34473872414362366864527339627455556D6658555663744A575870697A5266396F46523542454242483562365458765A7248522B722B305438367A4B504D4A4D2F6A4D38614B4652514F46517738393835565430352F3879744C476D74464E2B3438384930733637416248776B53567566767355337A3049726B346B2B527A55354C6B4A306565334248487947615332507461584B795A59453334353072344B4B7A665132512B39764E706F445A31552F492F616E4A696E646D744F34704F7250325253306747556B58362F5A656A4A4650583456516750362F554F426F4D6C35396F3833364B6C4F46754D754C653545774C57657870646C315A61385145724A6E52696B774766314B78556E5059704764656E564C372B694D566E7742534474764661306E766B51763861356962612B51347A6C4E5673643354547866507479756369793677414C61702F77427A777374557A65784E7039683879617A634D50716A48496E4B344B352F54534D78706A352F2F542F51436B645756364D71566F7961434D7A334B6F464B3064507947437343483065334E57357A674E493573754F763676557236754C46396A687145366D4132305A67307A4C4C68617A4C67727A6C745662455551616D5438695256394A414E633677334F2F4A365A68797A344E30385747756E37724C6E7A683659732B544D4B56545137305A3651744F41435543555852514170537A732F313148687072444F394D696663497173394C2F73453276355252504253336C6E524B5054715156576153497168713973304632462F492F574F54637874624E3358504B786C4636477230576362707A56757479334752497A593451576757564C544C754242794C6A6A767232684E5361566E33766D4A75377A77767954682F6C2B54507965506D63664A356458747A77727838615968794C3564527A614A615962636D666265754C624F6D44553173677037496D53693555462B65577761506A6C394B4A6B575767736C57386F476A786B367156367644327743736746554374327173412F69776236496B32616661764C74306A6654666A31687873753539417863637436743764714D51354F43704B496F6F76354C2F64434D79356D72464A5478543371327871677559454A4D75483132466879453854675A4E764C364E4879446D4F524F39345A31776275523156793855654E314E465478456B784A5A564B49384E6B6446626530536D725A73725362794B58315465654A6F59475238386339507638414845562B35466C61716E54545471564F777242304D2B764A612B546679684B323331447A7957334E48472B7965562B78756A7847414367504536425236425A6B413877475A4E594D655967737347452F324532394F4D75756C6265555A57537A6C47344D72377473585A6554666A4E63745665516C714179375935302B31746F6F6F7A5936306A4F544931475133746D6C676437677A456132595569382F636772374F58496F3262374F6E467839733633444B3256644972654D366C3238553832456978556B6B4A333242305433794C2F616E794A7053444E6D51684A35614A316978755545306D433374394B57724E5A4543724B496E694768356F6F74704B4646425037743350534F44575246723650533138396A534B317A5A384F6D3138366A58473037504463427130445A6B323030497957666576466347396B6145754E71646C55504730624D4E456F6A38657452497A4230566E436A66627A656A39794534353635696C57636D6145767070525A36463172544F6D53644A3073434C6C5962307462736B75645176582B674742643870734D694959547244633049756C31745654357A6B3437584834624A67454D655348637347785544324646576C30647A66724959444F6D326552793376367375486262376A5878747447375254306E4A6650792B686E4776546A572F33504E7A48367A7A36484F582F41414E70785A42664C6E32317A67317A2F59306F4E4578336A75695A6B395379585052566278583768593030614E56307331394C3165307076525A656B4E49466B546F2F79434E7A2F6F4C484A4A4E317452504D4D7779705655326C7063733333444B68492F6E576F47664833696139656E63684A53694674376250444F31704F735841317769305757386371776E494851587147314D39615730583548564666453664466D5A672F57523246664F354C74582F414B707657575A5A32594B68615278305769614A475275794270793057646C4264652F46714A4F50696F37506450524A522B54363048362F55614A374A356F4761785A38792F70323476627A34344E632F426E6B6D746A6174354F764A72356658636D496F716C57626B56324464626D732B784F4B4A4E4E4C6C4A5877414953584852654A76573332493566544F39495A564F347968534F613176527372396E41736446774A33624F763353354736696D72546E523957697475342F5A706C4263577A4478375267594F4C5A58314B4A5565544F6B58545143664F305A3976534936492F78672F687935736C2B5647566A626E6B594F4F3239796F747346546345413038717A30537333777142787731726A755350704E5A58573258444B6D684977704F654B476B514C57642B71304D555A7A575A7553346E6B686C53584336755379745A6330467A36386D4B32564B6F7174577A7735476933787A54374D52706A6E6B30737A744E6E5A646D69586938464D2B7A506666766A71564E456A574D70556E423038774842616B6442516E736C75792F51444142562F43702F664C633046726452585A45573565707550454D6B6D76793543446E4257454B6A437936382F2F41455938357975327372354A7A5856783764584C72496556316637414D49686C34666A7A72334E6B6F46694A3965745830614B5A6B31474574463534365A4B74464C4E545856396C614A36336E6B764F4F686C59744468646C2F464B4F6A564C65627148416D507754315057364E344D36454B6F566D587A38652B7530426A663963725935304F685233514B4C576745303477383731326350472B384361776763594948774D5A53554E435379356C5466772B753032756B5965386A6B356359372B7268754B586C3975546D7345394864356164504374626D686C5259726F7A3465557476346A6A2B5A307466627836354D554D7054634E55784B72627A48425963574E3657553169346956466B6C56705A6D4C642B446662586E53385351435174616E79364A552B4950303231686E6D4557395344555974586C437A78776C39446E4D6141663055474A4C4D534E367A7479444F726F624B766A4B46632B43434A364E435449364D4B684A5757536A4D6C5379664B34622B476C6F7A63705A5772486673315974756A46692B326E7875694F546B37636A535732756268767471616C533065656E776A56616E516C646C7359664B59364C54792F51545A70686677784157674E5A6C66384147675A537139705164686B486B766B7042465139764661765A3757437332645156424D6961553546466C5455616D6A6847687653396A566344614A4A66456B565352535155755A5645426C555669446B5732557855527059306E71564B47626832387168353972656A736A2B4E5653696D6A493455754F32434E3050315030795350747973664A5737554B542F493838783962442F774354344479492F6E76382F6A2F68545644324344562F4E45573675796B323166456369746A305557746A643256645661356753534B505A476F327546787659524D57333346316634704F41756D5337496F53762B4E6D51437336667157566B444A525333694F77437242767970556464646E736A71316D387656634646596B357241674B48556E75585A42424473472F55667435734F6A2B65684F586C514A4F6F36386B594D4F596378754F493446594A4761387548392B566F64645A56734C376A3174705159773377724271375A436D574D724F6E457771364D6E374C64493742566678436C532F51432F6C69656A306E37646E7364674564413966566D564A434D2F79416954506B784C6553763548384B4F78312B333436495038414A2F3548304F5658796A62543230577733363072666C2B314D6E734B546A415378524C4234786C4F756B745A322B5271367674684E5248524F7A756F4B42494E58632F6D38314C4762654648575A55394267735A7637483976382F2B6F51554A42554F6F495839683339665566764B5871434A686D62782F3574526B4B4A5072722F73515648354B7333355058512B693068554A7A4E44323068454E524967336C546E5354624778655879777977716767616B59797136696B5A5A2F734C697971306136537345552B5A583658473871717A506433506B454273372B5A374964564B4B744351663558317346363636566A2F7752395664656D67614D474A4C326C6E554C3241732F2F6436356F65323848393078354879444D56554D434F69506744736D69773569505352454A5878536F71364F4B51545A46675947784C472F77543063696A70526E553749794B7564764F6E4553746F44456B4645336F4D6471546E534971536B337353314F767779686C5874696677415764564866386C67503559416C7373624E375169697470774156414F314661412B705146364C414657616E6965776973515141534A65796B57654D5674374C4B7039507073587278685A6A6650523337447156556F3231773579316D51634841697142635033422F61692B4D51366D59425A52754D71546D31484869703266705967456541692F344B7230563857667862763841355058585A50613664597076544D6A4E354C6D6F4B7A594832456D766D72465435446F6C50313858702B4F2B7A2B515479596C734D7563565876414A64474675414861475556316E5871672B696C44584D5667306568646A4F497A6379794934724D57366F774F71646C384C42625335335A624B794262497947315652524B316E6E6E724A4844576D7A6C6242446566636E5A6B70374A75384F6C536C4748797153744F6D6531717A685279525A56396A79722F414F3153504F66344A362F786B6F5741622F4B684138697135536C306F6B56676A49314A316B78745A7A4B70375A5A564D68585750626178505847736F6A536942646F7179775A5A6D2B367541725932343455686D4A6643646D2F4D5331724761534B2B755958545375623261323541786C6D5A576C4E796C4E4A7A786D3774585A47447172755858327157346E6B35546A6C543273746A3439515A485A354E4556765362545877556F76546C4337752F67735A7A5038416B44466D325263396572355A357474645670426132696B7A2B575A715778513537704D754278693173735776622F37706A52616D67416D686F6862782B70454D437032444C31433677557637484C786644547944446E58426D3052304A68793473635844614675314E326D6A30736D626A696133397776484962563167655756323745717336637676726330526E6672796C656E706566724E47524946342B4E485759556D61465150575A6C72416C53372B77486A483545654D744D3430776572796A6650342F5A73644B717A55646D3065346B3351334232686D334E4D2B34545A464545305A354D713156653554364770374A555144466A4969564970464557666E4F48343352374C4A624F32795737464B466652577534327574757336583135664C7237655478444D61534446765865697045327135744E35475656616764314873624F38615339534870566159735642506658736453796B66743065696B3944364672326832675A365A746B665058544A5874387579596379493137512F4E624D676F49354F31662F414B514550754167577957554544553836414254773847636832616F7A742F627A664B563969764270347463596C6D394D343347624B6F6553423345573963765A4B6A544D306561704955364B73446354426D7A70456C35706162426F7930585168364D6E52384A6663456B6E31734350466A327239424F6A34716B2F4A597953305564456553345A456E526238306446726669354A6C5153656B4D313456384C71713644794336783564447449614F614638574E3035703736774B6E587A6A2F7744367A523359657459312B33537253724B6870517555526A617A466E7065644A70344C2F6B38584577537036352F7A5A314430704D67717845702F7176544B56375A695742365873674172312F7A2B41666F6376783370695978697A7053475748544C59576A397A565657695743473342474330583274414C53684664514A6B4B684B673278596A424845686A52436F526D4B64664C7254584B6B2F476A34547139774A7836587A586731656B6D3036513036504C524B70547945765657566B634955743575703462646B6A61634B36466B394A426835452B353171532B637A5478496670614C2F6B436853354938514F6839644E614C3054584D6F57445050356B2F67426D4B63526F394162326F67336C413050736C55565047436D464C5934594336322B774A6477323371346B7274397734395676487035586661324C69382B486A593558577272786F30635A6867426F543766545478314C447A6A544F7152494D3164336F2B6E33305A57487A51754F4352313744585775704C6661746F6C4453396C6D47627869576757654B716C2F77414B53564D36394D416A654E6A2F414256486F30703430394D5A684E6930715774364B6B326A2F647A31555A707A732B307130704C4B68704D456F3233696538554B2F6B4343432B4573793131313837314C626C724F4E4F4732336C2B537A774A6B68785476796C363576764E72624E373056705470665866586E304856316B78547139632B6531394F6A486E7A61644D67504D6369503762484C4664474250655856466C6C55776C4357574E463833444C41576C4F586D396B7559563959394239775836592B2F38415279733778774258352F35326B5675387A66352F4D31614B41766D424E766D424635527A427A715646366130756F69796A516B6C31615A497745764B4B447573436D585A31674C356E346C6D54347A772F48636946354858506C3848796A4E79584B386C53484F594E412B517479687666426832556B73754B79366A78574A4B4B7449634E6E41305373636E6C6558684E7958317064767563666E67304975567070614F6C4D786C6E377A765373374F62504439336A6D304175534236694170643576347635536A79776E30476A4465714E306C32564E30395A536E6E34357345584C34495374465736426F532B754C4B7963334C6738793659415A36786845437552775336633675516B4C5852384670386750416648666C4E4E6E796A4F712F65635A666C4D43363844697561565676782F47614D6D32456732764E4D2F63676857303567573837524C483035446E477A705458687A35736A56455958474C6B70537337646C4A432B6F3267316A31304167567951656C3642483157356C346E76624E716D794D50517351413532417A35367579516D745235326C485766426A46776F6246714D435A6D46315A3143672B4B6849385A70756C52457273444275764A3543624A486A4F56303638517A636C45766E696B736E726A6F6659635A4C50484D624C62513153714F3562334937655A6F3566793748304D47705746726567556E375661366A4E325765514D31724E6A756345497653422F74704B7946535651394B5A725365655A377A4A6E6A38372F72336A7A4D34344E54652F3136746B3032366C5247646E3838386E524E77722F554271724C4744456F34414C465A6C76714B676777347242365930773549396E35663476674C77336350613146594B64584638394F6C4C55396C4A4D50734478627A522F664B694B747239653148694C423138685476707652316565725A4F746E385A5A57795A58382B6C444C344D75795A434B6E544D66442F5474764141644577326B6649384A7861512B772B513271756B6844464C2F385970445050627970766A757962444E6C572B544D6A2F51577751744E56597766635A6A37506B72765851764836565A774F6E6C3250794E34564F445A7875473931384479416A6C72544B74575A4C4F32334F735A30764F4E4D73315A444F657162457657586954646B4B566C5877764E725458736C624C7055564148696C546D6158715074413752627378583953796E794136664C504F50505079433948794E586D65497775626B4E736C416B4153505431597274776C574E35475755485947436C784D306C696C584557795270655130727747736D364C6B4F345A2B77444F387238543474754D33316E794F2F692B517A4A536263666F2B57635666526A3851665A5452786D623464695847656C616950586C2F51303246425A3246704A504C5A6F79364977704D5564335874343858705A5871514345462F3776537A6A6F2F67547A6C7568312B7944794E567654556C6444357242696D4A424C47623343486739477537656C6E4F6F43323036516C3479325571367568334479713746634A4F327334746A32676571797165544A79656A4644457643636F6A50757A766F5373647865503347485A7A6D5559387570646D34444C5A742F48637270724E755665573573686872536D474E596B4E4B426231396B374C344F716C57516F564E5556696632503766383964442F6A722F414A4852586D356866754B393477734742544E7A624170754B374C4C464B7255755342795371774C3735534C375354442F594C2B412F4647746A32346736776D7567716E2F69707A6474326538654D6565376E4E756E6A4C4A794363576D6D727679716648754B314E4456727835706165506E79322F6B3976782F5634434E7450477A303865362F6663744F6D69744C785035436F6738756B4256664D6F7A6856616A442F6277485954792F34596A3664656A54724E566D4D327A454A543233716238576136484D5756316A30695065476F53545A4245646E4E74516B4746736749505A644E4D5833684B2B6175612F6E52475346775079486C7547333870777335386B324779664B7134786C357A6D4B365037707771366558347A4930384E6D79635870357A376D326662727963586A35584E675A39754C6B4259616448314D386A534B57556F43724953517669335647587A36364A374937416E324434722B41423330617437764A784862386967744A754B5A6E667766367A6961454152674F79716B47425865507949314338716D4D6835516F747563766C4E3834794F496751505353426F68342B7561534E73546A6171734E64524468466C5661506754766B4534756B36333138686852304F544E75744659302B784E6D6F30354B7A637733566B31446D2F486A3474344542765A346B6B41416E6F4F3358376679472F68767833394967685A59726D77447642462B59697465554758515A33734F667452432B5549586A6634417376747176684A674D52514D66417969496C526768596853786A6156533035687663477A7334417573786270476563362F3436566E544B7A41484F363162327A61624878566942302B74664B6C5A654B4A52432B6A4F72457A4A43655643794E324134364A2F514149362B512F6766556C6571436C6D30624332303236316D5A5841696B7569644E595634707074664A4C3750767A724F67516849452B573634634F2B4A4E4D783455573056566D6B64437230576C682B50576149656A30475A49436A6E6F486F4271466C38522B4F7568306638416A2B5A6B686434414149595A4C4B542B7863614C316D46495034486A4F616B45646B6B6E79372B6851612F2F414742674A41573051497371556A4F3332475642696A394D734870706A79795664513076686E2F68654E524F36454B6F2F77417A344B6F786F35794571703631636E7963307053592F77434F676C58514B50782B416648792F77446773542F4858313376734377485956454B79542F73415564724D772F354C4B4655487674662F61652F7275594D4F5669456930512F78466A4D466C486B652F487969696B492F7744594B766B7052374C2F41424E6A665554524F75717555313958363258776C564B326936504E6D6D775872792F42422F496D522B5650663437424C642F3866555535707162447155396D4372485170506241794D575371642F67672B70464A50665442682F3237675158643052795A422F574D4A6C45793646426446462F4F634E444F556C3130446B7776684D345663646151734D47713463764F7170614C72686D4B2B427773326E775375536A4B47676F564B416A3864683432422F6A2B65346748763841674D652B76342B69755832556E746B6A4D4E485972465662787051535379306E4D3967686A4B7A4F762F486B6F483137576B4556724C614B72706C4B6A65676B3352483557504C7038722F316E3961712F6B4F576B446B38364C615458436D3838657179325A2F314C6834783538625455547A5761614479716B4859746E412F4242414A4A5479412F6278627469462F2F4836674E383139486C74684E712B4254376D612B4772316E727A4C4D423151722B50487941385357362F325052554A2F566D7236327176476278504C3552584F767464724330646A4F77746B545A38354E7A41486B796C2F4272355268795061626D6349455633386C5A5A336D3171786E4B6B326C5A533069724564725252332F4950384545662F7743752F77447455316363306A66556A70584E34705531587677496F78576245663841424C41673964666A386E2B506F33784B43316D58784171303639626355764A63722B4E71323179363734466C5043346457717A775236476345354C7655716D5239773453744C51774B752B4967676A3630733834313761522B344F645444376C775853615772507A44423370574B414F765149386A2B4648366B6A735746307650686C643570663136486A357561646F4F6C64544E6C6C5A3043554C425355483675774A4866695756516F4F52484A58344770796F745334456765386D334A756572796F5757443232784F686E76514E455458794C47644E3476516971515468464832496852576370424B765478536C56627279484841476B715367757248724F554A4E556E4A704A43717A6D523358304B376C744E645633656C7275374254766254376F5579776433444D354F7231686D39726F3765544C507075783331344B33354A4B676A782B75582F414744654D47457147586F6D624E7662467953544773777348676367435749626F6C63614D66352F6F67597079476B513242413174354E4E354D5A4D62366A722B5857317345643630712B61764A63524E74434262613334534A317A55666B684C4C6B476A504E514366484E6149552F757A4F6E6B6A66667457486F4D706876536F3955473567305253333867357875496638416B396557623966392B6C38665950347457354844343573496B2F68764E4B7A7030576176304756457A59684B753958726A6236486778374552557872577438626C4A52446A66785563654E703445437746704934504A634D3076795843624E46466242786D712B747A6F6C563538686E7863527279536C587A7250395365597673556F386E576E48533868523449724E57665A396C6932794D352B7A5A444E6C597A5648706C3874536133614E4F6A344F37346336457233334A717A4A367451462B7367635036675732626A496D4354796C6F4B45387257662F6C616249476C59767275766C643032345668715034307855792B5A356B79486D6D303558663247364D326D7556766975546B2F6A3345797761655262546F342F4A70545876676A344279417A5531557579724A36736936644636347370562F435667693061556B6E5577636A644C615661655A545A68436373305645314F6E53526E787A426274564C313730336F3359584E4451782F594C3942745868506C68696B37554772644D58416B6832564A52586F6D3145536A71476664467071785269626D6268624653754D5235626C726A52506A376D4C797A52486B2F4B4C4C3744704C6B4E45637A5330577066796F3148677431317941444E59726D526733707A555373567A684750556D72566D616B724F31576C4A614E476165664C6E6161793073327751746E386F496A5A5936505A4B382B7162725331625972342B32436E504574314C3851655538472F324E69586E7650374877326D564A4B4F3530686172633967363056686436725A78614F6A343349465943612F4F6C352B5656725346444B3045394B595059534E5230546A4458666C704464446B6153325730516A61656744516A51554D704D6F793837776355614E414A354C52303055546F7049486861766F79576B6374384F643565707174544C464A3157396646707976517161625A4E41766D4461337464592B436D7A2B4B6447493252395658336E6A4643655A65634F693079514B38347656752B6C58357159625233616143695131796978536C4C364F364B7A706A59772F736C39773546356C563441636441305535546E5866623631394732314471537965636263686973706861656E654E5768593854584A79754C695578615A38527876435A2B596E544C704847636D37704B63586A6B5A546F4E466A4668536139356F416B314E574C6D63555A3259424A2B5949724A554871704D306679474D643642594A6A526368494630385A66745351637A4A723477705967616F51335170482F42656C695778445972725639794B45676F7A3751557143454C48752B6E4F6B743857354162396E4534316C665465657A467462374E396566663939676E546A31354C52574F325A307978344C5A6379346F636A4B476964644D5634612B6A567276656C794843546C757679413070496151495254775477424867306F53526B614D6E5363714E4F7335537437475A785257592F556A6B6654643671615A337A77543042706C734873562B6879546A4F5A54505A6F6F44754E6544756C4C62764B486934774C684D5878487748533671574555307A465930775346425274374A7A7566683972573376686878466C3361657776464A7869613838317A356A584A704E4830566A6E76417731306771536E735A4A4D6B4E65612B6552484B6A724E6A3158577942586D317248546F6E6444357A6B786D454941514E516558732F4B67656658616D65422F4837444A3331476E74393331536C386E3543437130314773563948354F6E6F644D4259556D5A364167354642784551526870534674462B5355715A55455146733650466D7A7A5963744C537338787A4C4E4B32304E484B384B5141564C466C6C5030554D765A4179644379724D6F6A4D70674F2B6A6F596A696D39596F664E6A324F6E442B5861457343727177374148384479422F6E366B2F5739457A4C532B64507274486C396F355755573542665141307835532B536C4C33676F523031475A6A56517551305376374B7879556D5758484C79357A43756B41316E4B33496F2F4675412B456838664379305A65507479572F6C394357466E77523137647874702B31313633755A7773374D6B755079744C506B566B6D6B30587A38795674642B5275327A6B6142524C4E43515A434571597A364D6F563961714F7045443849716A762F4A51505A76615548647357496A38645A764A617659724362354B55644E6D707A654453317252682B435757467264436932764C4639414A63594C322B69765533536C327363773576557249704C47353265577A52666A58686D686154704A44526C354A586A52696F7079546367743572436C4B6478686B544B707457535739676F7462366947764D6F52795044387130344D4851642F367156364238782B74435157594F354A4448384E414452796250636D702B674D566E4D30306F6E6B4D6B39596148594541697634517264756B694B682F6C504945797978765A53573166364B2B4C4D787730465570467274496F70526863374E393866486174634E646D70782B54524B6D3277395344523672574F5831353435784A6C42577561614C73386B6678695971794C4B584E6E68526B7A744766685635426F704266476E6B792F765356765948505A382B6D414162382F723050717839582F6A753931327248566157375A2B6347434978337A413052767176514372574E5366355838684F2F647937614D493973553363726E4779767430377566633566565A32464B6166366C63556138654D504738686B6F79536C66616C4D69625A75636473387277744A4550746C2F6B5A476C396D387056766E7A76466456334C52663431755931616D724F35536C6648796651336B574A632B7A7956752F2B77492F50386B67392F6931655A2F3841485437673058304D6C642F674F6449315762566967696A4750696F46506861376D687A7877786F3873556B4330465257475864546A697442696144345A396E61654D4E7878596A74756E6A47584678577A3542446838504E3872767A3557356E624765642B5434322B565A354D4F4F38703548793539676E485848594E456E7A53305A767433643048612F467456704E56744756413030526B535A2F4C4A324135645A7A4A37424938534350342F4A2F34723770507845332B625A3664795070736E584A457A315149393879586A4569324B6263356E795A7958326931534643717954467143315730534B49744A4168654F637870767068307658726331583439384C33664936386278664A5A676E434F2B4E63326669334C6A4C38702B575A764535636C633651433850797645624D55495A386D6A4A71796E4E4C4242577778576458445653375A317369766D6479376475566F526F7A5A536F42414B41696F7035646B677155385344356778786E34462B7A2B6756633163746A35367345555A375061307A344732702B353966734F73506F44436636723059766C6C4E5A4B3739546A49387048766C5A473232552B56306F4B2F503437634A48453851617A61584A61694F59314B4B2F32336C4254506B7A6938632B717161494630315770466F7637554D6F335548332F52576678545771466D315A77716C434376744C4E2B523043436967412B5037667366352F4150315372333338614E586A6F5836306C766D6942576531634C6D3949397A4755704D6851696E7A416F63416C523855344656514B49375A4E6C5238683134343042517877596C4547666A6679413868773244505A6167347359796869456F7A5368542B3351426F706761656C4D794A494F6738454E6E6F317257566F55746E45577831465761424E6A592B4D3264564937396E546B7A486D475767566C3636494444766F392F56532F50786A652B6A6849744A554C6F786C374E756C4856476C45667A4973575656693857324A4651744A6C53305A3662426E594E43767637382B325247754A786C396B7A326A6C497A77765246716F655A71716855506A354B4736374E423266795365756832534F756953596E342B2B68515130565A586E4C7679636636585A5156416E2B716A73425637627856514F7A2F7835616E793173675A7636526D5964412B644F716F58445533485368436A51424C39557559527437585462537A5779757A415078393652543055592B6E6C396B52517046566C2B533541716E77314F53697454796C494173436B7567426F494949364A37412F774333582F5030562F734F6E5373614F2B587339457035554B6C5046356C536655435351784A5051372F6A72366D376650482B6C305368654E626E4144737A6B79474447796973735155376D4F4149734F4B2F36526262533242314B366F336E32496A6A46735A6369584371757670466C5333797243736A52733273697477696A2F436641757A4F4F75332F7742522F485150386B6E3866556D443472746A57796A546D43466579674E6950487950536A75592F77425343663841352F672F6E3867434338705A6B4475697247777455317134307969592F4C59337A4C34434B627A76625A55642B474978423146316336345336524769326A74516E7A51767036743873784651446E3039414944334F4A4A3736482F38662B4F7A2F482F2F4142754C38563545744B6B37343038714E346E325838314B6E70572F47666F666A7673442B4F2F3549412B6A66572B566A70333759484D4E3775786F5949684A6E73615A686B46486373634E2B4E715252796D55466B34713039593877356C742B334778723555634544436D6B6172503566675363532B6659774D793441575036673964494F372F414A483866742B502F774333386E75793377336B6275376A5268446F77593974634B664D6E7942555149505A5665696639656A2B44333050344E3535702B466B71494E6C5931714C76614169612B6C5864734A6F7662334231546A30556546495938414C65386C32425038416E3961785A4354474A6E77576B6E7A4469546F612F774272764C6D665149584F7055725077373747672B5866382F6E7272382F7A2F4974562B4A3874546A4A3542707769494C462F4B6D67732F644177375032352F436B6E6F646E2B502F32446F542B4E743056394871583965744D465A366F367843696E4D7457495767584F4D756A5476474E34724D56656F347058324461425A4657576C6D48614F52536254576F42487245736C62346E357A785358625465504A6F30786E56526E6E6D4A3841614D6632625650706979686A2B702F503146742B43386848476D4364654D724D47684C615075535063584A4C6961792F494862414B61644548766F482B4743673634314E4A73584F7A394D6543573976466D4F6636546F49516B556C726158777676714F7130464A4E49793971634750542B6C457979434C696A727671586C4C43576D6E7A764236536732664A2F39454B744A736B43336658586D667537762F7A2B794C54774A3650514948532B7639502B5A69664A6A3864634F6567795476467569437737384D666D7836424238724E33332B336B663248474D7136463376526547334C617834336A674E7A38712B7172734A4E4D7646716E546F504E5734566C4537712F6B4F2F794A79306767635973695A743337526A45666E664669697830636A38774B4E3471424E734C414665714B66323249784159412F372F414A362F50342F58363748774C6C6171576E2F597735516B6B3035464741492F49444C4A782B562F422F786A384872722F6E36416464356A5152746D577048535A704278706E6D4C4570536F746C6171586C6C667A5262624541567149622B50307563374C437068584432777174764147737256465872705236506E504556762F68586D4C4C59546B673253792B774E482F497A745365352B677A676A78436B654851502F494A4166422B566E6A5150586A4A744E6C667A6C6F3230386C596742536C4D794C3269742B704A50354149386576707457666A6D74597676414D6B4670644A7A6E7147573273644D794A656D52763470774F53564F6B61345375796C6A336759366668536D433232365156634A435631664430586863712B7235506B75686F2F47347675415843557078484836505A6D542F314A33597645753555425A73513369503969782F50314D764362352B614E7946337A7936377A7074764766735251555A56456E5542612F35435048742F79704B392B58314A6E2B4E366A4A2B6937584C51314C485177544973436453497930397767374D335236624E3575396F364D7479547759357149485142614152666E6268616A313638356B45366D485A536277337A4C45337062546B4E584B6D616C654F347842474B7368684F49413656592B505244412B31543473796741437533783358534C4E50544B58536F435139667A3630632B50697331376E354F536B2F496543425A426A34682F6F7055656B31697377566D6538567A6F61656B46656E70436E374C705235434B5831524D79676B7433504C7A356F2B7355797269396756583038697668544B4E4572626E6A38396D3538527A454B5168716A546C5A555346337A4D7238524F6556304851704C4F6E456B75386B705A73744E4F6E52624A704B6163316F756844697166483951485874794838394F4375672B5A436867652F50736679507830522F492F6A386D532F494279532B38784B4F7677364A4862443436376D412B3730727473564C5562444133754B69374B4D2F6B6743422F6F70554143326D4949345377664E6F4942727162567442556539484F353876476164443665517159354D2B55545846782B64577A4E396E4B4F565778317A4757624D637275732B7174583772556A3044624E74744D4F62677446724C342F5A4953584959477849655346764C706B494A6238674146664838487476705565752F37676A72533967556D346A773269332F6E6D65674C56456476484755317374666B365437654B2B7179446B61444B686F7871713131495373344E6133577836574E4336716A782F7741366E6C7439336C585A6E72526B6C594C2B5A58574649616373724A6E3259744C34303378585670785432786A756E336B312B32444D476D6634705779566D37355848684B70444768487361644135482B4C3865586D762F482F414C4F7575695047766D6C4D4D3554566E694372754A74694D682F6C32695142704E4672597471744762786A57514158443943587378575A554678513745737065737374656369766856656335503535683279334C486A3957615772516D6E524D316A553030495642306F3457586F7261636B467077536555737147554A546E4B61525A50696C344F6A2F63796377526B684D417A6B4A737636436757524E476B504A4A73535047624665767A39466D36385A312B42584C394E623648716A535354562F4C49513254614E3352656830463138724F70556746314730527647364F5264595A525264567958314C4F30317A736A6E38747452377050547A45637378517245636A5A304E566431566A4930565548676A2F3655437035654B7A49364B386E685641452F484B6167647344456548537153784473485A6D38756742366C37424A4C44727850653838633265535763307A6A596465493556443069515A73474C3532445353387451386A5A466B474F705952417634536344564F6B5165466B75536A56544F2B7A34685935562B5934752F4A4D3136426131525A617165776F385A73355A61667632727343504572324230537A483866583356786135644359335344454C352B79532B48514B6C694150483866782F4838456B2F774144726F6B43383066585258744233565336444972522F5370425A3651652B4B31492B425830326C4869734254494F694B6A5267373241743379314251732B6E634E5A5146476D4C6970313061494B7151616372474C536F316F7066384177524C69787A4D6C66555264763853565573792B544F42526C555072557853596A2F6A4C736A6533794C504C39704143616549422F6477784A646678324F757A33395846782F6979743858356D2B654A38316F51462B31793452466C30326D6263326D753362496171714D387A3951592B734E6A6D792B4C58656A6B2B5A6F616A724779775754497136696C5A2B5363726B34343835785049543137615A755030413657615676626F474C6A34787236626A37574D455775497444506C6C5930342B5644745A4B587A3150634A7874577478746F585552315657336F716F5A566D744E515A437756714D376E4B77386C704F5957674C52646C4A502F32513D3D227D7D5D7D5D2C226E616D65223A226D61726D616C6164652E6C65646765722E7472616E73666572227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: marmalade.ledger.transfer, args cannot be displayed on Ledger", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | WARNING : Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?", - "9 | Transaction hash : TX4rKze978k7T-MAzSJfTTHy1WCwAK8yi4RhZfAQzQE", - "10 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: marmalade.ledger.transfer, args cannot be displayed on Ledger", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | WARNING : Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?", - "9 | Transaction hash : TX4rKze978k7T-MAzSJfTTHy1WCwAK8yi4RhZfAQzQE", - "10 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] } ] \ No newline at end of file From 268ef653d4751ade2d6056ef2426d0748e5ce201 Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Fri, 16 Aug 2024 07:52:47 +0200 Subject: [PATCH 09/34] Modularize items files --- CMakeLists.txt | 1 + app/src/items.c | 248 ++--------------------------------------- app/src/items.h | 22 +--- app/src/items_defs.h | 36 ++++++ app/src/items_format.c | 234 ++++++++++++++++++++++++++++++++++++++ app/src/items_format.h | 38 +++++++ 6 files changed, 321 insertions(+), 258 deletions(-) create mode 100644 app/src/items_defs.h create mode 100644 app/src/items_format.c create mode 100644 app/src/items_format.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a337b1e..675db23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,6 +145,7 @@ file(GLOB_RECURSE LIB_SRC #### ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/items.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/items_format.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/crypto_helper.c ${CMAKE_CURRENT_SOURCE_DIR}/app/src/json/json_parser.c diff --git a/app/src/items.c b/app/src/items.c index 088ce8f..12c7ecc 100644 --- a/app/src/items.c +++ b/app/src/items.c @@ -16,22 +16,10 @@ ********************************************************************************/ #include "crypto_helper.h" #include "items.h" +#include "items_format.h" #include "parser_impl.h" #include -static items_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_signingToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_requiringToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_gasToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen); -static items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen); static items_error_t items_storeSigningTransaction(uint8_t *items_idx); static items_error_t items_storeNetwork(uint8_t *items_idx); static items_error_t items_storeRequiringCapabilities(uint8_t *items_idx); @@ -51,7 +39,7 @@ static items_error_t items_storeCrossTransferItem(parsed_json_t *json_all, uint1 static items_error_t items_storeRotateItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); static items_error_t items_storeUnknownItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); -#define CURR_ITEM_TOKEN item_array.items[items_idx].json_token_index +#define MAX_ITEM_LENGTH_TO_DISPLAY 1000 // TODO : Check other apps to find this number item_array_t item_array; @@ -62,7 +50,7 @@ void items_initItems() { MEMZERO(&item_array, sizeof(item_array_t)); for (uint8_t i = 0; i < sizeof(item_array.items) / sizeof(item_array.items[0]); i++) { - item_array.items[i].can_display = true; + item_array.items[i].can_display = bool_true; } } @@ -387,8 +375,8 @@ static items_error_t items_storeTransferItem(parsed_json_t *json_all, uint16_t t (*unknown_capabitilies)++; item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; - if (num_of_args > 5) { - item_array.items[items_idx].can_display = false; + if (num_of_args > 5 || json_all->tokens[token_index].end - json_all->tokens[token_index].start > MAX_ITEM_LENGTH_TO_DISPLAY) { + item_array.items[items_idx].can_display = bool_false; } } @@ -412,8 +400,8 @@ static items_error_t items_storeCrossTransferItem(parsed_json_t *json_all, uint1 (*unknown_capabitilies)++; item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; - if (num_of_args > 5) { - item_array.items[items_idx].can_display = false; + if (num_of_args > 5 || json_all->tokens[token_index].end - json_all->tokens[token_index].start > MAX_ITEM_LENGTH_TO_DISPLAY) { + item_array.items[items_idx].can_display = bool_false; } } @@ -436,8 +424,8 @@ static items_error_t items_storeRotateItem(parsed_json_t *json_all, uint16_t tra (*unknown_capabitilies)++; item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; - if (num_of_args > 5) { - item_array.items[items_idx].can_display = false; + if (num_of_args > 5 || json_all->tokens[token_index].end - json_all->tokens[token_index].start > MAX_ITEM_LENGTH_TO_DISPLAY) { + item_array.items[items_idx].can_display = bool_false; } } @@ -456,223 +444,9 @@ static items_error_t items_storeUnknownItem(parsed_json_t *json_all, uint16_t tr (*unknown_capabitilies)++; item_array.toString[items_idx] = items_unknownCapabilityToDisplayString; - if (num_of_args > 5) { - item_array.items[items_idx].can_display = false; + if (num_of_args > 5 || json_all->tokens[token_index].end - json_all->tokens[token_index].start > MAX_ITEM_LENGTH_TO_DISPLAY) { + item_array.items[items_idx].can_display = bool_false; } return items_ok; -} - -static items_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - uint16_t item_token_index = item.json_token_index; - - *outValLen = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; - snprintf(outVal, *outValLen, "%s", json_all.buffer + json_all.tokens[item_token_index].start); - - return parser_ok; -} - -static items_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = 1; - snprintf(outVal, *outValLen, " "); - return parser_ok; -} - -static items_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = sizeof(WARNING_TEXT); - snprintf(outVal, *outValLen, WARNING_TEXT); - return parser_ok; -} - -static items_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = sizeof(CAUTION_TEXT); - snprintf(outVal, *outValLen, CAUTION_TEXT); - return parser_ok; -} - -static items_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = sizeof(TX_TOO_LARGE_TEXT); - snprintf(outVal, *outValLen, TX_TOO_LARGE_TEXT); - return parser_ok; -} - -static items_error_t items_signingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = sizeof("Transaction"); - snprintf(outVal, *outValLen, "Transaction"); - return parser_ok; -} - -static items_error_t items_requiringToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = sizeof("Capabilities"); - snprintf(outVal, *outValLen, "Capabilities"); - return parser_ok; -} - -static items_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { - char amount[50]; - uint8_t amount_len = 0; - char to[65]; - uint8_t to_len = 0; - char from[65]; - uint8_t from_len = 0; - uint16_t token_index = 0; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - uint16_t item_token_index = item.json_token_index; - - object_get_value(&json_all, item_token_index, "args", &token_index); - - parser_arrayElementToString(token_index, 0, from, &from_len); - - parser_arrayElementToString(token_index, 1, to, &to_len); - - parser_arrayElementToString(token_index, 2, amount, &amount_len); - - *outValLen = amount_len + from_len + to_len + sizeof(" from ") + sizeof(" to ") + 4 * sizeof("\""); - snprintf(outVal, *outValLen, "%s from \"%s\" to \"%s\"", amount, from, to); - - return parser_ok; -} - -static items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { - char amount[50]; - uint8_t amount_len = 0; - char to[65]; - uint8_t to_len = 0; - char from[65]; - uint8_t from_len = 0; - char chain[3]; - uint8_t chain_len = 0; - uint16_t token_index = 0; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - uint16_t item_token_index = item.json_token_index; - - object_get_value(&json_all, item_token_index, "args", &token_index); - - parser_arrayElementToString(token_index, 0, from, &from_len); - - parser_arrayElementToString(token_index, 1, to, &to_len); - - parser_arrayElementToString(token_index, 2, amount, &amount_len); - - parser_arrayElementToString(token_index, 3, chain, &chain_len); - - *outValLen = amount_len + from_len + to_len + chain_len + sizeof("Cross-chain ") + sizeof(" from ") + sizeof(" to ") + 6 * sizeof("\"") + sizeof(" to chain "); - snprintf(outVal, *outValLen, "Cross-chain %s from \"%s\" to \"%s\" to chain \"%s\"", amount, from, to, chain); - - return parser_ok; -} - -static items_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { - uint16_t token_index = 0; - uint16_t item_token_index = item.json_token_index; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - - object_get_value(&json_all, item_token_index, "args", &token_index); - array_get_nth_element(&json_all, token_index, 0, &token_index); - - *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("\"\""); - snprintf(outVal, *outValLen, "\"%s\"", json_all.buffer + json_all.tokens[token_index].start); - - return parser_ok; -} - -static items_error_t items_gasToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { - char gasLimit[10]; - uint8_t gasLimit_len = 0; - char gasPrice[64]; - uint8_t gasPrice_len = 0; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - uint16_t item_token_index = item.json_token_index; - uint16_t meta_token_index = item_token_index; - - parser_getJsonValue(&item_token_index, JSON_GAS_LIMIT); - gasLimit_len = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; - snprintf(gasLimit, gasLimit_len, "%s", json_all.buffer + json_all.tokens[item_token_index].start); - - item_token_index = meta_token_index; - parser_getJsonValue(&item_token_index, JSON_GAS_PRICE); - gasPrice_len = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; - snprintf(gasPrice, gasPrice_len, "%s", json_all.buffer + json_all.tokens[item_token_index].start); - - *outValLen = gasLimit_len + gasPrice_len + sizeof("at most ") + sizeof(" at price "); - snprintf(outVal, *outValLen, "at most %s at price %s", gasLimit, gasPrice); - - return parser_ok; -} - -static items_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { - *outValLen = sizeof(base64_hash); - snprintf(outVal, *outValLen, "%s", base64_hash); - return parser_ok; -} - -static items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { - uint16_t token_index = 0; - uint16_t args_count = 0; - uint8_t len = 0; - uint8_t outVal_idx= 0; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; - uint16_t item_token_index = item.json_token_index; - - object_get_value(&json_all, item_token_index, "name", &token_index); - len = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("name: "); - snprintf(outVal, len, "name: %s", json_all.buffer + json_all.tokens[token_index].start); - outVal_idx += len; - - // Remove null terminator - outVal[outVal_idx - 1] = ','; - - // Add space - outVal[outVal_idx] = ' '; - outVal_idx++; - - if (!item.can_display) { - len = sizeof("args cannot be displayed on Ledger"); - snprintf(outVal + outVal_idx, len, "args cannot be displayed on Ledger"); - outVal_idx += len; - return parser_ok; - } - - object_get_value(&json_all, item_token_index, "args", &token_index); - array_get_element_count(&json_all, token_index, &args_count); - - - if (args_count) { - uint16_t args_token_index = 0; - for (uint8_t i = 0; i < args_count - 1; i++) { - array_get_nth_element(&json_all, token_index, i, &args_token_index); - if (json_all.tokens[args_token_index].type == JSMN_STRING) { - // Strings go in between double quotes - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\","); - snprintf(outVal + outVal_idx, len, "arg %d: \"%s\",", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); - } else { - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: ,"); - snprintf(outVal + outVal_idx, len, "arg %d: %s,", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); - } - outVal_idx += len; - - // Remove null terminator - outVal[outVal_idx - 1] = ' '; - } - - // Last arg (without comma) - array_get_nth_element(&json_all, token_index, args_count - 1, &args_token_index); - if (json_all.tokens[args_token_index].type == JSMN_STRING) { - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\""); - snprintf(outVal + outVal_idx, len, "arg %d: \"%s\"", args_count, json_all.buffer + json_all.tokens[args_token_index].start); - } else { - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: "); - snprintf(outVal + outVal_idx, len, "arg %d: %s", args_count, json_all.buffer + json_all.tokens[args_token_index].start); - } - outVal_idx += len; - } else { - len = sizeof("no args"); - snprintf(outVal + outVal_idx, len, "no args"); - outVal_idx += len; - } - - *outValLen = outVal_idx; - - return parser_ok; } \ No newline at end of file diff --git a/app/src/items.h b/app/src/items.h index 71ef436..c700793 100644 --- a/app/src/items.h +++ b/app/src/items.h @@ -19,27 +19,7 @@ #include "zxtypes.h" #include "parser_common.h" #include "json_parser.h" - -#define WARNING_TEXT "UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds." -#define CAUTION_TEXT "'meta' field of transaction not recognized" -#define TX_TOO_LARGE_TEXT "Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?" - -typedef struct { - char key[25]; - uint16_t json_token_index; - bool can_display; -} item_t; - -typedef enum { - items_ok, - items_error, -} items_error_t; - -typedef struct { - item_t items[20]; - uint8_t numOfItems; - items_error_t (*toString[20])(item_t item, char *outVal, uint16_t *outValLen); -} item_array_t; +#include "items_defs.h" void items_initItems(); void items_storeItems(); diff --git a/app/src/items_defs.h b/app/src/items_defs.h new file mode 100644 index 0000000..8eae797 --- /dev/null +++ b/app/src/items_defs.h @@ -0,0 +1,36 @@ +/******************************************************************************* + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#pragma once + +#include +#include "zxtypes.h" + +typedef struct { + char key[25]; + uint16_t json_token_index; + bool_t can_display; +} item_t; + +typedef enum { + items_ok, + items_error, +} items_error_t; + +typedef struct { + item_t items[20]; + uint8_t numOfItems; + items_error_t (*toString[20])(item_t item, char *outVal, uint16_t *outValLen); +} item_array_t; diff --git a/app/src/items_format.c b/app/src/items_format.c new file mode 100644 index 0000000..a434bc8 --- /dev/null +++ b/app/src/items_format.c @@ -0,0 +1,234 @@ +/******************************************************************************* + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ + +#include "items_format.h" +#include "parser.h" + +extern char base64_hash[44]; + +items_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t item_token_index = item.json_token_index; + + *outValLen = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; + snprintf(outVal, *outValLen, "%s", json_all.buffer + json_all.tokens[item_token_index].start); + + return items_ok; +} + +items_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = 1; + snprintf(outVal, *outValLen, " "); + return items_ok; +} + +items_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof(WARNING_TEXT); + snprintf(outVal, *outValLen, WARNING_TEXT); + return items_ok; +} + +items_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof(CAUTION_TEXT); + snprintf(outVal, *outValLen, CAUTION_TEXT); + return items_ok; +} + +items_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof(TX_TOO_LARGE_TEXT); + snprintf(outVal, *outValLen, TX_TOO_LARGE_TEXT); + return items_ok; +} + +items_error_t items_signingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof("Transaction"); + snprintf(outVal, *outValLen, "Transaction"); + return items_ok; +} + +items_error_t items_requiringToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof("Capabilities"); + snprintf(outVal, *outValLen, "Capabilities"); + return items_ok; +} + +items_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { + char amount[50]; + uint8_t amount_len = 0; + char to[65]; + uint8_t to_len = 0; + char from[65]; + uint8_t from_len = 0; + uint16_t token_index = 0; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t item_token_index = item.json_token_index; + + object_get_value(&json_all, item_token_index, "args", &token_index); + + parser_arrayElementToString(token_index, 0, from, &from_len); + + parser_arrayElementToString(token_index, 1, to, &to_len); + + parser_arrayElementToString(token_index, 2, amount, &amount_len); + + *outValLen = amount_len + from_len + to_len + sizeof(" from ") + sizeof(" to ") + 4 * sizeof("\""); + snprintf(outVal, *outValLen, "%s from \"%s\" to \"%s\"", amount, from, to); + + return items_ok; +} + +items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { + char amount[50]; + uint8_t amount_len = 0; + char to[65]; + uint8_t to_len = 0; + char from[65]; + uint8_t from_len = 0; + char chain[3]; + uint8_t chain_len = 0; + uint16_t token_index = 0; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t item_token_index = item.json_token_index; + + object_get_value(&json_all, item_token_index, "args", &token_index); + + parser_arrayElementToString(token_index, 0, from, &from_len); + + parser_arrayElementToString(token_index, 1, to, &to_len); + + parser_arrayElementToString(token_index, 2, amount, &amount_len); + + parser_arrayElementToString(token_index, 3, chain, &chain_len); + + *outValLen = amount_len + from_len + to_len + chain_len + sizeof("Cross-chain ") + sizeof(" from ") + sizeof(" to ") + 6 * sizeof("\"") + sizeof(" to chain "); + snprintf(outVal, *outValLen, "Cross-chain %s from \"%s\" to \"%s\" to chain \"%s\"", amount, from, to, chain); + + return items_ok; +} + +items_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { + uint16_t token_index = 0; + uint16_t item_token_index = item.json_token_index; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + + object_get_value(&json_all, item_token_index, "args", &token_index); + array_get_nth_element(&json_all, token_index, 0, &token_index); + + *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("\"\""); + snprintf(outVal, *outValLen, "\"%s\"", json_all.buffer + json_all.tokens[token_index].start); + + return items_ok; +} + +items_error_t items_gasToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + char gasLimit[10]; + uint8_t gasLimit_len = 0; + char gasPrice[64]; + uint8_t gasPrice_len = 0; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t item_token_index = item.json_token_index; + uint16_t meta_token_index = item_token_index; + + parser_getJsonValue(&item_token_index, JSON_GAS_LIMIT); + gasLimit_len = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; + snprintf(gasLimit, gasLimit_len, "%s", json_all.buffer + json_all.tokens[item_token_index].start); + + item_token_index = meta_token_index; + parser_getJsonValue(&item_token_index, JSON_GAS_PRICE); + gasPrice_len = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; + snprintf(gasPrice, gasPrice_len, "%s", json_all.buffer + json_all.tokens[item_token_index].start); + + *outValLen = gasLimit_len + gasPrice_len + sizeof("at most ") + sizeof(" at price "); + snprintf(outVal, *outValLen, "at most %s at price %s", gasLimit, gasPrice); + + return items_ok; +} + +items_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { + *outValLen = sizeof(base64_hash); + snprintf(outVal, *outValLen, "%s", base64_hash); + return items_ok; +} + +items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { + uint16_t token_index = 0; + uint16_t args_count = 0; + uint8_t len = 0; + uint8_t outVal_idx= 0; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + uint16_t item_token_index = item.json_token_index; + + object_get_value(&json_all, item_token_index, "name", &token_index); + len = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("name: "); + snprintf(outVal, len, "name: %s", json_all.buffer + json_all.tokens[token_index].start); + outVal_idx += len; + + // Remove null terminator + outVal[outVal_idx - 1] = ','; + + // Add space + outVal[outVal_idx] = ' '; + outVal_idx++; + + if (item.can_display == bool_false) { + len = sizeof("args cannot be displayed on Ledger"); + snprintf(outVal + outVal_idx, len, "args cannot be displayed on Ledger"); + outVal_idx += len; + return items_ok; + } + + object_get_value(&json_all, item_token_index, "args", &token_index); + array_get_element_count(&json_all, token_index, &args_count); + + + if (args_count) { + uint16_t args_token_index = 0; + for (uint8_t i = 0; i < args_count - 1; i++) { + array_get_nth_element(&json_all, token_index, i, &args_token_index); + if (json_all.tokens[args_token_index].type == JSMN_STRING) { + // Strings go in between double quotes + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\","); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\",", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); + } else { + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: ,"); + snprintf(outVal + outVal_idx, len, "arg %d: %s,", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); + } + outVal_idx += len; + + // Remove null terminator + outVal[outVal_idx - 1] = ' '; + } + + // Last arg (without comma) + array_get_nth_element(&json_all, token_index, args_count - 1, &args_token_index); + if (json_all.tokens[args_token_index].type == JSMN_STRING) { + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\""); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\"", args_count, json_all.buffer + json_all.tokens[args_token_index].start); + } else { + len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: "); + snprintf(outVal + outVal_idx, len, "arg %d: %s", args_count, json_all.buffer + json_all.tokens[args_token_index].start); + } + outVal_idx += len; + } else { + len = sizeof("no args"); + snprintf(outVal + outVal_idx, len, "no args"); + outVal_idx += len; + } + + *outValLen = outVal_idx; + + return items_ok; +} \ No newline at end of file diff --git a/app/src/items_format.h b/app/src/items_format.h new file mode 100644 index 0000000..7776c0e --- /dev/null +++ b/app/src/items_format.h @@ -0,0 +1,38 @@ +/******************************************************************************* + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#pragma once + +#include +#include "zxtypes.h" +#include "items_defs.h" + +#define WARNING_TEXT "UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds." +#define CAUTION_TEXT "'meta' field of transaction not recognized" +#define TX_TOO_LARGE_TEXT "Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?" + +items_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_nothingToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_warningToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_cautionToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_txTooLargeToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_signingToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_requiringToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_gasToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen); From 9c0d73d3d76f5f2751ef75951e6739b6f309cb29 Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Fri, 16 Aug 2024 09:52:50 +0200 Subject: [PATCH 10/34] Page test vectors --- tests/testcases.json | 1972 +++++++++++++++++++++++++----------------- 1 file changed, 1192 insertions(+), 780 deletions(-) diff --git a/tests/testcases.json b/tests/testcases.json index 31dec81..aa7d461 100644 --- a/tests/testcases.json +++ b/tests/testcases.json @@ -1,782 +1,1194 @@ [ - { - "index": 0, - "name": "Simple_transfer", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uixsNZgk", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 1, - "name": "Gas_with_args", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B312C747275652C6E756C6C5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Unknown Capability 1 : name: coin.GAS, arg 1: 1, arg 2: true, arg 3: null", - "5 | Transfer 1 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-6", - "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Unknown Capability 1 : name: coin.GAS, arg 1: 1, arg 2: true, arg 3: null", - "5 | Transfer 1 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-6", - "8 | Transaction hash : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8OLyco", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 2, - "name": "Network_null", - "blob": "7B226E6574776F726B4964223A6E756C6C2C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | Requiring : Capabilities", - "2 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "3 | Paying Gas : ", - "4 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "5 | On Chain : 0", - "6 | Using Gas : at most 600 at price 1.0e-5", - "7 | Transaction hash : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb-Cn8w", - "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | Requiring : Capabilities", - "2 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "3 | Paying Gas : ", - "4 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "5 | On Chain : 0", - "6 | Using Gas : at most 600 at price 1.0e-5", - "7 | Transaction hash : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb-Cn8w", - "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 3, - "name": "Transfer_with_decimal_amount", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C7B22646563696D616C223A223132333435363738392E30313233343536373839227D5D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Paying Gas : ", - "5 | Transfer 1 : {\"decimal\":\"123456789.0123456789\"} from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-6", - "8 | Transaction hash : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4bAvk4", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Paying Gas : ", - "5 | Transfer 1 : {\"decimal\":\"123456789.0123456789\"} from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-6", - "8 | Transaction hash : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4bAvk4", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 4, - "name": "Simple_transfer_create", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B22726563702D6B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637225D7D7D2C22636F6465223A2228636F696E2E7472616E736665722D637265617465205C22653461316232393830633038366334353531616237643231343863663536653937373463363465623836663739356435666438336533396363666432656336365C22205C22383735653434393365313963383732313538336266623436663037363866313032363665626363613333633461306530346263303939613730343461393066375C222028726561642D6B6579736574205C22726563702D6B735C222920342E393833343034383829227D7D2C227369676E657273223A5B7B227075624B6579223A2265346131623239383063303836633435353161623764323134386366353665393737346336346562383666373935643566643833653339636366643265633636222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2265346131623239383063303836633435353161623764323134386366353665393737346336346562383666373935643566643833653339636366643265633636222C2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637222C342E39383334303438385D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393134322C2274746C223A32383830302C226761734C696D6974223A36303030302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2265346131623239383063303836633435353161623764323134386366353665393737346336346562383666373935643566643833653339636366643265633636227D2C226E6F6E6365223A225C22313633343030393135363934335C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : e4a1b2980c086c4551ab7d2148cf56e9774c64eb86f795d5fd83e39ccfd2ec66", - "4 | Paying Gas : ", - "5 | Transfer 1 : 4.98340488 from \"e4a1b2980c086c4551ab7d2148cf56e9774c64eb86f795d5fd83e39ccfd2ec66\" to \"875e4493e19c8721583bfb46f0768f10266ebcca33c4a0e04bc099a7044a90f7\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 60000 at price 1.0e-6", - "8 | Transaction hash : SrjHkjfzLHLiOS-5_lcZvLOhiU42NynfAfezMzbeXsw", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : e4a1b2980c086c4551ab7d2148cf56e9774c64eb86f795d5fd83e39ccfd2ec66", - "4 | Paying Gas : ", - "5 | Transfer 1 : 4.98340488 from \"e4a1b2980c086c4551ab7d2148cf56e9774c64eb86f795d5fd83e39ccfd2ec66\" to \"875e4493e19c8721583bfb46f0768f10266ebcca33c4a0e04bc099a7044a90f7\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 60000 at price 1.0e-6", - "8 | Transaction hash : SrjHkjfzLHLiOS-5_lcZvLOhiU42NynfAfezMzbeXsw", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 5, - "name": "Second_transfer_create", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B22726563702D6B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637225D7D7D2C22636F6465223A2228636F696E2E7472616E736665722D637265617465205C22373335383066666233653563613938353934343233393564346331636230626633616134653732343635363463653934336237616535303862336565376330335C22205C22383735653434393365313963383732313538336266623436663037363866313032363665626363613333633461306530346263303939613730343461393066375C222028726561642D6B6579736574205C22726563702D6B735C222920342E383930393334353529227D7D2C227369676E657273223A5B7B227075624B6579223A2237333538306666623365356361393835393434323339356434633163623062663361613465373234363536346365393433623761653530386233656537633033222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2237333538306666623365356361393835393434323339356434633163623062663361613465373234363536346365393433623761653530386233656537633033222C2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637222C342E38393039333435355D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393039382C2274746C223A32383830302C226761734C696D6974223A36303030302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2237333538306666623365356361393835393434323339356434633163623062663361613465373234363536346365393433623761653530386233656537633033227D2C226E6F6E6365223A225C22313633343030393131333037335C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 73580ffb3e5ca9859442395d4c1cb0bf3aa4e7246564ce943b7ae508b3ee7c03", - "4 | Paying Gas : ", - "5 | Transfer 1 : 4.89093455 from \"73580ffb3e5ca9859442395d4c1cb0bf3aa4e7246564ce943b7ae508b3ee7c03\" to \"875e4493e19c8721583bfb46f0768f10266ebcca33c4a0e04bc099a7044a90f7\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 60000 at price 1.0e-6", - "8 | Transaction hash : pJsk0-vgbqfzOBFc4zHtFMSMa0aCZpXBZ_QQFxox1-k", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 73580ffb3e5ca9859442395d4c1cb0bf3aa4e7246564ce943b7ae508b3ee7c03", - "4 | Paying Gas : ", - "5 | Transfer 1 : 4.89093455 from \"73580ffb3e5ca9859442395d4c1cb0bf3aa4e7246564ce943b7ae508b3ee7c03\" to \"875e4493e19c8721583bfb46f0768f10266ebcca33c4a0e04bc099a7044a90f7\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 60000 at price 1.0e-6", - "8 | Transaction hash : pJsk0-vgbqfzOBFc4zHtFMSMa0aCZpXBZ_QQFxox1-k", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 6, - "name": "Transfer_with_2_args", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432225D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: coin.TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew7VnMY", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: coin.TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew7VnMY", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 7, - "name": "Rotate_transaction", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933225D7D7D2C22636F6465223A2228636F696E2E726F74617465205C22643333303064323834663462636662633931353535313834656630323661333536653537666630666139376235653663393833303735303839326364333039335C222028726561642D6B6579736574205C226B735C222929227D7D2C227369676E657273223A5B7B227075624B6579223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933225D2C226E616D65223A22636F696E2E524F54415445227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633333436363736342C2274746C223A32383830302C226761734C696D6974223A313530302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663227D2C226E6F6E6365223A225C22313633333436363736345C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 81b4511b257fb975dace13e823c257c17ac6a695da65f91b6036d6e1429268fc", - "4 | Paying Gas : ", - "5 | Rotate for account : \"d3300d284f4bcfbc91555184ef026a356e57ff0fa97b5e6c9830750892cd3093\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 1500 at price 1.0e-5", - "8 | Transaction hash : WQImvdxCaI7U5Qy2U_3Mxoa3i-Lp-PyNu9aZNtXclHo", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 81b4511b257fb975dace13e823c257c17ac6a695da65f91b6036d6e1429268fc", - "4 | Paying Gas : ", - "5 | Rotate for account : \"d3300d284f4bcfbc91555184ef026a356e57ff0fa97b5e6c9830750892cd3093\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 1500 at price 1.0e-5", - "8 | Transaction hash : WQImvdxCaI7U5Qy2U_3Mxoa3i-Lp-PyNu9aZNtXclHo", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 8, - "name": "Rotate_with_args", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933225D7D7D2C22636F6465223A2228636F696E2E726F74617465205C22643333303064323834663462636662633931353535313834656630323661333536653537666630666139376235653663393833303735303839326364333039335C222028726561642D6B6579736574205C226B735C222929227D7D2C227369676E657273223A5B7B227075624B6579223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933222C6E756C6C5D2C226E616D65223A22636F696E2E524F54415445227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633333436363736342C2274746C223A32383830302C226761734C696D6974223A313530302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663227D2C226E6F6E6365223A225C22313633333436363736345C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 81b4511b257fb975dace13e823c257c17ac6a695da65f91b6036d6e1429268fc", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: coin.ROTATE, arg 1: \"d3300d284f4bcfbc91555184ef026a356e57ff0fa97b5e6c9830750892cd3093\", arg 2: null", - "6 | On Chain : 0", - "7 | Using Gas : at most 1500 at price 1.0e-5", - "8 | Transaction hash : Rr78KvlVRiX59dDOqZFaK9vgW6GzgMss13p67yGOkN4", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 81b4511b257fb975dace13e823c257c17ac6a695da65f91b6036d6e1429268fc", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: coin.ROTATE, arg 1: \"d3300d284f4bcfbc91555184ef026a356e57ff0fa97b5e6c9830750892cd3093\", arg 2: null", - "6 | On Chain : 0", - "7 | Using Gas : at most 1500 at price 1.0e-5", - "8 | Transaction hash : Rr78KvlVRiX59dDOqZFaK9vgW6GzgMss13p67yGOkN4", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 9, - "name": "Transaction_with_no_capabilities", - "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A22286E6F742D636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Unscoped Signer : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "5 | WARNING : UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds.", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : EsF-vcYfXYn8-NpYIvBcOMYCfUxiV6wxECU5FWNFz5g", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Unscoped Signer : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "5 | WARNING : UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds.", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : EsF-vcYfXYn8-NpYIvBcOMYCfUxiV6wxECU5FWNFz5g", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 10, - "name": "Transaction_with_clist_null", - "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A22286E6F742D636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A6E756C6C7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Unscoped Signer : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "5 | WARNING : UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds.", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : 0j8JyVmew5_ibulW2WO-OXb9j5woNPX1T9Y1BQQvmFM", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Unscoped Signer : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "5 | WARNING : UNSAFE TRANSACTION. This transaction's code was not recognized and does not limit capabilities for all signers. Signing this transaction may make arbitrary actions on the chain including loss of all funds.", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : 0j8JyVmew5_ibulW2WO-OXb9j5woNPX1T9Y1BQQvmFM", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 11, - "name": "k_account_names", - "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2264666462333839363931393534343439303633376330666432663334663862663434363364343136666264393135393930633861313336623161393730636135225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D637265617465205C226B3A623961633363613535353963633666333934656130653331633131626531366566643663366666363830346239386365376365653439366263636139363136345C22205C226B3A646664623338393639313935343434393036333763306664326633346638626634343633643431366662643931353939306338613133366231613937306361355C222028726561642D6B6579736574205C226B735C222920322E3029227D7D2C227369676E657273223A5B7B22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E53464552222C2261726773223A5B226B3A62396163336361353535396363366633393465613065333163313162653136656664366336666636383034623938636537636565343936626363613936313634222C226B3A64666462333839363931393534343439303633376330666432663334663862663434363364343136666264393135393930633861313336623161393730636135222C325D7D5D2C227075624B6579223A2262396163336361353535396363366633393465613065333163313162653136656664366336666636383034623938636537636565343936626363613936313634227D5D2C226D657461223A7B226372656174696F6E54696D65223A313634313333313232302C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A226B3A62396163336361353535396363366633393465613065333163313162653136656664366336666636383034623938636537636565343936626363613936313634227D2C226E6F6E6365223A225C225C5C5C22323032322D30312D30345432313A32313A32302E3434305A5C5C5C225C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : b9ac3ca5559cc6f394ea0e31c11be16efd6c6ff6804b98ce7cee496bcca96164", - "4 | Paying Gas : ", - "5 | Transfer 1 : 2 from \"k:b9ac3ca5559cc6f394ea0e31c11be16efd6c6ff6804b98ce7cee496bcca96164\" to \"k:dfdb3896919544490637c0fd2f34f8bf4463d416fbd915990c8a136b1a970ca5\"", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : 9VlNQ6wmY5UpfOcazQNGpBZDt9Cd_sl_DO0POpiBDvU", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : b9ac3ca5559cc6f394ea0e31c11be16efd6c6ff6804b98ce7cee496bcca96164", - "4 | Paying Gas : ", - "5 | Transfer 1 : 2 from \"k:b9ac3ca5559cc6f394ea0e31c11be16efd6c6ff6804b98ce7cee496bcca96164\" to \"k:dfdb3896919544490637c0fd2f34f8bf4463d416fbd915990c8a136b1a970ca5\"", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : 9VlNQ6wmY5UpfOcazQNGpBZDt9Cd_sl_DO0POpiBDvU", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 12, - "name": "basic_cross_chain", - "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E534645525F58434841494E222C2261726773223A5B226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C312E302C2230225D7D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Paying Gas : ", - "5 | Transfer 1 : Cross-chain 1.0 from \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to chain \"0\"", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : nw3YtHZ5EgogG2oQ9JbOOEqyhy7IN4cevGjdEKuWgQM", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Paying Gas : ", - "5 | Transfer 1 : Cross-chain 1.0 from \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to chain \"0\"", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : nw3YtHZ5EgogG2oQ9JbOOEqyhy7IN4cevGjdEKuWgQM", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 13, - "name": "decimal_cross_chain", - "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E534645525F58434841494E222C2261726773223A5B226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C7B22646563696D616C223A223132333435363738392E30313233343536373839227D2C2230225D7D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Paying Gas : ", - "5 | Transfer 1 : Cross-chain {\"decimal\":\"123456789.0123456789\"} from \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to chain \"0\"", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : gaYu1-LR6N9V0bUt1u_N9p4cbm_dwy7IeHC52rD92gs", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Paying Gas : ", - "5 | Transfer 1 : Cross-chain {\"decimal\":\"123456789.0123456789\"} from \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\" to chain \"0\"", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : gaYu1-LR6N9V0bUt1u_N9p4cbm_dwy7IeHC52rD92gs", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 14, - "name": "cross_chain_not_4_args", - "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E534645525F58434841494E222C2261726773223A5B226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C7B22646563696D616C223A223132333435363738392E30313233343536373839227D2C2230222C747275655D7D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: coin.TRANSFER_XCHAIN, arg 1: \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\", arg 2: \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\", arg 3: {\"decimal\":\"123456789.0123456789\"}, arg 4: \"0\", arg 5: true", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : LY8HM_kQ2nRO7Wl0PD9flhbibi0K1CXxv27KmlDBQmo", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : testnet04", - "2 | Requiring : Capabilities", - "3 | Of Key : ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: coin.TRANSFER_XCHAIN, arg 1: \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\", arg 2: \"k:ffd8cd79deb956fa3c7d9be0f836f20ac84b140168a087a842be4760e40e2b1c\", arg 3: {\"decimal\":\"123456789.0123456789\"}, arg 4: \"0\", arg 5: true", - "6 | On Chain : 1", - "7 | Using Gas : at most 600 at price 0.00001", - "8 | Transaction hash : LY8HM_kQ2nRO7Wl0PD9flhbibi0K1CXxv27KmlDBQmo", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 15, - "name": "Multiple_transfers", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646661222C315D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646662222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646663222C335D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Paying Gas : ", - "5 | Transfer 1 : 1 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfa\"", - "6 | Transfer 2 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfb\"", - "7 | Transfer 3 : 3 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfc\"", - "8 | Transfer 4 : 4 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", - "9 | On Chain : 0", - "10 | Using Gas : at most 600 at price 1.0e-6", - "11 | Transaction hash : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOREfZhk", - "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Paying Gas : ", - "5 | Transfer 1 : 1 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfa\"", - "6 | Transfer 2 : 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfb\"", - "7 | Transfer 3 : 3 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfc\"", - "8 | Transfer 4 : 4 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", - "9 | On Chain : 0", - "10 | Using Gas : at most 600 at price 1.0e-6", - "11 | Transaction hash : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOREfZhk", - "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 16, - "name": "Multiple_cross_chain_transfers", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646661222C315D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646662222C322C2233225D2C226E616D65223A22636F696E2E5452414E534645525F58434841494E227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646663222C332C2232225D2C226E616D65223A22636F696E2E5452414E534645525F58434841494E227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Paying Gas : ", - "5 | Transfer 1 : 1 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfa\"", - "6 | Transfer 2 : Cross-chain 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfb\" to chain \"3\"", - "7 | Transfer 3 : Cross-chain 3 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfc\" to chain \"2\"", - "8 | Transfer 4 : 4 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", - "9 | On Chain : 0", - "10 | Using Gas : at most 600 at price 1.0e-6", - "11 | Transaction hash : AoXqSSMScM_u4glsmLV3C8Eawexbm2YEFgFMHYFzm4o", - "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a", - "4 | Paying Gas : ", - "5 | Transfer 1 : 1 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfa\"", - "6 | Transfer 2 : Cross-chain 2 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfb\" to chain \"3\"", - "7 | Transfer 3 : Cross-chain 3 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfc\" to chain \"2\"", - "8 | Transfer 4 : 4 from \"aab7d3e457f3f78480832d6ac4ace7387f460620a63a5b68c8c799d6bff1566a\" to \"4c310df6224d674d80463a29cde00cb0ecfb71e0cfdce494243a61b8ea572dfd\"", - "9 | On Chain : 0", - "10 | Using Gas : at most 600 at price 1.0e-6", - "11 | Transaction hash : AoXqSSMScM_u4glsmLV3C8Eawexbm2YEFgFMHYFzm4o", - "12 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 17, - "name": "meta_field_missing", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B22756E6B6E6F776E2D6669656C64223A747275652C226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "6 | CAUTION : 'meta' field of transaction not recognized", - "7 | Transaction hash : fysHQicr1iPz-sbSntIM3Rx_Iw_agBhRxt-XL9X7ENk", - "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Transfer 1 : 11 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\"", - "6 | CAUTION : 'meta' field of transaction not recognized", - "7 | Transaction hash : fysHQicr1iPz-sbSntIM3Rx_Iw_agBhRxt-XL9X7ENk", - "8 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 18, - "name": "arbitrary_cap_with_no_args", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B5D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, no args", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : hnaoFEVgtSMrwKbm2Ui4wnARtUwMo6rtB3fnvZGb8oE", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, no args", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : hnaoFEVgtSMrwKbm2Ui4wnARtUwMo6rtB3fnvZGb8oE", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 19, - "name": "arbitrary_cap_with_one_arg", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930225D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : kQqVYwYzDNSKqcRwJ3Yd4xgG2UW9j2sdcupQx-T6XEY", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : kQqVYwYzDNSKqcRwJ3Yd4xgG2UW9j2sdcupQx-T6XEY", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 20, - "name": "arbitrary_cap_with_two_args", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267225D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : ONXn9kz2V9InGB-RddO3kUCy-GHQOEs8jRYqO2vzxuY", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\"", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : ONXn9kz2V9InGB-RddO3kUCy-GHQOEs8jRYqO2vzxuY", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 21, - "name": "arbitrary_cap_with_two_args_one_num", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267222C32322E325D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 22.2", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : OEV1W2Adz7vvU3qYzV9V48pDhxRdFDi2KG4JXx73WTA", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 22.2", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : OEV1W2Adz7vvU3qYzV9V48pDhxRdFDi2KG4JXx73WTA", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 22, - "name": "arbitrary_cap_with_various_json_types", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B7B226B657931223A7B226B657932223A2276616C32227D2C226B657933223A2D322E34362C226B657934223A7B226B657935223A747275652C226B657936223A7B226B657937223A302E30317D2C226B657938223A5B2261222C66616C73652C6E756C6C2C392C31302E32332C2D35382E32345D7D7D2C7B7D2C5B5D2C66616C73652C6E756C6C5D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: {\"key1\":{\"key2\":\"val2\"},\"key3\":-2.46,\"key4\":{\"key5\":true,\"key6\":{\"key7\":0.01},\"key8\":[\"a\",false,null,9,10.23,-58.24]}}, arg 2: {}, arg 3: [], arg 4: false, arg 5: null", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : 5RygRqoczKtecEebMtaPLrulHa5aprNcjkRhMAAogNc", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, arg 1: {\"key1\":{\"key2\":\"val2\"},\"key3\":-2.46,\"key4\":{\"key5\":true,\"key6\":{\"key7\":0.01},\"key8\":[\"a\",false,null,9,10.23,-58.24]}}, arg 2: {}, arg 3: [], arg 4: false, arg 5: null", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | Transaction hash : 5RygRqoczKtecEebMtaPLrulHa5aprNcjkRhMAAogNc", - "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 23, - "name": "multiple_arbitrary_caps", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B5D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455230227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455231227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455232227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267222C32322E325D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455233227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267222C353030302C32322E325D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455234227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", - "6 | Unknown Capability 2 : name: mycoin.MY_TRANSFER1, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", - "7 | Unknown Capability 3 : name: mycoin.MY_TRANSFER2, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\"", - "8 | Unknown Capability 4 : name: mycoin.MY_TRANSFER3, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 22.2", - "9 | Unknown Capability 5 : name: mycoin.MY_TRANSFER4, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 5000, arg 4: 22.2", - "10 | On Chain : 0", - "11 | Using Gas : at most 600 at price 1.0e-5", - "12 | Transaction hash : QJDO0ks635Xpnq2GC85cqoQUxLgESujMgun7NUgrf5E", - "13 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", - "6 | Unknown Capability 2 : name: mycoin.MY_TRANSFER1, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", - "7 | Unknown Capability 3 : name: mycoin.MY_TRANSFER2, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\"", - "8 | Unknown Capability 4 : name: mycoin.MY_TRANSFER3, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 22.2", - "9 | Unknown Capability 5 : name: mycoin.MY_TRANSFER4, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"second arg\", arg 3: 5000, arg 4: 22.2", - "10 | On Chain : 0", - "11 | Using Gas : at most 600 at price 1.0e-5", - "12 | Transaction hash : QJDO0ks635Xpnq2GC85cqoQUxLgESujMgun7NUgrf5E", - "13 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 24, - "name": "multiple_arbitrary_caps_multiple_transfers", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B5D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455230227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455231227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373931222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373931222C32322E322C2234225D2C226E616D65223A22636F696E2E5452414E534645525F58434841494E227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373932222C353030302C2230225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455234227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", - "6 | Unknown Capability 2 : name: mycoin.MY_TRANSFER1, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", - "7 | Transfer 1 : 4 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471791\"", - "8 | Transfer 2 : Cross-chain 22.2 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471791\" to chain \"4\"", - "9 | Unknown Capability 3 : name: mycoin.MY_TRANSFER4, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471792\", arg 3: 5000, arg 4: \"0\"", - "10 | On Chain : 0", - "11 | Using Gas : at most 600 at price 1.0e-5", - "12 | Transaction hash : yMXcVG1vcnLrbtdiKHI1MAYgrBgoDqr15YSRID70DyU", - "13 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", - "6 | Unknown Capability 2 : name: mycoin.MY_TRANSFER1, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\"", - "7 | Transfer 1 : 4 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471791\"", - "8 | Transfer 2 : Cross-chain 22.2 from \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\" to \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471791\" to chain \"4\"", - "9 | Unknown Capability 3 : name: mycoin.MY_TRANSFER4, arg 1: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\", arg 2: \"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471792\", arg 3: 5000, arg 4: \"0\"", - "10 | On Chain : 0", - "11 | Using Gas : at most 600 at price 1.0e-5", - "12 | Transaction hash : yMXcVG1vcnLrbtdiKHI1MAYgrBgoDqr15YSRID70DyU", - "13 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - }, - { - "index": 25, - "name": "arbitrary_caps_large_args", - "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C226164666173222C342C352C362C372C385D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", - "output": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, args cannot be displayed on Ledger", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | WARNING : Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?", - "9 | Transaction hash : Y2q38WX4sd5fWzw2knr7mfAltsaYxhWnDGtFaZ7NV40", - "10 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ], - "output_expert": [ - "0 | Signing : Transaction", - "1 | On Network : mainnet01", - "2 | Requiring : Capabilities", - "3 | Of Key : 83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790", - "4 | Paying Gas : ", - "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, args cannot be displayed on Ledger", - "6 | On Chain : 0", - "7 | Using Gas : at most 600 at price 1.0e-5", - "8 | WARNING : Transaction too large for Ledger to display. PROCEED WITH GREAT CAUTION. Do you want to continue?", - "9 | Transaction hash : Y2q38WX4sd5fWzw2knr7mfAltsaYxhWnDGtFaZ7NV40", - "10 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb91b6ea9ee5724cde09ef758bf2" - ] - } + { + "index": 0, + "name": "Simple_transfer", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164224A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 11 from \"83934c0f9b005f378ba3520f9dea9", + "5 | Transfer 1 [2/4] : 52fb0a90e5aa36f1b5ff837d9b30c471790", + "5 | Transfer 1 [3/4] : o \"9790d119589a26114e1a42d92598b3f6325", + "5 | Transfer 1 [4/4] : 51c566819ec48e0e8c54dae6ebb42", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uix", + "9 | Transaction hash [2/2] : sNZgk", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 11 from \"83934c0f9b005f378ba3520f9dea9", + "5 | Transfer 1 [2/4] : 52fb0a90e5aa36f1b5ff837d9b30c471790", + "5 | Transfer 1 [3/4] : o \"9790d119589a26114e1a42d92598b3f6325", + "5 | Transfer 1 [4/4] : 51c566819ec48e0e8c54dae6ebb42", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : fPSCfMUaoK1N31qwhwBFUPwG-YR_guPP894uix", + "8 | Transaction hash [2/2] : sNZgk", + "9 | Sign for Address : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 1, + "name": "Gas_with_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B312C747275652C6E756C6C5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : aab7d3e457f3f78480832d6ac4ace7387f4606", + "3 | Of Key [2/2] : 20a63a5b68c8c799d6bff1566a", + "4 | Unknown Capability 1 [1/2] : name: coin.GAS, arg 1: 1, arg 2: true,", + "4 | Unknown Capability 1 [2/2] : arg 3: null", + "5 | Transfer 1 [1/4] : 2 from \"aab7d3e457f3f78480832d6ac4ace7", + "5 | Transfer 1 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "5 | Transfer 1 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "5 | Transfer 1 [4/4] : 71e0cfdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash [1/2] : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8", + "8 | Transaction hash [2/2] : OLyco", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : aab7d3e457f3f78480832d6ac4ace7387f4606", + "3 | Of Key [2/2] : 20a63a5b68c8c799d6bff1566a", + "4 | Unknown Capability 1 [1/2] : name: coin.GAS, arg 1: 1, arg 2: true,", + "4 | Unknown Capability 1 [2/2] : arg 3: null", + "5 | Transfer 1 [1/4] : 2 from \"aab7d3e457f3f78480832d6ac4ace7", + "5 | Transfer 1 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "5 | Transfer 1 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "5 | Transfer 1 [4/4] : 71e0cfdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash [1/2] : anrl4cUVN53NFJCQ9tH4szt-ZzlCQ_SZuDI7e8", + "8 | Transaction hash [2/2] : OLyco", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 2, + "name": "Network_null", + "blob": "7B226E6574776F726B4964223A6E756C6C2C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | Requiring : Capabilities", + "2 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "2 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "3 | Paying Gas : ", + "4 | Transfer 1 [1/4] : 11 from \"83934c0f9b005f378ba3520f9dea9", + "4 | Transfer 1 [2/4] : 52fb0a90e5aa36f1b5ff837d9b30c471790\" t", + "4 | Transfer 1 [3/4] : o \"9790d119589a26114e1a42d92598b3f6325", + "4 | Transfer 1 [4/4] : 51c566819ec48e0e8c54dae6ebb42\"", + "5 | On Chain : 0", + "6 | Using Gas : at most 600 at price 1.0e-5", + "7 | Transaction hash [1/2] : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb", + "7 | Transaction hash [2/2] : -Cn8w", + "8 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "8 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | Requiring : Capabilities", + "2 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "2 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "3 | Paying Gas : ", + "4 | Transfer 1 [1/4] : 11 from \"83934c0f9b005f378ba3520f9dea9", + "4 | Transfer 1 [2/4] : 52fb0a90e5aa36f1b5ff837d9b30c471790\" t", + "4 | Transfer 1 [3/4] : o \"9790d119589a26114e1a42d92598b3f6325", + "4 | Transfer 1 [4/4] : 51c566819ec48e0e8c54dae6ebb42\"", + "5 | On Chain : 0", + "6 | Using Gas : at most 600 at price 1.0e-5", + "7 | Transaction hash [1/2] : epv3lSVeZCWEYpPZet-ddYqpFSekJiIcw2azMb", + "7 | Transaction hash [2/2] : -Cn8w", + "8 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "8 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 3, + "name": "Transfer_with_decimal_amount", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C7B22646563696D616C223A223132333435363738392E30313233343536373839227D5D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : aab7d3e457f3f78480832d6ac4ace7387f4606", + "3 | Of Key [2/2] : 20a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/5] : {\"decimal\":\"123456789.0123456789\"} fro", + "5 | Transfer 1 [2/5] : m \"aab7d3e457f3f78480832d6ac4ace7387f4", + "5 | Transfer 1 [3/5] : 60620a63a5b68c8c799d6bff1566a\" to \"4c3", + "5 | Transfer 1 [4/5] : 10df6224d674d80463a29cde00cb0ecfb71e0c", + "5 | Transfer 1 [5/5] : fdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash [1/2] : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4", + "8 | Transaction hash [2/2] : bAvk4", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : aab7d3e457f3f78480832d6ac4ace7387f4606", + "3 | Of Key [2/2] : 20a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/5] : {\"decimal\":\"123456789.0123456789\"} fro", + "5 | Transfer 1 [2/5] : m \"aab7d3e457f3f78480832d6ac4ace7387f4", + "5 | Transfer 1 [3/5] : 60620a63a5b68c8c799d6bff1566a\" to \"4c3", + "5 | Transfer 1 [4/5] : 10df6224d674d80463a29cde00cb0ecfb71e0c", + "5 | Transfer 1 [5/5] : fdce494243a61b8ea572dfd\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-6", + "8 | Transaction hash [1/2] : u4kRsc0DEmRbOOG2gePtMADMTOGGtRsXrMQ2R4", + "8 | Transaction hash [2/2] : bAvk4", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 4, + "name": "Simple_transfer_create", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B22726563702D6B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637225D7D7D2C22636F6465223A2228636F696E2E7472616E736665722D637265617465205C22653461316232393830633038366334353531616237643231343863663536653937373463363465623836663739356435666438336533396363666432656336365C22205C22383735653434393365313963383732313538336266623436663037363866313032363665626363613333633461306530346263303939613730343461393066375C222028726561642D6B6579736574205C22726563702D6B735C222920342E393833343034383829227D7D2C227369676E657273223A5B7B227075624B6579223A2265346131623239383063303836633435353161623764323134386366353665393737346336346562383666373935643566643833653339636366643265633636222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2265346131623239383063303836633435353161623764323134386366353665393737346336346562383666373935643566643833653339636366643265633636222C2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637222C342E39383334303438385D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393134322C2274746C223A32383830302C226761734C696D6974223A36303030302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2265346131623239383063303836633435353161623764323134386366353665393737346336346562383666373935643566643833653339636366643265633636227D2C226E6F6E6365223A225C22313633343030393135363934335C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : e4a1b2980c086c4551ab7d2148cf56e9774c64", + "3 | Of Key [2/2] : eb86f795d5fd83e39ccfd2ec66", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 4.98340488 from \"e4a1b2980c086c4551ab7", + "5 | Transfer 1 [2/4] : d2148cf56e9774c64eb86f795d5fd83e39ccfd", + "5 | Transfer 1 [3/4] : 2ec66\" to \"875e4493e19c8721583bfb46f07", + "5 | Transfer 1 [4/4] : 68f10266ebcca33c4a0e04bc099a7044a90f7\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 60000 at price 1.0e-6", + "8 | Transaction hash [1/2] : SrjHkjfzLHLiOS-5_lcZvLOhiU42NynfAfezMz", + "8 | Transaction hash [2/2] : beXsw", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : e4a1b2980c086c4551ab7d2148cf56e9774c64", + "3 | Of Key [2/2] : eb86f795d5fd83e39ccfd2ec66", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 4.98340488 from \"e4a1b2980c086c4551ab7", + "5 | Transfer 1 [2/4] : d2148cf56e9774c64eb86f795d5fd83e39ccfd", + "5 | Transfer 1 [3/4] : 2ec66\" to \"875e4493e19c8721583bfb46f07", + "5 | Transfer 1 [4/4] : 68f10266ebcca33c4a0e04bc099a7044a90f7\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 60000 at price 1.0e-6", + "8 | Transaction hash [1/2] : SrjHkjfzLHLiOS-5_lcZvLOhiU42NynfAfezMz", + "8 | Transaction hash [2/2] : beXsw", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 5, + "name": "Second_transfer_create", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B22726563702D6B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637225D7D7D2C22636F6465223A2228636F696E2E7472616E736665722D637265617465205C22373335383066666233653563613938353934343233393564346331636230626633616134653732343635363463653934336237616535303862336565376330335C22205C22383735653434393365313963383732313538336266623436663037363866313032363665626363613333633461306530346263303939613730343461393066375C222028726561642D6B6579736574205C22726563702D6B735C222920342E383930393334353529227D7D2C227369676E657273223A5B7B227075624B6579223A2237333538306666623365356361393835393434323339356434633163623062663361613465373234363536346365393433623761653530386233656537633033222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2237333538306666623365356361393835393434323339356434633163623062663361613465373234363536346365393433623761653530386233656537633033222C2238373565343439336531396338373231353833626662343666303736386631303236366562636361333363346130653034626330393961373034346139306637222C342E38393039333435355D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393039382C2274746C223A32383830302C226761734C696D6974223A36303030302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2237333538306666623365356361393835393434323339356434633163623062663361613465373234363536346365393433623761653530386233656537633033227D2C226E6F6E6365223A225C22313633343030393131333037335C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 73580ffb3e5ca9859442395d4c1cb0bf3aa4e7", + "3 | Of Key [2/2] : 246564ce943b7ae508b3ee7c03", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 4.89093455 from \"73580ffb3e5ca98594423", + "5 | Transfer 1 [2/4] : 95d4c1cb0bf3aa4e7246564ce943b7ae508b3e", + "5 | Transfer 1 [3/4] : e7c03\" to \"875e4493e19c8721583bfb46f07", + "5 | Transfer 1 [4/4] : 68f10266ebcca33c4a0e04bc099a7044a90f7\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 60000 at price 1.0e-6", + "8 | Transaction hash [1/2] : pJsk0-vgbqfzOBFc4zHtFMSMa0aCZpXBZ_QQFx", + "8 | Transaction hash [2/2] : ox1-k", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 73580ffb3e5ca9859442395d4c1cb0bf3aa4e7", + "3 | Of Key [2/2] : 246564ce943b7ae508b3ee7c03", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 4.89093455 from \"73580ffb3e5ca98594423", + "5 | Transfer 1 [2/4] : 95d4c1cb0bf3aa4e7246564ce943b7ae508b3e", + "5 | Transfer 1 [3/4] : e7c03\" to \"875e4493e19c8721583bfb46f07", + "5 | Transfer 1 [4/4] : 68f10266ebcca33c4a0e04bc099a7044a90f7\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 60000 at price 1.0e-6", + "8 | Transaction hash [1/2] : pJsk0-vgbqfzOBFc4zHtFMSMa0aCZpXBZ_QQFx", + "8 | Transaction hash [2/2] : ox1-k", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 6, + "name": "Transfer_with_2_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432225D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/5] : name: coin.TRANSFER, arg 1: \"83934c0f9", + "5 | Unknown Capability 1 [2/5] : b005f378ba3520f9dea952fb0a90e5aa36f1b5", + "5 | Unknown Capability 1 [3/5] : ff837d9b30c471790\", arg 2: \"9790d11958", + "5 | Unknown Capability 1 [4/5] : 9a26114e1a42d92598b3f632551c566819ec48", + "5 | Unknown Capability 1 [5/5] : e0e8c54dae6ebb42\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew", + "8 | Transaction hash [2/2] : 7VnMY", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/5] : name: coin.TRANSFER, arg 1: \"83934c0f9", + "5 | Unknown Capability 1 [2/5] : b005f378ba3520f9dea952fb0a90e5aa36f1b5", + "5 | Unknown Capability 1 [3/5] : ff837d9b30c471790\", arg 2: \"9790d11958", + "5 | Unknown Capability 1 [4/5] : 9a26114e1a42d92598b3f632551c566819ec48", + "5 | Unknown Capability 1 [5/5] : e0e8c54dae6ebb42\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : FmmZBoFdyW_0T7oD1fXldK_MgKyvxTd4B3i7ew", + "8 | Transaction hash [2/2] : 7VnMY", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 7, + "name": "Rotate_transaction", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933225D7D7D2C22636F6465223A2228636F696E2E726F74617465205C22643333303064323834663462636662633931353535313834656630323661333536653537666630666139376235653663393833303735303839326364333039335C222028726561642D6B6579736574205C226B735C222929227D7D2C227369676E657273223A5B7B227075624B6579223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933225D2C226E616D65223A22636F696E2E524F54415445227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633333436363736342C2274746C223A32383830302C226761734C696D6974223A313530302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663227D2C226E6F6E6365223A225C22313633333436363736345C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 81b4511b257fb975dace13e823c257c17ac6a6", + "3 | Of Key [2/2] : 95da65f91b6036d6e1429268fc", + "4 | Paying Gas : ", + "5 | Rotate for account [1/2] : \"d3300d284f4bcfbc91555184ef026a356e57f", + "5 | Rotate for account [2/2] : f0fa97b5e6c9830750892cd3093\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 1500 at price 1.0e-5", + "8 | Transaction hash [1/2] : WQImvdxCaI7U5Qy2U_3Mxoa3i-Lp-PyNu9aZNt", + "8 | Transaction hash [2/2] : XclHo", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 81b4511b257fb975dace13e823c257c17ac6a6", + "3 | Of Key [2/2] : 95da65f91b6036d6e1429268fc", + "4 | Paying Gas : ", + "5 | Rotate for account [1/2] : \"d3300d284f4bcfbc91555184ef026a356e57f", + "5 | Rotate for account [2/2] : f0fa97b5e6c9830750892cd3093\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 1500 at price 1.0e-5", + "8 | Transaction hash [1/2] : WQImvdxCaI7U5Qy2U_3Mxoa3i-Lp-PyNu9aZNt", + "8 | Transaction hash [2/2] : XclHo", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 8, + "name": "Rotate_with_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B2270726564223A226B6579732D616C6C222C226B657973223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933225D7D7D2C22636F6465223A2228636F696E2E726F74617465205C22643333303064323834663462636662633931353535313834656630323661333536653537666630666139376235653663393833303735303839326364333039335C222028726561642D6B6579736574205C226B735C222929227D7D2C227369676E657273223A5B7B227075624B6579223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2264333330306432383466346263666263393135353531383465663032366133353665353766663066613937623565366339383330373530383932636433303933222C6E756C6C5D2C226E616D65223A22636F696E2E524F54415445227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633333436363736342C2274746C223A32383830302C226761734C696D6974223A313530302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238316234353131623235376662393735646163653133653832336332353763313761633661363935646136356639316236303336643665313432393236386663227D2C226E6F6E6365223A225C22313633333436363736345C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 81b4511b257fb975dace13e823c257c17ac6a6", + "3 | Of Key [2/2] : 95da65f91b6036d6e1429268fc", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/3] : name: coin.ROTATE, arg 1: \"d3300d284f4", + "5 | Unknown Capability 1 [2/3] : bcfbc91555184ef026a356e57ff0fa97b5e6c9", + "5 | Unknown Capability 1 [3/3] : 830750892cd3093\", arg 2: null", + "6 | On Chain : 0", + "7 | Using Gas : at most 1500 at price 1.0e-5", + "8 | Transaction hash [1/2] : Rr78KvlVRiX59dDOqZFaK9vgW6GzgMss13p67y", + "8 | Transaction hash [2/2] : GOkN4", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 81b4511b257fb975dace13e823c257c17ac6a6", + "3 | Of Key [2/2] : 95da65f91b6036d6e1429268fc", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/3] : name: coin.ROTATE, arg 1: \"d3300d284f4", + "5 | Unknown Capability 1 [2/3] : bcfbc91555184ef026a356e57ff0fa97b5e6c9", + "5 | Unknown Capability 1 [3/3] : 830750892cd3093\", arg 2: null", + "6 | On Chain : 0", + "7 | Using Gas : at most 1500 at price 1.0e-5", + "8 | Transaction hash [1/2] : Rr78KvlVRiX59dDOqZFaK9vgW6GzgMss13p67y", + "8 | Transaction hash [2/2] : GOkN4", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 9, + "name": "Transaction_with_no_capabilities", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A22286E6F742D636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Unscoped Signer [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "4 | Unscoped Signer [2/2] : 0168a087a842be4760e40e2b1c", + "5 | WARNING [1/6] : UNSAFE TRANSACTION. This transaction's", + "5 | WARNING [2/6] : code was not recognized and does not ", + "5 | WARNING [3/6] : limit capabilities for all signers. Si", + "5 | WARNING [4/6] : gning this transaction may make arbitr", + "5 | WARNING [5/6] : ary actions on the chain including los", + "5 | WARNING [6/6] : s of all funds.", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : EsF-vcYfXYn8-NpYIvBcOMYCfUxiV6wxECU5FW", + "8 | Transaction hash [2/2] : NFz5g", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Unscoped Signer [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "4 | Unscoped Signer [2/2] : 0168a087a842be4760e40e2b1c", + "5 | WARNING [1/6] : UNSAFE TRANSACTION. This transaction's", + "5 | WARNING [2/6] : code was not recognized and does not ", + "5 | WARNING [3/6] : limit capabilities for all signers. Si", + "5 | WARNING [4/6] : gning this transaction may make arbitr", + "5 | WARNING [5/6] : ary actions on the chain including los", + "5 | WARNING [6/6] : s of all funds.", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : EsF-vcYfXYn8-NpYIvBcOMYCfUxiV6wxECU5FW", + "8 | Transaction hash [2/2] : NFz5g", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 10, + "name": "Transaction_with_clist_null", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A22286E6F742D636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A6E756C6C7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Unscoped Signer [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "4 | Unscoped Signer [2/2] : 0168a087a842be4760e40e2b1c", + "5 | WARNING [1/6] : UNSAFE TRANSACTION. This transaction's", + "5 | WARNING [2/6] : code was not recognized and does not ", + "5 | WARNING [3/6] : limit capabilities for all signers. Si", + "5 | WARNING [4/6] : gning this transaction may make arbitr", + "5 | WARNING [5/6] : ary actions on the chain including los", + "5 | WARNING [6/6] : s of all funds.", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : 0j8JyVmew5_ibulW2WO-OXb9j5woNPX1T9Y1BQ", + "8 | Transaction hash [2/2] : QvmFM", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Unscoped Signer [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "4 | Unscoped Signer [2/2] : 0168a087a842be4760e40e2b1c", + "5 | WARNING [1/6] : UNSAFE TRANSACTION. This transaction's", + "5 | WARNING [2/6] : code was not recognized and does not ", + "5 | WARNING [3/6] : limit capabilities for all signers. Si", + "5 | WARNING [4/6] : gning this transaction may make arbitr", + "5 | WARNING [5/6] : ary actions on the chain including los", + "5 | WARNING [6/6] : s of all funds.", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : 0j8JyVmew5_ibulW2WO-OXb9j5woNPX1T9Y1BQ", + "8 | Transaction hash [2/2] : QvmFM", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 11, + "name": "k_account_names", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2264666462333839363931393534343439303633376330666432663334663862663434363364343136666264393135393930633861313336623161393730636135225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D637265617465205C226B3A623961633363613535353963633666333934656130653331633131626531366566643663366666363830346239386365376365653439366263636139363136345C22205C226B3A646664623338393639313935343434393036333763306664326633346638626634343633643431366662643931353939306338613133366231613937306361355C222028726561642D6B6579736574205C226B735C222920322E3029227D7D2C227369676E657273223A5B7B22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E53464552222C2261726773223A5B226B3A62396163336361353535396363366633393465613065333163313162653136656664366336666636383034623938636537636565343936626363613936313634222C226B3A64666462333839363931393534343439303633376330666432663334663862663434363364343136666264393135393930633861313336623161393730636135222C325D7D5D2C227075624B6579223A2262396163336361353535396363366633393465613065333163313162653136656664366336666636383034623938636537636565343936626363613936313634227D5D2C226D657461223A7B226372656174696F6E54696D65223A313634313333313232302C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A226B3A62396163336361353535396363366633393465613065333163313162653136656664366336666636383034623938636537636565343936626363613936313634227D2C226E6F6E6365223A225C225C5C5C22323032322D30312D30345432313A32313A32302E3434305A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : b9ac3ca5559cc6f394ea0e31c11be16efd6c6f", + "3 | Of Key [2/2] : f6804b98ce7cee496bcca96164", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 2 from \"k:b9ac3ca5559cc6f394ea0e31c11b", + "5 | Transfer 1 [2/4] : e16efd6c6ff6804b98ce7cee496bcca96164\" ", + "5 | Transfer 1 [3/4] : to \"k:dfdb3896919544490637c0fd2f34f8bf", + "5 | Transfer 1 [4/4] : 4463d416fbd915990c8a136b1a970ca5\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : 9VlNQ6wmY5UpfOcazQNGpBZDt9Cd_sl_DO0POp", + "8 | Transaction hash [2/2] : iBDvU", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : b9ac3ca5559cc6f394ea0e31c11be16efd6c6f", + "3 | Of Key [2/2] : f6804b98ce7cee496bcca96164", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 2 from \"k:b9ac3ca5559cc6f394ea0e31c11b", + "5 | Transfer 1 [2/4] : e16efd6c6ff6804b98ce7cee496bcca96164\" ", + "5 | Transfer 1 [3/4] : to \"k:dfdb3896919544490637c0fd2f34f8bf", + "5 | Transfer 1 [4/4] : 4463d416fbd915990c8a136b1a970ca5\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : 9VlNQ6wmY5UpfOcazQNGpBZDt9Cd_sl_DO0POp", + "8 | Transaction hash [2/2] : iBDvU", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 12, + "name": "basic_cross_chain", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E534645525F58434841494E222C2261726773223A5B226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C312E302C2230225D7D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/5] : Cross-chain 1.0 from \"k:ffd8cd79deb956", + "5 | Transfer 1 [2/5] : fa3c7d9be0f836f20ac84b140168a087a842be", + "5 | Transfer 1 [3/5] : 4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c", + "5 | Transfer 1 [4/5] : 7d9be0f836f20ac84b140168a087a842be4760", + "5 | Transfer 1 [5/5] : e40e2b1c\" to chain \"0\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : nw3YtHZ5EgogG2oQ9JbOOEqyhy7IN4cevGjdEK", + "8 | Transaction hash [2/2] : uWgQM", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/5] : Cross-chain 1.0 from \"k:ffd8cd79deb956", + "5 | Transfer 1 [2/5] : fa3c7d9be0f836f20ac84b140168a087a842be", + "5 | Transfer 1 [3/5] : 4760e40e2b1c\" to \"k:ffd8cd79deb956fa3c", + "5 | Transfer 1 [4/5] : 7d9be0f836f20ac84b140168a087a842be4760", + "5 | Transfer 1 [5/5] : e40e2b1c\" to chain \"0\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : nw3YtHZ5EgogG2oQ9JbOOEqyhy7IN4cevGjdEK", + "8 | Transaction hash [2/2] : uWgQM", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf" + ] + }, + { + "index": 13, + "name": "decimal_cross_chain", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E534645525F58434841494E222C2261726773223A5B226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C7B22646563696D616C223A223132333435363738392E30313233343536373839227D2C2230225D7D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/6] : Cross-chain {\"decimal\":\"123456789.0123", + "5 | Transfer 1 [2/6] : 456789\"} from \"k:ffd8cd79deb956fa3c7d9", + "5 | Transfer 1 [3/6] : be0f836f20ac84b140168a087a842be4760e40", + "5 | Transfer 1 [4/6] : e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f", + "5 | Transfer 1 [5/6] : 836f20ac84b140168a087a842be4760e40e2b1", + "5 | Transfer 1 [6/6] : c\" to chain \"0\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : gaYu1-LR6N9V0bUt1u_N9p4cbm_dwy7IeHC52r", + "8 | Transaction hash [2/2] : D92gs", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/6] : Cross-chain {\"decimal\":\"123456789.0123", + "5 | Transfer 1 [2/6] : 456789\"} from \"k:ffd8cd79deb956fa3c7d9", + "5 | Transfer 1 [3/6] : be0f836f20ac84b140168a087a842be4760e40", + "5 | Transfer 1 [4/6] : e2b1c\" to \"k:ffd8cd79deb956fa3c7d9be0f", + "5 | Transfer 1 [5/6] : 836f20ac84b140168a087a842be4760e40e2b1", + "5 | Transfer 1 [6/6] : c\" to chain \"0\"", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : gaYu1-LR6N9V0bUt1u_N9p4cbm_dwy7IeHC52r", + "8 | Transaction hash [2/2] : D92gs", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 14, + "name": "cross_chain_not_4_args", + "blob": "7B226E6574776F726B4964223A22746573746E65743034222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B226B73223A7B226B657973223A5B2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163225D2C2270726564223A226B6579732D616C6C227D7D2C22636F6465223A2228636F696E2E7472616E736665722D63726F7373636861696E205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C22205C22666664386364373964656239353666613363376439626530663833366632306163383462313430313638613038376138343262653437363065343065326231635C222028726561642D6B6579736574205C226B735C2229205C22305C2220312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C22636C697374223A5B7B226E616D65223A22636F696E2E474153222C2261726773223A5B5D7D2C7B226E616D65223A22636F696E2E5452414E534645525F58434841494E222C2261726773223A5B226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C226B3A66666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163222C7B22646563696D616C223A223132333435363738392E30313233343536373839227D2C2230222C747275655D7D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313634303239303236372C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2231222C226761735072696365223A302E30303030312C2273656E646572223A2266666438636437396465623935366661336337643962653066383336663230616338346231343031363861303837613834326265343736306534306532623163227D2C226E6F6E6365223A225C225C5C5C22323032312D31322D32335432303A31323A30362E3636345A5C5C5C225C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/7] : name: coin.TRANSFER_XCHAIN, arg 1: \"k:", + "5 | Unknown Capability 1 [2/7] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "5 | Unknown Capability 1 [3/7] : 0168a087a842be4760e40e2b1c\", arg 2: \"k", + "5 | Unknown Capability 1 [4/7] : :ffd8cd79deb956fa3c7d9be0f836f20ac84b1", + "5 | Unknown Capability 1 [5/7] : 40168a087a842be4760e40e2b1c\", arg 3: {", + "5 | Unknown Capability 1 [6/7] : \"decimal\":\"123456789.0123456789\"}, arg", + "5 | Unknown Capability 1 [7/7] : 4: \"0\", arg 5: true", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : LY8HM_kQ2nRO7Wl0PD9flhbibi0K1CXxv27Kml", + "8 | Transaction hash [2/2] : DBQmo", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : testnet04", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "3 | Of Key [2/2] : 0168a087a842be4760e40e2b1c", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/7] : name: coin.TRANSFER_XCHAIN, arg 1: \"k:", + "5 | Unknown Capability 1 [2/7] : ffd8cd79deb956fa3c7d9be0f836f20ac84b14", + "5 | Unknown Capability 1 [3/7] : 0168a087a842be4760e40e2b1c\", arg 2: \"k", + "5 | Unknown Capability 1 [4/7] : :ffd8cd79deb956fa3c7d9be0f836f20ac84b1", + "5 | Unknown Capability 1 [5/7] : 40168a087a842be4760e40e2b1c\", arg 3: {", + "5 | Unknown Capability 1 [6/7] : \"decimal\":\"123456789.0123456789\"}, arg", + "5 | Unknown Capability 1 [7/7] : 4: \"0\", arg 5: true", + "6 | On Chain : 1", + "7 | Using Gas : at most 600 at price 0.00001", + "8 | Transaction hash [1/2] : LY8HM_kQ2nRO7Wl0PD9flhbibi0K1CXxv27Kml", + "8 | Transaction hash [2/2] : DBQmo", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 15, + "name": "Multiple_transfers", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646661222C315D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646662222C325D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646663222C335D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : aab7d3e457f3f78480832d6ac4ace7387f4606", + "3 | Of Key [2/2] : 20a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 1 from \"aab7d3e457f3f78480832d6ac4ace7", + "5 | Transfer 1 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "5 | Transfer 1 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "5 | Transfer 1 [4/4] : 71e0cfdce494243a61b8ea572dfa\"", + "6 | Transfer 2 [1/4] : 2 from \"aab7d3e457f3f78480832d6ac4ace7", + "6 | Transfer 2 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "6 | Transfer 2 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "6 | Transfer 2 [4/4] : 71e0cfdce494243a61b8ea572dfb\"", + "7 | Transfer 3 [1/4] : 3 from \"aab7d3e457f3f78480832d6ac4ace7", + "7 | Transfer 3 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "7 | Transfer 3 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "7 | Transfer 3 [4/4] : 71e0cfdce494243a61b8ea572dfc\"", + "8 | Transfer 4 [1/4] : 4 from \"aab7d3e457f3f78480832d6ac4ace7", + "8 | Transfer 4 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "8 | Transfer 4 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "8 | Transfer 4 [4/4] : 71e0cfdce494243a61b8ea572dfd\"", + "9 | On Chain : 0", + "10 | Using Gas : at most 600 at price 1.0e-6", + "11 | Transaction hash [1/2] : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOR", + "11 | Transaction hash [2/2] : EfZhk", + "12 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "12 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : aab7d3e457f3f78480832d6ac4ace7387f4606", + "3 | Of Key [2/2] : 20a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 1 from \"aab7d3e457f3f78480832d6ac4ace7", + "5 | Transfer 1 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "5 | Transfer 1 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "5 | Transfer 1 [4/4] : 71e0cfdce494243a61b8ea572dfa\"", + "6 | Transfer 2 [1/4] : 2 from \"aab7d3e457f3f78480832d6ac4ace7", + "6 | Transfer 2 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "6 | Transfer 2 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "6 | Transfer 2 [4/4] : 71e0cfdce494243a61b8ea572dfb\"", + "7 | Transfer 3 [1/4] : 3 from \"aab7d3e457f3f78480832d6ac4ace7", + "7 | Transfer 3 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "7 | Transfer 3 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "7 | Transfer 3 [4/4] : 71e0cfdce494243a61b8ea572dfc\"", + "8 | Transfer 4 [1/4] : 4 from \"aab7d3e457f3f78480832d6ac4ace7", + "8 | Transfer 4 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "8 | Transfer 4 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "8 | Transfer 4 [4/4] : 71e0cfdce494243a61b8ea572dfd\"", + "9 | On Chain : 0", + "10 | Using Gas : at most 600 at price 1.0e-6", + "11 | Transaction hash [1/2] : cYmajadc0EPG3ifvKR1Yd_-wlG79UZirK47JOR", + "11 | Transaction hash [2/2] : EfZhk", + "12 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "12 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 16, + "name": "Multiple_cross_chain_transfers", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22616162376433653435376633663738343830383332643661633461636537333837663436303632306136336135623638633863373939643662666631353636615C22205C22346333313064663632323464363734643830343633613239636465303063623065636662373165306366646365343934323433613631623865613537326466645C2220322E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C22636C697374223A5B7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646661222C315D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646662222C322C2233225D2C226E616D65223A22636F696E2E5452414E534645525F58434841494E227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646663222C332C2232225D2C226E616D65223A22636F696E2E5452414E534645525F58434841494E227D2C7B2261726773223A5B2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661222C2234633331306466363232346436373464383034363361323963646530306362306563666237316530636664636534393432343361363162386561353732646664222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393139352C2274746C223A3930302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D362C2273656E646572223A2261616237643365343537663366373834383038333264366163346163653733383766343630363230613633613562363863386337393964366266663135363661227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A33352E3233315A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : aab7d3e457f3f78480832d6ac4ace7387f4606", + "3 | Of Key [2/2] : 20a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 1 from \"aab7d3e457f3f78480832d6ac4ace7", + "5 | Transfer 1 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "5 | Transfer 1 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "5 | Transfer 1 [4/4] : 71e0cfdce494243a61b8ea572dfa\"", + "6 | Transfer 2 [1/5] : Cross-chain 2 from \"aab7d3e457f3f78480", + "6 | Transfer 2 [2/5] : 832d6ac4ace7387f460620a63a5b68c8c799d6", + "6 | Transfer 2 [3/5] : bff1566a\" to \"4c310df6224d674d80463a29", + "6 | Transfer 2 [4/5] : cde00cb0ecfb71e0cfdce494243a61b8ea572d", + "6 | Transfer 2 [5/5] : fb\" to chain \"3\"", + "7 | Transfer 3 [1/5] : Cross-chain 3 from \"aab7d3e457f3f78480", + "7 | Transfer 3 [2/5] : 832d6ac4ace7387f460620a63a5b68c8c799d6", + "7 | Transfer 3 [3/5] : bff1566a\" to \"4c310df6224d674d80463a29", + "7 | Transfer 3 [4/5] : cde00cb0ecfb71e0cfdce494243a61b8ea572d", + "7 | Transfer 3 [5/5] : fc\" to chain \"2\"", + "8 | Transfer 4 [1/4] : 4 from \"aab7d3e457f3f78480832d6ac4ace7", + "8 | Transfer 4 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "8 | Transfer 4 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "8 | Transfer 4 [4/4] : 71e0cfdce494243a61b8ea572dfd\"", + "9 | On Chain : 0", + "10 | Using Gas : at most 600 at price 1.0e-6", + "11 | Transaction hash [1/2] : AoXqSSMScM_u4glsmLV3C8Eawexbm2YEFgFMHY", + "11 | Transaction hash [2/2] : Fzm4o", + "12 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "12 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : aab7d3e457f3f78480832d6ac4ace7387f4606", + "3 | Of Key [2/2] : 20a63a5b68c8c799d6bff1566a", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 1 from \"aab7d3e457f3f78480832d6ac4ace7", + "5 | Transfer 1 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "5 | Transfer 1 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "5 | Transfer 1 [4/4] : 71e0cfdce494243a61b8ea572dfa\"", + "6 | Transfer 2 [1/5] : Cross-chain 2 from \"aab7d3e457f3f78480", + "6 | Transfer 2 [2/5] : 832d6ac4ace7387f460620a63a5b68c8c799d6", + "6 | Transfer 2 [3/5] : bff1566a\" to \"4c310df6224d674d80463a29", + "6 | Transfer 2 [4/5] : cde00cb0ecfb71e0cfdce494243a61b8ea572d", + "6 | Transfer 2 [5/5] : fb\" to chain \"3\"", + "7 | Transfer 3 [1/5] : Cross-chain 3 from \"aab7d3e457f3f78480", + "7 | Transfer 3 [2/5] : 832d6ac4ace7387f460620a63a5b68c8c799d6", + "7 | Transfer 3 [3/5] : bff1566a\" to \"4c310df6224d674d80463a29", + "7 | Transfer 3 [4/5] : cde00cb0ecfb71e0cfdce494243a61b8ea572d", + "7 | Transfer 3 [5/5] : fc\" to chain \"2\"", + "8 | Transfer 4 [1/4] : 4 from \"aab7d3e457f3f78480832d6ac4ace7", + "8 | Transfer 4 [2/4] : 387f460620a63a5b68c8c799d6bff1566a\" to", + "8 | Transfer 4 [3/4] : \"4c310df6224d674d80463a29cde00cb0ecfb", + "8 | Transfer 4 [4/4] : 71e0cfdce494243a61b8ea572dfd\"", + "9 | On Chain : 0", + "10 | Using Gas : at most 600 at price 1.0e-6", + "11 | Transaction hash [1/2] : AoXqSSMScM_u4glsmLV3C8Eawexbm2YEFgFMHY", + "11 | Transaction hash [2/2] : Fzm4o", + "12 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "12 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 17, + "name": "meta_field_missing", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2239373930643131393538396132363131346531613432643932353938623366363332353531633536363831396563343865306538633534646165366562623432222C31315D2C226E616D65223A22636F696E2E5452414E53464552227D5D7D5D2C226D657461223A7B22756E6B6E6F776E2D6669656C64223A747275652C226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 11 from \"83934c0f9b005f378ba3520f9dea9", + "5 | Transfer 1 [2/4] : 52fb0a90e5aa36f1b5ff837d9b30c471790\" t", + "5 | Transfer 1 [3/4] : o \"9790d119589a26114e1a42d92598b3f6325", + "5 | Transfer 1 [4/4] : 51c566819ec48e0e8c54dae6ebb42\"", + "6 | CAUTION [1/2] : 'meta' field of transaction not recogn", + "6 | CAUTION [2/2] : ized", + "7 | Transaction hash [1/2] : fysHQicr1iPz-sbSntIM3Rx_Iw_agBhRxt-XL9", + "7 | Transaction hash [2/2] : X7ENk", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Transfer 1 [1/4] : 11 from \"83934c0f9b005f378ba3520f9dea9", + "5 | Transfer 1 [2/4] : 52fb0a90e5aa36f1b5ff837d9b30c471790\" t", + "5 | Transfer 1 [3/4] : o \"9790d119589a26114e1a42d92598b3f6325", + "5 | Transfer 1 [4/4] : 51c566819ec48e0e8c54dae6ebb42\"", + "6 | CAUTION [1/2] : 'meta' field of transaction not recogn", + "6 | CAUTION [2/2] : ized", + "7 | Transaction hash [1/2] : fysHQicr1iPz-sbSntIM3Rx_Iw_agBhRxt-XL9", + "7 | Transaction hash [2/2] : X7ENk", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 18, + "name": "arbitrary_cap_with_no_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B5D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, no args", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : hnaoFEVgtSMrwKbm2Ui4wnARtUwMo6rtB3fnvZ", + "8 | Transaction hash [2/2] : Gb8oE", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER, no args", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : hnaoFEVgtSMrwKbm2Ui4wnARtUwMo6rtB3fnvZ", + "8 | Transaction hash [2/2] : Gb8oE", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 19, + "name": "arbitrary_cap_with_one_arg", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930225D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/3] : name: mycoin.MY_TRANSFER, arg 1: \"8393", + "5 | Unknown Capability 1 [2/3] : 4c0f9b005f378ba3520f9dea952fb0a90e5aa3", + "5 | Unknown Capability 1 [3/3] : 6f1b5ff837d9b30c471790\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : kQqVYwYzDNSKqcRwJ3Yd4xgG2UW9j2sdcupQx-", + "8 | Transaction hash [2/2] : T6XEY", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/3] : name: mycoin.MY_TRANSFER, arg 1: \"8393", + "5 | Unknown Capability 1 [2/3] : 4c0f9b005f378ba3520f9dea952fb0a90e5aa3", + "5 | Unknown Capability 1 [3/3] : 6f1b5ff837d9b30c471790\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : kQqVYwYzDNSKqcRwJ3Yd4xgG2UW9j2sdcupQx-", + "8 | Transaction hash [2/2] : T6XEY", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 20, + "name": "arbitrary_cap_with_two_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267225D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/4] : name: mycoin.MY_TRANSFER, arg 1: \"8393", + "5 | Unknown Capability 1 [2/4] : 4c0f9b005f378ba3520f9dea952fb0a90e5aa3", + "5 | Unknown Capability 1 [3/4] : 6f1b5ff837d9b30c471790\", arg 2: \"secon", + "5 | Unknown Capability 1 [4/4] : d arg\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : ONXn9kz2V9InGB-RddO3kUCy-GHQOEs8jRYqO2", + "8 | Transaction hash [2/2] : vzxuY", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/4] : name: mycoin.MY_TRANSFER, arg 1: \"8393", + "5 | Unknown Capability 1 [2/4] : 4c0f9b005f378ba3520f9dea952fb0a90e5aa3", + "5 | Unknown Capability 1 [3/4] : 6f1b5ff837d9b30c471790\", arg 2: \"secon", + "5 | Unknown Capability 1 [4/4] : d arg\"", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : ONXn9kz2V9InGB-RddO3kUCy-GHQOEs8jRYqO2", + "8 | Transaction hash [2/2] : vzxuY", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 21, + "name": "arbitrary_cap_with_two_args_one_num", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267222C32322E325D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/4] : name: mycoin.MY_TRANSFER, arg 1: \"8393", + "5 | Unknown Capability 1 [2/4] : 4c0f9b005f378ba3520f9dea952fb0a90e5aa3", + "5 | Unknown Capability 1 [3/4] : 6f1b5ff837d9b30c471790\", arg 2: \"secon", + "5 | Unknown Capability 1 [4/4] : d arg\", arg 3: 22.2", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : OEV1W2Adz7vvU3qYzV9V48pDhxRdFDi2KG4JXx", + "8 | Transaction hash [2/2] : 73WTA", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/4] : name: mycoin.MY_TRANSFER, arg 1: \"8393", + "5 | Unknown Capability 1 [2/4] : 4c0f9b005f378ba3520f9dea952fb0a90e5aa3", + "5 | Unknown Capability 1 [3/4] : 6f1b5ff837d9b30c471790\", arg 2: \"secon", + "5 | Unknown Capability 1 [4/4] : d arg\", arg 3: 22.2", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : OEV1W2Adz7vvU3qYzV9V48pDhxRdFDi2KG4JXx", + "8 | Transaction hash [2/2] : 73WTA", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 22, + "name": "arbitrary_cap_with_various_json_types", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B7B226B657931223A7B226B657932223A2276616C32227D2C226B657933223A2D322E34362C226B657934223A7B226B657935223A747275652C226B657936223A7B226B657937223A302E30317D2C226B657938223A5B2261222C66616C73652C6E756C6C2C392C31302E32332C2D35382E32345D7D7D2C7B7D2C5B5D2C66616C73652C6E756C6C5D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/6] : name: mycoin.MY_TRANSFER, arg 1: {\"key", + "5 | Unknown Capability 1 [2/6] : 1\":{\"key2\":\"val2\"},\"key3\":-2.46,\"key4\"", + "5 | Unknown Capability 1 [3/6] : :{\"key5\":true,\"key6\":{\"key7\":0.01},\"ke", + "5 | Unknown Capability 1 [4/6] : y8\":[\"a\",false,null,9,10.23,-58.24]}},", + "5 | Unknown Capability 1 [5/6] : arg 2: {}, arg 3: [], arg 4: false, a", + "5 | Unknown Capability 1 [6/6] : rg 5: null", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : 5RygRqoczKtecEebMtaPLrulHa5aprNcjkRhMA", + "8 | Transaction hash [2/2] : AogNc", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/6] : name: mycoin.MY_TRANSFER, arg 1: {\"key", + "5 | Unknown Capability 1 [2/6] : 1\":{\"key2\":\"val2\"},\"key3\":-2.46,\"key4\"", + "5 | Unknown Capability 1 [3/6] : :{\"key5\":true,\"key6\":{\"key7\":0.01},\"ke", + "5 | Unknown Capability 1 [4/6] : y8\":[\"a\",false,null,9,10.23,-58.24]}},", + "5 | Unknown Capability 1 [5/6] : arg 2: {}, arg 3: [], arg 4: false, a", + "5 | Unknown Capability 1 [6/6] : rg 5: null", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | Transaction hash [1/2] : 5RygRqoczKtecEebMtaPLrulHa5aprNcjkRhMA", + "8 | Transaction hash [2/2] : AogNc", + "9 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "9 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 23, + "name": "multiple_arbitrary_caps", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B5D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455230227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455231227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455232227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267222C32322E325D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455233227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C227365636F6E6420617267222C353030302C32322E325D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455234227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", + "6 | Unknown Capability 2 [1/3] : name: mycoin.MY_TRANSFER1, arg 1: \"839", + "6 | Unknown Capability 2 [2/3] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "6 | Unknown Capability 2 [3/3] : 36f1b5ff837d9b30c471790\"", + "7 | Unknown Capability 3 [1/4] : name: mycoin.MY_TRANSFER2, arg 1: \"839", + "7 | Unknown Capability 3 [2/4] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "7 | Unknown Capability 3 [3/4] : 36f1b5ff837d9b30c471790\", arg 2: \"seco", + "7 | Unknown Capability 3 [4/4] : nd arg\"", + "8 | Unknown Capability 4 [1/4] : name: mycoin.MY_TRANSFER3, arg 1: \"839", + "8 | Unknown Capability 4 [2/4] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "8 | Unknown Capability 4 [3/4] : 36f1b5ff837d9b30c471790\", arg 2: \"seco", + "8 | Unknown Capability 4 [4/4] : nd arg\", arg 3: 22.2", + "9 | Unknown Capability 5 [1/4] : name: mycoin.MY_TRANSFER4, arg 1: \"839", + "9 | Unknown Capability 5 [2/4] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "9 | Unknown Capability 5 [3/4] : 36f1b5ff837d9b30c471790\", arg 2: \"seco", + "9 | Unknown Capability 5 [4/4] : nd arg\", arg 3: 5000, arg 4: 22.2", + "10 | On Chain : 0", + "11 | Using Gas : at most 600 at price 1.0e-5", + "12 | Transaction hash [1/2] : QJDO0ks635Xpnq2GC85cqoQUxLgESujMgun7NU", + "12 | Transaction hash [2/2] : grf5E", + "13 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "13 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", + "6 | Unknown Capability 2 [1/3] : name: mycoin.MY_TRANSFER1, arg 1: \"839", + "6 | Unknown Capability 2 [2/3] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "6 | Unknown Capability 2 [3/3] : 36f1b5ff837d9b30c471790\"", + "7 | Unknown Capability 3 [1/4] : name: mycoin.MY_TRANSFER2, arg 1: \"839", + "7 | Unknown Capability 3 [2/4] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "7 | Unknown Capability 3 [3/4] : 36f1b5ff837d9b30c471790\", arg 2: \"seco", + "7 | Unknown Capability 3 [4/4] : nd arg\"", + "8 | Unknown Capability 4 [1/4] : name: mycoin.MY_TRANSFER3, arg 1: \"839", + "8 | Unknown Capability 4 [2/4] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "8 | Unknown Capability 4 [3/4] : 36f1b5ff837d9b30c471790\", arg 2: \"seco", + "8 | Unknown Capability 4 [4/4] : nd arg\", arg 3: 22.2", + "9 | Unknown Capability 5 [1/4] : name: mycoin.MY_TRANSFER4, arg 1: \"839", + "9 | Unknown Capability 5 [2/4] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "9 | Unknown Capability 5 [3/4] : 36f1b5ff837d9b30c471790\", arg 2: \"seco", + "9 | Unknown Capability 5 [4/4] : nd arg\", arg 3: 5000, arg 4: 22.2", + "10 | On Chain : 0", + "11 | Using Gas : at most 600 at price 1.0e-5", + "12 | Transaction hash [1/2] : QJDO0ks635Xpnq2GC85cqoQUxLgESujMgun7NU", + "12 | Transaction hash [2/2] : grf5E", + "13 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "13 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 24, + "name": "multiple_arbitrary_caps_multiple_transfers", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B5D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455230227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455231227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373931222C345D2C226E616D65223A22636F696E2E5452414E53464552227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373931222C32322E322C2234225D2C226E616D65223A22636F696E2E5452414E534645525F58434841494E227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373932222C353030302C2230225D2C226E616D65223A226D79636F696E2E4D595F5452414E5346455234227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", + "6 | Unknown Capability 2 [1/3] : name: mycoin.MY_TRANSFER1, arg 1: \"839", + "6 | Unknown Capability 2 [2/3] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "6 | Unknown Capability 2 [3/3] : 36f1b5ff837d9b30c471790\"", + "7 | Transfer 1 [1/4] : 4 from \"83934c0f9b005f378ba3520f9dea95", + "7 | Transfer 1 [2/4] : 2fb0a90e5aa36f1b5ff837d9b30c471790\" to", + "7 | Transfer 1 [3/4] : \"83934c0f9b005f378ba3520f9dea952fb0a9", + "7 | Transfer 1 [4/4] : 0e5aa36f1b5ff837d9b30c471791\"", + "8 | Transfer 2 [1/5] : Cross-chain 22.2 from \"83934c0f9b005f3", + "8 | Transfer 2 [2/5] : 78ba3520f9dea952fb0a90e5aa36f1b5ff837d", + "8 | Transfer 2 [3/5] : 9b30c471790\" to \"83934c0f9b005f378ba35", + "8 | Transfer 2 [4/5] : 20f9dea952fb0a90e5aa36f1b5ff837d9b30c4", + "8 | Transfer 2 [5/5] : 71791\" to chain \"4\"", + "9 | Unknown Capability 3 [1/6] : name: mycoin.MY_TRANSFER4, arg 1: \"839", + "9 | Unknown Capability 3 [2/6] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "9 | Unknown Capability 3 [3/6] : 36f1b5ff837d9b30c471790\", arg 2: \"8393", + "9 | Unknown Capability 3 [4/6] : 4c0f9b005f378ba3520f9dea952fb0a90e5aa3", + "9 | Unknown Capability 3 [5/6] : 6f1b5ff837d9b30c471792\", arg 3: 5000, ", + "9 | Unknown Capability 3 [6/6] : arg 4: \"0\"", + "10 | On Chain : 0", + "11 | Using Gas : at most 600 at price 1.0e-5", + "12 | Transaction hash [1/2] : yMXcVG1vcnLrbtdiKHI1MAYgrBgoDqr15YSRID", + "12 | Transaction hash [2/2] : 70DyU", + "13 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "13 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 : name: mycoin.MY_TRANSFER0, no args", + "6 | Unknown Capability 2 [1/3] : name: mycoin.MY_TRANSFER1, arg 1: \"839", + "6 | Unknown Capability 2 [2/3] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "6 | Unknown Capability 2 [3/3] : 36f1b5ff837d9b30c471790\"", + "7 | Transfer 1 [1/4] : 4 from \"83934c0f9b005f378ba3520f9dea95", + "7 | Transfer 1 [2/4] : 2fb0a90e5aa36f1b5ff837d9b30c471790\" to", + "7 | Transfer 1 [3/4] : \"83934c0f9b005f378ba3520f9dea952fb0a9", + "7 | Transfer 1 [4/4] : 0e5aa36f1b5ff837d9b30c471791\"", + "8 | Transfer 2 [1/5] : Cross-chain 22.2 from \"83934c0f9b005f3", + "8 | Transfer 2 [2/5] : 78ba3520f9dea952fb0a90e5aa36f1b5ff837d", + "8 | Transfer 2 [3/5] : 9b30c471790\" to \"83934c0f9b005f378ba35", + "8 | Transfer 2 [4/5] : 20f9dea952fb0a90e5aa36f1b5ff837d9b30c4", + "8 | Transfer 2 [5/5] : 71791\" to chain \"4\"", + "9 | Unknown Capability 3 [1/6] : name: mycoin.MY_TRANSFER4, arg 1: \"839", + "9 | Unknown Capability 3 [2/6] : 34c0f9b005f378ba3520f9dea952fb0a90e5aa", + "9 | Unknown Capability 3 [3/6] : 36f1b5ff837d9b30c471790\", arg 2: \"8393", + "9 | Unknown Capability 3 [4/6] : 4c0f9b005f378ba3520f9dea952fb0a90e5aa3", + "9 | Unknown Capability 3 [5/6] : 6f1b5ff837d9b30c471792\", arg 3: 5000, ", + "9 | Unknown Capability 3 [6/6] : arg 4: \"0\"", + "10 | On Chain : 0", + "11 | Using Gas : at most 600 at price 1.0e-5", + "12 | Transaction hash [1/2] : yMXcVG1vcnLrbtdiKHI1MAYgrBgoDqr15YSRID", + "12 | Transaction hash [2/2] : 70DyU", + "13 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "13 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + }, + { + "index": 25, + "name": "arbitrary_caps_large_args", + "blob": "7B226E6574776F726B4964223A226D61696E6E65743031222C227061796C6F6164223A7B2265786563223A7B2264617461223A7B7D2C22636F6465223A2228636F696E2E7472616E73666572205C22383339333463306639623030356633373862613335323066396465613935326662306139306535616133366631623566663833376439623330633437313739305C22205C22393739306431313935383961323631313465316134326439323539386233663633323535316335363638313965633438653065386335346461653665626234325C222031312E3029227D7D2C227369676E657273223A5B7B227075624B6579223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C22636C697374223A5B7B2261726773223A5B5D2C226E616D65223A22636F696E2E474153227D2C7B2261726773223A5B2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930222C226164666173222C342C352C362C372C385D2C226E616D65223A226D79636F696E2E4D595F5452414E53464552227D5D7D5D2C226D657461223A7B226372656174696F6E54696D65223A313633343030393231342C2274746C223A32383830302C226761734C696D6974223A3630302C22636861696E4964223A2230222C226761735072696365223A312E30652D352C2273656E646572223A2238333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930227D2C226E6F6E6365223A225C22323032312D31302D31325430333A32373A35332E3730305A5C22227D", + "output": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/2] : name: mycoin.MY_TRANSFER, args cannot ", + "5 | Unknown Capability 1 [2/2] : be displayed on Ledger", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | WARNING [1/3] : Transaction too large for Ledger to di", + "8 | WARNING [2/3] : splay. PROCEED WITH GREAT CAUTION. D", + "8 | WARNING [3/3] : o you want to continue?", + "9 | Transaction hash [1/2] : Y2q38WX4sd5fWzw2knr7mfAltsaYxhWnDGtFaZ", + "9 | Transaction hash [2/2] : 7NV40", + "10 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "10 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ], + "output_expert": [ + "0 | Signing : Transaction", + "1 | On Network : mainnet01", + "2 | Requiring : Capabilities", + "3 | Of Key [1/2] : 83934c0f9b005f378ba3520f9dea952fb0a90e", + "3 | Of Key [2/2] : 5aa36f1b5ff837d9b30c471790", + "4 | Paying Gas : ", + "5 | Unknown Capability 1 [1/2] : name: mycoin.MY_TRANSFER, args cannot ", + "5 | Unknown Capability 1 [2/2] : be displayed on Ledger", + "6 | On Chain : 0", + "7 | Using Gas : at most 600 at price 1.0e-5", + "8 | WARNING [1/3] : Transaction too large for Ledger to di", + "8 | WARNING [2/3] : splay. PROCEED WITH GREAT CAUTION. D", + "8 | WARNING [3/3] : o you want to continue?", + "9 | Transaction hash [1/2] : Y2q38WX4sd5fWzw2knr7mfAltsaYxhWnDGtFaZ", + "9 | Transaction hash [2/2] : 7NV40", + "10 | Sign for Address [1/2] : 8d5d63bb1071a8dfc5c09ac96cfa50341a74eb", + "10 | Sign for Address [2/2] : 91b6ea9ee5724cde09ef758bf2" + ] + } ] \ No newline at end of file From 363e49900d3e6b59804d9360e11da0dc58fc68a1 Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Mon, 19 Aug 2024 12:26:02 +0200 Subject: [PATCH 11/34] Error checking --- app/src/items.c | 49 +++++++++++++++++++++--------------------- app/src/items_defs.h | 20 +++++++++++++++-- app/src/items_format.c | 16 +++++++------- app/src/parser.c | 9 ++++---- app/src/parser_impl.c | 10 +++++---- 5 files changed, 62 insertions(+), 42 deletions(-) diff --git a/app/src/items.c b/app/src/items.c index 12c7ecc..68b1e2a 100644 --- a/app/src/items.c +++ b/app/src/items.c @@ -59,10 +59,9 @@ item_array_t *items_getItemArray() { } void items_storeItems() { - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; uint8_t items_idx = 0; uint8_t unknown_capabitilies = 1; - uint16_t token_index = 0; + parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; items_storeSigningTransaction(&items_idx); @@ -108,7 +107,9 @@ static items_error_t items_storeSigningTransaction(uint8_t *items_idx) { } static items_error_t items_storeNetwork(uint8_t *items_idx) { - if (parser_getJsonValue(&item_array.items[*items_idx].json_token_index, JSON_NETWORK_ID) == parser_ok) { + uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; + + if (parser_getJsonValue(curr_token_idx, JSON_NETWORK_ID) == parser_ok) { strcpy(item_array.items[*items_idx].key, "On Network"); item_array.toString[*items_idx] = items_stdToDisplayString; (*items_idx)++; @@ -126,11 +127,11 @@ static items_error_t items_storeRequiringCapabilities(uint8_t *items_idx) { } static items_error_t items_storeKey(uint8_t *items_idx) { - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; if (parser_getJsonValue(curr_token_idx, JSON_SIGNERS) == parser_ok) { - array_get_nth_element(&json_all, *curr_token_idx, 0, curr_token_idx); + array_get_nth_element(json_all, *curr_token_idx, 0, curr_token_idx); if (parser_getJsonValue(curr_token_idx, JSON_PUBKEY) == parser_ok) { strcpy(item_array.items[*items_idx].key, "Of Key"); item_array.toString[*items_idx] = items_stdToDisplayString; @@ -142,20 +143,20 @@ static items_error_t items_storeKey(uint8_t *items_idx) { } static items_error_t items_validateSigners(uint8_t *items_idx) { - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; uint16_t token_index = 0; if (parser_getJsonValue(curr_token_idx, JSON_SIGNERS) == parser_ok) { - array_get_nth_element(&json_all, *curr_token_idx, 0, curr_token_idx); + array_get_nth_element(json_all, *curr_token_idx, 0, curr_token_idx); if (parser_getJsonValue(curr_token_idx, JSON_CLIST) == parser_ok) { uint16_t clist_token_index = *curr_token_idx; for (uint8_t i = 0; i < parser_getNumberOfClistElements(); i++) { - if (array_get_nth_element(&json_all, clist_token_index, i, &token_index) == parser_ok) { + if (array_get_nth_element(json_all, clist_token_index, i, &token_index) == parser_ok) { uint16_t name_token_index = 0; - if (object_get_value(&json_all, token_index, JSON_NAME, &name_token_index) == parser_ok) { - if (MEMCMP("coin.TRANSFER", json_all.buffer + json_all.tokens[name_token_index].start, + if (object_get_value(json_all, token_index, JSON_NAME, &name_token_index) == parser_ok) { + if (MEMCMP("coin.TRANSFER", json_all->buffer + json_all->tokens[name_token_index].start, sizeof("coin.TRANSFER") - 1) == 0) { if (parser_findPubKeyInClist(item_array.items[*items_idx - 1].json_token_index) == parser_ok) { item_array.items[*items_idx].json_token_index = 0; @@ -180,11 +181,11 @@ static items_error_t items_validateSigners(uint8_t *items_idx) { } static items_error_t items_storePayingGas(uint8_t *items_idx, uint8_t *unknown_capabitilies) { - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; if (parser_getJsonValue(curr_token_idx, JSON_SIGNERS) == parser_ok) { - array_get_nth_element(&json_all, *curr_token_idx, 0, curr_token_idx); + array_get_nth_element(json_all, *curr_token_idx, 0, curr_token_idx); if (parser_getJsonValue(curr_token_idx, JSON_CLIST) == parser_ok) { parser_getGasObject(curr_token_idx); items_storeGasItem(*curr_token_idx, *items_idx, unknown_capabitilies); @@ -198,39 +199,39 @@ static items_error_t items_storePayingGas(uint8_t *items_idx, uint8_t *unknown_c } static items_error_t items_storeAllTransfers(uint8_t *items_idx, uint8_t *unknown_capabitilies) { - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); uint16_t *curr_token_idx = &item_array.items[*items_idx].json_token_index; uint16_t token_index = 0; uint8_t num_of_transfers = 1; if (parser_getJsonValue(curr_token_idx, JSON_SIGNERS) == parser_ok) { - array_get_nth_element(&json_all, *curr_token_idx, 0, curr_token_idx); + array_get_nth_element(json_all, *curr_token_idx, 0, curr_token_idx); if (parser_getJsonValue(curr_token_idx, JSON_CLIST) == parser_ok) { uint16_t clist_token_index = *curr_token_idx; for (uint8_t i = 0; i < parser_getNumberOfClistElements(); i++) { - if (array_get_nth_element(&json_all, clist_token_index, i, &token_index) == parser_ok) { + if (array_get_nth_element(json_all, clist_token_index, i, &token_index) == parser_ok) { uint16_t name_token_index = 0; - if (object_get_value(&json_all, token_index, JSON_NAME, &name_token_index) == parser_ok) { - if (MEMCMP("coin.TRANSFER_XCHAIN", json_all.buffer + json_all.tokens[name_token_index].start, + if (object_get_value(json_all, token_index, JSON_NAME, &name_token_index) == parser_ok) { + if (MEMCMP("coin.TRANSFER_XCHAIN", json_all->buffer + json_all->tokens[name_token_index].start, sizeof("coin.TRANSFER_XCHAIN") - 1) == 0) { *curr_token_idx = token_index; - items_storeCrossTransferItem(&json_all, token_index, *items_idx, &num_of_transfers, unknown_capabitilies); + items_storeCrossTransferItem(json_all, token_index, *items_idx, &num_of_transfers, unknown_capabitilies); (*items_idx)++; - } else if (MEMCMP("coin.TRANSFER", json_all.buffer + json_all.tokens[name_token_index].start, + } else if (MEMCMP("coin.TRANSFER", json_all->buffer + json_all->tokens[name_token_index].start, sizeof("coin.TRANSFER") - 1) == 0) { *curr_token_idx = token_index; - items_storeTransferItem(&json_all, token_index, *items_idx, &num_of_transfers, unknown_capabitilies); + items_storeTransferItem(json_all, token_index, *items_idx, &num_of_transfers, unknown_capabitilies); (*items_idx)++; - } else if (MEMCMP("coin.ROTATE", json_all.buffer + json_all.tokens[name_token_index].start, + } else if (MEMCMP("coin.ROTATE", json_all->buffer + json_all->tokens[name_token_index].start, sizeof("coin.ROTATE") - 1) == 0) { *curr_token_idx = token_index; - items_storeRotateItem(&json_all, token_index, *items_idx, unknown_capabitilies); + items_storeRotateItem(json_all, token_index, *items_idx, unknown_capabitilies); (*items_idx)++; - } else if (MEMCMP("coin.GAS", json_all.buffer + json_all.tokens[name_token_index].start, + } else if (MEMCMP("coin.GAS", json_all->buffer + json_all->tokens[name_token_index].start, sizeof("coin.GAS") - 1) != 0) { // Any other case that's not coin.GAS *curr_token_idx = token_index; - items_storeUnknownItem(&json_all, token_index, *items_idx, unknown_capabitilies); + items_storeUnknownItem(json_all, token_index, *items_idx, unknown_capabitilies); item_array.toString[*items_idx] = items_unknownCapabilityToDisplayString; (*items_idx)++; } diff --git a/app/src/items_defs.h b/app/src/items_defs.h index 8eae797..73b2f10 100644 --- a/app/src/items_defs.h +++ b/app/src/items_defs.h @@ -18,6 +18,22 @@ #include #include "zxtypes.h" +#define MAX_NUMBER_OF_ITEMS 25 + +#define PARSER_TO_ITEMS_ERROR(__CALL) \ + { \ + parser_error_t __err = __CALL; \ + CHECK_APP_CANARY() \ + if (__err != parser_ok) return items_error; \ + } + +#define ITEMS_TO_PARSER_ERROR(__CALL) \ + { \ + items_error_t __err = __CALL; \ + CHECK_APP_CANARY() \ + if (__err != items_ok) return parser_unexpected_error; \ + } + typedef struct { char key[25]; uint16_t json_token_index; @@ -30,7 +46,7 @@ typedef enum { } items_error_t; typedef struct { - item_t items[20]; + item_t items[MAX_NUMBER_OF_ITEMS]; uint8_t numOfItems; - items_error_t (*toString[20])(item_t item, char *outVal, uint16_t *outValLen); + items_error_t (*toString[MAX_NUMBER_OF_ITEMS])(item_t item, char *outVal, uint16_t *outValLen); } item_array_t; diff --git a/app/src/items_format.c b/app/src/items_format.c index a434bc8..4024014 100644 --- a/app/src/items_format.c +++ b/app/src/items_format.c @@ -78,11 +78,11 @@ items_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t object_get_value(&json_all, item_token_index, "args", &token_index); - parser_arrayElementToString(token_index, 0, from, &from_len); + PARSER_TO_ITEMS_ERROR(parser_arrayElementToString(token_index, 0, from, &from_len)); - parser_arrayElementToString(token_index, 1, to, &to_len); + PARSER_TO_ITEMS_ERROR(parser_arrayElementToString(token_index, 1, to, &to_len)); - parser_arrayElementToString(token_index, 2, amount, &amount_len); + PARSER_TO_ITEMS_ERROR(parser_arrayElementToString(token_index, 2, amount, &amount_len)); *outValLen = amount_len + from_len + to_len + sizeof(" from ") + sizeof(" to ") + 4 * sizeof("\""); snprintf(outVal, *outValLen, "%s from \"%s\" to \"%s\"", amount, from, to); @@ -105,13 +105,13 @@ items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint object_get_value(&json_all, item_token_index, "args", &token_index); - parser_arrayElementToString(token_index, 0, from, &from_len); + PARSER_TO_ITEMS_ERROR(parser_arrayElementToString(token_index, 0, from, &from_len)); - parser_arrayElementToString(token_index, 1, to, &to_len); + PARSER_TO_ITEMS_ERROR(parser_arrayElementToString(token_index, 1, to, &to_len)); - parser_arrayElementToString(token_index, 2, amount, &amount_len); + PARSER_TO_ITEMS_ERROR(parser_arrayElementToString(token_index, 2, amount, &amount_len)); - parser_arrayElementToString(token_index, 3, chain, &chain_len); + PARSER_TO_ITEMS_ERROR(parser_arrayElementToString(token_index, 3, chain, &chain_len)); *outValLen = amount_len + from_len + to_len + chain_len + sizeof("Cross-chain ") + sizeof(" from ") + sizeof(" to ") + 6 * sizeof("\"") + sizeof(" to chain "); snprintf(outVal, *outValLen, "Cross-chain %s from \"%s\" to \"%s\" to chain \"%s\"", amount, from, to, chain); @@ -157,7 +157,7 @@ items_error_t items_gasToDisplayString(__Z_UNUSED item_t item, char *outVal, uin return items_ok; } -items_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { +items_error_t items_hashToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { *outValLen = sizeof(base64_hash); snprintf(outVal, *outValLen, "%s", base64_hash); return items_ok; diff --git a/app/src/parser.c b/app/src/parser.c index 2415c9b..9759f97 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -54,9 +54,6 @@ parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t d } parser_error_t parser_validate(parser_context_t *ctx) { - - // TODO: validate the tx (JSON validation) - // Iterate through all items to check that all can be shown and are valid uint8_t numItems = 0; CHECK_ERROR(parser_getNumItems(ctx, &numItems)) @@ -100,6 +97,8 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c *pageCount = 1; uint8_t numItems = 0; item_array_t *item_array = items_getItemArray(); + char tempVal[300] = {0}; + uint16_t tempValLen = 0; CHECK_ERROR(parser_getNumItems(ctx, &numItems)) CHECK_APP_CANARY() @@ -107,7 +106,9 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c cleanOutput(outKey, outKeyLen, outVal, outValLen); snprintf(outKey, outKeyLen, "%s", item_array->items[displayIdx].key); - item_array->toString[displayIdx](item_array->items[displayIdx], outVal, &outValLen); + ITEMS_TO_PARSER_ERROR(item_array->toString[displayIdx](item_array->items[displayIdx], tempVal, &tempValLen)); + pageString(outVal, outValLen, tempVal, pageIdx, pageCount); + return parser_ok; } diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index f89bc0e..491b231 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -105,10 +105,12 @@ parser_error_t parser_arrayElementToString(uint16_t json_token_index, uint16_t e uint16_t token_index = 0; parsed_json_t json_all = parser_tx_obj.tx_json.json; - array_get_nth_element(&json_all, json_token_index, element_idx, &token_index); + CHECK_ERROR(array_get_nth_element(&json_all, json_token_index, element_idx, &token_index)); strncpy(outVal, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start; outVal[*outValLen] = '\0'; + + return parser_ok; } parser_error_t parser_getGasObject(uint16_t *json_token_index) { @@ -117,9 +119,9 @@ parser_error_t parser_getGasObject(uint16_t *json_token_index) { uint16_t name_token_index = 0; for (uint16_t i = 0; i < parser_getNumberOfClistElements(); i++) { - array_get_nth_element(json_all, *json_token_index, i, &token_index); + CHECK_ERROR(array_get_nth_element(json_all, *json_token_index, i, &token_index)); - object_get_value(json_all, token_index, JSON_NAME, &name_token_index); + CHECK_ERROR(object_get_value(json_all, token_index, JSON_NAME, &name_token_index)); if (MEMCMP("coin.GAS", json_all->buffer + json_all->tokens[name_token_index].start, json_all->tokens[name_token_index].end - json_all->tokens[name_token_index].start) == 0) { *json_token_index = token_index; @@ -131,7 +133,7 @@ parser_error_t parser_getGasObject(uint16_t *json_token_index) { } parser_error_t parser_validateMetaField() { - char *keywords[20] = { + const char *keywords[20] = { JSON_CREATION_TIME, JSON_TTL, JSON_GAS_LIMIT, From 2be9fa026df440d2173444cbb07b3ed5d7b27332 Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Mon, 19 Aug 2024 23:24:34 +0200 Subject: [PATCH 12/34] Solve stack overflows --- app/src/items.c | 24 ++++------ app/src/items.h | 2 +- app/src/items_format.c | 80 +++++++++++++++++-------------- app/src/items_format.h | 1 + app/src/jsmn/jsmn.c | 37 ++++++-------- app/src/jsmn/jsmn.h | 5 +- app/src/json/json_parser.c | 19 +++++++- app/src/json/json_parser.h | 2 +- app/src/parser.c | 1 - app/src/parser_impl.c | 50 +++++++++---------- tests_zemu/tests/common.ts | 2 +- tests_zemu/tests/standard.test.ts | 64 +++++++++++++------------ 12 files changed, 148 insertions(+), 139 deletions(-) diff --git a/app/src/items.c b/app/src/items.c index 68b1e2a..6912ccd 100644 --- a/app/src/items.c +++ b/app/src/items.c @@ -32,7 +32,7 @@ static items_error_t items_storeChainId(uint8_t *items_idx); static items_error_t items_storeUsingGas(uint8_t *items_idx); static items_error_t items_checkTxLengths(uint8_t *items_idx); static items_error_t items_storeHash(uint8_t *items_idx); -static items_error_t items_storeSignature(uint8_t *items_idx); +static items_error_t items_storeSignForAddr(uint8_t *items_idx); static items_error_t items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies); static items_error_t items_storeTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); static items_error_t items_storeCrossTransferItem(parsed_json_t *json_all, uint16_t transfer_token_index, uint8_t items_idx, uint8_t *num_of_transfers, uint8_t *unknown_capabitilies); @@ -41,7 +41,7 @@ static items_error_t items_storeUnknownItem(parsed_json_t *json_all, uint16_t tr #define MAX_ITEM_LENGTH_TO_DISPLAY 1000 // TODO : Check other apps to find this number -item_array_t item_array; +item_array_t item_array = {0}; uint8_t hash[BLAKE2B_HASH_SIZE] = {0}; char base64_hash[44]; @@ -61,7 +61,6 @@ item_array_t *items_getItemArray() { void items_storeItems() { uint8_t items_idx = 0; uint8_t unknown_capabitilies = 1; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; items_storeSigningTransaction(&items_idx); @@ -89,7 +88,7 @@ void items_storeItems() { items_storeHash(&items_idx); - items_storeSignature(&items_idx); + items_storeSignForAddr(&items_idx); item_array.numOfItems = items_idx; } @@ -324,16 +323,9 @@ static items_error_t items_storeHash(uint8_t *items_idx) { return items_ok; } -static items_error_t items_storeSignature(uint8_t *items_idx) { +static items_error_t items_storeSignForAddr(uint8_t *items_idx) { strcpy(item_array.items[*items_idx].key, "Sign for Address"); - /* - Currently launching cpp tests, so this is not available - uint8_t address[32]; - uint16_t address_size; - CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); - snprintf(outVal, address_size + 1, "%s", address); - */ - item_array.toString[*items_idx] = items_hashToDisplayString; + item_array.toString[*items_idx] = items_signForAddrToDisplayString; (*items_idx)++; return items_ok; @@ -342,10 +334,10 @@ static items_error_t items_storeSignature(uint8_t *items_idx) { static items_error_t items_storeGasItem(uint16_t json_token_index, uint8_t items_idx, uint8_t *unknown_capabitilies) { uint16_t token_index = 0; uint16_t args_count = 0; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); - object_get_value(&json_all, json_token_index, "args", &token_index); - array_get_element_count(&json_all, token_index, &args_count); + object_get_value(json_all, json_token_index, "args", &token_index); + array_get_element_count(json_all, token_index, &args_count); if (args_count > 0) { snprintf(item_array.items[items_idx].key, sizeof(item_array.items[items_idx].key), "Unknown Capability %d", *unknown_capabitilies); diff --git a/app/src/items.h b/app/src/items.h index c700793..97d6dae 100644 --- a/app/src/items.h +++ b/app/src/items.h @@ -18,8 +18,8 @@ #include #include "zxtypes.h" #include "parser_common.h" -#include "json_parser.h" #include "items_defs.h" +#include "json_parser.h" void items_initItems(); void items_storeItems(); diff --git a/app/src/items_format.c b/app/src/items_format.c index 4024014..8292988 100644 --- a/app/src/items_format.c +++ b/app/src/items_format.c @@ -16,15 +16,16 @@ #include "items_format.h" #include "parser.h" +#include "crypto.h" extern char base64_hash[44]; items_error_t items_stdToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); uint16_t item_token_index = item.json_token_index; - *outValLen = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; - snprintf(outVal, *outValLen, "%s", json_all.buffer + json_all.tokens[item_token_index].start); + *outValLen = json_all->tokens[item_token_index].end - json_all->tokens[item_token_index].start + 1; + snprintf(outVal, *outValLen, "%s", json_all->buffer + json_all->tokens[item_token_index].start); return items_ok; } @@ -73,10 +74,10 @@ items_error_t items_transferToDisplayString(item_t item, char *outVal, uint16_t char from[65]; uint8_t from_len = 0; uint16_t token_index = 0; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); uint16_t item_token_index = item.json_token_index; - object_get_value(&json_all, item_token_index, "args", &token_index); + object_get_value(json_all, item_token_index, "args", &token_index); PARSER_TO_ITEMS_ERROR(parser_arrayElementToString(token_index, 0, from, &from_len)); @@ -100,10 +101,10 @@ items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint char chain[3]; uint8_t chain_len = 0; uint16_t token_index = 0; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); uint16_t item_token_index = item.json_token_index; - object_get_value(&json_all, item_token_index, "args", &token_index); + object_get_value(json_all, item_token_index, "args", &token_index); PARSER_TO_ITEMS_ERROR(parser_arrayElementToString(token_index, 0, from, &from_len)); @@ -122,13 +123,13 @@ items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint items_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { uint16_t token_index = 0; uint16_t item_token_index = item.json_token_index; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); - object_get_value(&json_all, item_token_index, "args", &token_index); - array_get_nth_element(&json_all, token_index, 0, &token_index); + object_get_value(json_all, item_token_index, "args", &token_index); + array_get_nth_element(json_all, token_index, 0, &token_index); - *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("\"\""); - snprintf(outVal, *outValLen, "\"%s\"", json_all.buffer + json_all.tokens[token_index].start); + *outValLen = json_all->tokens[token_index].end - json_all->tokens[token_index].start + sizeof("\"\""); + snprintf(outVal, *outValLen, "\"%s\"", json_all->buffer + json_all->tokens[token_index].start); return items_ok; } @@ -138,18 +139,18 @@ items_error_t items_gasToDisplayString(__Z_UNUSED item_t item, char *outVal, uin uint8_t gasLimit_len = 0; char gasPrice[64]; uint8_t gasPrice_len = 0; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); uint16_t item_token_index = item.json_token_index; uint16_t meta_token_index = item_token_index; parser_getJsonValue(&item_token_index, JSON_GAS_LIMIT); - gasLimit_len = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; - snprintf(gasLimit, gasLimit_len, "%s", json_all.buffer + json_all.tokens[item_token_index].start); + gasLimit_len = json_all->tokens[item_token_index].end - json_all->tokens[item_token_index].start + 1; + snprintf(gasLimit, gasLimit_len, "%s", json_all->buffer + json_all->tokens[item_token_index].start); item_token_index = meta_token_index; parser_getJsonValue(&item_token_index, JSON_GAS_PRICE); - gasPrice_len = json_all.tokens[item_token_index].end - json_all.tokens[item_token_index].start + 1; - snprintf(gasPrice, gasPrice_len, "%s", json_all.buffer + json_all.tokens[item_token_index].start); + gasPrice_len = json_all->tokens[item_token_index].end - json_all->tokens[item_token_index].start + 1; + snprintf(gasPrice, gasPrice_len, "%s", json_all->buffer + json_all->tokens[item_token_index].start); *outValLen = gasLimit_len + gasPrice_len + sizeof("at most ") + sizeof(" at price "); snprintf(outVal, *outValLen, "at most %s at price %s", gasLimit, gasPrice); @@ -163,17 +164,26 @@ items_error_t items_hashToDisplayString(__Z_UNUSED item_t item, char *outVal, ui return items_ok; } +items_error_t items_signForAddrToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen) { + uint8_t address[65]; + uint16_t address_size; + CHECK_ERROR(crypto_fillAddress(address, sizeof(address), &address_size)); + *outValLen = address_size; + snprintf(outVal, address_size, "%s", address); + return items_ok; +} + items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen) { uint16_t token_index = 0; uint16_t args_count = 0; uint8_t len = 0; uint8_t outVal_idx= 0; - parsed_json_t json_all = parser_getParserTxObj()->tx_json.json; + parsed_json_t *json_all = &(parser_getParserTxObj()->tx_json.json); uint16_t item_token_index = item.json_token_index; - object_get_value(&json_all, item_token_index, "name", &token_index); - len = json_all.tokens[token_index].end - json_all.tokens[token_index].start + sizeof("name: "); - snprintf(outVal, len, "name: %s", json_all.buffer + json_all.tokens[token_index].start); + object_get_value(json_all, item_token_index, "name", &token_index); + len = json_all->tokens[token_index].end - json_all->tokens[token_index].start + sizeof("name: "); + snprintf(outVal, len, "name: %s", json_all->buffer + json_all->tokens[token_index].start); outVal_idx += len; // Remove null terminator @@ -190,21 +200,21 @@ items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, return items_ok; } - object_get_value(&json_all, item_token_index, "args", &token_index); - array_get_element_count(&json_all, token_index, &args_count); + object_get_value(json_all, item_token_index, "args", &token_index); + array_get_element_count(json_all, token_index, &args_count); if (args_count) { uint16_t args_token_index = 0; for (uint8_t i = 0; i < args_count - 1; i++) { - array_get_nth_element(&json_all, token_index, i, &args_token_index); - if (json_all.tokens[args_token_index].type == JSMN_STRING) { + array_get_nth_element(json_all, token_index, i, &args_token_index); + if (json_all->tokens[args_token_index].type == JSMN_STRING) { // Strings go in between double quotes - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\","); - snprintf(outVal + outVal_idx, len, "arg %d: \"%s\",", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); + len = json_all->tokens[args_token_index].end - json_all->tokens[args_token_index].start + sizeof("arg X: \"\","); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\",", i + 1, json_all->buffer + json_all->tokens[args_token_index].start); } else { - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: ,"); - snprintf(outVal + outVal_idx, len, "arg %d: %s,", i + 1, json_all.buffer + json_all.tokens[args_token_index].start); + len = json_all->tokens[args_token_index].end - json_all->tokens[args_token_index].start + sizeof("arg X: ,"); + snprintf(outVal + outVal_idx, len, "arg %d: %s,", i + 1, json_all->buffer + json_all->tokens[args_token_index].start); } outVal_idx += len; @@ -213,13 +223,13 @@ items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, } // Last arg (without comma) - array_get_nth_element(&json_all, token_index, args_count - 1, &args_token_index); - if (json_all.tokens[args_token_index].type == JSMN_STRING) { - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: \"\""); - snprintf(outVal + outVal_idx, len, "arg %d: \"%s\"", args_count, json_all.buffer + json_all.tokens[args_token_index].start); + array_get_nth_element(json_all, token_index, args_count - 1, &args_token_index); + if (json_all->tokens[args_token_index].type == JSMN_STRING) { + len = json_all->tokens[args_token_index].end - json_all->tokens[args_token_index].start + sizeof("arg X: \"\""); + snprintf(outVal + outVal_idx, len, "arg %d: \"%s\"", args_count, json_all->buffer + json_all->tokens[args_token_index].start); } else { - len = json_all.tokens[args_token_index].end - json_all.tokens[args_token_index].start + sizeof("arg X: "); - snprintf(outVal + outVal_idx, len, "arg %d: %s", args_count, json_all.buffer + json_all.tokens[args_token_index].start); + len = json_all->tokens[args_token_index].end - json_all->tokens[args_token_index].start + sizeof("arg X: "); + snprintf(outVal + outVal_idx, len, "arg %d: %s", args_count, json_all->buffer + json_all->tokens[args_token_index].start); } outVal_idx += len; } else { diff --git a/app/src/items_format.h b/app/src/items_format.h index 7776c0e..e7b1127 100644 --- a/app/src/items_format.h +++ b/app/src/items_format.h @@ -35,4 +35,5 @@ items_error_t items_crossTransferToDisplayString(item_t item, char *outVal, uint items_error_t items_rotateToDisplayString(item_t item, char *outVal, uint16_t *outValLen); items_error_t items_gasToDisplayString(item_t item, char *outVal, uint16_t *outValLen); items_error_t items_hashToDisplayString(item_t item, char *outVal, uint16_t *outValLen); +items_error_t items_signForAddrToDisplayString(__Z_UNUSED item_t item, char *outVal, uint16_t *outValLen); items_error_t items_unknownCapabilityToDisplayString(item_t item, char *outVal, uint16_t *outValLen); diff --git a/app/src/jsmn/jsmn.c b/app/src/jsmn/jsmn.c index 422139e..b6f4453 100644 --- a/app/src/jsmn/jsmn.c +++ b/app/src/jsmn/jsmn.c @@ -33,10 +33,9 @@ static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, return NULL; } tok = &tokens[parser->toknext++]; - tok->start = tok->end = -1; - tok->size = 0; + tok->start = tok->end = 0xFFFF; #ifdef JSMN_PARENT_LINKS - tok->parent = -1; + tok->parent = 0xFFFF; #endif return tok; } @@ -49,7 +48,6 @@ static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, token->type = type; token->start = start; token->end = end; - token->size = 0; } /** @@ -211,15 +209,14 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, if (token == NULL) { return JSMN_ERROR_NOMEM; } - if (parser->toksuper != -1) { - jsmntok_t *t = &tokens[parser->toksuper]; + if (parser->toksuper != 0xFFFF) { #ifdef JSMN_STRICT /* In strict mode an object or array can't become a key */ + jsmntok_t *t = &tokens[parser->toksuper]; if (t->type == JSMN_OBJECT) { return JSMN_ERROR_INVAL; } #endif - t->size++; #ifdef JSMN_PARENT_LINKS token->parent = parser->toksuper; #endif @@ -240,7 +237,7 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, } token = &tokens[parser->toknext - 1]; for (;;) { - if (token->start != -1 && token->end == -1) { + if (token->start != 0xFFFF && token->end == 0xFFFF) { if (token->type != type) { return JSMN_ERROR_INVAL; } @@ -248,8 +245,8 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, parser->toksuper = token->parent; break; } - if (token->parent == -1) { - if (token->type != type || parser->toksuper == -1) { + if (token->parent == 0xFFFF) { + if (token->type != type || parser->toksuper == 0xFFFF) { return JSMN_ERROR_INVAL; } break; @@ -259,7 +256,7 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, #else for (i = parser->toknext - 1; i >= 0; i--) { token = &tokens[i]; - if (token->start != -1 && token->end == -1) { + if (token->start != 0xFFFF && token->end == 0xFFFF) { if (token->type != type) { return JSMN_ERROR_INVAL; } @@ -274,7 +271,7 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, } for (; i >= 0; i--) { token = &tokens[i]; - if (token->start != -1 && token->end == -1) { + if (token->start != 0xFFFF && token->end == 0xFFFF) { parser->toksuper = i; break; } @@ -287,9 +284,6 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, return r; } count++; - if (parser->toksuper != -1 && tokens != NULL) { - tokens[parser->toksuper].size++; - } break; case '\t': case '\r': @@ -300,7 +294,7 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, parser->toksuper = parser->toknext - 1; break; case ',': - if (tokens != NULL && parser->toksuper != -1 && + if (tokens != NULL && parser->toksuper != 0xFFFF && tokens[parser->toksuper].type != JSMN_ARRAY && tokens[parser->toksuper].type != JSMN_OBJECT) { #ifdef JSMN_PARENT_LINKS @@ -308,7 +302,7 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, #else for (i = parser->toknext - 1; i >= 0; i--) { if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { - if (tokens[i].start != -1 && tokens[i].end == -1) { + if (tokens[i].start != 0xFFFF && tokens[i].end == 0xFFFF) { parser->toksuper = i; break; } @@ -334,10 +328,10 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, case 'f': case 'n': /* And they must not be keys of the object */ - if (tokens != NULL && parser->toksuper != -1) { + if (tokens != NULL && parser->toksuper != 0xFFFF) { const jsmntok_t *t = &tokens[parser->toksuper]; if (t->type == JSMN_OBJECT || - (t->type == JSMN_STRING && t->size != 0)) { + (t->type == JSMN_STRING && (t->end - t->start) != 0)) { return JSMN_ERROR_INVAL; } } @@ -350,9 +344,6 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, return r; } count++; - if (parser->toksuper != -1 && tokens != NULL) { - tokens[parser->toksuper].size++; - } break; #ifdef JSMN_STRICT @@ -366,7 +357,7 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, if (tokens != NULL) { for (i = parser->toknext - 1; i >= 0; i--) { /* Unmatched opened object or array */ - if (tokens[i].start != -1 && tokens[i].end == -1) { + if (tokens[i].start != 0xFFFF && tokens[i].end == 0xFFFF) { return JSMN_ERROR_PART; } } diff --git a/app/src/jsmn/jsmn.h b/app/src/jsmn/jsmn.h index 44dd8a5..f6466aa 100644 --- a/app/src/jsmn/jsmn.h +++ b/app/src/jsmn/jsmn.h @@ -68,9 +68,8 @@ enum jsmnerr { */ typedef struct jsmntok { jsmntype_t type; - int start; - int end; - int size; + unsigned short start; + unsigned short end; #ifdef JSMN_PARENT_LINKS int parent; #endif diff --git a/app/src/json/json_parser.c b/app/src/json/json_parser.c index bffe0f8..804142a 100644 --- a/app/src/json/json_parser.c +++ b/app/src/json/json_parser.c @@ -1,7 +1,22 @@ -#include "json_parser.h" +/******************************************************************************* + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include #include "../common/parser_common.h" -#include "jsmn.h" +#include "jsmn/jsmn.h" +#include "json_parser.h" #define EQUALS(_P, _Q, _LEN) (MEMCMP( (const void*) PIC(_P), (const void*) PIC(_Q), (_LEN))==0) diff --git a/app/src/json/json_parser.h b/app/src/json/json_parser.h index 2b93e48..953a61b 100644 --- a/app/src/json/json_parser.h +++ b/app/src/json/json_parser.h @@ -27,7 +27,7 @@ // Limit depending on target #if defined(TARGET_NANOS) || defined(TARGET_NANOX) #undef MAX_NUMBER_OF_TOKENS -#define MAX_NUMBER_OF_TOKENS 10 // TODO : Check how many are actually needed, currently made to fit in memory. +#define MAX_NUMBER_OF_TOKENS 120 #endif #if defined(TARGET_STAX) || defined(TARGET_FLEX) diff --git a/app/src/parser.c b/app/src/parser.c index 9759f97..c2a7b7a 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -109,6 +109,5 @@ parser_error_t parser_getItem(const parser_context_t *ctx, uint8_t displayIdx, c ITEMS_TO_PARSER_ERROR(item_array->toString[displayIdx](item_array->items[displayIdx], tempVal, &tempValLen)); pageString(outVal, outValLen, tempVal, pageIdx, pageCount); - return parser_ok; } diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 491b231..08f8c68 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -18,28 +18,29 @@ #include "crypto_helper.h" #include +parser_tx_t *parser_tx_obj; -parser_tx_t parser_tx_obj; +parser_error_t _read_json_tx(parser_context_t *c, parser_tx_t *v) { + parser_tx_obj = v; -parser_error_t _read_json_tx(parser_context_t *c, __Z_UNUSED parser_tx_t *v) { - CHECK_ERROR(json_parse(&parser_tx_obj.tx_json.json, (const char *) c->buffer, + CHECK_ERROR(json_parse(&(parser_tx_obj->tx_json.json), (const char *) c->buffer, c->bufferLen)); - parser_tx_obj.tx_json.tx = (const char *) c->buffer; - parser_tx_obj.tx_json.flags.cache_valid = 0; - parser_tx_obj.tx_json.filter_msg_type_count = 0; - parser_tx_obj.tx_json.filter_msg_from_count = 0; + parser_tx_obj->tx_json.tx = (const char *) c->buffer; + parser_tx_obj->tx_json.flags.cache_valid = 0; + parser_tx_obj->tx_json.filter_msg_type_count = 0; + parser_tx_obj->tx_json.filter_msg_from_count = 0; return parser_ok; } parser_tx_t *parser_getParserTxObj() { - return &parser_tx_obj; + return parser_tx_obj; } uint16_t parser_getNumberOfClistElements() { uint16_t number_of_elements = 0; - parsed_json_t *json_all = &parser_tx_obj.tx_json.json; + parsed_json_t *json_all = &parser_tx_obj->tx_json.json; uint16_t token_index = 0; parser_getJsonValue(&token_index, JSON_SIGNERS); @@ -52,7 +53,7 @@ uint16_t parser_getNumberOfClistElements() { } parser_error_t parser_findPubKeyInClist(uint16_t key_token_index) { - parsed_json_t *json_all = &parser_tx_obj.tx_json.json; + parsed_json_t *json_all = &parser_tx_obj->tx_json.json; uint16_t token_index = 0; uint16_t clist_token_index = 0; uint16_t args_token_index = 0; @@ -85,14 +86,12 @@ parser_error_t parser_findPubKeyInClist(uint16_t key_token_index) { } parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key) { - parsed_json_t json_obj; + parsed_json_t *json_all = &(parser_tx_obj->tx_json.json); uint16_t token_index = 0; - CHECK_ERROR(object_get_value(&parser_tx_obj.tx_json.json, *json_token_index, key, &token_index)); + CHECK_ERROR(object_get_value(json_all, *json_token_index, key, &token_index)); - CHECK_ERROR(json_parse(&json_obj, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[token_index].start, parser_tx_obj.tx_json.json.tokens[token_index].end - parser_tx_obj.tx_json.json.tokens[token_index].start)); - - if (MEMCMP("null", json_obj.buffer, json_obj.bufferLen) == 0) { + if (MEMCMP("null", json_all->buffer + json_all->tokens[token_index].start, json_all->tokens[token_index].end - json_all->tokens[token_index].start) == 0) { return parser_no_data; } @@ -103,11 +102,11 @@ parser_error_t parser_getJsonValue(uint16_t *json_token_index, const char *key) parser_error_t parser_arrayElementToString(uint16_t json_token_index, uint16_t element_idx, char *outVal, uint8_t *outValLen) { uint16_t token_index = 0; - parsed_json_t json_all = parser_tx_obj.tx_json.json; + parsed_json_t *json_all = &(parser_tx_obj->tx_json.json); - CHECK_ERROR(array_get_nth_element(&json_all, json_token_index, element_idx, &token_index)); - strncpy(outVal, json_all.buffer + json_all.tokens[token_index].start, json_all.tokens[token_index].end - json_all.tokens[token_index].start); - *outValLen = json_all.tokens[token_index].end - json_all.tokens[token_index].start; + CHECK_ERROR(array_get_nth_element(json_all, json_token_index, element_idx, &token_index)); + strncpy(outVal, json_all->buffer + json_all->tokens[token_index].start, json_all->tokens[token_index].end - json_all->tokens[token_index].start); + *outValLen = json_all->tokens[token_index].end - json_all->tokens[token_index].start; outVal[*outValLen] = '\0'; return parser_ok; @@ -115,7 +114,7 @@ parser_error_t parser_arrayElementToString(uint16_t json_token_index, uint16_t e parser_error_t parser_getGasObject(uint16_t *json_token_index) { uint16_t token_index = 0; - parsed_json_t *json_all = &parser_tx_obj.tx_json.json; + parsed_json_t *json_all = &parser_tx_obj->tx_json.json; uint16_t name_token_index = 0; for (uint16_t i = 0; i < parser_getNumberOfClistElements(); i++) { @@ -145,15 +144,16 @@ parser_error_t parser_validateMetaField() { uint16_t meta_token_index = 0; uint16_t meta_num_elements = 0; uint16_t key_token_idx = 0; + parsed_json_t *json_all = &(parser_tx_obj->tx_json.json); if (parser_getJsonValue(&meta_token_index, JSON_META) == parser_ok) { - object_get_element_count(&parser_tx_obj.tx_json.json, meta_token_index, &meta_num_elements); + object_get_element_count(json_all, meta_token_index, &meta_num_elements); for (uint16_t i = 0; i < meta_num_elements; i++) { - object_get_nth_key(&parser_tx_obj.tx_json.json, meta_token_index, i, &key_token_idx); + object_get_nth_key(json_all, meta_token_index, i, &key_token_idx); - MEMCPY(meta_curr_key, parser_tx_obj.tx_json.json.buffer + parser_tx_obj.tx_json.json.tokens[key_token_idx].start, - parser_tx_obj.tx_json.json.tokens[key_token_idx].end - parser_tx_obj.tx_json.json.tokens[key_token_idx].start); - meta_curr_key[parser_tx_obj.tx_json.json.tokens[key_token_idx].end - parser_tx_obj.tx_json.json.tokens[key_token_idx].start] = '\0'; + MEMCPY(meta_curr_key, json_all->buffer + json_all->tokens[key_token_idx].start, + json_all->tokens[key_token_idx].end - json_all->tokens[key_token_idx].start); + meta_curr_key[json_all->tokens[key_token_idx].end - json_all->tokens[key_token_idx].start] = '\0'; if (strcmp(keywords[i], meta_curr_key) != 0) { return parser_invalid_meta_field; diff --git a/tests_zemu/tests/common.ts b/tests_zemu/tests/common.ts index 806c641..082de04 100644 --- a/tests_zemu/tests/common.ts +++ b/tests_zemu/tests/common.ts @@ -28,4 +28,4 @@ export const defaultOptions = { } export const txBlobExample = - '{"networkId":"mainnet01","payload":{"exec":{"data":{"ks":{"pred":"keys-all","keys":["368820f80c324bbc7c2b0610688a7da43e39f91d118732671cd9c7500ff43cca"]}},"code":"(coin.transfer-create \\"alice\\" \\"bob\\" (read-keyset \\"ks\\") 100.1)\\n(coin.transfer \\"bob\\" \\"alice\\" 0.1)"}},"signers":[{"pubKey":"6be2f485a7af75fedb4b7f153a903f7e6000ca4aa501179c91a2450b777bd2a7","clist":[{"args":["alice","bob",100.1],"name":"coin.TRANSFER"},{"args":[],"name":"coin.GAS"}]},{"pubKey":"368820f80c324bbc7c2b0610688a7da43e39f91d118732671cd9c7500ff43cca","clist":[{"args":["bob","alice",0.1],"name":"coin.TRANSFER"}]}],"meta":{"creationTime":1580316382,"ttl":7200,"gasLimit":1200,"chainId":"0","gasPrice":1.0e-5,"sender":"alice"},"nonce":"2020-01-29 16:46:22.916695 UTC"}' + '{"networkId":"mainnet01","payload":{"exec":{"data":{},"code":"(coin.transfer \\"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790\\" \\"9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42\\" 11.0)"}},"signers":[{"pubKey":"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790","clist":[{"args":[],"name":"coin.GAS"},{"args":["83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790","9790d119589a26114e1a42d92598b3f632551c566819ec48e0e8c54dae6ebb42",11],"name":"coin.TRANSFER"}]}],"meta":{"creationTime":1634009214,"ttl":28800,"gasLimit":600,"chainId":"0","gasPrice":1.0e-5,"sender":"83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790"},"nonce":"\\"2021-10-12T03:27:53.700Z\\""}' diff --git a/tests_zemu/tests/standard.test.ts b/tests_zemu/tests/standard.test.ts index 92e324d..dd573cd 100644 --- a/tests_zemu/tests/standard.test.ts +++ b/tests_zemu/tests/standard.test.ts @@ -179,35 +179,37 @@ describe('Standard', function () { } }) - // test.concurrent.each(models)('sign tx1 normal', async function (m) { - // const sim = new Zemu(m.path) - // try { - // await sim.start({ ...defaultOptions, model: m.name }) - // const app = new KadenaApp(sim.getTransport()) - - // const txBlob = Buffer.from(txBlobExample) - // const responseAddr = await app.getAddressAndPubKey(accountId) - // const pubKey = responseAddr.publicKey - - // // do not wait here.. we need to navigate - // const signatureRequest = app.sign(accountId, txBlob) - - // // Wait until we are not in the main menu - // await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) - // await sim.compareSnapshotsAndApprove('.', `${m.prefix.toLowerCase()}-sign_asset_freeze`,50000) - - // const signatureResponse = await signatureRequest - // console.log(signatureResponse) - - // expect(signatureResponse.return_code).toEqual(0x9000) - // expect(signatureResponse.error_message).toEqual('No errors') - - // // Now verify the signature - // const prehash = Buffer.concat([Buffer.from('TX'), txBlob]); - // const valid = ed25519.verify(signatureResponse.signature, prehash, pubKey) - // expect(valid).toEqual(true) - // } finally { - // await sim.close() - // } - // }) + /* + test.concurrent.each(models)('sign tx1 normal', async function (m) { + const sim = new Zemu(m.path) + try { + await sim.start({ ...defaultOptions, model: m.name }) + const app = new KadenaApp(sim.getTransport()) + + const txBlob = Buffer.from(txBlobExample) + const responseAddr = await app.getAddressAndPubKey(accountId) + const pubKey = responseAddr.publicKey + + // do not wait here.. we need to navigate + const signatureRequest = app.sign(accountId, txBlob) + + // Wait until we are not in the main menu + await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) + await sim.compareSnapshotsAndApprove('.', `${m.prefix.toLowerCase()}-sign_asset_freeze`,50000) + + const signatureResponse = await signatureRequest + console.log(signatureResponse) + + expect(signatureResponse.return_code).toEqual(0x9000) + expect(signatureResponse.error_message).toEqual('No errors') + + // Now verify the signature + const prehash = Buffer.concat([Buffer.from('TX'), txBlob]); + const valid = ed25519.verify(signatureResponse.signature, prehash, pubKey) + expect(valid).toEqual(true) + } finally { + await sim.close() + } + }) + */ }) From e7f77dbafa4463aa9bcbf1fbc0b8ba40f6c0768a Mon Sep 17 00:00:00 2001 From: 0xPxt Date: Tue, 20 Aug 2024 18:50:03 +0200 Subject: [PATCH 13/34] Upload snapshots --- tests_zemu/snapshots/fl-blind-sign/00000.png | Bin 9606 -> 0 bytes tests_zemu/snapshots/fl-blind-sign/00001.png | Bin 7279 -> 0 bytes tests_zemu/snapshots/fl-blind-sign/00002.png | Bin 28460 -> 0 bytes tests_zemu/snapshots/fl-blind-sign/00003.png | Bin 28241 -> 0 bytes tests_zemu/snapshots/fl-blind-sign/00004.png | Bin 29065 -> 0 bytes tests_zemu/snapshots/fl-blind-sign/00005.png | Bin 26332 -> 0 bytes tests_zemu/snapshots/fl-blind-sign/00006.png | Bin 21289 -> 0 bytes tests_zemu/snapshots/fl-blind-sign/00007.png | Bin 10230 -> 0 bytes .../snapshots/fl-sign_tx_normal/00000.png | Bin 0 -> 9471 bytes .../snapshots/fl-sign_tx_normal/00001.png | Bin 0 -> 13014 bytes .../snapshots/fl-sign_tx_normal/00002.png | Bin 0 -> 17445 bytes .../snapshots/fl-sign_tx_normal/00003.png | Bin 0 -> 27188 bytes .../snapshots/fl-sign_tx_normal/00004.png | Bin 0 -> 20213 bytes .../snapshots/fl-sign_tx_normal/00005.png | Bin 0 -> 16500 bytes .../snapshots/fl-sign_tx_normal/00006.png | Bin 0 -> 10107 bytes .../00008.png => fl-sign_tx_normal/00007.png} | Bin tests_zemu/snapshots/s-blind-sign/00000.png | Bin 349 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00001.png | Bin 560 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00002.png | Bin 571 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00003.png | Bin 593 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00004.png | Bin 642 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00005.png | Bin 572 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00006.png | Bin 540 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00007.png | Bin 561 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00008.png | Bin 555 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00009.png | Bin 631 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00010.png | Bin 627 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00011.png | Bin 605 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00012.png | Bin 548 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00013.png | Bin 596 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00014.png | Bin 633 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00015.png | Bin 624 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00016.png | Bin 604 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00017.png | Bin 564 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00018.png | Bin 586 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00019.png | Bin 599 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00020.png | Bin 553 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00021.png | Bin 556 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00022.png | Bin 585 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00023.png | Bin 608 -> 0 bytes tests_zemu/snapshots/s-blind-sign/00024.png | Bin 594 -> 0 bytes tests_zemu/snapshots/s-sign_tx_normal/00000.png | Bin 0 -> 333 bytes tests_zemu/snapshots/s-sign_tx_normal/00001.png | Bin 0 -> 363 bytes tests_zemu/snapshots/s-sign_tx_normal/00002.png | Bin 0 -> 388 bytes tests_zemu/snapshots/s-sign_tx_normal/00003.png | Bin 0 -> 644 bytes tests_zemu/snapshots/s-sign_tx_normal/00004.png | Bin 0 -> 607 bytes tests_zemu/snapshots/s-sign_tx_normal/00005.png | Bin 0 -> 286 bytes tests_zemu/snapshots/s-sign_tx_normal/00006.png | Bin 0 -> 611 bytes tests_zemu/snapshots/s-sign_tx_normal/00007.png | Bin 0 -> 649 bytes tests_zemu/snapshots/s-sign_tx_normal/00008.png | Bin 0 -> 623 bytes tests_zemu/snapshots/s-sign_tx_normal/00009.png | Bin 0 -> 660 bytes tests_zemu/snapshots/s-sign_tx_normal/00010.png | Bin 0 -> 423 bytes tests_zemu/snapshots/s-sign_tx_normal/00011.png | Bin 0 -> 266 bytes tests_zemu/snapshots/s-sign_tx_normal/00012.png | Bin 0 -> 504 bytes tests_zemu/snapshots/s-sign_tx_normal/00013.png | Bin 0 -> 678 bytes tests_zemu/snapshots/s-sign_tx_normal/00014.png | Bin 0 -> 436 bytes tests_zemu/snapshots/s-sign_tx_normal/00015.png | Bin 0 -> 683 bytes tests_zemu/snapshots/s-sign_tx_normal/00016.png | Bin 0 -> 646 bytes .../00025.png => s-sign_tx_normal/00017.png} | Bin .../00026.png => s-sign_tx_normal/00018.png} | Bin tests_zemu/snapshots/sp-blind-sign/00001.png | Bin 410 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00002.png | Bin 868 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00003.png | Bin 806 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00004.png | Bin 873 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00005.png | Bin 761 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00006.png | Bin 844 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00007.png | Bin 917 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00008.png | Bin 881 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00009.png | Bin 941 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00010.png | Bin 874 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00011.png | Bin 908 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00012.png | Bin 879 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00013.png | Bin 836 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00014.png | Bin 563 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00015.png | Bin 858 -> 0 bytes tests_zemu/snapshots/sp-blind-sign/00016.png | Bin 446 -> 0 bytes .../00000.png | Bin .../snapshots/sp-sign_tx_normal/00001.png | Bin 0 -> 406 bytes .../snapshots/sp-sign_tx_normal/00002.png | Bin 0 -> 413 bytes .../snapshots/sp-sign_tx_normal/00003.png | Bin 0 -> 442 bytes .../snapshots/sp-sign_tx_normal/00004.png | Bin 0 -> 909 bytes .../snapshots/sp-sign_tx_normal/00005.png | Bin 0 -> 459 bytes .../snapshots/sp-sign_tx_normal/00006.png | Bin 0 -> 333 bytes .../snapshots/sp-sign_tx_normal/00007.png | Bin 0 -> 808 bytes .../snapshots/sp-sign_tx_normal/00008.png | Bin 0 -> 874 bytes .../snapshots/sp-sign_tx_normal/00009.png | Bin 0 -> 884 bytes .../snapshots/sp-sign_tx_normal/00010.png | Bin 0 -> 284 bytes .../snapshots/sp-sign_tx_normal/00011.png | Bin 0 -> 550 bytes .../snapshots/sp-sign_tx_normal/00012.png | Bin 0 -> 896 bytes .../snapshots/sp-sign_tx_normal/00013.png | Bin 0 -> 1007 bytes .../snapshots/sp-sign_tx_normal/00014.png | Bin 0 -> 587 bytes .../00017.png => sp-sign_tx_normal/00015.png} | Bin .../00018.png => sp-sign_tx_normal/00016.png} | Bin tests_zemu/snapshots/st-blind-sign/00000.png | Bin 8904 -> 0 bytes tests_zemu/snapshots/st-blind-sign/00001.png | Bin 27737 -> 0 bytes tests_zemu/snapshots/st-blind-sign/00002.png | Bin 25470 -> 0 bytes tests_zemu/snapshots/st-blind-sign/00003.png | Bin 26637 -> 0 bytes tests_zemu/snapshots/st-blind-sign/00004.png | Bin 28579 -> 0 bytes tests_zemu/snapshots/st-blind-sign/00005.png | Bin 14381 -> 0 bytes tests_zemu/snapshots/st-blind-sign/00006.png | Bin 9437 -> 0 bytes .../snapshots/st-sign_tx_normal/00000.png | Bin 0 -> 8991 bytes .../snapshots/st-sign_tx_normal/00001.png | Bin 0 -> 22006 bytes .../snapshots/st-sign_tx_normal/00002.png | Bin 0 -> 26337 bytes .../snapshots/st-sign_tx_normal/00003.png | Bin 0 -> 18358 bytes .../snapshots/st-sign_tx_normal/00004.png | Bin 0 -> 15444 bytes .../snapshots/st-sign_tx_normal/00005.png | Bin 0 -> 9557 bytes .../00007.png => st-sign_tx_normal/00006.png} | Bin tests_zemu/snapshots/x-blind-sign/00001.png | Bin 410 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00002.png | Bin 868 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00003.png | Bin 806 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00004.png | Bin 873 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00005.png | Bin 761 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00006.png | Bin 844 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00007.png | Bin 917 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00008.png | Bin 881 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00009.png | Bin 941 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00010.png | Bin 874 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00011.png | Bin 908 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00012.png | Bin 879 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00013.png | Bin 836 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00014.png | Bin 563 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00015.png | Bin 858 -> 0 bytes tests_zemu/snapshots/x-blind-sign/00016.png | Bin 446 -> 0 bytes .../00000.png | Bin tests_zemu/snapshots/x-sign_tx_normal/00001.png | Bin 0 -> 406 bytes tests_zemu/snapshots/x-sign_tx_normal/00002.png | Bin 0 -> 413 bytes tests_zemu/snapshots/x-sign_tx_normal/00003.png | Bin 0 -> 442 bytes tests_zemu/snapshots/x-sign_tx_normal/00004.png | Bin 0 -> 909 bytes tests_zemu/snapshots/x-sign_tx_normal/00005.png | Bin 0 -> 459 bytes tests_zemu/snapshots/x-sign_tx_normal/00006.png | Bin 0 -> 333 bytes tests_zemu/snapshots/x-sign_tx_normal/00007.png | Bin 0 -> 808 bytes tests_zemu/snapshots/x-sign_tx_normal/00008.png | Bin 0 -> 874 bytes tests_zemu/snapshots/x-sign_tx_normal/00009.png | Bin 0 -> 884 bytes tests_zemu/snapshots/x-sign_tx_normal/00010.png | Bin 0 -> 284 bytes tests_zemu/snapshots/x-sign_tx_normal/00011.png | Bin 0 -> 550 bytes tests_zemu/snapshots/x-sign_tx_normal/00012.png | Bin 0 -> 896 bytes tests_zemu/snapshots/x-sign_tx_normal/00013.png | Bin 0 -> 1007 bytes tests_zemu/snapshots/x-sign_tx_normal/00014.png | Bin 0 -> 587 bytes .../00017.png => x-sign_tx_normal/00015.png} | Bin .../00018.png => x-sign_tx_normal/00016.png} | Bin 140 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests_zemu/snapshots/fl-blind-sign/00000.png delete mode 100644 tests_zemu/snapshots/fl-blind-sign/00001.png delete mode 100644 tests_zemu/snapshots/fl-blind-sign/00002.png delete mode 100644 tests_zemu/snapshots/fl-blind-sign/00003.png delete mode 100644 tests_zemu/snapshots/fl-blind-sign/00004.png delete mode 100644 tests_zemu/snapshots/fl-blind-sign/00005.png delete mode 100644 tests_zemu/snapshots/fl-blind-sign/00006.png delete mode 100644 tests_zemu/snapshots/fl-blind-sign/00007.png create mode 100644 tests_zemu/snapshots/fl-sign_tx_normal/00000.png create mode 100644 tests_zemu/snapshots/fl-sign_tx_normal/00001.png create mode 100644 tests_zemu/snapshots/fl-sign_tx_normal/00002.png create mode 100644 tests_zemu/snapshots/fl-sign_tx_normal/00003.png create mode 100644 tests_zemu/snapshots/fl-sign_tx_normal/00004.png create mode 100644 tests_zemu/snapshots/fl-sign_tx_normal/00005.png create mode 100644 tests_zemu/snapshots/fl-sign_tx_normal/00006.png rename tests_zemu/snapshots/{fl-blind-sign/00008.png => fl-sign_tx_normal/00007.png} (100%) delete mode 100644 tests_zemu/snapshots/s-blind-sign/00000.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00001.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00002.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00003.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00004.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00005.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00006.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00007.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00008.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00009.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00010.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00011.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00012.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00013.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00014.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00015.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00016.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00017.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00018.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00019.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00020.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00021.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00022.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00023.png delete mode 100644 tests_zemu/snapshots/s-blind-sign/00024.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00000.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00001.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00002.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00003.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00004.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00005.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00006.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00007.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00008.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00009.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00010.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00011.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00012.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00013.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00014.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00015.png create mode 100644 tests_zemu/snapshots/s-sign_tx_normal/00016.png rename tests_zemu/snapshots/{s-blind-sign/00025.png => s-sign_tx_normal/00017.png} (100%) rename tests_zemu/snapshots/{s-blind-sign/00026.png => s-sign_tx_normal/00018.png} (100%) delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00001.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00002.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00003.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00004.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00005.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00006.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00007.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00008.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00009.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00010.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00011.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00012.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00013.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00014.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00015.png delete mode 100644 tests_zemu/snapshots/sp-blind-sign/00016.png rename tests_zemu/snapshots/{sp-blind-sign => sp-sign_tx_normal}/00000.png (100%) create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00001.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00002.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00003.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00004.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00005.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00006.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00007.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00008.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00009.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00010.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00011.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00012.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00013.png create mode 100644 tests_zemu/snapshots/sp-sign_tx_normal/00014.png rename tests_zemu/snapshots/{sp-blind-sign/00017.png => sp-sign_tx_normal/00015.png} (100%) rename tests_zemu/snapshots/{sp-blind-sign/00018.png => sp-sign_tx_normal/00016.png} (100%) delete mode 100644 tests_zemu/snapshots/st-blind-sign/00000.png delete mode 100644 tests_zemu/snapshots/st-blind-sign/00001.png delete mode 100644 tests_zemu/snapshots/st-blind-sign/00002.png delete mode 100644 tests_zemu/snapshots/st-blind-sign/00003.png delete mode 100644 tests_zemu/snapshots/st-blind-sign/00004.png delete mode 100644 tests_zemu/snapshots/st-blind-sign/00005.png delete mode 100644 tests_zemu/snapshots/st-blind-sign/00006.png create mode 100644 tests_zemu/snapshots/st-sign_tx_normal/00000.png create mode 100644 tests_zemu/snapshots/st-sign_tx_normal/00001.png create mode 100644 tests_zemu/snapshots/st-sign_tx_normal/00002.png create mode 100644 tests_zemu/snapshots/st-sign_tx_normal/00003.png create mode 100644 tests_zemu/snapshots/st-sign_tx_normal/00004.png create mode 100644 tests_zemu/snapshots/st-sign_tx_normal/00005.png rename tests_zemu/snapshots/{st-blind-sign/00007.png => st-sign_tx_normal/00006.png} (100%) delete mode 100644 tests_zemu/snapshots/x-blind-sign/00001.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00002.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00003.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00004.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00005.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00006.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00007.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00008.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00009.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00010.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00011.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00012.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00013.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00014.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00015.png delete mode 100644 tests_zemu/snapshots/x-blind-sign/00016.png rename tests_zemu/snapshots/{x-blind-sign => x-sign_tx_normal}/00000.png (100%) create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00001.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00002.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00003.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00004.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00005.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00006.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00007.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00008.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00009.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00010.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00011.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00012.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00013.png create mode 100644 tests_zemu/snapshots/x-sign_tx_normal/00014.png rename tests_zemu/snapshots/{x-blind-sign/00017.png => x-sign_tx_normal/00015.png} (100%) rename tests_zemu/snapshots/{x-blind-sign/00018.png => x-sign_tx_normal/00016.png} (100%) diff --git a/tests_zemu/snapshots/fl-blind-sign/00000.png b/tests_zemu/snapshots/fl-blind-sign/00000.png deleted file mode 100644 index a5c92f262dd71dd3d809d04b987b47ed46427007..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9606 zcmeHN`9GBX*B?uFio#9E)`B7<(v+Q4LlTngTXwQD1~axO6(LJxnXyv}w{owPPozLf-^FHTu&ih=?@0uDOJ1Tw@1Ogp1 zx^?p&2*mLd1md*e;ROD<(pzE(0?C;e-PFGyQ9zxcj+JOnC%P;-hI8FHV#ApoC-(sO z$tse&cEm0|>$KdhBcgHxyYmj2=Y<3W@0!6#F#~Nq{5)dEZ`@iR--viIKfwi(r^nJR zf-&w%OI) z{g}>5doJn#0(;p_dj9(Tzn;mLGxHwgVm1d@HbXEeo>3^6hCk~icPPrh$C zwmc#Z({xkd@dlfj3zs5ql@TVH?8szpZ7zx^YJ3s(C z#!S=A7I>$N0u$GHG|gnwSp^l8)pAaB(#7N84_S3EKxnJC{*5cSyt^dd659I0&nrCM z-lEWvZG==r{*tWGGOVZfbWt4$N8@iL|A^@vqVHXSayrGu^{D>F#cE3j&R97AU0~`J zCB`XkoKZp9h=3tfKB=@j)w+n`-rfI@DKKm!c5=$Ett?a4Mf#}jiTR>B?a|`8nSgoq zCDE3RkKX!j>1AKE*J6f0+#8PX*?e92OsT)#M?5A)q7c};$P!F*lHSSxwCiD0i9$-+ z&1-H($Dek=v0-y9H7nZ)$LvMy?L*o}I8wSN{I1$&hv~|pq)P)4hnImTITkSY*P7EC zz!GfxCvku~8-lH07$nQ>?)19t3A})fdL!0l@*@^@O+B^ z+xkbtFhf>PPtT&Qtk*>TFghi!XS(msnysqcImw=2?YRyU!YW(~ctL<8B|L8;Z58}0 zLOXR$qu5ydsNir!rvke#6=E_(rngvWIF1e{#w8v#$`}}vlY)+9nU8kH9sql~EigRn zIyVUQ7ebmYXC(g34H3?b2sQ7G=`0+TGYLOTOpQy_^vPR_)LmODp+ZyEG~QM{>~P}W zQ@Z){BmgXkTh3M%TFAg?z9U8|tv9&TkOO1}upsb?BQI+U81xc2Dr$nya=W z0Ror{w_7itR3d+yuyqKE=tFc|rRJ#cDd+Sf`x9!fZzFS*AL{d)XM6m?-9n@^bOf7B zXPH)J?g=Kk2yoMs2FB+sh5?cLEKb0wX=}N3*52B^gCSN_wzQZ=Z&Y~jl1r?-xo`(o z-T7f(<$C&9pdha9kQDbvR#fw;^fd~Ba$opKWKhH8-rk-(<#lSwGNQxE@*N^Vrd(|;Zrnl;Rc-O(T+j%B{s)Gd1tVJ@JY*q2YE?&KGNXO+{s1gkJg=)#X zA17<%$r46XIUgj3TcP#nR2GoQ!k77%@m6Ird^gCB@cJ#`4^A!7H)nLNSL9UDeY>8& zz)!iJGQ~9ak2vGeaRHqZPJTmm{wsSmA+9B{8kmfdhR3ORv)J2TrWZTA--6i6G4e$y z$BtBhiIGXtP!wO#Mz7>m*-UrTvAyG8Oyyj)LVu zK=AQ2^;DGT3yBNi+R|ygrJ++Xjj({0$w&GEvPNee)flc+9Z7Eeyb3@9qGKs?EsC%e zOUo1O4K5%@?ov^OMWGBKX!?7{qYrYbXI`W3ZR%Ak|3zYE%BE*%X-yK{=5?Q7$CP>E z0erNs<6oe0WIZtsYW)gg_Z36I9b2)#w>P02glEziAzQ-r2Rym=F6=56A57m;=f&ik zrhP9zGrI=i^LVx}W8FM-Vt2+9lN1;)z{Q%pmq2b;6U_r`4l}V*d%`^B$t(m3G-UodLpIMYvX@mm?h6 z8(CG^I(6VTB&b?LsJ64qrNa~V@PD)xZaz7#3=NkV=&C1eSwC|NzJ5ikgoyGfv{rNI7 zPp(sy{ozhFf{@qT4`+(IbyCic^9TR6kYaB>bi%w68`bk-O}RDl2a_$xTliaHBL7E& z2)0VyH}{W|=8LrYU?(c|XCNu8X};<9{+Jwcq*2D};0h1hscO5+_-_ptUuie)DU@e? z#4}m~cb7Wh5`)q%{s-0mdA0nnHgZg4#{pzUz$MO6@0|SnJ72>Sg8N{0fhWyfa zEH`6nS8cfFI$Lf3NlG02kbaQwS^}H&$Y-J^*(js0F|{5{wN-&%<1c)rV*GZM3kx=8 zAyj4+51RN@TF)mi1FtEz8U{Iz+h!Ym=!h5#ktrVZbQA4CzqlY{7C?OyEQfL4+liE9 zsIg}PPb2roLzB1lalus>hjY!7)?H;MCS$D02{IG2zEA6qU}q`X)^At)RG_L~T+^a5 z^zN9W1Y)t^eyew{2Hbu1ru7Q_MM5l!?F%263$JWXnFh^M=Pg7{P8}W zvQ>J(F%FbRZZzkahIi$GAAcnHH`(c6#YXkA$*s9teuZ8UXzT1n&xX3EmhuWL9{#3D zlax`GM=2raFIc{NJ3_V1~6RV%g zVPcIN^opqOQu(V(VyW;~%ao0O)H36wQ{(neVeL!7{cxSD2^WEst|7Lt7NDd2PpnNJ z>s6fK7gfN=GS%`&L)A4*+$^+P=ckrc^~S2_V~Kvh9B@&AGdmUS(}Iwi1%~VNF+Yp@(UU?N=x(->J)zaIfGYN$ygw_kjI> zt#+inlq&Z~Mt#)n6iG@0s4K>f>w+6PCYd<$+ zRY~Dcgtmh5I|bi8m?=Oe#fa2*x+R+3uQOh3A8nO*9z@jDIajd4!4}G+p3b+~)H_(J zZFpH&c&f6nip_Xl7~ipXnrHP^@b|T_Xq3>f4v%+^#q^Z&vgGR#)`QseH9QzIQw=Qi zRik_Dy#&=XZGUied{Sp~INItM85gZD&^O@OAhfWyy>tjaUD@d9y~#D!I}Jo?*SZTE5UTgPTE9^Y#^fNPP)?S0ym4({gL##u)bvm&3A zAsb1w`}qJ5#z zNGAeh=~h7AITJ#pwRmDNZP$eG*hQU|QThA#_j3G9Dn_R0)x$i4Q4OAWh>09((Bf%V zam`9q)z|uh4y?=&y~1bp3Jz6pqj5-9_xUH_`T4WO_n_u|r*_#y4ew}@8h_q7M*Fkp zmb%J-y8zh?%CA8HPkCH^9EZaUR$i1e&}XgC?UC>#^a}X%qZC!C)yc<2nNI zRI4_$dDma_ib=yXbt(;`=Kj@=Z?Z={HQ}_n(d^q_@l94%+9n_h#v3y@X z8(QzI9*wguNxtz`J$3OG;Qt3J=aSB92$xemr7>v}1d6-zSIIW6TFBQG)TZR|!<3Dn z8k_H7N=6G1Srg=XkUH$DivMOjntlYS1Wz7qyvP6a26l3ywCVzhNq~f@t`rX%W!z-E zYUmm)X(#T#3s#KQKlCAaB;M)*4`=At zadiAXsQqsMiNerGbbf;2lF%ApfPiqt;DOwx$ea6&XyD^!nHqTTkYe6cC>4xAuH3qsmOt+-LKM2;NgVuO8LpZi zv~oS%tD(-B4DA-ocZ(-#)V*Zul?{dexZUAp1!@>8G>P#Z>nfitk8bMwwQif#f)=uYBIvZBBwRg}ae&J;Ta=SJG;; z1Z7@}YO2h)bMyGNCtTzDf;=SBEJUnIH#sdE}G_HZ+<73ymi_H7(?7UJm;_j5{+KpC&!IF0x*+s8jY{Z zP_2QmJa|cMo@o%~l4e7pUjRA15NUMs$vbB>8YygaecQoT^{I!}$3ctvr8FuNd3m?% zv1x`Z3P4TYo&09Q#4pj86V?1YkknnjA9l%1TDSq4eA$UxqC=y?PiAU!-fE{E$RKm@ z(*6eqoP3hkwY10;S)P8hbr(>`)%9f!+>O7hy!hK!*LoWK@Mo=()Jl@wP7+`BV_x(< zvsEppm%O2RX#G+WG`bio(WVaiKb*}@(WP4g+{)N4K@h-Py`1fIy0&uae7Go=ahN9Rjoyb$U{dhkQSGG!jz9*n z$)FSep&t{^7HypP)poJJzGfv{lsgcvF8O_Bdp0N{T>q~#MH?)jNH8G8=b1(%)`J_s zfKvVSP?9cCN2u!FeG&Wd?Ep-J*~nCah1L*NGq?E`x%*CJkUo-l zcY1u|h>~~ZW^QNspknM{{g<-O3*vKq7Xfb}I*8R~GTHMlZrsk0<-2h*^g`My9DACl zL_Q-~sUAW{wC-)r;rgKV0h&W4HNHM_>eR)ynsTEEb;&Z+vh6q%js>WA{*>r!$((LY zH$8W#lQnbeth~SBskC0bU%8__!9QZYA6G?&-k~1p8jehk{Oa^`8*!!o3q5Kpt20713-&u#ZoJhc=3r1dL%w+izwF5hISv;J!q0_g$cF4J z!(e@179D&edHt!&PYyMDp^Ta)6N;!CV$|Di&fkHMCC_a?Tbyv2(Vgk1|0wWtZBsV$ z8rrGoyrO-d6H)W=1m3|=Lng~iA05(TsGOQP!o9^;BL9{CLsxe&9O*dT8N>b+8R$5! z!=dA<0Z)#x*?6=u@Z_VtvPy6FmV#_0!DzH~CNx?TwE&|BslQq7VDt3zdehl{YUPU$ z^V#*Y7M{EIA~M--#7)$(Hqp$bVkSngS2r-fuK0m-5)2J6VFC2UqA!n8a4bsa$bQEY zTbpbBVMkb6Mj1e)*G=q?9*_S}u*XPSTRl~v=c=)!^h0|8kStH%vUF%z!0VkT-zf78 z*->0g)x+Y#_)L7D-U%C7KY)C~TVG6WhB2~r&AX*Hb3JlrT(7u1bY4`;t58U~j_=;Fz62?Ww_uq!jw#NhQn1hNaio0<%J<`|-#2 zmfs+TB1|_?O~T}ETwLn>MA<9_Rxi<7(GQG0fnEIR!+`#;$u76K=cSqJ=a5z6uR+fS zr&^%Z1!hfZVIjo1U0k#ojs%RN_Sw4c zG&FZNv%f+C`#(9U^(0f4vUfP3bh}kXXd-;fq=;@3tQFk*L!t z$DK{d_5=nTDH+HQM2 zTOUg9KP*2I)eJKnn>=(GZ={+EgYe5N9A0p z#-*JQ)$iT*w=|KkV6le1hv&Z`Cc`ev=T!IzLycKg6^D-f#De8eI>1Eq+keSubSKuc Y0aiRWN4^bwUj;IPn%=Cr{viH;02(t-Q~&?~ diff --git a/tests_zemu/snapshots/fl-blind-sign/00001.png b/tests_zemu/snapshots/fl-blind-sign/00001.png deleted file mode 100644 index 010cc7ec107301afa63e99822f644926484f257f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7279 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 Yav>X{ElvU-5)FJj{eNya@av_20ll-m+W-In diff --git a/tests_zemu/snapshots/fl-blind-sign/00002.png b/tests_zemu/snapshots/fl-blind-sign/00002.png deleted file mode 100644 index 569563712afa8a64c3efbf0b86c8b86d204e33b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28460 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 N1*ZP^o5C~y{{?OZO8x)< diff --git a/tests_zemu/snapshots/fl-blind-sign/00003.png b/tests_zemu/snapshots/fl-blind-sign/00003.png deleted file mode 100644 index 64943e98545d53ae7efe7890e93df27d7abd2f2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28241 zcmdqJWl&sS^espTPH>k10TLX7y9Not-5~@C*0{TCfZ))$1b1oNL+}8>Y22FN(73*v z-~ZLrtErm#G@quZ>Y}Z24`^V}>PNivj`E!wyfb>QXi^=-a1q9T< z$`akj@H%$-?~I#~mX=;>Mz?XzeAmf+m&)|a;}i@oD4*C?J!`VZO|z^{h}=AJ=?#LW zmLMS9sA}Wy9bDRAG}0``?flb6_6-b^X(py6gILuW&YYNkvBO!q0)gDuYbaf`a+w_5Eu^tRC3; z6BBmuT~6G&Yp3x9tU#7_X>%`24(dDo<|BFuu5{=SRA!6CeMG*EFeR}n%DU;*2V@Cm1n-Jq3zqPd!kE(9P z9HK_mzYFp2W;2(#-=e~Pp2ykjn>iv1$tOZUyc}t)qju~I!xLW-fG;K20Fkg&Fy~SE z)Gip>#Sq~d&B2Dh4RaKr9I|$p#1v4{Pzw874*{+CeY6~tnN-d&A7YEoGZ`;o3FGw{ zzmQxyxenoGPVQV3#(#mpd1@K-&W=J$(XJXhbg9@h6N&V&Q(H^s&a=~ag`toEoyYB{ zY(m&GXp)5?w^d}~7FBV4HcPo=bZ0X|6hR`Zl5H|1TY4W30SWK#R}k;nCB3QVk36D~ z@DNl+Q#?vd6k_<$<$>Ydn9*6!in`|7{cpVFibF}LkmDV;;Lg;z9w!?PZ)P$DpynSgYXt3YT>S)Th*+8dR>n;*$ zNk&6fc*%x(WW5GL>X7t~OjaD9FhNirKTV=6w9G;lD}Rg9(S#OZ-RLLn zq|MsZo|tvwlw_F}EOVil5XHg>gy8flkJaIi#)d3h#6w>7iLdnW-R`Hn^LLbu3mq#w z2!W-#26@6Sm*`6PP@O@qm$Bv8E&SGO+uN+4JRJ`&#lZVn3>vwvo zDHhgUm8}@egF5O@E+f+W7PH~mlGN>FZ-6vZR|m<=1~ulq3KMz9UtfIyfr7xrjX}an z)8*xi#Hc@H4FvayT_W;>Hys*5!k%gO#6&;5=MS_F=qetUZPspSY;2=CPQn*Xu8Rgj zP@7&^8n`w0Q=K6r=w@82IDNO**0R805vPmx(1|G!po(9f)p_i!w#}y#N&lP!(@;4r z#I6Y_!Ze6fJJNGA%ADW!@^3XnInkmRC%d|Nx+FQh0K>UQ=U)b$C zYO`MZ2LjgP2=?-px6TlccB8dxh*2a$pvs$QEBC@71JtjPhj!Mx&C__=VqY6Z6u==9 zuRFut+b{{vfQvRBH7Kbu{?<>_smHBslr1PXAS3uv;_hXrZi`^Rd4$78cevc{3}lg& zWUk2qO?tkLNy;hM-AfL!A+5S0JYb8NVGHSRCRp}C=7mz@QQEA#G@ed|>3BtSB6Z3}hf zDep=BUvXuBY^px^4Re`yGn!AJ)=jmLQPb4o^%NZ!fQR)$K(joqYJ`w4SHnf}T3U_u zQ`dfu&zog@WIsR#v-suZ_|6JCz!X#;)Uy`CgyKX?^gY!mx(=L-=ChR<-nw|@08de@ zO8Tm#KqWEs&?I$drtW#huF{Yg$)gv7b>ca@a&m1Rv0`6h?<+zT5)}bD>D65vKXz|N zw`g5E3G)Fe@54CH%7AfA+QXfUTIhIDAhY$3vpLr+n{|$ov6;R5c}?gcHJk9~amXn? zA0gVkz;yRG;e*aD=TX}75Ekyj%@A>hOt^M-QU3ez|o~k%f`t-5XEoIj3i?diR ze`f6Gw_Js%(;}Ft&G};m@$JSnkOJTfo0ymci|<`}KR!JXvs*#0?(d-k17F)_o1cBlRZ5)8^Iq;FXF}cylyY^GK)8&O04y@w2XkMvvudYmh{vYXu-1R z6N~ep(n@2SfN!07wi*JJLfZzyCI!Z7U@asZ^UkrzxE;x_uXEPxFy;{3`EsxXFRvi~ zm};S=HI5rvWD!& zr&Xmnp_2U*DGv2fi1tQ^dB5+-AB*1Hw~RG0FY)n;_}ItE{U?2y^gz>Du4%Uff~(9A zojW04opC|&b`mQ0Z|%PHkzAD6zreBB*s&8Bl8R57-oV)*UcX9PA@#%vZW!#adu3cJ zrH5pm4GfzJ9p!5Ca9^pl2x;hY3a-`nxi-fV-=oRR?%z1QytKe1 z7BV|X{$;cFD{!??0ZPyMg6#pbBOi98f@!Sq*gRZyg7rF7B}%nL76+_@=-lku8WW#` z9r5z{r-fcBOz?;SfG~fa@9w-E-o2iZ;{9#^hGpSj5XzD8IMy=(JsLaF9r<{7!4`94 zJ^_}ru#7sd%DGihy$^X_Q|fu)WlWB5xja4~^@=COefL(!63(3fi+2dKEc^`BnJjZz z{x6V&Z>OBaT!H>bVoX`&K2z*>Y$Pmwh{BBgan!_W$hw^Mfz2Ymm2$-QfFnY&fI zW*i7ZLEa(zXydYeIlN8(a6NPftTyV#U1PQrlSz9Vs|}T9IOw>Js*x&9%H?IG<#X?M zLSNZg*EH-zEQ8<}V3#BwNgn%8Ry27~&&3S%GL)Q)%02wYDTP%M)O?>(osYO(_wq zqgE7kZD~>i6__ZwVghQm$MN9oVfmYrgv-X^&n#L*-i@i5C>zt$8YkIbH{zl2agegX z#yIUd+6(qE8MdmHC`lsB^w_{(PQ4b**YrXDRkN#K8_Fect_~GHyo%%9rf6C}gS<+g zU1GJ&RczbBFLxqT$xO#QE{|VVAC;qk9Q{%y#{TlbE3QmOl{}Vd)7_V3J>EK^KvP6?bLCBwZPycgO--{>(1H?SGga5 zHIQ=n$_~J5)l!rKbIzG5BlVP`xb%@>Aq$hQCxFLvLw@%=!wf``Hfo_-{8#mAwq6og zMZVsCr;-}T`YTPYKDmPdX`?%A6g)sf_wpi<8umtx1gN!Eb?GNV>1VFqjUDs$?(d9L zVFId+KDk8?pv{H>iLe*L{^_nY@j!|^?Tn|(ZRJt=N=UtEGW#`moKS30w}kbs>lqHi zd29#roeNIljq{P;yMybz7x{OH+_}s>{0|3x=H2?cXX5k>#Z&{F`K|$iJ--vPKQUwG+7g)+Jm0lky8>ydZJmZ?wnd z2Z~^7Jhv$aB%AmS`G~6Na=N#9Vc9O|Rn}054q=$jlr|RHZl2`lYVk3F zdTn%Kah1C*-A%US0yiUutl0zXOKOIDns1@;SKL)Ys01CfbZ*3tbo_j!)v#cYd=s&EY!Z5;?`lp2pdL9Mup9PekjLS6Co z0{k}F#D8WqBKPlTzRT3SN5dA0xgOu%8`t)g&?^AN?aXUp>%LolJ9VTqRV zJR|dh7#*GqU|qhzT@}sCT(NrdyTN>+S@l#7nn?7XyPpO6`Q>(}{-Tp=3l}g;+{Q{9 z*0Vdh4$*}t_a`R~UPyJ&qtK|5BX`^TOaE?QQrB3Ow|&JbsA$K%GK@xnN24rEwe2e8 z7Z6|@u${|kni55!alqRMvSm-RC1K=vr18Rz^iCt1LzlyJg1ja1#(dhy;tb$2s~m=N zc+`f@P64a&=2f9+RU1vkWu6x`{Xafujc0u8tn@&irFL-3bhY|2dzuG8+=KrTdO5T; zCGA+!7S@Tgd+XkQW_vDDbI=B$QR~JL^DFt*R=etZ!(@l%%sb(eu($F6)0P3Q9M|CU zVQhf=0$VsOhR?P0{qp#4kZt?!ZT}v%AI8*RqUoAcFB@giS)4n!7cWI6jMBb(JxXz) z6ZQ3SdA=?ae@DW$m%VWhMR%F@1T5*=R`JXaC@q6u)q>{8`AFojpFgKxZr%ExV>U_~ z?x(g%WUj3*Qf0-hkKn(bsOcsG{b>wm!^;G%oH0pLD}?)DBG-^6St1zXQ&w8{36GG# z9TdMy7jLpp_EwQcrxXi})EDJA=fHg9em&Csg5 z8c^F6FcWou{JZ&eWd88%6i-r$%ju-HDtu2Bpf1FUyDzO!Fxm?A!j=ISj}&2gi3t*K z+9|w?=?sIM6EiQWI)bvZJ87a6Y4t0r=_jqh+FEX{hW5>w;|!81(bhE8st~un0!D4! zv+lJM-@8la)&;5&Xc5~4k6NMnod0H0dc6`7YI-j^FSw<&{8MJ@)tHM!vR0aBsLvZ4 zkBopuJ@rTCWnr9EUrW2bxl}WRUl@3~RU(Q0bR~3f82WdX;)?3hWh)vqWk6FEI z3TG2Z@Q?}P@%k!h`%A>Bfna>4uhD@jEpx>l*7avI7p7XO^83*r2U?h+8QH)l&w57O zQCYZu;Kwtie<^yFH!Rp_hIW*7&~&)LcpY+leQ))WuKTbzw|buC`VHqiUz6)h_sZi@ z6Ie|v1^l7KxTYg>ti8>WZ=_z6-`%Kr(Qc@dX98ZpXh&rxc}|G|ViHfb-7k_-+|^gF z`)Lr0HS||1)#538geHo0@J`#!V*Kss;FenIk5Lpaf0Eplq_ih}M1dhC3oHt&CA^Ahvmes*l{ny%8MEbY;hzsvdfTzj7OM&QN z^AgsMi;>6x+rzFqv7~|T2f^$RyWRkWKD%^EY+34zeMx|?{b7l`f;+_C`MdO!q&E0p zRNomzsJZp`(m1u+qs(;~mb5Ix)5aWbwl!JhtNTuJIMC3FOrXNFS|(v$$A7$3!i%kj zq%Y=dQv0W1xsc8|x2h|~OdnLf%-H=m;Ug}Ljd|JmDEY@>Lk=0{!!m2ZI_GXEyIwi) z&iTG*o{7x4G>pU{XJ7^B%w=q@t2D;)+HH}G*-%~NYqzL`3lyLWJto)|fOvkwMfSuG zuxmz^Of0_*01J{YUgZt-haJIn!og8c^95rArkd=3k1dx1l8Cyz&(;!)DsRqwtU>v2 z|L_(IczT#kwrht|&%dh)=OAZOoy{EG=?kHC_RvRuM)QdSjWk)BM4`B-Xcnxc#}=r?MoOF_OYQUMT1pR;8M-f;p)1sx-GN9 z;N~RC?|Ka+WGMIayp-rdeXpEN`N$H=?(!1E)~;}f#!FlLhqa9lom}u?YK~E)Sn8`M zVhrPnkV6`e4Ak}FkKyF&@Z0S+KC5V&sL3&PHA42j9kBsCAh&rwQ#KN>2EErx)0>Z<9ZZz>RIRv+1ylk$VusyTkKnK%ef}afAyfS%BOlSl`I;#FzDzr=2&VO#H`UVtqc?m0y>6cHg zEf=@Fly^9pCu`;pZheoheUyrsel8uHaBK)6K03$g3o?3bgOAcPYAaLFR#e%I{8cbi(Y<@{+Im8)8*xlIk1VDoT5`p#H;wA zzrkN~tUY8mo4KmvJo0;T8m7+%2NNY%H@lyo3ImcYTJ?QbBsB@M4ny=@Qcz(*K$z#(tx zVaO(O(k}c#c7gOP;JYe?m0w;SU0Zma|IOx* zj(tP5-b^MG$gJkmWN2(D2CcnFd1`k#gWjN3NafK1eK3hkzVD3KKngAbE-spD$4@~f z6a-x?PbY-`o0u6hAqfvrUTs2FzO5L5%(!>2aZXVZfuQQ3C>s;KSFw!x{;f{hkpp$R z4T{NIj+$R3SMB+ug_4V{L-7!vB*#vDo+4IJeswV}Kh#VcH%SpPu zW8Z!wK(`%}WGP&T6E((eN@-w>F2z3Z6P~9IZSa1^1B5Df1a_^I(qE$vcG73?nAnDJ ziEbA1#lNoV@mrF}X6pbvVv4(j&s{%W0qkV+`LtO`v&}v)pak~P&8-fdp#5#e?OqVD zMdP6suO^E<{2yjE6696O7(KW(^$&GPc*b5AfL(K7Hr#%i`&k_|cz#I0pRlwpGGVDt z>7?xfkRzOAR#z*bnCYGID)x!vz!lNFZa1DEZuhK!EoLL%Vl$=hGI@!_%lA>26jP{Y z2C)FO5LaGq)meSw(|ddE-(BGq)mB~RAs;~B4)Zepr?oi`Cbi27U8zGMoyIlS_eR;@ zwF$$vmeE!!5JUfTTIgY1|6#juU?T=G(!G-6{_Sg83o_uvQW^#eYL+}6y9--LBFsi@z4^P+#8F*Sp&xziiLH5$e8(Z1YEOUuha` zfJyimcq@OGNX8U?wB=CVsQ`SjFQernr=R)2#Z$^1Dz9>jU~r~*O}kdC%PytqA&dMS zZN7o^;h<)yQYrKOqyGi65i8UBpGe>3L%V}nublWc^a*>+{Cd1OfrQ#sZHLQCm)wEp zrzePD(2={aX?@g$!%*%q{I+A!F4T1D*7phcNK|IXG?5+z^$!T}VP~1(lhU=5r2+cn zr>E5HEcf=;;(BVHli#jEQ1^z#A&axiOWr%z7v<N~V!waIF()5if{+koazyTb40QY`fTG3}P9<5x<%AKq*vL3yxL*#1dQ zdwNUXmoIYX?LIgYBqcr4;IqRirY01!e=deCw zs8hN+t8#MN5l1}V+pKI9Fz)?Lev!j3Mn%rL2Yy2cBndYoex+%iSmKM7LphcDZL71g zBD;B!0LNRp0J=+@@?ijYad&~_Qob6XrNq|$iuy5|#mmY4`zvcd4x7FG*`*u7uQ+~eAuXNy; zL2~LmQa_fOp{D2cxH7QowYz4M*<(Gc>_g%al=BrSgA9>v<^~3rH(C*y0IlHm&ODur zwp)iZui5jHQ)GPnMS|uzdW+kriNomWZ_(tM-=oi&l^} z*0458Tw7r^*^J3k9nt2>DSP~6VZJ2LwRQ~M5=Kw1wm4d0k^p!J^3#HDNRi0uSpv(~ zO8i8!@7`Hhc{U<3#(l_@{!kke|lT^RAYuhoG(J z^Es|My2Lip&O#6Q53|Al;*oZ&cVZAkH{ryxMF)4~0^SY$pq#c9vp>7*fZVUwZJgI$ zEli0`Kh7d9q%>V@&6kNa@ycU}E+EP)lcaIpX=YC*w$`6+^D?V@X#~`pilt2dFI;@b z9dcK6x7i+H>i?#XjfKqU7Bv}fl0n_Ht?ylsJsA2njSKL`W6%kf1)lP){e$`(S0_V? z15`iv{P=*(Hr4iSM{sExg6J$j>DisQOKWZaX2OLl4fYO?q@I=T*`f)mYg^EmA>)EV z8b-n|2y0tz+SA^8OP;W-4p7PKAk%+5GRxQ>Kx3czGCT<|w8m~35u*YhWBl+${5C^q zf86%WE-v5Ii4jVNJ^6L7;Y5U}+eGJcTF(ZNP^#ReYV?*=g z#~@9|wjK30kJ79~y##!K-L0nF6a>Xs^L+~L*2=pT23o1+iU!#n7@(CHDv7#==#+TM zj`va|9A15n$;Rzq8ygM(1cA(}|wDiht_1r4IEuQ0wLM|u8B zQmOOpi!Jv99D>A?=_Hm5;vJd3DJKC+Z`j1`qd!ol4no@v3-Hhr)I-6P|H7htMGn)8 z^|;DQ8VGJ~ySX^6i?0H?Z0s)XUQ=O5^vY!^GaS>loloBU<0dl4Ex8v=w>zaKXdTJ6 z?VAm9<%V31t}ic}7VUuAdGz66t1*dm?Yvh-EG%Z}$Q@A3o*%E*X5)524=*Fu7oO>727rkN* ztb?F)(XR26On~OIk?E>SzHH;7-A%OAyc_f=bsppr>ly`lPe+kOL})2Gx4d6fdo)DI zC*cyhz#qD0e=@(;?ul;P=4?3@hd_ck@Yz*=uxb_lEe|<>^c6K{sfKQaZ zE$Q-{Xg5R=L71;dKjq!>h9t}j77|Gf4e$L78}Eq0Xf$gP=7vK89}DYgeNwFDXj?M- z&iqVd>9ZweKjaM~R)tkkn7=oikwQGeH`0*R_?4y`S6DC5&K5e3vf+^R(X*dWZnL&z zmHHC>=-${LX<(7Gk^m_4Q0hc_Yw)gf>nm-gC84v_CP{yxCdXyMR(_;2^_CU;{r3!P z34p@Ro7NoX)zb`PO>^&sV3xHJJzcAEN7`qaU{a- zcCHv-`1bo7mgx{Y=~#FQCU!hXVWJw8QFU}KQF5jD`}eD&*klN~eHgKOF1N3Ld1XpW zr-$hd5rr?K@2yq5uEyxGsho@yOItI|Y95!Y2^T`S@f7jD`{j$!BR;Uyn>Yt^ZuPyh zr$y-L9zG%2>sK~TbqQR7`=&_JEXBY<;4Y#B_j*dU?S;>K=0qlMN4W%f<%H8~%oHXcN7S@SVR&;J z6JL1Q67|fm^*i_FP%Zs992(zT8i1yXmmrUDSp3(@m)@a{t~FAA3~kjet^R~;{!UN` zzZXvA=Hgj(E=0{ z2N}c@KY)J6**IvUI$S-U*8hrg3)nG=;;81&RFlphj?5R`y73WIw4*I`0EW3{ucN+J zSsZXOOnh~IrtL0Z9S!YQm$Qay^WFo1cll4s1ATu1V|0NdS$VT~Y4>+{YSm~%DV9j%qCM*Txt9Nd%5p8h{m@NH{|8%_g~M+j029Rn z{j!fxw%s*Kb3Q^q=mSw!XW(C#9;|@9lN^3q=$vcO6uauZ$MT{bAEbE7Z3VDlv`35q zuWUZ;E6TbIr`DMID4`}KT;@_UmF1^oGXt8>&#@niGl~e(`#l1!a z2kb$bL@z&`{M)VOKtB_eaa6rs=Y9t0jpp5^d6cHDYV8K$Q*ZoW zh>3*1HOA@*w}$^eG(7#u6vWtna9kAQS6nPUI8|vFvW4FHAg{_bN4(#n}3rLqH(+z;k|FX~aR_NZ!^O=2! z;P$Il4!2YHAL^W^^>33q&iOBvKeLdA&Sw=c^3*B#w`Ck>bO6(CL**7R8!(Qtw?-_G zHaY;Acc*&9k^-QHUcjoYi8j*t&c$RxoOjuzTPd-U=%#o;vfm{vZV@-C6fvEs^) zKIIZtg07WmAtyw0;p~%F)EkJ`mehjQ;8Y8*?lmo)(PGSF9q-)|Yw);b;gb}!ekNep zq1Q-pMZu=k`PBlkEV_M9ir)QDMPN<`FwBF47zj#6cd7+hiaL^A=Yi)375(d&)*8{M zaZC8)<2aV>Jy)yAU-U51`lD@noiFSX`MT_pgCiO)CtRO#{|8$yj4h_DI|`iQa2zca zamEPk(lNtao{GJ4gk=LMA8I4&H}(o|QS43EL>wF{{0MJ9e9-&czEZBk9=+))vLvK^ ztb-E7_jBH@ijT#1&2lMbV>4o%>Z5t9)?Of}Hz5$kFrx_>Jd>n9f9spmnWh-C#VvgJ zi{970<}7@pOWJ-^7MEg#P$vHyYd5RMTSGS1U-(JP4>H@3eSZsG&v8JNi|7vukTych z|4B3X0@|nffYrj~ATSFJ2>tCq=~`fj<}Z|C=y&Vlhd;qfmt^xXK^$Bdpl~gDb}JXg_j4I z)PQU!B)jx;Eu7uaVQu=ad6(VV^@9cKfzWFX0NVDstK1k2^08teXA3m^hrpHOzkZ`{ zRDxKJ@VpTg?Iu85AVwnQS}(68jtK!Wy+(LKFN*%&J&-jq|YM2GlzQvJac76uNkDN7N_v+!?KwZ5>9@t zbZyZi4&)??>yuL9{ERX0iEZ?dL;3u>76cI z)_+Ng#kS2j*>NM)>F*e{`y#}$nTz{Roe-ha{kF)^SQk^F}o~Ld&5~1=!xCp$>3Zlz`Zyd%JbN7rYjf=@3QscP%TtK_+ms z(j5`#Fep~0@?O(aOs?|GnAiDK?(^gSyq~N@=P4^!;#X_Qm1mlFV?#=s3g%*$E``w4 zX1$mPVEj16>|xn3^r%?5ePi3}*tur~5W-RZCJ_@c{r;8bV5yfHY~~9t21bx zt;AVLX#hvtT~=`!nTSr^+6gl91l(}37lzA)_0*OB$8}y~kfn9<=H~QI&+-*mMorZX zoWO-;HIx(tScVA`yxi>>@XFbSSiklV-2lf-I)303D65}7yE8SrbSYTii$O&-NxvUP z$Y1{vjFwNFREtik$D0g~V_fT%=TPX63G5=a87^g2;NCnCQ7%b3*R%#oe2=hk*_HZ^ zmpyhPEML%`y-he=dtq;lMf3dxWPJ#X@~YopH_yZlGG!?LGVURhZ~G-&wS?Hp7QZj! z<*`n=|HL23N0KjBYDqLSCmEX`zdeqejQo;=J1nUlfyoS2!6O@v3wC?~PY-GVb;ttl z-HEF3_jtb(ul)jqvb(yvLajx`;t92MGXr8gF7r%kbnf~o;HQ5dZ27hc$R*n*EMscj zqE~8sJO3hC$$8GF6MK%^HeU8$a-&B!nK?P4_^tHNKk-tO53jwIlKvxT!>*BAs8deV zht@tpsPXOYH_w!!{a169rH(3#WTkH1ot>HVOFV({XubKP@uGvSTT zaFWt%CU_N3yJb5k($#!TGuWdR8z3R}Mm|p8V6SgqIR?1c^%pW~0^u!NI7;tQ!FTkE zBd0|IsGKu!>z@rW3zotL6879ur13e`zNoX*g)4re+}f!>0%!|451TqoV{(Q!l}l+e zv*X;OQJYI96@v*)B;p3QK5GCJ+>bgOeF^O7nsv@6^fc~Ic9trMMdi$<;-VW}@s_8P zxkFK|*g|Ft)p~m~y(Yj>oE?UqFBPPcU)Qj5{2l-4>!63rs+0S1OBVr36uAPUc~G;# zZEY_AV)X)1km3y9TBd(|?~_OmgWnz;C}4YZ{al(=R$>4!X&w0s~HA>vDtLJUE$vao6yCOP|93f@a2W>p_}Zn@^_KCA$|Ejt0AXob(ZCci(S zo~*Mu8QKzfSa9RboZ`V!;<94!nwCd=XTz079kx~Qo3PteJ)DU->5gMu4iE>5tpR1# zoiXuLZNtky($^dm?}**Th;bbQf`3X6;p14(t@{Bu*?QY|0au30`%oqw{)R3YF4S>~ z%XNcO;1+ZXC0&sqGL!U>-8)+YXw^Vr|=Gb78Q7dI>uP%&U zx)x<4hYv3wT$Y#HCeoivA=fOp8Nn%#lOY&CCNlr58@fmY9k<0Hnodtey0U-iNs9Yg zzeE^O{s_A#MZnMcA+b%C;xqVzf7a8hk)C!OTBUREC}})LPR2EOx)pNi$HAZtC84a2~Rr#^;%}wU>c& z9+lSNt~R?FfVZmixBk0WZYmiojTo+L<-$AQEP%U)(*>7dFyI=wX+xsMl^L>cZn#YO z4Qn|3L5MVt73b2uw&Sv`s9ZwOe6{23^mh*U(@fgSu8Qhs^T zoXo6$w#QhZ%Go%#&-wHRhEQy#0N3y6FZSL3bXSyvHNoW&;9Ql@&QwCsQS8m%6)wNE zfPjEe+wS(2-`d474azwB6tr0GNPSm%xj?g%08`RJJQr^_WVal1hAU9jqE>mUc;!(4 zCliQJHBGdGuqHbKbJtpHrH!+} zeZ>yi=6+F|%l5K%{QAQ~(%J?1)QPf2i!;|N=_i+n3wwKq=!3N7Z#h=LaNA;~M%%^* zR6?u12NWw59*+0O`UWVj4znH6nKgx8Ay(Kg4bSb0YZrT8r|oYeIs^fVFJSwB{A8ej zuI|er-q7CT=5lIO?CrE**+_}3uMmVS_HO>y;8wm8!QyIKTHa*91l+f_y~p5qT`o8P zVb_mDRL=ps&6->v)X-$$5k!@p0SvgJ z67II&s)XR|{Jpp1q^?qCXB;l8;98Hi|zPvG1Ewk7+xfG02L_j}il4iM7~X5%FF_9OBU zm&UtBjC}!#Eq;u&vz)Li0>HkRV*KQ0(OCBCPEJd!2o2yNoLj9@c?M`dp50~|N!(v8 zT-YZ{z+c&F*(OSKOUI_p-dbej<+WA<_AId`AAXBdJO}ihGkHW%stNAAD|?M|Kvo*R z!)H@u{UL-CRBOH0Mll`_PZb9{FJ1>&RG|;go!YUPPQByN97DijuRNDcSsZ{lxKn_I zP^0dC%Dvnz?K8>)%w91O7HWij%~`uKpd;m+EJ_)QDCIVOwA_8vs=3PkcP#PgfXQcc z1fF^$m$3FRM(sUVUyaZv>ft|2n^ypa%CsM>IyI@hJelDTCb7?q~04~EntRueWO7IyQj zh~}@7%gcutvY!AJA+*fKhV}Kkb6nYQkJk`6aSz& z8sN5WxZ446L!C@%z%JQAmclwZ^ED+m)h#VtS)bNe%7p7!G3-S-mV5Kwo( z_ikdtx5-VdWdMN?x}QZ)-Sknw)9ExjluwSbORBW$JXUte@3GUFwtW#j=FI~a=yt$@ zBt#n-RY&g@SKV>DZN=WrNcgVQhT-Md0&+8D926d!J|!8=5xLmJhN$tH%!nAB8#S>z zU);vh3H?G5&9v|qv8DD`#elPF0L<+VWb@9Qzg^1%|Ig`o0KpotaL9X%SIB!0vedj9) zuy^iD;kE_B(Sb1}5s+c1dj_%MuMS14lu%rvz-Mz8@p)MV59-wW~rH8;kqmh(0=VK(^RP0X!>{2z}j(~8S>1#GEgg#>t}$Q|@j z_oLzmKNzU-goQoZT(yn0Rxa{ojMv0k@^d%<$CN&SNnb&#)pWE?$)#gHiR^E@*VR~g z$!pb_*gMZzVVMI92}lOnD)XbB8GDo|Cpl(KQpXN(w%;dtZGeuFnOk0G(N_nT5q_SL6j^T5+!UY7En;>IMFV4oD;5>(0B2*%}Pz7 z`_W{4#=7D4yeIMrt~@I|GA_0Ed2fEE)h*J`T-m4X^Q25&yG2>@x8G>0!^fVY5Ffoe z0b(%*b8e3~MQu$ue{-133jB*xaYV}ZA&U9Q1-z>)btG+?!jiW2zLCPq6ZJ{XKW(wk zzYtR?)rFhcjpVCq#Syq!ycYlsn+~`zl|S<_317%(El}TIH3KhhBGA1Y%X<(kM20^Bz!$E=;9xKHWZD0 zL!TW+#TfejaA=sG9j9{U1%4#Rzy6^i@iztbwqPGh-=Kl;eY<4RtnMnJZSjmfeg}mAYI!8!Wa#0P|oX0^YAoeT{O0B-0T)SYf^HA0tVV3 ze-aBl<}`A&PKNu(oZpL|z8UEv1eQtUCGjY2e8&AAxY7FJX7F~%6ZqE)ryL0Xhp_Wd z=mKQ5ME-@(0)w76$-amL$*)g=6J0rVY36TG16S-lI*o68otXJFzALID{Oq;{vh*?Ir_`asRUuxN0|`tBiR-Q zm+qWwsHub0@A|)QM`}x zD`nO!G-U~J66LiN_M}lVylxF6_^@HxOgLs9Vu)ca&Lp`7N2wS5ZzB6C;h+5JIk=BqW0Y@iZn}iwS@^!!b-thT>3is@n=T%rA#a6(NJo6-itcyJ7P) zH)TO9#h~aWbQkttV$^Gqk``IlF`cpK*BUYH?|-XRMfjy4Xz(CH^4yR(+3 z3^oEuBeKBz*eEm^{)-}&rTHHGol3<~7sq>YzucGGu&J_^tw)v+3wJQf_Tqhu{`RZ8 zC>5zV21AbQ1GNK-5g(P_#lb=CWw_^&_oI3VQfQwFiS4E+3QK1_S!8foSF&@+abE0k zw$GQYSzm5uUwq@y{H#bwG5dLJ*nKIr%-zhP8$=KZKEZ8C6tI65rU`WV&tM}> zl?;Tyb$$EfY-=;iiJV;CeD{`GzMC>fm@i$tt}eo#1hzCEp@cR`SF38-;6Q@~$z*q# z?5MI3g~@W7J2f4|3itYWt56fCpUE^5@QAC`*u9m)NrJwzib}wFnF8nRI79@f`1faY zf|%WPT|YfNR~Rm`B6N%GffD9#8U8l8?&Hy%+Fn%DYX=KylyQYYX9OU%@zQ!t+HZb4 zGsv<|!*L|l7C1v=Q(&pp7?fm=X($sa?MK-E^T_6Ar&2zSZ^Dy;qZ-O;m>n}Qau3{4 z9HS5>7-4rcvN#=>kbnd>8apdES z6#H^)B`&Ri`0{3mCZ0EmFWv7u-&cJ{15Y}9DJ+S;%cpc?d|wn@@A`e*4bJ@*X)K(>csW7Dl(UO5?9E?!*-=CYtK5Agt zYeg|Kjn*#Cq{_ZsK(u!Zfte}r9xe3hcam=Pk2%ts{r3MTuNj6rw@=!!wsEj|FXL;a z__KL0i5hz0V;Og+$4piTD>imRsV+8It#P7p8?GoY|ETYLgz$$1erlkeloXkg6pJ;< z-jMph=X49_bni5#A^b}CjlkRRMeRU0^CtRR(0fcRZ$v~ZzVq0Ni}l=u!g~n48FFNYH-E0`gxwTiIOPK(lXDG!`QKr@ zpXlPp^#w)S))EE=fiAIi2JE493jwWx{{AUUu2FOjvCsJvd_|9D?MB}ideobopC09& ze>rQ2RjVu%y1ig3wM;jK`DcWP$c^#dYMR#g4uL3ju0kO-jvpQ%Fu!J$YvsRZganh} z7aCxL?@AC&k+|8e@J+xxf|3p+(e=gk56FHOl2L*5bFEa!F>*3;;)Cr#!wlfXc#pgY zs(V`HIwM|G2E4WnX5}!r_HR{zgyIypH@4Ez0{cE!$6s%@VXeZ(?aDO`f2yp?P829n5G4O z_1E&uz$7O4DZ;La+}uzuz`a)*E7U|cg ze=Kr^I&@D6Z?*}4S86L941ad>qlJf+U?SJq;&!n?`;OP7z3`rsL!tYaaM4r4x$R=A z-gV%JAe;P=9&@pDs8HQu+oY6Lc%b3c``Gh3ce@MILo?rk+WThck2%Slj7GDjbE-J< z4}NS;P7}yo2Gg9)2DdtEYsLBb22{9t^L;NCld1(<2koaDS$~8siXRduka>5fg`GP~ zugS=N1qXli(ZY5nB(U+|?7G&;;6$)B8n9f*=v z<>lqDFSB++Ro6&0O~0q4s_;}P{d4!?SA#rw8#YPA6*6!*=>F!#5Fha}P0 zlY|0NYP*xfvh)p(a}U0Oy}0M$+34$tkn??8H|nfl10F}k3*k=Pn;wJCPnb&3r+CI2 z3GhXyC?P}RER2{_lpBBg_xp3cR<1f)U*6)T*%*w?RL-5f2lyopf=N>`j3&7mE4cG-yKJ+ zA1qIMN&3T?3|ReMzrAS{-+3wGf@wX$wA8eAG7n0^-5~EyTdI^k=;BWZ2te{%i&(0y zn|(BhmY;}nW1V1pVGo+a`?qrDBfrjbkC57xbRh7g8l86O1)zh1E+HSie~6S1iZn23 zen_0nM723a_)hW5kGus$hIDETYV+4uk9uZ$FL$cL&*uXS`hKgo=5k^t49gf%!pm`C zf*Phh5c(95rt9aK$Q*eQ286jd4aWI;=sM1~N^i*O=q}y{T;&I&?w85#C}-OTBJ$TH zARjVoX10VMarNHT8HUo)b$DS&wpM%IWLFW|j~LMG|Bo87El5 zD|h6x#n_9pg|oA@Dd@~IbLjoCj@fk%8 zEWU?IUdG(ypi093e?ma}j7wKZW(7qQ8ugctmD#Ucc_%`+=U4~e8>da>IS+fNN0|)8 zOH@YPfq{r$G5eL3WEjCgetMH zy>>gO6QJ)lyr(dk6rZXWJu%15o2{zkM1&4-$X2Mi_AWr`3vo5wy)?*)UPTVoa{tTe z+^c~gVGI5JMsU_%GQ9o$(MF_U*3>mcV!UP(%UJx0oy2z=p4I!7h6mxzAL&Xs`}}AM zh+oi&GY2u3uvjtO67<<_4{H;xl8gAr@o8*UcJtN~lIoN1CZZ(0t&9X4i68Jb0@R8Q z>^gP}M+LPKovY3+-S1rU6PmuhqTkorsKUf-_an&zbKse%!h$K`HJgOUI=WKnzh2kR ze5u1fwq3gw{|(=0JcXR)6PjX|l!Xn>>-fRzI&FoLS24>W? zAaySd)11NIc5@pZ0(`UX(63Ln@04n_S5!(@ z_w8<-`FScVrcaRy#-p!3Bd1&v`_&mfOhOPcz#U3cYd&mQWd{fy;b_^Ac>2*f}K^wv+Q z8kH$bfz82*{~zFeH8Y;I?j%Vv<)uyV*2wa<`%Fza&6cSkm|6fL?DPhpuR>Oq+0j}8 z0?o-;3%A;?t{yIWx+q%@HVs99NX24$!$jP=$tBh$&&K3ji8d(H2l>!NW4^W9)M7e3 z5iZ);q4IyVmI$ZoygmqM4+6U%AG%9k(U% z^-z4vHKy>?O)$>w6ZptM`MOqxz@I|hdu3&JQV7mV~L*27UMQ{|OPEcI7LF@d2G z-7F~C|DW@uI;Oy*-9$_(J9F1Fb(uGBAzJ^>Lo<~ zcK~KPnJ8=1Q6p5eZ7~lvyIaS?GRVWG^;Bc={ATOGI?2h<*w|t6Q#o+<@?$F|AUODO z%nUez9#8 z!+A?@));@qcNR%Duj|5xjPuxp(q4R{;d0WMumo{@3fV>7_GCU)9;3zx4fOW`k}K{p zws=2SDCnTLf^wG*Pb&9>JFlZrvKFoXMLU3g!J=G9*cFj_A->Y=Mr^6M~VY&d_%B;2lr)Kba-%!XEiS;6RGzZ(AjO=Rc?M6v^&q5?T7A*!x;- zbS&ZMO3)Hq!rRQ;lszWtNF1;w7pS5D|Iv`ZHr@J>cjrFX#JMqTHrjQ-+JoilG0*`ooEqU5jbuBonWW6KL0$ zdHxgZYM~^7Q2k<~y4L=r27xGB)5{0Ag2@S4&Yui#?OU&xCIKhWvC|9=Nb4Kfk(J2B zU7!%&H{aJCqi48QLE;9Gkm!L{P)Ug_(|@fLwdA>ze{I*MZc1N&c+Oc{tXhNrz@JZP zWl^h+N4ez*W!hVIAPfYbJgMP$E6O-TJM`xu6*MYPdhHiAU2j}z&F}aR z9RDO#Yd+271?GwQcker(5!3PY)b2Il44Z@(J?QJpri-EsxC3PN{#ZjFjcGjWP&h1-Q*I-*?upR48IccSABJ-$S;~8QCA`MOn*}$YCDW+d+XQ9y2dpG> z2`I;R%oYUx0vi^`4)IUXjn zu9w>|bA6pKC6_f&KCqf-FA}Wg(0K#%=xVw=ekeCjpTI=}Wzc3;B|UU4_-gQ1BM1aJ@1WoyMHycsA0h+UDcZ8NXLl z&t=3W9NdIo_jThg)p(~YC#)j}PpbT^<$UvkTvK3|iiPxsRAWbnN*erLs!PrjxJlU3XhrdJpf z4yCfbpGzh1V$@Q=_TKO!De2#D!)O5p+3DAA3=7LE8nWFw73nf35>B1;83n~^mEchJ z3LJf>*frPLWIFexJErOe$<*{Aj1&_+9WQgA$q!Mewp%@eSc!l{%aSWrve0;h5_(~O z-8-sh71ka2|~*vt~a`Pn#NNx^a(xbxTNX~Zk2W3{dJc1 z(5+h%HXetp_*y)4z9i=@x!>;OIT$m${$_KI`M4`^=jAAVLa@ZC>9nse)epQ)b)Vmk^sn+5pPC4Y^KG{ZFGJ|G`Q56so@_RFOj#*WSF_Oc^Hya$me+sA3Jpx7!l~L4k6)F4f{=U0-#*IJ+^Z^Pk zO`}KMj&ez$ZvT$J0~$ksYq=mHYd;)|T98-1#E|&=Ltl(3AA#VUgXv@`JDHO;d?5K`)EAsCfxfy%lqEDU<1> zU~i;_uV1B<*L&QC$9%nu`iRGBsw6=vZ<@$Su|M_({8yBHrccWRDYx_{w4>ewImJB8 zxF?q&a5oeGD)7^{WO1bHb*#mErwowSBz~)w!Jg{rTQ)|H{%G^aX$!4HaQ=qve-lg| zSiwUT_L>;gDR=&K*=_HI%)eNE>J+1tMT5i8U$So@IRK zo{otcYPdAbp*H{;@MLXm?c@ZA+-+U|(o0e-Q6|Eq>(%Rv7JIpog61?=TRg71DvY&AM-Ck-uFimy&Q2BS2R3|eF4a1e$rs9TP)W-@~`2| zyDB58e`ka5n|FoEGf<~!dPPeu0~;;85!wjWqiMj+bd;B{qQs*m67hp9?^fRqsLom~ zs&QaldV)Sve8-3Li6`7Vo9FK2i62DCw@;Q6vp#YUw&{8^hZ<@ISDeZ*y>65?QTxPc z;N2`S7n}%{mOcPc3R?1a2pFH=asDI+S&!Y%u!|LbTii9cEVoD+74315LI}NTcw1%W zsH&ia_*2Kt(kt@A6h0z9*6%*J3B{eSmb|Q7SPS8^GpSF)b^qtH&Qd?8) z)zP!xb+Wu+luL{@ZuZlgkPrR5OT{}kw31nL98%uyaUsJm&+sM)gY8_ z8R%~rSoR%nK&MKMa~B+8qae{AS}%`%)y#=WH~C&)Zh~v}NYJLM%m@}Xazl3seO*PQg>ml zjIQHaLv3^MQbl1+luG%^!#+9UrjsRpWSfRyF1lu7LzX-1oHvr)JkVfE1y8Ejg}4XG z1Xh#ab5QkN#im)(IbD&xO(ZrnUb5!XIy2a*iF`L70VR_;5T2ushE3fBTAffWdRuti ztS)2a8})se!w+DzA^4L#KY#r(&EnA4)Qr8n{ud+UB0h~%_OBdNw7sqo{fK z?`%^cy8L@Q{nOh&WkWxqMMQ+Ax+MvWbCR=@1L5wcLJLEy^SG-;ch{*?7 z<9Jj{qpz`hdVJKJM|0_wPf29j<|sw+t@)Jz<#0w+ z&04*$PBw%2zLLn|oMFXDE!k25Xbj5ZLp6sc%Km;^eyD%HooZuxGC=Li$j zIoMSN{%tBW0b51OlV%6wggH8=vko-I@cWq;EpE^?&M-m1er=nZ@Nti^Paht_WO1MR zbu~fn%#bBV#5T7BDk0Z*YuzPf0n$^kLF6*C+RIQo@@ufxhA{k_^d{`z%}7oPo`fBg zr)QSVhi+o|OK5v}Ph=l9wPp0-Rmw<2vza2YMy@DMsnK+qRF68PvR}w%9#NWw74qfH z-mw>;#8i4yn7&Xu%o?}8{{jDyKQb22bBOx7kJ%#Wn7CQ8zgeV+y&feaXW@HAH`-wuJv@?w2*y2H%--DB?{s z5Rou-upU9*hc zhRgSWY$2DcR1gl9QU3t^%6GMD&Vr%synR(%)Wy-a z{zD3J?L%P(e+}v)@BC_~Os=rBQxt4m!1UZZUfJ=2B6n(Q5v61ROG5v8uxzG(DziY6 zEillr%R1s>^_%V{s8g3a-=5VP{Zkbv$!yijNCQQ6cWq^iiu-XBnY?iSq`l2}r?d|i zNnFitd@u?-(Qp2MiIrtkZ1f16@<}Ycbp<*33d0NI1FYWQp=v__RyS_sSflb?f z{BiR;eC#f$$z*lItMWFXJYs%AWkTVVGUinGc{K*_bnc1cGKeW z$eRwig96CNa)ue|30Q$_jK+4rBDT$e-pXoMG6~JO<w#{k>wUgHY zVGh=_7FPpI7Kk0%7H~DuGi?(1pe4e)@2Z79fG(Z<|7L@P|Bre>{Lj7AQ$Cfrwf*Bw zdyuj2J2H=BwKQyzV3^gdH!ClazQTPSi2whmwe+|kc0jjCklY2$DNY)zX2Ie*rC#@F z1oC`98OosCw$dyd#Nlv-L)Qrf56{3S*rRmTE}(+Unx-byMAwG>yr&Wezzvl2WI-dq zmE}LvDnWbqj%r3cs~B^PcV?@IbpL?+)LFpA6wB9~hX_PYU|@*i#nu#^GeE|WpG#?g zK&Xf(W0_jqf=6RE+XbGWI{=Aq^~OB7blhSjQCLX|{bqbHOyFERi<3l6 zkqy^6jJmryUGlDY6Ob}P?isA%^g3)RRIa6mq(Re;bwA2&Qo-gN$fc{F8wmeTJBGVn zd@P7RT`|s=sn4ka@MfgBrVKEWE*9w8?xuE7rUm%ABzg{(y#Cf#m#{`~aUfZRDkhq? z^eD;AUOqWTQS4AOLV{8Hm;|mXbp!vP+`JY_Wq&T&mf4%OXyJ2llhJ*p9(O-Q3L{|0 zjQi8Fb>#PU28Z4N%7XE5YeVoZ1O}E`uog4)c!wz#rEi@|Xod~9^>{sCLYyLkteoHJ zya*7_fZlIhYq-U3?RWSgU@wdau-7Mg&PU&s$K6&lK*UCJR3ORHjFvP@d+8^D@82E$>dfgb1K{NV+~U$=9_ z`3w`uo*Vvl6P=nbB)qoDWLkzN9B+nVQ;jb$h2=LLb- zM~LE;hn*_}O^X1kB#8|}G%oY86!JM?a)%97@-TZw=vvTJ!H&={aRcYeI|ynwT1^N3 z<>wL&lIO@{vL|+XPA^z#0AvrnF_J#iII{(46T(}~cUSsGYTAqeGOzZO?DPogt{K2C zA}KXoHu}XS`2mL>6;Kfaa1TpS3NHfoph;FQCWNCXOIi_fwUlxrbpt+KjN;B%XRHU_ssa%5ZmJfA>idGi2OI+d zK#u7BG^X3ZFmb8er1NmC$R{3C?-6kv&H>N_dgAV;C{4`1PjT(1f|dE5*%)o<9b-_d z@!8w)N`IN^NiBaiXS8iN@&IJm4HGR5T`ZpK>nASejbu9aiqPwm}Teu8HwkjB~t9Kh)38g*}R-+)8IXJjdT0%TC_dULhXQ^`?r zBdu9ix&8AgO?U|5)1LqCXoduU4;zVyZs+9x_$pEV1(740C)_V9-=nQ%m@;m z$uRY>x`@#2V-;-7`CY-N_c8=o4?i}P)xSfO`;58+o(SC8Y1BPf2BjQ^Tb`<nLE6>I!;-tBzljlxQ9o9Ivv(h#4&snB>Uz+Vg7&$4+M zd~T{gJUU9-m2*`8r&7IFvoj#0()c{mZHR}(NLHGJ)AQDXh&L`TTcUdh^t*B83E>nD zWl@dGdq}JmN+wjFZClfeEJARun$K+EV%BooYx6*@t2aAC6!<33!^u~+-w3|&VDuB?=KBOn1nAd zjF}ohAK&_fi@GEP#Q z1NAovOlf|-xz-$0v`PVg64@3$97eaM7t!$$@tg4Pc#}3Cju&g+ISC?fp2a{z40rNfg$Ym1 zxP@Fy)-5p89vF~^!B+F1u|BwUtB3Je=l3hYGrE;nG`!*0aoi*ez$ajm{L5e5n%?(6F7 z16j?wQ0!6zi>=Uu41i$^EKNZJtZv!6!R>fd)OVsc%oi@w!1>kUtzRs#e+N&K*g!vj zBaRKqbG9*U6RlA8M`ib(Yo9EDH`JjwJQ@M-4vpWj@pp@D z;uxE@l#6*%JmL*m_Gt9)ixi;TXcEAPsJ|8E@8asTR2s=sYMj|Ow43SQ1MxpoB)4n*=>FIY+OaH<7;=1x7Ng!sq( zGV`z@Fv*Nwj;FlVCGSvjHeeHKA6qtm-((U; zp@U&nxzq^A`i-`=cJ2F|eLj9baDL;0oJEhi4|d~%7(T$>HsGhN@$P?Q>$BZJ>J8?g V`>YluAn?1Q@>ElyOzvgy{{sJ-bol@P diff --git a/tests_zemu/snapshots/fl-blind-sign/00004.png b/tests_zemu/snapshots/fl-blind-sign/00004.png deleted file mode 100644 index 611d046e88b6904cceaa2dad48c648bf5ea8ecd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29065 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 dS1pzgy_d7`OUA^$qyzW^0vQnvsA diff --git a/tests_zemu/snapshots/fl-blind-sign/00005.png b/tests_zemu/snapshots/fl-blind-sign/00005.png deleted file mode 100644 index 4dfd86530889ca50f6a989f777987747ce65d7bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26332 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 F`(JWtueksK diff --git a/tests_zemu/snapshots/fl-sign_tx_normal/00000.png b/tests_zemu/snapshots/fl-sign_tx_normal/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..09ee44de307d8655f96cf08656a7005ea647f77b GIT binary patch literal 9471 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 literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/fl-sign_tx_normal/00001.png b/tests_zemu/snapshots/fl-sign_tx_normal/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..2bf5392f67f12a5668dd8fbbb611ebe124b64de9 GIT binary patch literal 13014 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 R;QJ~da}&#}m6z{7{x@(e0+;{* literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/fl-sign_tx_normal/00002.png b/tests_zemu/snapshots/fl-sign_tx_normal/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..2b63d6250dd2aa2b94076af39e2594f30f98f8e8 GIT binary patch literal 17445 zcmeIac{r4B{5EVUlq{u^Y%M|&*|QCjBwMl%L-s9XXRJ|@L=i$}gvcI4G8!tĢp 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 o&|kOzu|Sc^v=$044{5vH$=8 literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/fl-sign_tx_normal/00003.png b/tests_zemu/snapshots/fl-sign_tx_normal/00003.png new file mode 100644 index 0000000000000000000000000000000000000000..96a4db964c1f6ed1155fdcd4e30ff65cb03f5045 GIT binary patch literal 27188 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 literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/fl-sign_tx_normal/00004.png b/tests_zemu/snapshots/fl-sign_tx_normal/00004.png new file mode 100644 index 0000000000000000000000000000000000000000..56470a2aa55d902f8edcb3b7b904865767d4391c GIT binary patch literal 20213 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 D)?bMz literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/fl-sign_tx_normal/00005.png b/tests_zemu/snapshots/fl-sign_tx_normal/00005.png new file mode 100644 index 0000000000000000000000000000000000000000..ed06d330df1d6e67742bf8103da49cf86bec1ff0 GIT binary patch literal 16500 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 TLS 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 diff --git a/tests_zemu/snapshots/s-blind-sign/00004.png b/tests_zemu/snapshots/s-blind-sign/00004.png deleted file mode 100644 index ecae92498517dc0b078c53e9ceb4123a2c0efc9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 642 zcmV-|0)737P)NklW3?))xeP}!VV zjqkR~$&rH9Yi3=2BV4G(7PKo?Qf=QOtEOu@?N*xGMK$M!%{QHG6=W?bvh}H+S%SFREcf#^{+1I)>&>fMLeoF;p2!QoY8!Apw`THp@&n-In>LQu=|d z577i%BKjTS;W=UrSLo&?Qf^aV<1!^AM&&=40!h&&Ku(xrku7xRP8Jpx7A7LP2QZ;o zh@FIiEU%44-$_0*p|*KwZi7(_fu9D@6tt5vQ1dVr@|8ydj_ppj&AxPWrK58%wJ88D zlUVJ$CkpI#!@aLE0cLOmt1o(oEN~C9L9%>i{rb=QvX>b*;lQ;!%mk}@P)=S6koMyLLKXmb>kHPz zn&AH|v6XoooP7WQUik-VDX5yDH2I`7S4nX&1rjm;{bncFsGu9jKlh#`&c}=4eGt$3 za2&!3KH3OwW-p7N&g}GBNiCl7aXvF5pG+5V`>yp(1515Kd?b_g2iMpc_yvopmw_C8 zv^T(Z3n-H+r6f12Br-v**rm{h2VTx&nO)gSkVgvDKxtM<+_q}F5lUnXm8D4w49gv2m zO}l%CUL_m^Y(S{d=Kzg0-M%s41btZ|y(t)Dh&n*XDn=-EZQIf30GiE9y#&n^fnuZ{ z)%LB$LgO>8p+ll%@ps3(D4&nTJQ_S1eCiDNJa?&0000< KMNUMnLSTYpq5eJq diff --git a/tests_zemu/snapshots/s-blind-sign/00006.png b/tests_zemu/snapshots/s-blind-sign/00006.png deleted file mode 100644 index 55ce716cf7eebbcf4225ab62962a4ccbe054d427..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 540 zcmV+%0^|LOP)QL+e*`mT-nw`GnkX@s#gkoi`<{#s3Fch?aN(L)GsYEOfqh)m4y-}oE#VE6)RAA64$=l#Ot=b*pQ zr~M-wXyc7A&Dms;;K=^Dy_DUmnW#5Cf0<5VzG~ZsfkhYTpZKl+Ue93AkZtYsz2muQ zpMHMDRgVPPO?DVQ-cB}ZV&{^=78OzsRe(3M7J1@SYL@Jltdx?}tmnOe?`egmTBH;7 zAba3i`4Sdu!YB*ET>)#$hR&QG$4tcrQ&@vt8p_wZAXAzHb#9O)&t+uaPJ|KUVKHW1 z#GG?AkLlH4z%{^b1t4Q8@B2%2h$>0>sG+Pky6-A(nmGj6f|?S*_<-#Kvk}JBHtZY ea_@b>K;sXzt(V|ktkCiR00006Vw{}mBBBC;D387Z#lD5tJ9Ndq{S2cxELWZVvZBoC zmdJswDL(!jgmPzCD7`@>F8?HFAM`_MJipZX;c!5h$Ok!$XZ>&l z;RqjXfSbi+F`Ny;qQw(F&f$IV;B*GfPp$7YuJXe$2Ip2{9qWUwX3J}eLGo@ z(~T8a^d+|jx6$cjuTPfPC5QlaqxwPHB%d&-^C#(Z)Nwu!s8aW_$LM>qpyq@~1{O^QH z>m)i@{;sIQr9n8h5A3a>wpIje38q$)jA$j_Q@2_){B&BvUptNYO&G^t7yAjnR>M5*}olKpO{-9Hb2A# zxgG;=KX6u--p2J%tN)@CAkuNqps1sObpXwkM!0hpG{v9TcXq%OcpNYp?3XyESZ-}P zRMVu$pHAf@su2QY%-6#~GrNd!&2-?of-c4%KNYj z@n*S_^19kck$GnD_jG*+01(ALATh=t`Ghy9Yzc5hF~$4mZ<(Ve2HimM+SO(7^H-0q7kREO*Gqe-cC87tR>3DA(0Cj}ulj7+l zJiY!Q!Dk1U_@|ZnO!7lj*+#=nI!DW_zQe-8!oo*`uOqFpfv6COlcGoE0`f_aHag?! zDhSl&rlwxXdPY^@5hp@PI0T+@bhXlenr3iAey}=-uV14HY&D;5P6V7%`Z{@*lFeyc^3ZD9Za002ovPDHLkV1mP_{<8o8 diff --git a/tests_zemu/snapshots/s-blind-sign/00009.png b/tests_zemu/snapshots/s-blind-sign/00009.png deleted file mode 100644 index 7d00a7669a8c97459b3e160c75b2dfc901ff4e1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 631 zcmV--0*L*IP)7rhrBzsc#p%c|MhG2Ui(If%W%Nj9EP|T|3736Vfg5S z(M%&r%cAkRNakQAzX#Drc#x6RuO<^G{!@W{f^dGzDX$>gTtR!U!-eEZSQ6t%u9;rE zK1a~GAZdK2;eIe37B9!*orf5+>M`&fq~klA8?*q#zV^Qh(f?s0Z}K&E|7}<#vEE3?^SV4tk@G;0FE#!2U#avxwKG#HrXn^CrAw3 zgGPY^Fr#?~v_RD9j9eAB?|q}mh9`pxxv34c6EHH{ls>!CGa=hpqazzdl(>7$M5mYV zaTE@inCyTS$<$|~Y67rez#)!;IA`3g$W_D+80~@t!Hkc)8DqKt?kGiE3V--=)?VwC RDs2D&002ovPDHLkV1lR?AP@im diff --git a/tests_zemu/snapshots/s-blind-sign/00010.png b/tests_zemu/snapshots/s-blind-sign/00010.png deleted file mode 100644 index 8b72d06d5b5f1da0f7eb3b0d54f667466ade5a8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 627 zcmV-(0*w8MP)9ip4V((jPC*KF5IvwbV=V~5B z*@7>f??j_k-&xICf%;x;`~XxoxNXk^W-Zr%xg?|sk(U0--2R%*T9>nMjn${k0Q5~Z zxXkL)7K97BD&bgHO$`YS!j3>I-)&~1o$xu4Y`|t6avt2nwGw57{&617QQa z|4gyrsZo{c5**AL>*4CISJeYqsYJgC9)Q_}nB09%S)Vuy-qX@BBsLGn3?QvNtomSf zb*KyLmk~TX1KD39*)~LB*daYZ;@5XC=gjJ}II4#Jl+T$8^+WR2bO$Y8odUx!z z=!mc2zlTQ%y;fgY&D4SPnjQQABr({p-yN*RzYex2Xb6!Je`of;p;7BH3UjP}xB?Kq zDF)N5ez=lwgsT%ublK7{z)2V}O;{oiG_?%4E;brY|9vrsFv|wAUhME_?0UIi4 zZa0t&pi?B7tT{N54eGrDod}NTFV-p0Cv({30Tp1$08@WDqO$^$#Uc}?&O6#L+{giX z@R7}^Xs)Y?8}3KFDnlk>Zqx>#qHt!<6I?U0xYBV{(FRjh(vhh6000g^#ajsqAh9fb zs@?!&!vPC`sU0*=lOElwsX&tk)td#PbLnHs7}^I&u1j|(#BC?B0MPR{BM-prrxXw1 zMCyPCb)j1{CFeXR7Zw&42w*Cr6jH~}(!x3wfh0ObId#B~#Vdzf71S^zNh?*(Z#X*@%2s~%p00000NkvXXu0mjffEN-T diff --git a/tests_zemu/snapshots/s-blind-sign/00012.png b/tests_zemu/snapshots/s-blind-sign/00012.png deleted file mode 100644 index e2679379cdbc47cfcaec4cc656e5e606798b442c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 548 zcmV+<0^9wGP)68zQ#N&fu(V%IbVay@*vLv~g4IR{4C zgO{v6oK85vbrQ<%ilHHxov^M>Fu0Orzt9t798cEauy(NrYntS-AjwyA$rBUR*f%-a zJNiWeOi3Cw8Vf`j8qkJ?h z$1_Qzq{^{mwal>8q~eX>V1kO1nzDy{dBoCs11yDp3wtihYw<~w6kw#PhBI290AtNL z$sPkKTEuD?x<=08Q44u4x*d*r3T5C#%vH<8L=rxU7&oJOk2n;wzkW41U4@U{rcqGr zq651)-VLQ4|3BCV_kmqSas>j7wP!k03uzJ|H=+yV*f&^yUMP1}(^y?Rt(5vV9{+qcd9Kdo`~`a>0L{ zSAbcoFRW&+Kz>aQR*8$bH`hG?fWh$xv=F2QsM_cub2E;NTa%3Q>+d^HO-}%JscAv@ zD(H1iJZBHWtUjDcIAN#~!tRo#A()e}Ad9Pa)k<^_V&*d z1pqA0{EXR*>r50Q99!-u=70ssG(}1{=*gS1(1eCicgvlIeY5s9n%fV#2reR##FgmF z0c0(qnzIXt!=yL=LBv;dYyj6kIMCBbaM4PjNeB=$f>l9+OJS2IM<5H$1B#|ae{k|d$n|j_LWZDFC{~V0ujc()>&L7wKZeUStcy6D5?1}j4`$j1X81V0ZD znq0VIlPjpapCR<%R0U+MI5jMag@*A_yTzQVPGoX@QmfT0Z}SU54H{1{s5Y%8!ZioT z2l^s$aZhXAQQKyi8)PP)1ITv5b6&+@;OYU!7_GhltGY#%-&Ad|u{yXJn!B6aA3w-x i!k+`kdghj9NaGh;rk3<2jUe>^0000_+nL?Bddc3C##R!CiA=m{lwiT8SgkxKGw@HL8tN4_#%GX6c zi9$GNJTZ?&WY6>UPi?XHok*7A#^OW{P3^HW zGJyRL;0@44SHq*RbbKum{o>}denMJ<ol<(bgBwmJ=@kL2l22}Osk+D&44Lw2s`qp>!|c*Xx#QQ@wz z7ob+T;sSU?@JAtotJv1#L=~i!I!0{eAKlWec#s}a;Ny-{l>)Ve-&u&!#<^#Y?I10f z9E%mT?xM|Cd&Q0DDo88j&wDHXQ-$a{cnqgtx)U0cAT;t{KKz=rV0GqKCTbru zb-9ovlksZO7;hJ#MX^2Vu2_z-M*r6|E~>x+@ywtNIf{LLX9xMd6Gf+Udg8T~N0F}J zpUqFAvvwcsW^O<}E>5KCz|x#EGo(i7F42G+5N z@|puoplJbQo_2-&1mP}2od=8UkaeoR$>a2b~S1Cf`oeCar~GDa3jv5-*ft&X5OB8PFs zpCr%kSWJv~I~qVss!rFF`Bwh71n7vg{CU9Lyi^(Q?M4d=wfF(81O_uHZ`k1g0000< KMNUMnLSTXo+8)mU diff --git a/tests_zemu/snapshots/s-blind-sign/00016.png b/tests_zemu/snapshots/s-blind-sign/00016.png deleted file mode 100644 index ef9ddf5c7736fb55a456b5ce6cf092106ac9cb50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 604 zcmV-i0;BzjP)6t0**V~zGt_h(TB7KmFKEy!8ydbBp$`$n`4%NsdkXYOS` zf`4;fQ|h()U^UALl+R-0eRabrZ16hXJ80eiI_S#kGTelgmPQncUcXJ<)@2grSp9Su zAbpb!rdj=TT*5m|CjqQ0hKA{eAI}1{c()pfHe$jH=^`BtYZrg8*1Jp#PrhO$KYRm= zue;H8YMDJBXxYCcO8}#|BBSbRi>8;)4NNZ*ki>)YOZpg3I+t7>2zml(+9*xkd$ZO& zbOzl4;vNC#1`xjQ%FU6ZDe;Iz1nzzVSX>9FM1mn&XMCivThJy0IM-_EE6|&4i*v?r z05P&AudXfZ!Yk8a#Xu}&_A?PK$f7SK)x3NrVj&mUJ&m^wFuac4AG=>Q;52|G=pQCi0WH^4%{}Lu#v%$Fk2x;bmKxv^`D-|8Wg{p&CVDP%BL53Mh qpYQCwwA(PB3+h>3B{|m!8+-r)itMi(P zikEtL1Y&lxDw}T-iqLY zADuTME9(o^j1`Elv&1HeKIbNygY~*MkQ#mlvQngzfl&07S^r40?4pO(9e#%O>6!p~ z;vAIV#`<(^!U3vE2(z0_4GG?a5z(o|8E3uJGltJSsRstmY7!5&`VhBZ#n*7oFJ36) z*z>jMNskBMtFlxQmtXgY+;5aeyA($r@e%rDL*(gqw-43{!Op})q6rIDcKL|hYA zsJC)9h1_&Qe7Q8H+Rl@SI0Us7Vv%_Wa@(Jol=&!60Lv7SV}OZZhXE#7>qG7!bl+0q zn`nPv;sFGlG$C%0zTVfvK=%18#B-WP@#U5K41 zb;^VeTKuRKYV{g$vIsS~wjn6Ee>MwZks+HtJrU!wAhu>(%?FOpraC0{AsD546q9~O zl&a@07Xpj*>aeEVNp3lS?TS&|)?O%hz+BvE{>;F*3Gm{K?Hz@wn!Bt6{u2gy0NCq4 zhqZq4)>J(;g%nV8{1uPr4zebPf=@@E?bylibMXt%S7!~7NqG(c0000QLMHZ)CMXc($ zoq#wLp6FhV8@>HJq=!N}au-a;vPApUGFC-UhB75cA$zv#Mh&ukBf3Usw8U#yeiX$8 z|JS?%%+kJ~&2|CpxJ$I4#+jUZv)=;%2#!CX#fP})A%r`X5~q`f^Xu=sO-*+Ib*X7V zcrWO+UAWI4q|rWXNw^?%5yI|vOG7XxVSyo6@2Zt(5OU_E5lnE_De+*{r=&$(opX~= z`~UzJPiDqc#mIEGW z$XkZq0rKgDjvqWAC)Ej@D?Lbbq>U%5f`%V8;{B00<_%n%aTMq=s&Km&PV9lOmr6zQ?w}Myub+f5v=4^?;C41p zFpT!$2*L@WlTfV7riS1S!ip>@-!(JQAlxUCby%!j_Jh?X85ZnOt0Cu!|A3_dkBTyb z$&EcL0Jmk+PNg8BL>eXbct-UJAsSjO+kF!&1kSpG(vXOq6^J6vJ`~0P*6$?B%zZ$} zcCwz#%V=j?oSl}G2jPkXEggbAh}ww`WI-+G3Cn&OkT*A{EC&Y2g6j4zx`41P6}=SE zNTVcK<&kdy1Dw4HG(%P1@vuoIJgCk3&Rzjh5h6i(D>{nq%e2RnEP6(qP>$Q#PmD?ri_b~im8)U|AupxHu#G9}Bub&_g+DdEp*f+OTE74Q002ovPDHLkV1oX^4r>4a diff --git a/tests_zemu/snapshots/s-blind-sign/00020.png b/tests_zemu/snapshots/s-blind-sign/00020.png deleted file mode 100644 index d13d0441a4f6c34d9a75d1bbc6ae4ef6310a108d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 553 zcmV+^0@nSBP)sK9Msfbn_5>jymWd4JueS@h|OPmiJS zb*7MwkjA9?nS>p%3AC5WeAIkmdach`@sy6t&TEu7IpllT{ggVbeIt}r3=S*tL8LAC z|3*7Nl=l^HVgv9sE1Uo*2HSZbFl+kwZS6}L#UgP6nrQnI#l*l5SAExq_u&ixj2weu zy$@#+PH;6siLPEsg2Av%^B7R7cZ-#%6XwZe0h=}CJlM-B-GXhk8jifMV1seJNWH5? zo^CTui$s@8R#mHw0qR*+;VRjnFdX*-;D#1C;HWY1%h19G6Jf{koz*-?4bv8S38Yj+ zKP6C`FR*l&eMc*7TE$nSN33l{VV!vf^mGI@ zfs}`u{N2bQJ&Yd!+S9Se1&%@W0pf7-3_?XHFp@UC{^!GI2Nd5{Cka@GN~Mv`=CcY$ rWTb_W!q!sDKJaP2O~-i6XFwfMkOZ-w$j*V1e)F^6I3};@DZwDttx+ zh=b!9)1#3jLlsaz3fV|qaQsY5te8cd5ly^=9x*b=mF;nk8u`8ugcn1(C*J#8Xt*Qz zui*jE%ld>hLj}U;y2wM#rWc#>g}ylN?Oe(?ls zI&5;zNH}Sc|AsD^jOJSBK$wm7gj$9m)Od-fprrg*Cw*O@v;nAeaj&H&tE)rkswvlH z%Pl1I314UO21(Z}`GDyCpIlbUm0PG-Ge)X{=!*hN;|W;TZr4W-BW*x?c8&8&ORVS; zXLg?CE>wrwsd_2~Cx9qy!u*UJJlBoz3(-_k3L>LOFpD}|Pr6d|Wvq#Tmp^4Ye8 zP*9GQe2`V98TL2fI=$KNmpz@)GP`tXMZ}#*;gUgMsm#Ewh#We*zcEx#K+ZI*@1uLa uybVzFJx9p1TA8OHnK@r{LU;*U!ur2KoqEUDh3!)S0000&~|Wj1mb%%8Eu3$uJslzW-p1!uPNF&gCiMu<)q=ZXJ_?Fjy@XeR1qePGR0 zf%I7%`~aNyfQW+Q4{0Gt4N$ew!-YefO%l$p-`_MfJrVqf)Mof@hwLoqbxb^W4<2iM zI+E~)P$j_bilrgJv{7O%R+gg00eu`kCzEwJtX<;4tdrapn}H&H>Y<@{-~uK$PN_eF zfR1A>c4|Hg=xh0xm;-(2Ru`0YL6tRVKUio0nHnzaI@I(>^VJkO`^^89}d zS;A=Zp_mQu^8MO{#YBlvDa{*D(trn0wayc1cHr5PZYlq&W&;;@ql$B2U|_%pZLNq> zRIP3HT6zo?o~3SwsG*okvjPdQ+GWM{1Qi%B>-G`QV`$-HQB3_Sin9pP(A>u0o(E6lylg_wh6pXR{&_H7$BP4 zHi!4=x`a>6kWy21OQmgM{%IoFg&92D5tXOpjs&phS-uOW6TKU4+T6R)8=HeyOq#gk zEPK#0D@Dx~3Umau3S`7LzI8odS#x&yL17wPsb zoaI-V84BB|8mV;vLcxv=gZhgOeUz1qJUqRKM6QDW3zvo_`QZ;hWGj~Kk#~?sq*#FN zwn%PO;o#E51v=F^0}y#%Kh((Pnq`4S@-6Qy^U@x9mVoc=K2D6HGL+PtDw`-%c{AIs zER(EX!s6EqsRNWML%rWsEG#T6{BuN=8CI)0+NtTfCE1Cop-YQJ zdk&>1pa%G+7aJHj>}q7n2A4X&c4sSMK%NOGet3^GGS$cJ(ux>~pJ{v4wIVoCxrI_K u1j{R5ms~TE%&iV=O-BqCT?-2f0{#Hcs|$+Bj8Xvr0000KbojyuHLpvpykQcF^gw>%5mL9M-qFv$91xN$27 zW@y^y`99dQ=UbIXpnEY#i*9r*=NaWfBKP%eiawYD+wo(R_*kc#ZQlv3A5I5^nS8)e zq1zLzAI>BkF~gRs9gr$?qhrPWr<%DMGg$aSG_K$g8^G>&c^0A(O9O4%y?5biYz2MA zO_N5PnAz}jrv-0fFfIpN5NC52hdU&*z_2T!c5HVm0SG7ZN^B8}3fUh-O401xR~{O2 z0G*OuCvY2WDnt|aoGJ#X5yGNMh$gngK0snb>|;b3LS;X?(m`5dEH9dBHB>ly%2ze|-i zJnp^8&=4t97_@ju0q9ze7Ee1!x2%@H%K$~?yik5DDJnKh`solX9*6;jbQ5W{AugvF z#TBKLX1x3^b0S7!T`;zc?Tyh6NV^T5Ek@xQRY!l4d{8an8dWb&!W_t@AAwkGuxlRn g*or<23k$9I1Ftdt9X+?fRsaA107*qoM6N<$f-rak{{R30 diff --git a/tests_zemu/snapshots/s-sign_tx_normal/00000.png b/tests_zemu/snapshots/s-sign_tx_normal/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..c83ee899047fcb495dc47c0b8f90cde0aa8129e3 GIT binary patch literal 333 zcmV-T0kZyyP)X}0Gj4l&Y$`40Gp+Lw90krQ}WJ3xpje%`GR z{)0gOfMzmZd|~8%7walWmL+BXpxsf>cO6psFEgO5h;~ig4NWzo>?mli(imwEo{V({ zNc7LVyOFO6SQ+ZWaqh=88@afwVt@rePpxHiHIO98>GY)i@pO4?Y8}>c4IzXOLI@#* f5JCtcKg9#yLnS&k6T$FYx<ll~%$Gvr!Yz^1Q9TI&QCfU6txDFsKX$-H6!?*)Rb0WOXBkMY~=pQ(l*_H~C zs%dDEwd1QlhLC+hZV^2^b(WmMdOyhY$F0eK3^>EI6${OFvr$Gj?j6o!aLT=WpRFAs z9nH1FJQ<5_yLHFk=Yp+V38}BFExKk=@HU>h=>P!0TQNEed6L8P9pv@s|6lj~d`XPQ zL%Kt959Ch5GZQ?85Tq*lxqo3PtE77mOs~6n<>Q|Z;Y#kZN*X~aA{Z8c i5JCtcgb+dqAwa&)tLV=gp?Yip0000#{xo literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_tx_normal/00003.png b/tests_zemu/snapshots/s-sign_tx_normal/00003.png new file mode 100644 index 0000000000000000000000000000000000000000..664749451bdc08fcd83bdf9d9f43274eeaf2868d GIT binary patch literal 644 zcmV-~0(B%kA~a z#TL6yp97#noq>EhxP2S#J`r8N9?v78I&yUS>i8)+qI&;~t97xTTp$x}BAcr=6<1&6 z&`^snaMp=`z!DQ@4yE3kh)gYPxTo}ARk_=-0QE4QwTxVaJ0%}T$rCM$j9_9JAie;%HRs=M0M}M4H{bp;fC1CK;!_*ez}cI26dLY#fF}eiMk{aZ7q`Y zF7#S?s!=?v`{N;U0L2)y%0^@WN|`KVr7H$`CS$BZ-5(FxR}iui*2wHW7{u08WVqB8 z?*R8M`X`LN1B~PhOhZ-uR9(czL?a2V2c;flA&9LO|NnNW6DLj_2$5C<_`*c0cBF?P zM~oY`FY6y+h_^k`5Y6_G(j0FOfc=I(Vj+eI4VX_b4F!8rj>}Wj5zZ2M?aj|qT3{l#- ed!0D37d!#KY5u2Zlx-OR0000RQkF}s}3W=_ji78ej zPV??Nm4aqD;^UBh2-=`@!Q2QZS0xAtMT3G?N94-bvwgfr``Ny#&ALd(Ky9|rqg7pP zC=0d2z3>6OV;*2xCGfeX2keMAGRamDtorbokm|S&QUl}cL{*%BcmwL)WqW@{xp>9n9HhLbmAhqSJ5|P#U7#J8}@dt%v?bjFWY;^zt002ovPDHLkV1jX@5~TnD literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_tx_normal/00005.png b/tests_zemu/snapshots/s-sign_tx_normal/00005.png new file mode 100644 index 0000000000000000000000000000000000000000..d283c27a0777eefde10f33b02a55ca817a655b91 GIT binary patch literal 286 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!2~2j9iA5fsi&SUjv*Cu-d^<-YEj^E2;A`G zAA4D%zRtwT4Bm{Z_1f0AR9pns#{6EkC2-NVx4Yh*DqU`7o|%6yeQKIuh-Ub~BR%;K zu5XUJxbyX)OKLjLeq=VEwEc2is{i;#!HZ!>gk^TQow7dQ7NxhUym(^PCB}0xtAkFK z8!45S{qub{`J&Dhc;>uK>{rlfF~FNgktz9e{=MOdjTq~Rmq6TMboBE8cpv2jB_dSNF85;E>Q)=`x;qYqusYeB?3BRVCIAews^*kq@zDTykqS|d zQerYAq@QSRVq#+AH&IDN;8ja<52ZUA2gwGl${*1^T{%N$hz^8t?*_5~QN*hF08_HR zAz~)-=9=8-u7X_37{_j&JUabw^0_+zwZ}gK3p@NYD!|&ZUKeH1A2AZ8%LFZ!;PhYg z$^dv#n@nG7@&qCSA&QyGOa3%x6^)tz4EjccM{~w8pJMczYucZOEpktMBNd@kX6Yba x%?wq**vcTj19T@#GR)FU2EwHtnV7g2{sCUi;#=r7uwDQF002ovPDHLkV1kAFA;$m! literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_tx_normal/00007.png b/tests_zemu/snapshots/s-sign_tx_normal/00007.png new file mode 100644 index 0000000000000000000000000000000000000000..a4ff8a9da88cd3452d0672ea19abad7da443033b GIT binary patch literal 649 zcmV;40(Sk0P)$slHm&@%TA}kMN8CeUfkNax;L;D^L{lkVMTvDp-41a09=LSGRZ_S zF;9A&ek>1l2roBhi8VWkki65ncAg^MwTrdo?Psfdu^O365#Px=FwbD5@=SRpo%zGt*OxrAM% zQ@EhRy?ZM-9I(1`53onUU>CeV7>H(sfjMeufjo*6o)}ZkUTu+Ua4{ut8+c}bNY04FfVL>v+bO;c)@-GA#B^!#r?4Z$eGLo@4BQw_DneV$ zjjr)gg3Au?idTxX{_+Y2jL^kii0(20Zb4!#6R^X($VnVzED$y#AioHBPNf}n0A~vf zvP`?n?T92qPlUKwn4Ko`sgp;t{C$s~2s9I1Y&Y$QdCg_)^w(T#4c-PV7%~8yGoZWh z+l}CMYNCdGuMk*mL8oE+PCV!zF=Vh#`pjfASWklMxS)Z;&P%7Tp<>Dzi68p2xJ1p`fcWQ5j70h5Cn8ddu)%i+>;sGqd4?XRhfGUC8=!Z zaxcbY&i<-CxyvL`mi&EYMDaKYpHfxX=E*$9#d{5VWBr^Bbl9ps?oh;X?IW$B*Yt73RhIEMe1~2=P1VQ1??rdp=ZD^Le;sGDCj`u^*5dL>qL7~Lg`|U$F7gKj zDvIU#-w4ekomksbE(uR%H*qB_c2T8++S2_-)n-BSrw-=iLT1y zaQGI$;QoWUD-x>ezH3s6TYJjHNE{x5_`@@|7Ld*KoQ8KJkZFiXmuyT;OicVd;8q0K zKX|d4N_@hjw}s8k14SuV8B}Wmn_d*W=8mfMn@SaCZjaPC(A9Ny6eKqMWC<(_8rN*9 z?wcm?_QS?L?@7#Ul@Es!+hj;O)RQlTrlI`Cnp+zzf^2W5su5t@y?pPo3XCV6O$)~Y z5O%J0t9@r6IU^_M#cEV09_qrc`PLv|T>xA8t~{{~zNUjj_O14@i2`Dk!sfH~e6J*< zG6x>JN3gk>tqUOKh5Ix78K9?_5;@+hKmfKe@SQDLJ25fQ#vgLx*nR9Jlg$7C002ov JPDHLkV1l(DA$I@( literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_tx_normal/00009.png b/tests_zemu/snapshots/s-sign_tx_normal/00009.png new file mode 100644 index 0000000000000000000000000000000000000000..7b3e255903d7982d46d9bc5e96153deb0369e790 GIT binary patch literal 660 zcmV;F0&D$=P)opqav(y-MrGm<7or)B` zT=*dClCHH-Pw$G|){SAHZOM<=!Thb{ajIhi@)qY+?e2%8I3n#|?9i~L#O_H4*hynD z54dVhfS$Zi{YMCTW)EoO0dpiW;n#ca?7hDLvGTcIJQ)X7JVR#rUcVH&wGzl4ueaAD zL?N8#wI_lW0=ec`a}VtC=ol>9UiB&OLtSN;%TBxoi(3MhMd|J%#UPEX`2=Izz+0DD z7#caV+_0@+fbz%n%2iK+X|5{F!mt>r)9=AZcYx|XY-geqSp6Lwyw3)xM9*xJZQ$hL zD4)hwi&BKa-^dcFsEEktl6*5QN8?O{ZXeDgC{VhqzX8WgtrSc4% zLn+}>E;1cr4<_po*ljI!BdB|;l>^$W70dZER__p=6Hp}4XO4_3omys$6g6j2MZYhm z-B`Cfr8;**ah=7YxJdBsTF!WT9B@%e#8V+gYDe!V3d<3y%AS-wtq59Yvz0d+BJlqV uT%7=ms+KwULYA5niF5oByk}x!X#4?BrD(NMS8Qtl0000!dW=AlABaQ$@Ki+=|Ula5JEt@(3x$e|z zJC{dg^I39t1*<(P-ox`SbKh;E+Uaa?*HU%Qg}%V0`fbCWlvinBz^eVJ;id+lRAI5q zB2f*@LBr{1AJo&lLNwC*N0;ou^1GC*&8@_&?C~ysV(CvilGC6Hdml^t;`Qwb%yKd& z)HsOEt9%8}2j@TruOnmGlQzAyP><{9Rl#!fbh6nKf{3b8RVT?pe%cK=4qAQ5{U)lT z*mnLmq36g>%C*Q>((`2pz%aJ;@8<|K7Fq(b3%|#~WJ*DU&cW6V)n|^~S4^FNmNSNw zQMIh59E*B^O1ZpGM9a+1tqs=MUH$(L$XGFK0(@Zr0000000000006*O@(WK^>35zn Re6Roj002ovPDHLkV1k!E$Q=Lx literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_tx_normal/00011.png b/tests_zemu/snapshots/s-sign_tx_normal/00011.png new file mode 100644 index 0000000000000000000000000000000000000000..fdaec24057224a4e8dc92a49f26455290dc77f73 GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!2~2j9iA5fsf(U2jv*Cu-d?}W*Q~(PkZADX zAO9KFxDA>Si_VJqJ^TNTE&JBRS661m@EohU9L#gnz4n`pfvaZs`~T8gZ|bLCY&^4K zjbhvV!iQFtoWz-D#_cYA+ z>Z+CNTp1#wzfP5y8xp@VY_n}WtM0{ygBb@BOcD&F8tOktfIJBV4w>vzAEnOISn-z~ O#PxLbb6Mw<&;$VQ4R!SZ literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_tx_normal/00012.png b/tests_zemu/snapshots/s-sign_tx_normal/00012.png new file mode 100644 index 0000000000000000000000000000000000000000..1c947ca390034255a71393f5cd715c58bfd499fb GIT binary patch literal 504 zcmVMaps8oNXpQ3ag=iW=%JB+nWOZRx-;s2@E*}q2GL$7U z2SCccAFjf-Z|bresDVU%r=BP*)g7f~z07F>w3F31nq>#QZ8BM~6~IY{iLeRPMiFHd z_*A-v@EH?7jBrP3cf&0~-~AR=o2xy5p5t_Hb{K>|$8oJ_{eE?|4)|i0UB-9oG#||U z?ebW2AI=&K_f@7CEI-kq*xXlWzLQ8t23tQa#9GfXnLL=qT7U%5iJvK{!-XkNW{^AP zgqwkkI61;}_mZuirAijeoIkNSm}LuO{FA0&W=+Inf{mdk8vib#>8u3rJNs6^9q~7i zUIF58ZVBOSU6XxNgu+m%<7m%%8tb$8u|AvM5FFu+^*uOJt@{vz z1~QHsZ>wQ?wN6V=UEOilJ}nK?CW9@ciz(CCzBKGakE9As)w_7i>jnMVi3^!kwKvvp z*+#RMM~U93>xr=k@Yi=P1*TFK{PwXEc?hHll>2cig^%AR5;3wcEw<^K3|ZRgv%wF- zj^-Ui>(0mP#hZNK#8`F{S?0lFnkh{#JVxuAXK4pt?}TKYqMjI}pr7(_2CnQIH*VbM zKwV&9OAft__{_c~uX=5ko|W@E4pTBO0IToJH{;2--XZsAB7=J)tLg-h!~)MStW`Kh zwr?sp2W))o*EGSpB&G`W5DMvhLOw3b>&!h_0b&d~n>fDnQZ=tk*C{tozqfWNH5O4gC*6u2EA859eVdoTYuu^6c<|B#gD zVT*L(BIN|o#o=pJmJv1Ae*-KYcJsm+Pj~qzbtM^*#3V^i810e?vp5YfGeM6% z6@)#&%>8n4GF`2IZL5c8vX@ds2kc9@Ue2V@vHh~{iF7)rhJZc$4RGQ>&d39#@)HWM z2*hgOUkTI2OCDhz#?N}82mO!8^*av-2*O;OBT_704c;du{}y$l>h($ M07*qoM6N<$f<(D9R{#J2 literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_tx_normal/00014.png b/tests_zemu/snapshots/s-sign_tx_normal/00014.png new file mode 100644 index 0000000000000000000000000000000000000000..9dacc12684642bb5639756826151ef2a2a7c7e9e GIT binary patch literal 436 zcmV;l0ZaagP)l*xQwvfhcEmZ{QJUPa?xFLbsI6S-D@%$7*@nZc72s0scjw&dPwi3 zdk4vvbJ`!Av<6Cidl#{CuSlkuc4LdiX})-deDG-{Byn2W8Kd>mH<=vA%mx5}%OMtt zuDxvar{=!Iul`T6$a!dn-Bq<(2WH=WEsNg*l&2g1G+X^b;+okklCxebExw)#vn+B3 zR%gp$BinYCTx5McQCwd^U98dFy89zy1kKEP%zp4$fOUel^dHW8@R%=C;$Idj6 z(wsp9x6yfXK*IN2fYQ6Zsmpzsf=yJl!{vUURO-qT+&}H>0R>ya5G$EY|0b}V!-0Kl z(9p5Sj85Pnz+(KyJ^9!GOaxZ-;3elKqTXf`mis^Zr#xB;pX=F3DGeX`5EU;Ec!eOt zFIwR3yb3AjVc_*w*6xvKzhjZEvpVwL4w{C);>|xUz^3RtT{?lKYnG#t>)~@^1K5t9 zlvQpLuvc5!UD-UN@Zhx4u}S!v=O}Vo?)o|0;w2LkKa3^Ghsyw_pVI80O#{NUe9yMf zDpNSA{kq^@Y6YKg7n+_8;D(D44%UYTcx_rohFjw$rUfRktdx0Cc>SruH4Ebxd0F4|PJ-`I1GVC7pyCa30vp>@SkI^$sUrB!_ ze8h+gAP1A5?Oe>;y-d50OZtFu@8$Q<;sIfEA69P?)ut7N5x%bhg(*q#Buh~OgheNL zAQKZ46JLPrC}Icb`*n3##a}#5@VJC1A9<8QTJuC@K)I=l(tz2Ol-8J(u+K_UTH)DG zYG?YD$Vj3J@@8b){WA^lc>n`7i5{|PKd-msHOCknhzsxNY|;Ad>#7C zUWv<79=y=0{Vy?c;J2W&OHaNbxVT14zbUbvSce@Wp>SX2>avrqsM-dmln%i0O`VHPSXv&rhu^o&bMHGAW?=)j4PU?O-xMG_yg^NLFYvs Rqx1j(002ovPDHLkV1l$^NN@lE literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_tx_normal/00016.png b/tests_zemu/snapshots/s-sign_tx_normal/00016.png new file mode 100644 index 0000000000000000000000000000000000000000..67e4ac1ca6a7cddec90c62e84d22f4a36dae5ce1 GIT binary patch literal 646 zcmV;10(t$3P)x9Y5*n~XEuIhZ;`w<0!X%6>JlEBg(K8H7 zXiTBPWh6akFno^#gxvMry4=eIY*cK8%l**8#I+XOyY}%$i>(RL$T(e(0c>_SOs@?Z zG8U=P$uNX5*xutkep>;%(a`fPz`~UP$ooH&#TxKCHn{D(G5w8>Q3PH-b z@SwMH7E;bbq5GM(d*s=DOq8rwg3gmAUtr-o%TdYo&>dKStw-jS z)h^PQ&X%+vWz|MQ!%3mFFX3ypBhhK^uAjqgJY-_xhq06~u~;ncKWdWI8=!_-$)JYR zUN(nFr+%15c=Bml5bW-Zr!!!Ng-hxMVwf z9H16?kd$PYR)B|mPI5ZH zC}Fw;t8Yk#*j`haWwJJuPFmzac${iG9l#*p1XZX$=@-GTw#NZrZGbxQx&>HcXve6W zk|)5dk|T>X?#i|T6B82?KaTclr2fZbw5U^Rm9evEobY>5QVFP9CsHbKxxCH+xofCI zKr^roAv0C=k>G1SBWKl=B;jXZr;)4|$vN>_p54`(K4b$46R17`Jp_sh!(QVtkE=HO zB@PIrwMcDFZ5bNwsr_%ER#QO29L{&Z8P+evdDRpQr4F#a4kELt08XLiQ?PabiLILd g%BGxfVq${h4~?rKnzeAU+5i9m07*qoM6N<$g6)$n>i_@% literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-blind-sign/00025.png b/tests_zemu/snapshots/s-sign_tx_normal/00017.png similarity index 100% rename from tests_zemu/snapshots/s-blind-sign/00025.png rename to tests_zemu/snapshots/s-sign_tx_normal/00017.png diff --git a/tests_zemu/snapshots/s-blind-sign/00026.png b/tests_zemu/snapshots/s-sign_tx_normal/00018.png similarity index 100% rename from tests_zemu/snapshots/s-blind-sign/00026.png rename to tests_zemu/snapshots/s-sign_tx_normal/00018.png diff --git a/tests_zemu/snapshots/sp-blind-sign/00001.png b/tests_zemu/snapshots/sp-blind-sign/00001.png deleted file mode 100644 index 383bb8b669473b4d1e69e5fe32ad8f676ddbb563..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!2~2@x4h6`U|>x2ba4!+nDh2#bl)KZ9*2v3 zv*uR(_dXT(V?~N<<&H+N+ZU?$rDeQQ*zI{BM;fT@!MpR7`+~gwuJ3r!{rA51LO%C( z>^vXkjaGM!>LZMIZ+Yd-CLpqRw7~eK$2%Cf!A3Fbt>xKT!=xMUo`kv`muu8->uKskX z{+s{TJ?!ESHe_#`yUt~j%lSL&L^tODJ(j=d+$|=R%IMwOf2US0-sbn#BCmI6b7WBJ z|8U>QKHu*01o?iO8`$je#%ZEOyYj?1U=SgL2g&pN_KHRM-s)us346NwxvX;Dmb`2u{Z(AaVQAhWNHo`E7P1}+-4##><$ZpX((+7_H^O-EG?{G z%3O`sBh9r2a%TM_R3gH*ClJ;%2EGj1Gn+V=jKN9Fqfp|A(8w8st;{zsor=2@cLB0B zvi>aR$v&-DX^`EBb&dNRU~230HRlG-R%9$iwBpy$KjkqVQ9z}tB-TEGXv!rHJrVt< z`e=87o#~E2&b+T0z0lNWv23Z4RIL^?9^$>{+=Yq5r=yS05ZsH|nXSVw*QcjBe>{C% zcieHhRx@I_OdfAJ8(MkZwU|j>FR#*Nh!>~_)J`|-fcQahqQA^`WKJ~Yh6}5EVnH|$ zcq)3)xTvZ|ZU&EUJpG5DKet6V9)ln>^-SqINs{D6h+^UNkZqDDHHt!**x7nDR76bT zguDuhKN#w}hwOe;l*|20Q-&C+b;sAg%EC%c?<6Qs9>1yu2@Drb{=f?ZM}4m(O! z5*t*OXp%XVK41-XPGJRZQv@kOA2)ILuQUSWN$dW8WlQKdVPGFTcf#FQ2-B|`1KIqEP)eLaW4P%R8yGSFxq`qx3YTWJjke}ZQy%PH9`C-EYm60 ztw*{w&h8c9m=tFUSLK70$|~ zs=Q?YWY2a#u35%y{!AawJOfl5$5hS5>;}Ea*O3Kr|BxCD7f6Zp^%2E>CW{7OdYJ$K z0002sVCZ`ja~4Y?y!ch9FTK{qDZC{X6eKdcj~jzya6;CqIRcZhb_n`*4qgJ^lH9o; z-O6=c)xF8c=H-J_y7!b>Lpe@oQ{m%Uk~vXrMdw4CaiZFp4;h0)`7|qZ7L`uM7%WA0 zZ~xiQ;!)9yPDh3HK}10!te%wEvP9cSf!n*HfiDme1t^`c>4kB zVeWCLS-0-W*7~_tvu^ksKG0}te^BGW0B5xpnV0#g!4z4PDx)^-nT0ztTRZYTxHtw` zvL*S5y^gpXpaMD(004GUkB0ibl=Sm_w~|GHIy}qt+vjnU`5la zZ=`;(S_aE#V%1nh3|CONdwS7a@z>x9FJd`lB&YV{N2B_5=!<}{T)FB<{A$OWa51CO zp3bVGL*OOM|F;x1km=lA!706;`rJ@z?;JNYX%>(fZYgPHXBAnGBBm9UcZ&5>WOZ@J k^ptr3000000R9&L0WEuC zay1kbEN{$@~S5#rU>omplYhJu7ZZLt$5lk9T zcT6qg8Us>KTs6|Bp4@Ltif+QO?l`0}EgyG6H}z!HYf80EYnyifc)`9%11SxZ*)k|wj2qA%4hr5DE7Dc%-O zNv&Qg(%okJ+O@p`2$OHbkY}z%gb+dq`7pl$%KYI%E5-M100000NkvXXu0mjf*dvp8 diff --git a/tests_zemu/snapshots/sp-blind-sign/00005.png b/tests_zemu/snapshots/sp-blind-sign/00005.png deleted file mode 100644 index cf30256e47f22c7d72ca229414c908ce5843584b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 761 zcmV}k6NU=02$|n>zo!I)z>*QL_H_|L2qA^ls;D)KD#1;X_J=>b@)3sDIpSGXzv0x2Q0UJ}bl_hCd=E42uD(q89k?6RCEPoo~ z0x-fXA%qYzfNi%8VpMpXt>?HV;{#dcdWV~g0q~8%7XXhMn#z-@29Qg>;<%&=VZv0Y zl@RXpel4P@5bxCT>#we7zn6Ijw|wfUf2%VZ*a2pu=JI8^BFdB!isrCGbF6-BNTIRh*c3NLs0 za#{k^R4 z2Cb&87F0YBr4pm9pX25gtudmrw#k6F^@+lZ@<<6oTeV*>1 zRWS{S-$ed@RY{KphTPC`AI6G8|Xi(7o{qS{Vl-(8UVm~)oAdW;mIo@n9$ z4IG_5dY+1N*K47?J43XKM#>Y5*>6u{|^fyJLCb rb-yt-Bx~3(00*ZaLI@#*kO%w%rS1VIzFT)j00000NkvXXu0mjfOoL~c diff --git a/tests_zemu/snapshots/sp-blind-sign/00006.png b/tests_zemu/snapshots/sp-blind-sign/00006.png deleted file mode 100644 index dd1e5426b3a58a40abb37ea1785226a69501b4f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 844 zcmV-S1GD^zP))Fp1~# z=))}oAgr8g#oor5HGo9en3AP{=>XPWV^Z>q#Ozap4#JXqmCXOljsaLJFbIMm2SL zk##m1rMnJfj-v@p*F4-9n7*f5qM?5dux1PcXMoZm)au)VB)k@JqS{x26>49B1rz+) zRTxytg*;6=V?k#wL#KP)_R%J5yHyi^*cN#<^^*r6k&XJ7?Yx;7gOglgg+7)}C&w6U zWqbDu@zI%uR}+YpGmx2;Dw%{^S?q|da!;&c$Ldu&5StoR*c*z_T=CQ=a$@BSa%6NM zgn3EiibWF*)rT7wo*d{SxYmf~4C`Y-w^^b5!c-k7vd;>AL^O2Z`mLLtiD>9ycKt*N zhyA$45HEMiWplXR+?-sR7U6r&j)EWvf*=S!3&EuXuUaQQziwIKM3ej(&1J}XfeTGG zWFCVfR(8RpQ?A({w;2X@(?>So;HR%UbXXIL5HvF>EjVbIy7!rwJDr>aT%_K4X-jo~ zT8yhm?~bJAZcbrWENID{L;31ie!pB)9~(kMdt}9x#0Svy1SVC+b5MUSVym60FmL zi<{~tY=PV6cb`pScRL5&y5<$|GeJV{A2-AtoOihpzyBGx3gNiMpPRp)AP9osc76eq WlW3~G*}BL80000kBG^JMN_iB4^4HNA-J_vNige@RqZ$M+sL z8SwbkkI%(inlCe>bIZg4_*M~{Af+uB{PggykQB_Hpa()Iv{`oSQ4n77R=*a zUzpS+unXK!#Gvb!Jc7zeJFyxHL`ooA>QN?yuvQ@)AYgQR&6_r-TRmgL9=!lSw4#m| zKpAhafT4P2Or0G#0MGKkB|RrZ4BCR{0ta9+_&z|7@x05>a>kT*^VQ+jn&=r>O6Bmq zkH3)7eXvtJ3Aa{#^?1!`DO&TDnXoXXX!@JQ-wBnPGQ#cRq_rz;yoYVQKk+GZ^|OR)Zho;=43^(*a0R+T2_pGW*@Ml4~WOs zRfq_JB(o2eqSG6zq3v({G38M_eTIkeGtyi$k$6W;eLG<=hjlQ`9A4)g{PUg}@G0NoXx1s$_g5iL5D^q9nlrOAD_K}PYJ#%7>8JRW%uvqA2%B+A3 zOBKRPnc!O?XqcP3R3Nd~EvoT^3?*3{G<#MV7-^p?HJr&Ur@ z(lOg&%nxL;p}$g1QP2UW^;X18!Nmtu^9wuS2&4(?HWSAUUH}K=lffC#82cWt>Lp*( zi?C!iPiQl&fI2|;=Qg23^ea$Fy_IKCy2F{;lj-|=si7VptdbTw0LYv`CM=a4_3<07 rLK!V{3}9LReZ>(Wgb+dqA(QzJfC@AVF<(zC00000NkvXXu0mjfR&1ye diff --git a/tests_zemu/snapshots/sp-blind-sign/00008.png b/tests_zemu/snapshots/sp-blind-sign/00008.png deleted file mode 100644 index e07fd4703e240de8da426917f7d91897450e1775..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 881 zcmV-%1CIQOP)_^Off5JkRmh z<2ZWb^)ncSJB+4?ebLDH>o{uc06ebcJI76D?S+x_U0}a_p8BZqBhqajKRIrU^vfoB z)Y@G(TVh)6WZwZ`NzqmYOMfHcEpnbGF(t;ZiD#A|er=W(t&w*SmwOOWX2uEG6L6EX z+L*>$CV*#lRjyw?XV26C5wI~8M`>FZZNsC*!)rjGx_l@-cYng{|76nyEVo${MNt$K zq=p)$O0CbRDQco)n`w}Ips@vSBDscYxy)wRD^F8l67;|H1BJYV(dY zFiPB~g3T*1uBxGyKSmJfaU6lo+#S`^V#<|e5Qf;kP{Ea>0gd7xJ82xxoMJa{$9Tm% zOFS-vVh4bItmAnAxWA^8?2-ra(aKcmtIK>4lAX)`t!+x!_#h#C64yK z9ZilcnW@?BYgH}G`<7$?uyZepqA0QvE1OpFc)O)V{Ad(7jl);5#4qT)YZt^f30KRw zv*s<@aPc_yhXBE&gP3@r;Efi6(2H^SRO|$5Yg1kxu?VhM{uFJx6M|LAX4}*orA;gZ z89n0IylQLs+&9e|;a&eLVmUFjbw?x`|9k?PUja=nHgEZ+{Kta6pkXY+BcR&wmqB@p zu~@lknpgez%AYO)bvs)Z&_IR!EcWGPJcw2Hi=rrsqFBK%My<@9?XucT00000NkvXX Hu0mjfegUS$ diff --git a/tests_zemu/snapshots/sp-blind-sign/00009.png b/tests_zemu/snapshots/sp-blind-sign/00009.png deleted file mode 100644 index 6844e6fc7d6a7532e21cb07bd8ba8a1169522f58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 941 zcmV;e15*5nP)Ns=Tdq5Prdv)1EJtBkRS>Yf62d)tGqt+ULwRt1m5sUgJ=#l||J7;T?;7;4&w;OKFdxg+C z1`CsMwg=(+5UV-YZvpmBw`)lfzl?zF^~RxdqxJINto`edeU!qpj(SVnT)Ns=TeSfqR7 zf_0EW`0C0EJsnacUMk)k-3%^YF#xRws{;^mVINIVjx=g{Hq`rVEhrtUsh-|{M$)Bw zC{bZr1*$8+6T*?N3I``9!3!o$A*iob)gZyXjEh{&C*ry5kDq_v>l zn+GM<6x6W|305Arr}~=mmYd!94dyHH)UXc^tX10~2_7;`2%*+uSbn0ZPH*8*Nt zf*^1lkAoN1nS`Y)Ai|Dp`F3qne%XGe#sl{NmtJy~^84%#Jf|x1kr)!-^D9lP8ZHbhVldWfRlrbpw~XAIF9#z^-Lxtwj~UEfMx4 zELKe6B8|)G)q0(&27^qHA`UgtruO5H^0hv=lJ%(9(X<^F%Pm?^cjadpwe@sX69t2p zFkg^(RaC^d^O#%~xudI+CIQK8YR4#Y$=@X;W=kKl$@Fy7 z!J0+?+Gx-W+Q1bs)N`2H?m)rB0xMuQf^hjRJ>+QhhA1&}n=5@7!VVNkMT~R5N@H5> z9J@-I2N{z4YX;L{hULkRbJwe+F9b}0`(_7bP;^rzQ_tRSt?X)T;9Z)zjWgSU-0^Rw zkq|-%A;c&^4JCJb(H_w{)|64Wvm9-@pqoa0BQNSIiOP{|oJrjgM&>mJrk}iOWJ6tf zzHwRfB%JGxLn_nsyz6w+NJg!xwy?K&0+`Yf)umjoj*Rmq1>gCM&d@Qe-BUODJ&!G1 zqxuS-09WMeeqIzx6Gme$R@`a|XiM?)blBb$ajm>2<}#$(jxyo%^k2`dsx5vY<94Dw zSrY;~fz!ReF|sJ{lANgly9awKgb+dqA;dHM0Bu+G2U??JYXATM07*qoM6N<$f*3!b APyhe` diff --git a/tests_zemu/snapshots/sp-blind-sign/00011.png b/tests_zemu/snapshots/sp-blind-sign/00011.png deleted file mode 100644 index 8261f458ec22b480ed93737c4dc842ec6c15a4e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 908 zcmV;719SX|P)+hOpn4AY^~Aysbh0l7lLRrJSkFQ6mwrW)WDU; ziUGJu_BQw|PYwX>+0?$?b0F940W8YFlr3e3h@L^&T_h*z9^eUFA4l(|H?#FhtQ>$f zhKiynio$|D6(~oAp6)*gvWc*s>+{6(iD?%(;IGz`ZIKu!9i=^bFUqj&RKCWLHULy2 zXMOUhn7yOnuYG