From 58ff3fb0295ce7297045c0fc01337721e2cc84fd Mon Sep 17 00:00:00 2001 From: abenso Date: Wed, 20 Nov 2024 17:35:02 -0300 Subject: [PATCH] sign tests in zemu --- app/rust/src/lib.rs | 16 +++---- app/src/apdu_handler.c | 20 ++++---- app/src/coin.h | 1 + app/src/common/actions.h | 10 ++-- app/src/common/tx.c | 4 ++ app/src/common/tx.h | 4 ++ app/src/crypto.c | 65 +++++++++++++------------- app/src/crypto.h | 3 +- app/src/parser_impl.c | 47 +++++++------------ app/src/parser_interface.c | 26 +++++------ app/src/parser_interface.h | 4 +- app/src/parser_txdef.h | 1 + tests_zemu/tests/common.ts | 2 +- tests_zemu/tests/effect_hash.test.ts | 62 ++++++++++++++++++++++++ tests_zemu/tests/standard.test.ts | 30 ------------ tests_zemu/tests/testscases/actions.ts | 34 ++++++++++++++ tests_zemu/tests/testscases/types.ts | 6 +++ 17 files changed, 204 insertions(+), 131 deletions(-) create mode 100644 tests_zemu/tests/effect_hash.test.ts create mode 100644 tests_zemu/tests/testscases/actions.ts create mode 100644 tests_zemu/tests/testscases/types.ts diff --git a/app/rust/src/lib.rs b/app/rust/src/lib.rs index 81b1b68..d155f03 100644 --- a/app/rust/src/lib.rs +++ b/app/rust/src/lib.rs @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************/ -// #![no_std] +#![no_std] #![no_builtins] #![allow(dead_code)] #![deny(unused_crate_dependencies)] @@ -42,14 +42,14 @@ pub(crate) use utils::prf::{expand_fq, expand_fr}; fn debug(_msg: &str) {} -// #[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))] -// use core::panic::PanicInfo; +#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))] +use core::panic::PanicInfo; -// #[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))] -// #[panic_handler] -// fn panic(_info: &PanicInfo) -> ! { -// loop {} -// } +#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))] +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} extern "C" { fn check_app_canary(); diff --git a/app/src/apdu_handler.c b/app/src/apdu_handler.c index a68d39e..982efd6 100644 --- a/app/src/apdu_handler.c +++ b/app/src/apdu_handler.c @@ -176,16 +176,16 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint __Z_UNUSED const char *error_msg = tx_parse(); CHECK_APP_CANARY() - // if (error_msg != NULL) { - // const int error_msg_length = strnlen(error_msg, sizeof(G_io_apdu_buffer)); - // memcpy(G_io_apdu_buffer, error_msg, error_msg_length); - // *tx += (error_msg_length); - // THROW(APDU_CODE_DATA_INVALID); - // } - - // view_review_init(tx_getItem, tx_getNumItems, app_sign); - // view_review_show(REVIEW_TXN); - // *flags |= IO_ASYNCH_REPLY; + if (error_msg != NULL) { + const int error_msg_length = strnlen(error_msg, sizeof(G_io_apdu_buffer)); + memcpy(G_io_apdu_buffer, error_msg, error_msg_length); + *tx += (error_msg_length); + THROW(APDU_CODE_DATA_INVALID); + } + + view_review_init(tx_getItem, tx_getNumItems, app_sign); + view_review_show(REVIEW_TXN); + *flags |= IO_ASYNCH_REPLY; } __Z_INLINE void handle_getversion(__Z_UNUSED volatile uint32_t *flags, volatile uint32_t *tx) { diff --git a/app/src/coin.h b/app/src/coin.h index e322744..b2ee38c 100644 --- a/app/src/coin.h +++ b/app/src/coin.h @@ -34,6 +34,7 @@ extern "C" { #define PK_LEN_25519 32u #define SK_LEN_25519 64u +#define EFFECT_HASH_LEN 64u #define COIN_AMOUNT_DECIMAL_PLACES 6 #define COIN_TICKER "PEN" diff --git a/app/src/common/actions.h b/app/src/common/actions.h index a3e7ba0..6a99ddb 100644 --- a/app/src/common/actions.h +++ b/app/src/common/actions.h @@ -24,6 +24,7 @@ #include "crypto.h" #include "tx.h" #include "zxerror.h" +#include "zxformat.h" extern uint16_t cmdResponseLen; @@ -66,17 +67,16 @@ __Z_INLINE zxerr_t app_fill_keys() { } __Z_INLINE void app_sign() { - const uint8_t *message = tx_get_buffer(); - const uint16_t messageLength = tx_get_buffer_length(); + parser_tx_t *tx = tx_get_txObject(); - zxerr_t err = crypto_sign(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength); + zxerr_t err = crypto_sign(tx, G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3); if (err != zxerr_ok) { set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR); io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); } else { - set_code(G_io_apdu_buffer, SK_LEN_25519, APDU_CODE_OK); - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, SK_LEN_25519 + 2); + set_code(G_io_apdu_buffer, EFFECT_HASH_LEN, APDU_CODE_OK); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, EFFECT_HASH_LEN + 2); } } diff --git a/app/src/common/tx.c b/app/src/common/tx.c index d3faf02..9acb569 100644 --- a/app/src/common/tx.c +++ b/app/src/common/tx.c @@ -82,6 +82,10 @@ const char *tx_parse() { void tx_parse_reset() { MEMZERO(&tx_obj, sizeof(tx_obj)); } +parser_tx_t* tx_get_txObject() { + return &tx_obj; +} + zxerr_t tx_getNumItems(uint8_t *num_items) { parser_error_t err = parser_getNumItems(&ctx_parsed_tx, num_items); diff --git a/app/src/common/tx.h b/app/src/common/tx.h index ab2376d..54f5fe3 100644 --- a/app/src/common/tx.h +++ b/app/src/common/tx.h @@ -18,12 +18,16 @@ #include "coin.h" #include "os.h" #include "zxerror.h" +#include "parser_txdef.h" void tx_initialize(); /// Clears the transaction buffer void tx_reset(); +/// Returns the transaction object +parser_tx_t* tx_get_txObject(); + /// Appends buffer to the end of the current transaction buffer /// Transaction buffer will grow until it reaches the maximum allowed size /// \param buffer diff --git a/app/src/crypto.c b/app/src/crypto.c index 11c5896..ea28554 100644 --- a/app/src/crypto.c +++ b/app/src/crypto.c @@ -21,6 +21,8 @@ #include "cx.h" #include "keys_def.h" #include "zxmacros.h" +#include "parser_interface.h" +#include "zxformat.h" uint32_t hdPath[HDPATH_LEN_DEFAULT]; @@ -70,6 +72,7 @@ __Z_INLINE zxerr_t computeSpendKey(keys_t *keys) { error = zxerr_ok; catch_cx_error: + MEMZERO(&keys, sizeof(keys)); MEMZERO(privateKeyData, sizeof(privateKeyData)); return error; @@ -129,35 +132,33 @@ zxerr_t crypto_fillAddress(uint8_t *buffer, uint16_t bufferLen, uint16_t *cmdRes return error; } -// zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, const uint8_t *message, uint16_t messageLen) { -// if (signature == NULL || message == NULL || signatureMaxlen < ED25519_SIGNATURE_SIZE || messageLen == 0) { -// return zxerr_invalid_crypto_settings; -// } -// -// cx_ecfp_private_key_t cx_privateKey; -// uint8_t privateKeyData[SK_LEN_25519] = {0}; -// -// zxerr_t error = zxerr_unknown; -// // Generate keys -// CATCH_CXERROR(os_derive_bip32_with_seed_no_throw(HDW_NORMAL, CX_CURVE_Ed25519, hdPath, HDPATH_LEN_DEFAULT, -// privateKeyData, NULL, NULL, 0)); -// -// CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_Ed25519, privateKeyData, SCALAR_LEN_ED25519, -// &cx_privateKey)); -// -// // Sign -// CATCH_CXERROR( -// cx_eddsa_sign_no_throw(&cx_privateKey, CX_SHA512, message, messageLen, signature, signatureMaxlen)); -// -// error = zxerr_ok; -// -// catch_cx_error: -// MEMZERO(&cx_privateKey, sizeof(cx_privateKey)); -// MEMZERO(privateKeyData, sizeof(privateKeyData)); -// -// if (error != zxerr_ok) { -// MEMZERO(signature, signatureMaxlen); -// } -// -// return error; -// } +zxerr_t crypto_sign(parser_tx_t *tx_obj, uint8_t *signature, uint16_t signatureMaxlen) { + if (signature == NULL || tx_obj == NULL || signatureMaxlen < EFFECT_HASH_LEN) { + return zxerr_invalid_crypto_settings; + } + + keys_t keys = {0}; + zxerr_t error = zxerr_invalid_crypto_settings; + + CATCH_ZX_ERROR(computeSpendKey(&keys)); + + for (uint16_t i = 0; i < tx_obj->plan.actions.qty; i++) { + CATCH_ZX_ERROR(compute_action_hash(&tx_obj->actions_plan[i], &keys.skb, &tx_obj->plan.memo.key, &tx_obj->plan.actions.hashes[i])); + } + + CATCH_ZX_ERROR(compute_transaction_plan(&tx_obj->plan, tx_obj->effect_hash, sizeof(tx_obj->effect_hash))); + + MEMCPY(signature, tx_obj->effect_hash, EFFECT_HASH_LEN); + + return zxerr_ok; + +catch_zx_error: + MEMZERO(&keys, sizeof(keys)); + MEMZERO(signature, signatureMaxlen); + + if (error != zxerr_ok) { + MEMZERO(signature, signatureMaxlen); + } + + return error; +} diff --git a/app/src/crypto.h b/app/src/crypto.h index 10accff..b0db07b 100644 --- a/app/src/crypto.h +++ b/app/src/crypto.h @@ -26,6 +26,7 @@ extern "C" { #include "coin.h" #include "keys_def.h" #include "zxerror.h" +#include "parser_txdef.h" extern uint32_t hdPath[HDPATH_LEN_DEFAULT]; @@ -34,7 +35,7 @@ zxerr_t crypto_fillKeys(uint8_t *output, uint16_t len, uint16_t *cmdResponseLen) zxerr_t crypto_fillAddress(uint8_t *buffer, uint16_t bufferLen, uint16_t *addrResponseLen, uint32_t account, uint8_t *randomizer); -zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, const uint8_t *message, uint16_t messageLen); +zxerr_t crypto_sign(parser_tx_t *tx_obj, uint8_t *signature, uint16_t signatureMaxlen); zxerr_t crypto_extractSpendingKeyBytes(uint8_t *key_bytes, uint32_t key_bytes_len); diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 878681d..6d675df 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -227,7 +227,6 @@ bool decode_detection_data(pb_istream_t *stream, const pb_field_t *field, void * parser_error_t _read(parser_context_t *c, parser_tx_t *v) { bytes_t data = {0}; - action_t actions_plan[ACTIONS_QTY] = {0}; data.ptr = c->buffer; data.len = c->bufferLen; actions_qty = 0; @@ -247,7 +246,7 @@ parser_error_t _read(parser_context_t *c, parser_tx_t *v) { // actions callbacks request.actions.funcs.decode = &decode_action; - request.actions.arg = &actions_plan; + request.actions.arg = &v->actions_plan; // detection data callbacks request.detection_data.clue_plans.funcs.decode = &decode_detection_data; @@ -270,33 +269,36 @@ parser_error_t _read(parser_context_t *c, parser_tx_t *v) { // get transaction parameters extract_data_from_tag(&data, &v->plan.transaction_parameters.parameters, penumbra_core_transaction_v1_TransactionPlan_transaction_parameters_tag); + v->plan.actions.qty = actions_qty; + + // print transaction parameters print_buffer(&v->plan.transaction_parameters.parameters, "real transaction parameters"); // print actions for (uint16_t i = 0; i < ACTIONS_QTY; i++) { - switch (actions_plan[i].action_type) { + switch (v->actions_plan[i].action_type) { case penumbra_core_transaction_v1_ActionPlan_spend_tag: - print_buffer(&actions_plan[i].action.spend.note.address.inner, "real spend action note address inner"); - print_buffer(&actions_plan[i].action.spend.note.value.asset_id.inner, "real spend action note value asset id inner"); - print_buffer(&actions_plan[i].action.spend.note.rseed, "real spend action note rseed"); - print_buffer(&actions_plan[i].action.spend.randomizer, "real spend action proof randomizer"); - print_buffer(&actions_plan[i].action.spend.value_blinding, "real spend action proof value_blinding"); - print_buffer(&actions_plan[i].action.spend.proof_blinding_r, "real spend action proof proof_blinding_r"); - print_buffer(&actions_plan[i].action.spend.proof_blinding_s, "real spend action proof proof_blinding_s"); + print_buffer(&v->actions_plan[i].action.spend.note.address.inner, "real spend action note address inner"); + print_buffer(&v->actions_plan[i].action.spend.note.value.asset_id.inner, "real spend action note value asset id inner"); + print_buffer(&v->actions_plan[i].action.spend.note.rseed, "real spend action note rseed"); + print_buffer(&v->actions_plan[i].action.spend.randomizer, "real spend action proof randomizer"); + print_buffer(&v->actions_plan[i].action.spend.value_blinding, "real spend action proof value_blinding"); + print_buffer(&v->actions_plan[i].action.spend.proof_blinding_r, "real spend action proof proof_blinding_r"); + print_buffer(&v->actions_plan[i].action.spend.proof_blinding_s, "real spend action proof proof_blinding_s"); // printf("position: %lu\n", actions_plan[i].action.spend.position); // printf("amount hi: %lu\n", actions_plan[i].action.spend.note.value.amount.hi); // printf("amount lo: %lu\n", actions_plan[i].action.spend.note.value.amount.lo); break; case penumbra_core_transaction_v1_ActionPlan_output_tag: - print_buffer(&actions_plan[i].action.output.value.asset_id.inner, "real output action note value asset id inner"); + print_buffer(&v->actions_plan[i].action.output.value.asset_id.inner, "real output action note value asset id inner"); // printf("output value amount hi: %lu\n", actions_plan[i].action.output.value.amount.hi); // printf("output value amount lo: %lu\n", actions_plan[i].action.output.value.amount.lo); - print_buffer(&actions_plan[i].action.output.dest_address.inner, "real output action note dest address inner"); - print_buffer(&actions_plan[i].action.output.rseed, "real output action note rseed"); - print_buffer(&actions_plan[i].action.output.value_blinding, "real output action note value_blinding"); - print_buffer(&actions_plan[i].action.output.proof_blinding_r, "real output action note proof_blinding_r"); - print_buffer(&actions_plan[i].action.output.proof_blinding_s, "real output action note proof_blinding_s"); + print_buffer(&v->actions_plan[i].action.output.dest_address.inner, "real output action note dest address inner"); + print_buffer(&v->actions_plan[i].action.output.rseed, "real output action note rseed"); + print_buffer(&v->actions_plan[i].action.output.value_blinding, "real output action note value_blinding"); + print_buffer(&v->actions_plan[i].action.output.proof_blinding_r, "real output action note proof_blinding_r"); + print_buffer(&v->actions_plan[i].action.output.proof_blinding_s, "real output action note proof_blinding_s"); break; } } @@ -307,19 +309,6 @@ parser_error_t _read(parser_context_t *c, parser_tx_t *v) { print_buffer(&v->plan.memo.plaintext.return_address.inner, "real memo return address inner"); print_buffer(&v->plan.memo.plaintext.return_address.alt_bech32m, "real memo return address alt bech32m"); - for (uint16_t i = 0; i < actions_qty; i++) { - CHECK_ERROR(compute_action_hash(&actions_plan[i], c->sk_bytes, &v->plan.memo.key, &v->plan.actions.hashes[i])); - } - v->plan.actions.qty = actions_qty; - - CHECK_ERROR(compute_transaction_plan(&v->plan, v->effect_hash, sizeof(v->effect_hash))); - - // TODO: only for testing - bytes_t effect_hash; - effect_hash.ptr = v->effect_hash; - effect_hash.len = sizeof(v->effect_hash); - print_buffer(&effect_hash, "effect_hash"); - return parser_ok; } diff --git a/app/src/parser_interface.c b/app/src/parser_interface.c index 0028dac..ab821c2 100644 --- a/app/src/parser_interface.c +++ b/app/src/parser_interface.c @@ -37,44 +37,44 @@ void print_buffer_interface(uint8_t *buffer, size_t len, const char *title) { #endif } -parser_error_t compute_transaction_plan(transaction_plan_t *plan, uint8_t *effect_hash, uint16_t effect_hash_len) { - if (plan == NULL || effect_hash == NULL) return parser_unexpected_error; +zxerr_t compute_transaction_plan(transaction_plan_t *plan, uint8_t *effect_hash, uint16_t effect_hash_len) { + if (plan == NULL || effect_hash == NULL) return zxerr_unknown; if (rs_compute_transaction_plan(plan, effect_hash, effect_hash_len) != parser_ok) { - return parser_unexpected_error; + return zxerr_unknown; } - return parser_ok; + return zxerr_ok; } -parser_error_t compute_action_hash(action_t *action, spend_key_bytes_t *sk_bytes, bytes_t *memo_key,action_hash_t *output) { +zxerr_t compute_action_hash(action_t *action, spend_key_bytes_t *sk_bytes, bytes_t *memo_key,action_hash_t *output) { if (action == NULL || output == NULL) - return parser_unexpected_error; + return zxerr_unknown; switch (action->action_type) { case penumbra_core_transaction_v1_ActionPlan_spend_tag: if (sk_bytes == NULL) - return parser_unexpected_error; + return zxerr_unknown; if (rs_spend_action_hash(sk_bytes, &action->action.spend, (uint8_t *)output, 64) != parser_ok) - return parser_unexpected_error; + return zxerr_encoding_failed; break; case penumbra_core_transaction_v1_ActionPlan_output_tag: if (sk_bytes == NULL) - return parser_unexpected_error; + return zxerr_unknown; if (rs_output_action_hash(sk_bytes, &action->action.output, memo_key, (uint8_t *)output, 64) != parser_ok) - return parser_unexpected_error; + return zxerr_encoding_failed; break; case penumbra_core_transaction_v1_ActionPlan_delegate_tag: case penumbra_core_transaction_v1_ActionPlan_undelegate_tag: if (rs_generic_action_hash(&action->action_data, action->action_type, (uint8_t *)output, 64) != parser_ok) - return parser_unexpected_error; + return zxerr_encoding_failed; break; default: - return parser_unexpected_error; + return zxerr_unknown; } // TODO: only for testing print_buffer_interface((uint8_t *)output, 64, "spend action hash"); - return parser_ok; + return zxerr_ok; } diff --git a/app/src/parser_interface.h b/app/src/parser_interface.h index e9a4a23..2de0a59 100644 --- a/app/src/parser_interface.h +++ b/app/src/parser_interface.h @@ -28,8 +28,8 @@ extern "C" { #include "zxerror.h" #include "zxmacros.h" -parser_error_t compute_transaction_plan(transaction_plan_t *plan, uint8_t *effect_hash, uint16_t effect_hash_len); -parser_error_t compute_action_hash(action_t *action, spend_key_bytes_t *sk_bytes, bytes_t *memo_key, action_hash_t *output); +zxerr_t compute_transaction_plan(transaction_plan_t *plan, uint8_t *effect_hash, uint16_t effect_hash_len); +zxerr_t compute_action_hash(action_t *action, spend_key_bytes_t *sk_bytes, bytes_t *memo_key, action_hash_t *output); #ifdef __cplusplus } diff --git a/app/src/parser_txdef.h b/app/src/parser_txdef.h index 5cb6b12..c2709e6 100644 --- a/app/src/parser_txdef.h +++ b/app/src/parser_txdef.h @@ -166,6 +166,7 @@ typedef struct { typedef struct { transaction_plan_t plan; + action_t actions_plan[ACTIONS_QTY]; uint8_t effect_hash[64]; } parser_tx_t; diff --git a/tests_zemu/tests/common.ts b/tests_zemu/tests/common.ts index 7695b98..bf30b36 100644 --- a/tests_zemu/tests/common.ts +++ b/tests_zemu/tests/common.ts @@ -29,5 +29,5 @@ export const defaultOptions = { } export const txBlobExample = - '0a9102128e020a300a0a089e92c9dbf28597800112220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a1012520a5084506123bb61575ea404e7734087db179136b0e9cc1f62ff29880c5199fe8176c2a1b57c60b61d79b955d145b503c30d6e233b33ddc598b7f6404befdbb39b27c209cf3e7c43044106c9b90d500c74461a20e21e9d6e187cd382414758297fafb4b1a06a4dc6efb9299b2d70d72c0ceec288222099e2b31b8470c3b28a61342a4e8e9dc03aa89a2d1cdb55b19b4d82319df87e012a201be58b456e9d10eddfe2cb2839d554e1e36d25ae82b018355d0ce9b17e8e0a12322097c33e865ddc7b32075fe88f54f03a10a7a7758e354eb0efc49bcbb7fb2805040a9102128e020a300a0a08f89e99f6e2a8bea60812220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a1012520a503b0c5b6250417576213e2a7eeee16e9a816b91cef8336be9c5b1d125f9e6e2769ccbc85fdd2bd1d29e92e78e659d5801964116ecc280156d2247a9433b5bb803682e26e9b6fa4dc59f9a3fb0c9ce662a1a20160054d1d9ce5b6db1fa846074dca4df8929f8123551eb600a52a693ee0815ad2220bb71525bc61fb4cdb82087468a0944361a5c394e7f24262f488e459224be9d032a20cac86a6cc8ae51f861e3cc2f023f256c89d298b0194936eb2253d5d4bdf1800c322026e955748103e77c098257ca9df191006d6bcc1ba7e0577a1d91dff264a8d0000a9102128e020a300a0a088bca90dc90ada4850512220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a1012520a501a02f34fd21d6a56d6cd308717d955b580af5462dd56b06f95e9d1d3f41d172e5a5a64c34857aa962024132d576dc02b16f881198f2465b9565d475ac97040c96f7f742b4eda3028b5f8ad9a9ab4a19d1a203f9ea78658e69d1750a841138818dd7cc1c6cdd02456a522616e0ce44cb1211a22208c2fd85a84e184a6fa3d2f644f1f6efe1f53f22c60addb9b00db453364d018032a20fc29fc2dee02e0e42af1a7874da7988828c8b5685069e9faab7a79f1d9b7d40032209df349c1cdfd9d0dada6333b14282f93632cf1ee4578239640dd2e184eb9a7030abe020abb020aa8010a300a0a0891db8cc1cec2829a0112220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a101220e406c5db8fd46de42bfa23021b24fba56aed33dd995c82af14ee66331655a5271a520a50890bc98e3698aa4578e419b028da5672e627c280d8b06166f4c42d5366bccf1fcf3b296cd61e8d744a21f75f2fb697183e18595d8a79008539d8fb138b405db09db65cc42d54c0e772e5d42d5f20b52f108495d5d38a89171a205434dbfd666bd395970e388f5b40e17ec166ab8a373919944a746e15926305012220b9b89bf8112d8f70501a485aa4d2eadd427e21d7a7c4c480335a5e1845fd44002a20e653e5cdaa0c1bf13a739544df995658622d44c44d2bcc1f270597e694c3220232209375bb05762a06306e8c3c81778a875a638d969df8f567bb80a37b982a176f120abe020abb020aa8010a300a0a089dd8f2fad1e2ed9e0812220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a1012203ab4367b3b7a3957e045bf4b4f6ef49112883f20161e9ea815ff6c7e9b72a0281a520a50890bc98e3698aa4578e419b028da5672e627c280d8b06166f4c42d5366bccf1fcf3b296cd61e8d744a21f75f2fb697183e18595d8a79008539d8fb138b405db09db65cc42d54c0e772e5d42d5f20b52f1085d0e884e0d73c1a20b0b138c127a91b4ed70c1bfe86738d66da4179d24001bad903622a5cba86060422203a339b4017ef099f4fa9f0e9f538b4a412adf436aa4274042c5689b57a54d4002a20e22e518d5e3ca1364372bb41bf715a2b875913df69ef04d102cba287b376ae0132202f95351d4a308667fef2551c24ca71dfb38ebde9c4ea112a5fdf5aeaef49c70e125508eff9ada202123f6b6f62687462637676666b6665696c6571706766786e75656b6279666376762d323737383432363234373330323535303935353735323131303131353638391a0c0a0a08a8cbd3dbcd9be3aa0a' + '0a47ca02440a220a20a5bebed7d3d238dc3623703eefed0b22dfca95cb8c9708e852bfb7abec0322231a0a088a93affdadeae4b406220a088c98d5acc8bcfebc042a0608e10210e1020abe020abb020aa8010a300a0a08d283c2a9b3d2fbcf0a12220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a10122016909e9d88b2ff1f7ab98456f44eedf83230f51d1776a13590649d35d3f2efb21a520a50890bc98e3698aa4578e419b028da5672e627c280d8b06166f4c42d5366bccf1fcf3b296cd61e8d744a21f75f2fb697183e18595d8a79008539d8fb138b405db09db65cc42d54c0e772e5d42d5f20b52f10d2feb9e3f4fb131a2092fbd4bf7397d974318381261ba89aeaaa60eb16a1bd804ce62e8a61a702060222205ca5c6c2f59fd29a2d71be1180ab8d4ce73abec65b4509121d1e119860347a042a2014dcf2bf539544cb41ef2b2d6ddee154427e21bf027b1008a53a43cb1d6fe4003220771a5320bacb67e4c6d923e74de4687b99ec048ba63bf96cda54703c9dbada0a122308b0c18ed216120e65776e75616c6c6f6369642d35301a0b0a0908e691828cc1e58158' diff --git a/tests_zemu/tests/effect_hash.test.ts b/tests_zemu/tests/effect_hash.test.ts new file mode 100644 index 0000000..f6c3af8 --- /dev/null +++ b/tests_zemu/tests/effect_hash.test.ts @@ -0,0 +1,62 @@ +/** ****************************************************************************** + * (c) 2018 - 2023 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. + ******************************************************************************* */ + +import Zemu from '@zondax/zemu' +import { PEN_PATH, defaultOptions, models } from './common' +import { PenumbraApp } from '@zondax/ledger-penumbra' +import { ACTIONS_TESTCASES } from './testscases/actions' + +jest.setTimeout(60000) + +describe('Standard', function () { + test.concurrent.each(models)('can start and stop container', async function (m) { + const sim = new Zemu(m.path) + try { + await sim.start({ ...defaultOptions, model: m.name }) + } finally { + await sim.close() + } + }) + + describe.each(ACTIONS_TESTCASES)('Wallet transactions', function (data) { + test.only.each(models)('sign', async function (m) { + const sim = new Zemu(m.path) + try { + await sim.start({ ...defaultOptions, model: m.name }) + const app = new PenumbraApp(sim.getTransport()) + + const messageToSign = Buffer.from(data.blob, 'hex') + + // do not wait here... we need to navigate + const signatureRequest = app.sign(PEN_PATH, 0, messageToSign) + + // Wait until we are not in the main menu + await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) + await sim.compareSnapshotsAndApprove('.', `${m.prefix.toLowerCase()}-sign_${data.name}`) + + + const signatureResponse = await signatureRequest + console.log(signatureResponse.signature.toString('hex')) + + // Now verify effect hash + expect(signatureResponse.signature.toString('hex')).toEqual(data.expected_effect_hash) + + } finally { + await sim.close() + } + }) + }) +}) diff --git a/tests_zemu/tests/standard.test.ts b/tests_zemu/tests/standard.test.ts index cd7c876..b1a9a10 100644 --- a/tests_zemu/tests/standard.test.ts +++ b/tests_zemu/tests/standard.test.ts @@ -182,33 +182,3 @@ describe('Standard', function () { await sim.close() } }) - - // TODO: WIP - test.only.each(models)('sign', async function (m) { - const sim = new Zemu(m.path) - try { - await sim.start({ ...defaultOptions, model: m.name }) - const app = new PenumbraApp(sim.getTransport()) - - const messageToSign = Buffer.from(txBlobExample, 'hex') - console.log("messageToSignLength!!!!!", messageToSign.length) - console.log("messageToSign!!!!!", messageToSign) - // do not wait here... we need to navigate - const signatureRequest = app.sign(PEN_PATH, ACCOUNT_ID, messageToSign) - - // Wait until we are not in the main menu - // await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) - // await sim.compareSnapshotsAndApprove('.', `${m.prefix.toLowerCase()}-sign`) - - - const signatureResponse = await signatureRequest - console.log(signatureResponse) - - // Now verify the signature - // const valid = ed25519.verify(signatureResponse.signature, messageToSign, pubKey) - // expect(valid).toEqual(true) - } finally { - await sim.close() - } - }) -}) diff --git a/tests_zemu/tests/testscases/actions.ts b/tests_zemu/tests/testscases/actions.ts new file mode 100644 index 0000000..d07ba3e --- /dev/null +++ b/tests_zemu/tests/testscases/actions.ts @@ -0,0 +1,34 @@ +import { TestCase } from "./types" + +export const ACTIONS_TESTCASES: TestCase[] = [ + { + idx: 0, + name: "Spend", + blob: "0abe020abb020aa8010a300a0a08a3e8afde8d8dd78f0712220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a101220bb84a170b10d0675de60f482f0cc65cbc77cbe566db59297b30fa92525fd80081a520a50890bc98e3698aa4578e419b028da5672e627c280d8b06166f4c42d5366bccf1fcf3b296cd61e8d744a21f75f2fb697183e18595d8a79008539d8fb138b405db09db65cc42d54c0e772e5d42d5f20b52f10f9c9b18290d53a1a20edb62b965f04bf87a910fce7041d8c95f56ba0978915d993b43ed5f3dcaca5032220330f85a74dabad563628e7899c4e6210a4a7bd68c8fc02282c045341763111012a20f627a78a52c085fe70175917de9402fd13654f7f4e436b069c3416f28e3a820632207c43f66c9a4e5fbdedb631d297d25fb9e12141165466594d0ecf07877cbee711121c08b29ea4932012066c77676a2d371a0c0a0a0882acd5f799e9baa808", + expected_effect_hash: "667b40348754327edd1e83d2a844a86730f4947fdc1c24700c69d8f0514f66ef090c0e5e0fac4b5ad1f2dbc351b491b7e75425b9ed0f8607a1b08ef7d6130d4e" + }, + { + idx: 1, + name: "Output", + blob: "0a9102128e020a300a0a08d5f28fccf7b7d5bd0312220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a1012520a507484aa099c5fd08c1d725cbfc1acff5b000a33504d77fd8073ae75d9888d7c51ff623eec0063b48bc2b6c0ac20e76c1b9f439c4f22f7b935fd88b7ee4d58afb949f655a4f00e3f65bddfa02912860b9c1a201194995744b0ef87acd41a5dc7473e82a5291c958901a4face985c129b67325a22208169a1a5a29f5dd8dff77e1076daf5191870f526f5da11f4d2f8d0060b2138042a20b47e7cb3e22195693363f8f98f97e9775cf7db9e5ecb3d83d2b5c61ea58bc010322097af9d19059c543d212507fa7cfb3a6b92dbeb6f199934e3daadddef33fe0b06125108a3b7e7fb19123b6775676d7375776d7866676279766d7471766f716a786571766963636d2d36313935303834363639353133383038393038313434383637393436381a0c0a0a08abc3849395f5a9fb0c", + expected_effect_hash: "89ef973f4089d8bcca061866fa92d2faac3ec4968e866fe271258718ccd795153916087152398b68a89d37b5de2dc247a2d0b9685d0b7af08740a43698742a3c" + }, + { + idx: 2, + name: "Delegate", + blob: "0a42c2023f0a220a20a6ee10ae789e8fb40f66fe10a0b3e912ee86a36bf57aa36eed3c3761b86721ac109c081a0a08d8b4e8bbb9f4eebb03220a08ded1eded8d8c81990a122a08e7b5d3900f12156b7262762d313330343730373138353632313637331a0b0a09089395e1ebfea3c206", + expected_effect_hash: "e3069d81a129242b8869e4d3431ab505cafe8f6924ef27f7fc9228b9964a6c4107d6ed58d149d807fc9a27d660d5953a2604d9904125fed412f2fbc34dc02d0a" + }, + { + idx: 3, + name: "Undelegate", + blob: "0a47ca02440a220a20029de1afcd3ef9abfe966d60ba79dd17e06bb34da7e371ea94f57f86d0ffbb6b1a0a08ecf1d082c2819cd604220a08c6d2c5a283daca9e022a0608b90410b904124608bdc6b3f60a123078677978636c7a74746d7a6b6363647461716d2d303339303238343538303433363731373035343133383837383730341a0c0a0a08e1dfefb6f199d0d70c", + expected_effect_hash: "3c37aeb1c52fe54a36b397af63d3eb73280a978543bfbd34ed72c5f71da80bccb09774ac9af53eb117d475951dc1f900fca42da2f483da885f9dbe726b6c5bd8" + }, + { + idx: 4, + name: "Output_Delegate_Undelegate_Spend", + blob: "0a9102128e020a300a0a0894a199a0ac8ebb9d0212220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a1012520a505512ee91cf29ee06701c090e72d9af59c92749f90be93a16441664639732c74a13d0a9152a955fa31bd80d295559321c728fd8b451fb193ccf41491b2667dfffcfccbe7ea1cf4206b419368d150558151a20ef9a1398ce73a12793aec09eed1c26b6f3361b89a3c720487898a10239529e682220ab1996fc6936f11d05bd410156e181d4e0262bba1c08d014065fac18702950022a20fe7cd7663b5392112f0b7358e5d3db117a925160bb950f60b000e59623d73c0232209e118026556b8d0a4b7606d2e71876d1ea47ee2fda2f82dda3a3535ce19e84070a42c2023f0a220a20542a9ac23bb7609cf5965daef2a3a4f324926d4f60a2c2b5b3a026341ae66bca10fa1e1a0a08c59fa8abc6cabce307220a08c7ccf1a588e8cdab0c0a47ca02440a220a20746b99362f4f5d3dc4d3ee32fca9cc7dd7fe39a38a4e87a08a3ba31d69ed78a51a0a08c3f4d5d6a3fdc3ec05220a089fd0ddcfd1f6c5f7022a0608842d10842d0abe020abb020aa8010a300a0a08c0afcfc7b0f787d80a12220a2029ea9c2f3371f6a487e7e95c247041f4a356f983eb064e5d2b3bcf322ca96a101220091c35d2ffa0f663a1d0a3fbbee6c78e8ff6c68df6e3d4cbd6fd0d0151c86fce1a520a50890bc98e3698aa4578e419b028da5672e627c280d8b06166f4c42d5366bccf1fcf3b296cd61e8d744a21f75f2fb697183e18595d8a79008539d8fb138b405db09db65cc42d54c0e772e5d42d5f20b52f10bfd5f1d3d7fe3b1a2095c4de024e4df91abc395673acf6e51e14df268c4e543062fe248b7e85fe8b002220f4514d4b1fe564d9646dd8569497e4201a91fd0b68253dfc4292bb6eabe125032a20ebc6bbe765eb8f8b022bd988c1792eafd56330f0abc62b26e26381a37e37db0a322047f0e7de3151b39cc6b04726aa5208bd694d212ba6ef412e096b388e833090041244088681d6ef01122e7779617061727168776a776d7663776d6263642d34393830393930383833323337323134343434383439353238361a0c0a0a08b2fabad7f9ebabec0b", + expected_effect_hash: "f1d5dc56649339d53417f1b9363eb57030137997688adcf9176a0b4a6e8c6ce4731a860d180de0dedfaca649a345ed9ab84cc1763048e7371c7ece3fa8838ed8" + } +] \ No newline at end of file diff --git a/tests_zemu/tests/testscases/types.ts b/tests_zemu/tests/testscases/types.ts new file mode 100644 index 0000000..de3849e --- /dev/null +++ b/tests_zemu/tests/testscases/types.ts @@ -0,0 +1,6 @@ +export interface TestCase { + idx: number + name: string + blob: string + expected_effect_hash: string +} \ No newline at end of file